Merge "msm: pm-8x60: Unconditionally support WFI hotplug" into msm-3.4
diff --git a/Documentation/devicetree/bindings/coresight/coresight.txt b/Documentation/devicetree/bindings/coresight/coresight.txt
new file mode 100644
index 0000000..c584073
--- /dev/null
+++ b/Documentation/devicetree/bindings/coresight/coresight.txt
@@ -0,0 +1,106 @@
+* CoreSight Components
+
+CoreSight components are compliant with the ARM CoreSight architecture
+specification and can be connected in various topologies to suite a particular
+SoCs tracing needs. These trace components can generally be classified as sinks,
+links and sources. Trace data produced by one or more sources flows through the
+intermediate links connecting the source to the currently selected sink. Each
+CoreSight component device should use these properties to describe its hardware
+characteristcs.
+
+Required properties:
+
+- compatible : name of the component used for driver matching
+- reg : physical base address and length of the register set(s) of the component
+- coresight-id : unique integer identifier for the component
+- coresight-name : unique descriptive name of the component
+- coresight-nr-inports : number of input ports on the component
+
+coresight-outports, coresight-child-list and coresight-child-ports lists will
+be of the same length and will have a one to one correspondence among the
+elements at the same list index.
+
+coresight-default-sink must be specified for one of the sink devices that is
+intended to be made the default sink. Other sink devices must not have this
+specified. Not specifying this property on any of the sinks is invalid.
+
+Optional properties:
+
+- coresight-outports : list of output port numbers of this component
+- coresight-child-list : list of phandles pointing to the children of this
+ component
+- coresight-child-ports : list of input port numbers of the children
+- coresight-default-sink : represents the default compile time CoreSight sink
+
+Examples:
+
+1. Sinks
+ tmc_etr: tmc@fc322000 {
+ compatible = "arm,coresight-tmc";
+ reg = <0xfc322000 0x1000>;
+
+ coresight-id = <0>;
+ coresight-name = "coresight-tmc-etr";
+ coresight-nr-inports = <1>;
+ coresight-default-sink;
+ };
+
+ tpiu: tpiu@fc318000 {
+ compatible = "arm,coresight-tpiu";
+ reg = <0xfc318000 0x1000>;
+
+ coresight-id = <1>;
+ coresight-name = "coresight-tpiu";
+ coresight-nr-inports = <1>;
+ };
+
+2. Links
+ funnel_merg: funnel@fc31b000 {
+ compatible = "arm,coresight-funnel";
+ reg = <0xfc31b000 0x1000>;
+
+ coresight-id = <4>;
+ coresight-name = "coresight-funnel-merg";
+ coresight-nr-inports = <2>;
+ coresight-outports = <0>;
+ coresight-child-list = <&tmc_etf>;
+ coresight-child-ports = <0>;
+ };
+
+ funnel_in0: funnel@fc319000 {
+ compatible = "arm,coresight-funnel";
+ reg = <0xfc319000 0x1000>;
+
+ coresight-id = <5>;
+ coresight-name = "coresight-funnel-in0";
+ coresight-nr-inports = <8>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_merg>;
+ coresight-child-ports = <0>;
+ };
+
+3. Sources
+ stm: stm@fc321000 {
+ compatible = "arm,coresight-stm";
+ reg = <0xfc321000 0x1000>,
+ <0xfa280000 0x180000>;
+
+ coresight-id = <9>;
+ coresight-name = "coresight-stm";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in1>;
+ coresight-child-ports = <7>;
+ };
+
+ etm0: etm@fc33c000 {
+ compatible = "arm,coresight-etm";
+ reg = <0xfc33c000 0x1000>;
+
+ coresight-id = <10>;
+ coresight-name = "coresight-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_kpss>;
+ coresight-child-ports = <0>;
+ };
diff --git a/Documentation/devicetree/bindings/gpio/gpio-msm.txt b/Documentation/devicetree/bindings/gpio/gpio-msm.txt
new file mode 100644
index 0000000..359d700
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-msm.txt
@@ -0,0 +1,39 @@
+MSM GPIO controller bindings
+
+Required properties:
+- compatible:
+ - "qcom,msm-gpio" for MSM controllers
+- #gpio-cells : Should be two.
+ - first cell is the pin number
+ - second cell is used to specify optional parameters (unused)
+- gpio-controller : Marks the device node as a GPIO controller.
+- #interrupt-cells : Should be 2.
+- interrupt-controller: Mark the device node as an interrupt controller
+
+Example:
+
+ msmgpio: gpio@fd510000 {
+ compatible = "qcom,msm-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ reg = <0xfd510000 0x4000>;
+ };
+
+To specify gpios for a device:
+
+ device1@f991f000 {
+ compatible = "qcom,msm-device-v1";
+ reg = <0xf991f000 0x1000>;
+ gpios = <&msmgpio 45 0>;
+ cs-gpios = <&msmgpio 46 0>;
+ };
+
+45, 46 - gpio numbers.
+The driver for device1 can call of_get_gpio() to extract the
+gpio45. In order to extract gpio46, the driver needs to call
+of_get_named_gpio with "cs-gpios" as the name parameter.
+Please refer to the file: include/linux/of_gpio.h for the
+complete list of APIs the driver can use to extract gpio
+information from the device tree.
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
index 95e7f88..32c9c35 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -7,11 +7,12 @@
Required properties:
- compatible: Must be "qcom,pil-q6v5-mss"
-- reg: Four pairs of physical base addresses and region sizes of
+- reg: Five pairs of physical base addresses and region sizes of
memory mapped registers. The first region corresponds to
QDSP6SS_PUB, the second to the bus port halt register
- base, the third to the MSS_RELAY_MSG_BUFFER base, and the
- fourth to the MSS_RESTART register.
+ base, the third to the MSS_RELAY_MSG_BUFFER base, the
+ fourth to the MSS_RESTART register, and the fifth to the
+ MSS_CLAMP_IO register.
- vdd_mss-supply: Reference to the regulator that supplies the processor.
- qcom,firmware-name: Base name of the firmware image. Ex. "mdsp"
- qcom,pil-self-auth: <0> if the hardware does not require self-authenticating
@@ -24,7 +25,8 @@
reg = <0xfc880000 0x100>,
<0xfd485000 0x400>,
<0xfc820000 0x020>,
- <0xfc401680 0x004>;
+ <0xfc401680 0x004>,
+ <0xfc980008 0x004>;
vdd_mss-supply = <&pm8841_s3>;
qcom,firmware-name = "mba";
diff --git a/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt
index c9bc284..2116888 100644
--- a/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt
@@ -76,11 +76,13 @@
1 = 0.25 uA
2 = 0.55 uA
3 = 0.75 uA
-
-- spmi-dev-container: This specifies that all the device nodes specified
- within this node should have their resources coalesced into a single
- spmi_device. This is used to specify all SPMI peripherals that
- logically make up a single regulator device.
+- qcom,force-type: Override the type and subtype register values. Useful for some
+ regulators that have invalid types advertised by the hardware.
+ The format is two unsigned integers of the form <type subtype>.
+- spmi-dev-container: Specifies that all the device nodes specified
+ within this node should have their resources coalesced into a
+ single spmi_device. This is used to specify all SPMI peripherals
+ that logically make up a single regulator device.
Note, if a given optional qcom,* binding is not present, then the qpnp-regulator
driver will leave that feature in the default hardware state.
diff --git a/Documentation/devicetree/bindings/sound/taiko_codec.txt b/Documentation/devicetree/bindings/sound/taiko_codec.txt
new file mode 100644
index 0000000..9f3719b
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/taiko_codec.txt
@@ -0,0 +1,82 @@
+taiko audio CODEC
+
+Required properties:
+
+ - compatible : "qcom,taiko-slim-pgd"
+ - elemental-addr: codec slimbus slave PGD enumeration address.(48 bits)
+
+ - qcom,cdc-reset-gpio: gpio used for codec SOC reset.
+
+ - <supply-name>-supply: phandle to the regulator device tree node
+ - qcom,<supply-name>-voltage - specifies voltage levels for supply. Should be
+ specified in pairs (min, max), units mV.
+ - qcom,<supply-name>-current - specifies max current in mA that can drawn
+ from the <supply-name>.
+
+ above three properties with "supply-name" set to "qcom,cdc-vdd-buck", "qcom,cdc-vdd-tx-h",
+ "qcom,cdc-vdd-rx-h", "qcom,cdc-vddpx-1", "qcom,cdc-vdd-a-1p2v", "qcom,cdc-vddcx-1",
+ "qcom,cdc-vddcx-2" should be present.
+
+ - qcom,cdc-micbias-ldoh-v - LDOH output in volts ( should be 1.95 V and 3.00 V).
+
+ - qcom,cdc-micbias-cfilt1-mv - cfilt1 output voltage in milli volts.
+ - qcom,cdc-micbias-cfilt2-mv - cfilt2 output voltage in milli volts.
+ - qcom,cdc-micbias-cfilt3-mv - cfilt3 output voltage in milli volts.
+ cfilt volatge can be set to max of qcom,cdc-micbias-ldoh-v - 0.15V.
+
+ - qcom,cdc-micbias1-cfilt-sel = cfilt to use for micbias1 (should be from 1 to 3).
+ - qcom,cdc-micbias2-cfilt-sel = cfilt to use for micbias2 (should be from 1 to 3).
+ - qcom,cdc-micbias3-cfilt-sel = cfilt to use for micbias3 (should be from 1 to 3).
+ - qcom,cdc-micbias4-cfilt-sel = cfilt to use for micbias4 (should be from 1 to 3).
+
+ - qcom,cdc-slim-ifd-dev - namme of the codec slim interface device.
+ - qcom,cdc-slim-ifd-elemental-addr - codec slimbus slave interface device
+ enumeration address.
+Example:
+
+taiko_codec {
+ compatible = "qcom,taiko-slim-pgd";
+ elemental-addr = [00 01 A0 00 17 02];
+
+ qcom,cdc-reset-gpio = <&msmgpio 63 0>;
+
+ cdc-vdd-buck-supply = <&pm8941_s2>;
+ qcom,cdc-vdd-buck-voltage = <2150000 2150000>;
+ qcom,cdc-vdd-buck-current = <500000>;
+
+ cdc-vdd-tx-h-supply = <&pm8941_s3>;
+ qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-tx-h-current = <200000>;
+
+ cdc-vdd-rx-h-supply = <&pm8941_s3>;
+ qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-rx-h-current = <200000>;
+
+ cdc-vddpx-1-supply = <&pm8941_s3>;
+ qcom,cdc-vddpx-1-voltage = <1800000 1800000>;
+ qcom,cdc-vddpx-1-current = <5000>;
+
+ cdc-vdd-a-1p2v-supply = <&pm8941_l1>;
+ qcom,cdc-vdd-a-1p2v-voltage = <1225000 1225000>;
+ qcom,cdc-vdd-a-1p2v-current = <5000>;
+
+ cdc-vddcx-1-supply = <&pm8941_l1>;
+ qcom,cdc-vddcx-1-voltage = <1225000 1225000>;
+ qcom,cdc-vddcx-1-current = <5000>;
+
+ cdc-vddcx-2-supply = <&pm8941_l1>;
+ qcom,cdc-vddcx-2-voltage = <1225000 1225000>;
+ qcom,cdc-vddcx-2-current = <5000>;
+
+ qcom,cdc-micbias-ldoh-v = <0x3>;
+ qcom,cdc-micbias-cfilt1-mv = <1800>;
+ qcom,cdc-micbias-cfilt2-mv = <2700>;
+ qcom,cdc-micbias-cfilt3-mv = <1800>;
+ qcom,cdc-micbias1-cfilt-sel = <0x0>;
+ qcom,cdc-micbias2-cfilt-sel = <0x1>;
+ qcom,cdc-micbias3-cfilt-sel = <0x2>;
+ qcom,cdc-micbias4-cfilt-sel = <0x2>;
+
+ qcom,cdc-slim-ifd = "taiko-slim-ifd";
+ qcom,cdc-slim-ifd-elemental-addr = [00 00 A0 00 17 02];
+};
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 8fb7a8e..7930de5 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1849,9 +1849,6 @@
config ARCH_MEMORY_REMOVE
def_bool n
-config ARCH_POPULATES_NODE_MAP
- def_bool n
-
config ENABLE_DMM
def_bool n
diff --git a/arch/arm/boot/dts/msm-pm8841.dtsi b/arch/arm/boot/dts/msm-pm8841.dtsi
index d84c8e0..967d5ec 100644
--- a/arch/arm/boot/dts/msm-pm8841.dtsi
+++ b/arch/arm/boot/dts/msm-pm8841.dtsi
@@ -91,6 +91,7 @@
compatible = "qcom,qpnp-regulator";
reg = <0x1700 0x300>;
status = "disabled";
+ qcom,force-type = <0x1c 0x08>;
qcom,ctl@1700 {
reg = <0x1700 0x100>;
@@ -131,6 +132,7 @@
compatible = "qcom,qpnp-regulator";
reg = <0x1d00 0x300>;
status = "disabled";
+ qcom,force-type = <0x1c 0x08>;
qcom,ctl@1d00 {
reg = <0x1d00 0x100>;
@@ -151,6 +153,7 @@
compatible = "qcom,qpnp-regulator";
reg = <0x2000 0x300>;
status = "disabled";
+ qcom,force-type = <0x1c 0x08>;
qcom,ctl@0 {
reg = <0x2000 0x100>;
@@ -171,6 +174,7 @@
compatible = "qcom,qpnp-regulator";
reg = <0x2300 0x300>;
status = "disabled";
+ qcom,force-type = <0x1c 0x08>;
qcom,ctl@2300 {
reg = <0x2300 0x100>;
@@ -191,6 +195,7 @@
compatible = "qcom,qpnp-regulator";
reg = <0x2600 0x300>;
status = "disabled";
+ qcom,force-type = <0x1c 0x08>;
qcom,ctl@2600 {
reg = <0x2600 0x100>;
@@ -211,6 +216,7 @@
compatible = "qcom,qpnp-regulator";
reg = <0x2900 0x300>;
status = "disabled";
+ qcom,force-type = <0x1c 0x08>;
qcom,ctl@2900 {
reg = <0x2900 0x100>;
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index cb1ac34..ee0a264 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -350,6 +350,72 @@
qcom,hw-settle-time = <0>;
qcom,fast-avg-setup = <0>;
};
+
+ chan@2 {
+ label = "vchg_sns";
+ qcom,channel-num = <2>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <6>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@5 {
+ label = "vcoin";
+ qcom,channel-num = <5>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <3>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@6 {
+ label = "vbat_sns";
+ qcom,channel-num = <6>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <3>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@7 {
+ label = "vph_pwr";
+ qcom,channel-num = <7>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <3>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@9 {
+ label = "ref_625mv";
+ qcom,channel-num = <9>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@10 {
+ label = "ref_1125v";
+ qcom,channel-num = <10>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
};
iadc@3600 {
@@ -425,7 +491,7 @@
#address-cells = <1>;
#size-cells = <1>;
compatible = "qcom,qpnp-regulator";
- reg = <0x1400 0x300>;
+ reg = <0x1a00 0x300>;
status = "disabled";
qcom,ctl@1a00 {
@@ -478,6 +544,7 @@
regulator-name = "8941_l5";
reg = <0x4400 0x100>;
compatible = "qcom,qpnp-regulator";
+ qcom,force-type = <0x04 0x10>;
status = "disabled";
};
@@ -492,6 +559,7 @@
regulator-name = "8941_l7";
reg = <0x4600 0x100>;
compatible = "qcom,qpnp-regulator";
+ qcom,force-type = <0x04 0x10>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/msm8974-cdp.dts b/arch/arm/boot/dts/msm8974-cdp.dts
index 29edf30..bfe24d2 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-cdp.dts
@@ -17,5 +17,9 @@
/ {
model = "Qualcomm MSM 8974 CDP";
compatible = "qcom,msm8974-cdp", "qcom,msm8974";
- qcom,msm-id = <126 1 0>;
+ qcom,msm-id = <126 1 0>, <126 8 0>;
+
+ serial@f991e000 {
+ status = "ok";
+ };
};
diff --git a/arch/arm/boot/dts/msm8974-coresight.dtsi b/arch/arm/boot/dts/msm8974-coresight.dtsi
new file mode 100644
index 0000000..c28ef9e
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-coresight.dtsi
@@ -0,0 +1,177 @@
+/* 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.
+ */
+
+/ {
+ tmc_etr: tmc@fc322000 {
+ compatible = "arm,coresight-tmc";
+ reg = <0xfc322000 0x1000>;
+
+ coresight-id = <0>;
+ coresight-name = "coresight-tmc-etr";
+ coresight-nr-inports = <1>;
+ coresight-default-sink;
+ };
+
+ tpiu: tpiu@fc318000 {
+ compatible = "arm,coresight-tpiu";
+ reg = <0xfc318000 0x1000>;
+
+ coresight-id = <1>;
+ coresight-name = "coresight-tpiu";
+ coresight-nr-inports = <1>;
+ };
+
+ replicator: replicator@fc31c000 {
+ compatible = "qcom,coresight-replicator";
+ reg = <0xfc31c000 0x1000>;
+
+ coresight-id = <2>;
+ coresight-name = "coresight-replicator";
+ coresight-nr-inports = <1>;
+ coresight-outports = <0 1>;
+ coresight-child-list = <&tmc_etr &tpiu>;
+ coresight-child-ports = <0 0>;
+ };
+
+ tmc_etf: tmc@fc307000 {
+ compatible = "arm,coresight-tmc";
+ reg = <0xfc307000 0x1000>;
+
+ coresight-id = <3>;
+ coresight-name = "coresight-tmc-etf";
+ coresight-nr-inports = <1>;
+ coresight-outports = <0>;
+ coresight-child-list = <&replicator>;
+ coresight-child-ports = <0>;
+ };
+
+ funnel_merg: funnel@fc31b000 {
+ compatible = "arm,coresight-funnel";
+ reg = <0xfc31b000 0x1000>;
+
+ coresight-id = <4>;
+ coresight-name = "coresight-funnel-merg";
+ coresight-nr-inports = <2>;
+ coresight-outports = <0>;
+ coresight-child-list = <&tmc_etf>;
+ coresight-child-ports = <0>;
+ };
+
+ funnel_in0: funnel@fc319000 {
+ compatible = "arm,coresight-funnel";
+ reg = <0xfc319000 0x1000>;
+
+ coresight-id = <5>;
+ coresight-name = "coresight-funnel-in0";
+ coresight-nr-inports = <8>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_merg>;
+ coresight-child-ports = <0>;
+ };
+
+ funnel_in1: funnel@fc31a000 {
+ compatible = "arm,coresight-funnel";
+ reg = <0xfc31a000 0x1000>;
+
+ coresight-id = <6>;
+ coresight-name = "coresight-funnel-in1";
+ coresight-nr-inports = <8>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_merg>;
+ coresight-child-ports = <1>;
+ };
+
+ funnel_kpss: funnel@fc345000 {
+ compatible = "arm,coresight-funnel";
+ reg = <0xfc345000 0x1000>;
+
+ coresight-id = <7>;
+ coresight-name = "coresight-funnel-kpss";
+ coresight-nr-inports = <4>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in1>;
+ coresight-child-ports = <5>;
+ };
+
+ funnel_mmss: funnel@fc364000 {
+ compatible = "arm,coresight-funnel";
+ reg = <0xfc364000 0x1000>;
+
+ coresight-id = <8>;
+ coresight-name = "coresight-funnel-mmss";
+ coresight-nr-inports = <8>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in1>;
+ coresight-child-ports = <1>;
+ };
+
+ stm: stm@fc321000 {
+ compatible = "arm,coresight-stm";
+ reg = <0xfc321000 0x1000>,
+ <0xfa280000 0x180000>;
+
+ coresight-id = <9>;
+ coresight-name = "coresight-stm";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in1>;
+ coresight-child-ports = <7>;
+ };
+
+ etm0: etm@fc33c000 {
+ compatible = "arm,coresight-etm";
+ reg = <0xfc33c000 0x1000>;
+
+ coresight-id = <10>;
+ coresight-name = "coresight-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_kpss>;
+ coresight-child-ports = <0>;
+ };
+
+ etm1: etm@fc33d000 {
+ compatible = "arm,coresight-etm";
+ reg = <0xfc33d000 0x1000>;
+
+ coresight-id = <11>;
+ coresight-name = "coresight-etm1";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_kpss>;
+ coresight-child-ports = <1>;
+ };
+
+ etm2: etm@fc33e000 {
+ compatible = "arm,coresight-etm";
+ reg = <0xfc33e000 0x1000>;
+
+ coresight-id = <12>;
+ coresight-name = "coresight-etm2";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_kpss>;
+ coresight-child-ports = <2>;
+ };
+
+ etm3: etm@fc33f000 {
+ compatible = "arm,coresight-etm";
+ reg = <0xfc33f000 0x1000>;
+
+ coresight-id = <13>;
+ coresight-name = "coresight-etm3";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_kpss>;
+ coresight-child-ports = <3>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index a187223..eb269eb 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -10,13 +10,38 @@
* GNU General Public License for more details.
*/
-
-/* QPNP controlled regulators: */
-
&spmi_bus {
-
qcom,pm8941@1 {
+ pm8941_s1: regulator@1400 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ qcom,enable-time = <500>;
+ qcom,pull-down-enable = <1>;
+ regulator-always-on;
+ status = "okay";
+ };
+
+ regulator@1700 {
+ regulator-min-microvolt = <2150000>;
+ regulator-max-microvolt = <2150000>;
+ qcom,enable-time = <500>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ regulator-name = "8941_s2_local";
+ regulator-always-on;
+ qcom,system-load = <100000>;
+ };
+
+ pm8941_s3: regulator@1a00 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,enable-time = <500>;
+ qcom,pull-down-enable = <1>;
+ regulator-always-on;
+ status = "okay";
+ };
+
pm8941_boost: regulator@a000 {
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
@@ -24,6 +49,216 @@
status = "okay";
};
+ pm8941_l1: regulator@4000 {
+ parent-supply = <&pm8941_s1>;
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ regulator-always-on;
+ status = "okay";
+ };
+
+ pm8941_l2: regulator@4100 {
+ parent-supply = <&pm8941_s3>;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_l3: regulator@4200 {
+ parent-supply = <&pm8941_s1>;
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_l4: regulator@4300 {
+ parent-supply = <&pm8941_s1>;
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_l6: regulator@4500 {
+ parent-supply = <&pm8941_s2>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_l8: regulator@4700 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_l9: regulator@4800 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_l10: regulator@4900 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_l11: regulator@4a00 {
+ parent-supply = <&pm8941_s1>;
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ regulator@4b00 {
+ parent-supply = <&pm8941_s2>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ regulator-name = "8941_l12_local";
+ regulator-always-on;
+ qcom,system-load = <100000>;
+ };
+
+ pm8941_l13: regulator@4c00 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_l14: regulator@4d00 {
+ parent-supply = <&pm8941_s2>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_l15: regulator@4e00 {
+ parent-supply = <&pm8941_s2>;
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_l16: regulator@4f00 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_l17: regulator@5000 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_l18: regulator@5100 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_l19: regulator@5200 {
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <2900000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_l20: regulator@5300 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_l21: regulator@5400 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_l22: regulator@5500 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_l23: regulator@5600 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_l24: regulator@5700 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_lvs1: regulator@8000 {
+ parent-supply = <&pm8941_s3>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_lvs2: regulator@8100 {
+ parent-supply = <&pm8941_s3>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
+ pm8941_lvs3: regulator@8200 {
+ parent-supply = <&pm8941_s3>;
+ qcom,enable-time = <200>;
+ qcom,pull-down-enable = <1>;
+ status = "okay";
+ };
+
pm8941_mvs1: regulator@8300 {
parent-supply = <&pm8941_boost>;
qcom,enable-time = <200>;
@@ -41,34 +276,40 @@
qcom,pm8841@5 {
- pm8841_s5: regulator@2000 {
- regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <1100000>;
+ regulator@1400 {
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ qcom,enable-time = <500>;
+ qcom,pull-down-enable = <1>;
+ regulator-always-on;
+ status = "okay";
+ regulator-name = "8841_s1_local";
+ qcom,system-load = <100000>;
+ };
+
+ regulator@1700 {
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ qcom,enable-time = <500>;
+ qcom,pull-down-enable = <1>;
+ regulator-always-on;
+ regulator-name = "8841_s2_local";
+ qcom,system-load = <100000>;
+ status = "okay";
+ };
+
+ pm8841_s3: regulator@1a00 {
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
qcom,enable-time = <500>;
qcom,pull-down-enable = <1>;
regulator-always-on;
status = "okay";
};
- pm8841_s6: regulator@2300 {
- regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <1100000>;
- qcom,enable-time = <500>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8841_s7: regulator@2600 {
- regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <1100000>;
- qcom,enable-time = <500>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8841_s8: regulator@2900 {
- regulator-min-microvolt = <850000>;
- regulator-max-microvolt = <1100000>;
+ pm8841_s4: regulator@1d00 {
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
qcom,enable-time = <500>;
qcom,pull-down-enable = <1>;
status = "okay";
@@ -76,7 +317,6 @@
};
};
-
/* RPM controlled regulators: */
&rpm_bus {
@@ -124,39 +364,6 @@
};
};
- rpm-regulator-smpb3 {
- status = "okay";
- pm8841_s3: regulator-s3 {
- regulator-min-microvolt = <1050000>;
- regulator-max-microvolt = <1050000>;
- qcom,init-voltage = <1050000>;
- status = "okay";
- };
- };
-
- rpm-regulator-smpb4 {
- status = "okay";
- pm8841_s4: regulator-s4 {
- regulator-min-microvolt = <900000>;
- regulator-max-microvolt = <900000>;
- qcom,init-voltage = <900000>;
- status = "okay";
- };
- };
-
- rpm-regulator-smpa1 {
- status = "okay";
- pm8941_s1: regulator-s1 {
- regulator-min-microvolt = <1300000>;
- regulator-max-microvolt = <1300000>;
- qcom,init-voltage = <1300000>;
- qcom,init-current = <100>;
- qcom,system-load = <100000>;
- regulator-always-on;
- status = "okay";
- };
- };
-
rpm-regulator-smpa2 {
status = "okay";
qcom,allow-atomic = <1>;
@@ -176,140 +383,6 @@
};
};
- rpm-regulator-smpa3 {
- status = "okay";
- pm8941_s3: regulator-s3 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,init-voltage = <1800000>;
- qcom,init-current = <100>;
- qcom,system-load = <100000>;
- regulator-always-on;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa1 {
- status = "okay";
- pm8941_l1: regulator-l1 {
- parent-supply = <&pm8941_s1>;
- regulator-min-microvolt = <1225000>;
- regulator-max-microvolt = <1225000>;
- qcom,init-voltage = <1225000>;
- qcom,init-current = <10>;
- qcom,system-load = <10000>;
- regulator-always-on;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa2 {
- status = "okay";
- pm8941_l2: regulator-l2 {
- parent-supply = <&pm8941_s3>;
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- qcom,init-voltage = <1200000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa3 {
- status = "okay";
- pm8941_l3: regulator-l3 {
- parent-supply = <&pm8941_s1>;
- regulator-min-microvolt = <1225000>;
- regulator-max-microvolt = <1225000>;
- qcom,init-voltage = <1225000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa4 {
- status = "okay";
- pm8941_l4: regulator-l4 {
- parent-supply = <&pm8941_s1>;
- regulator-min-microvolt = <12250000>;
- regulator-max-microvolt = <12250000>;
- qcom,init-voltage = <12250000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa5 {
- status = "okay";
- pm8941_l5: regulator-l5 {
- parent-supply = <&pm8941_s2>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,init-voltage = <1800000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa6 {
- status = "okay";
- pm8941_l6: regulator-l6 {
- parent-supply = <&pm8941_s2>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,init-voltage = <1800000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa7 {
- status = "okay";
- pm8941_l7: regulator-l7 {
- parent-supply = <&pm8941_s2>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,init-voltage = <1800000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa8 {
- status = "okay";
- pm8941_l8: regulator-l8 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,init-voltage = <1800000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa9 {
- status = "okay";
- pm8941_l9: regulator-l9 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2950000>;
- qcom,init-voltage = <2950000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa10 {
- status = "okay";
- pm8941_l10: regulator-l10 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2950000>;
- qcom,init-voltage = <2950000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa11 {
- status = "okay";
- pm8941_l11: regulator-l11 {
- parent-supply = <&pm8941_s1>;
- regulator-min-microvolt = <1300000>;
- regulator-max-microvolt = <1300000>;
- qcom,init-voltage = <1300000>;
- status = "okay";
- };
- };
-
rpm-regulator-ldoa12 {
status = "okay";
qcom,allow-atomic = <1>;
@@ -329,152 +402,6 @@
compatible = "qcom,rpm-regulator-smd";
};
};
-
- rpm-regulator-ldoa13 {
- status = "okay";
- pm8941_l13: regulator-l13 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2950000>;
- qcom,init-voltage = <2950000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa14 {
- status = "okay";
- pm8941_l14: regulator-l14 {
- parent-supply = <&pm8941_s2>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,init-voltage = <1800000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa15 {
- status = "okay";
- pm8941_l15: regulator-l15 {
- parent-supply = <&pm8941_s2>;
- regulator-min-microvolt = <2050000>;
- regulator-max-microvolt = <2050000>;
- qcom,init-voltage = <2050000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa16 {
- status = "okay";
- pm8941_l16: regulator-l16 {
- regulator-min-microvolt = <2700000>;
- regulator-max-microvolt = <2700000>;
- qcom,init-voltage = <2700000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa17 {
- status = "okay";
- pm8941_l17: regulator-l17 {
- regulator-min-microvolt = <2850000>;
- regulator-max-microvolt = <2850000>;
- qcom,init-voltage = <2850000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa18 {
- status = "okay";
- pm8941_l18: regulator-l18 {
- regulator-min-microvolt = <2850000>;
- regulator-max-microvolt = <2850000>;
- qcom,init-voltage = <2850000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa19 {
- status = "okay";
- pm8941_l19: regulator-l19 {
- regulator-min-microvolt = <2900000>;
- regulator-max-microvolt = <2900000>;
- qcom,init-voltage = <2900000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa20 {
- status = "okay";
- pm8941_l20: regulator-l20 {
- regulator-min-microvolt = <2950000>;
- regulator-max-microvolt = <2950000>;
- qcom,init-voltage = <2950000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa21 {
- status = "okay";
- pm8941_l21: regulator-l21 {
- regulator-min-microvolt = <2950000>;
- regulator-max-microvolt = <2950000>;
- qcom,init-voltage = <2950000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa22 {
- status = "okay";
- pm8941_l22: regulator-l22 {
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- qcom,init-voltage = <3000000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa23 {
- status = "okay";
- pm8941_l23: regulator-l23 {
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- qcom,init-voltage = <3000000>;
- status = "okay";
- };
- };
-
- rpm-regulator-ldoa24 {
- status = "okay";
- pm8941_l24: regulator-l24 {
- regulator-min-microvolt = <3075000>;
- regulator-max-microvolt = <3075000>;
- qcom,init-voltage = <3075000>;
- status = "okay";
- };
- };
-
- rpm-regulator-vsa1 {
- status = "okay";
- pm8941_lvs1: regulator-lvs1 {
- parent-supply = <&pm8941_s3>;
- status = "okay";
- };
- };
-
- rpm-regulator-vsa2 {
- status = "okay";
- pm8941_lvs2: regulator-lvs2 {
- parent-supply = <&pm8941_s3>;
- status = "okay";
- };
- };
-
- rpm-regulator-vsa3 {
- status = "okay";
- pm8941_lvs3: regulator-lvs3 {
- parent-supply = <&pm8941_s3>;
- status = "okay";
- };
- };
};
/ {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index e3dad4f..0b7d2c5 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -14,6 +14,7 @@
/include/ "msm8974_pm.dtsi"
/include/ "msm8974-iommu.dtsi"
/include/ "msm8974-camera.dtsi"
+/include/ "msm8974-coresight.dtsi"
/include/ "msm-gdsc.dtsi"
/include/ "msm8974-ion.dtsi"
/include/ "msm8974-gpu.dtsi"
@@ -33,10 +34,11 @@
msmgpio: gpio@fd510000 {
compatible = "qcom,msm-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
reg = <0xfd510000 0x4000>;
- #gpio-cells = <2>;
};
timer {
@@ -73,6 +75,13 @@
status = "disabled";
};
+ serial@f991e000 {
+ compatible = "qcom,msm-lsuart-v14";
+ reg = <0xf991e000 0x1000>;
+ interrupts = <0 108 0>;
+ status = "disabled";
+ };
+
usb@f9a55000 {
compatible = "qcom,hsusb-otg";
reg = <0xf9a55000 0x400>;
@@ -220,6 +229,53 @@
interrupt-names = "slimbus_irq", "slimbus_bam_irq";
qcom,min-clk-gear = <10>;
qcom,rxreg-access;
+
+ taiko_codec {
+ compatible = "qcom,taiko-slim-pgd";
+ elemental-addr = [00 01 A0 00 17 02];
+
+ qcom,cdc-reset-gpio = <&msmgpio 63 0>;
+
+ cdc-vdd-buck-supply = <&pm8941_s2>;
+ qcom,cdc-vdd-buck-voltage = <2150000 2150000>;
+ qcom,cdc-vdd-buck-current = <650000>;
+
+ cdc-vdd-tx-h-supply = <&pm8941_s3>;
+ qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-tx-h-current = <25000>;
+
+ cdc-vdd-rx-h-supply = <&pm8941_s3>;
+ qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-rx-h-current = <25000>;
+
+ cdc-vddpx-1-supply = <&pm8941_s3>;
+ qcom,cdc-vddpx-1-voltage = <1800000 1800000>;
+ qcom,cdc-vddpx-1-current = <10000>;
+
+ cdc-vdd-a-1p2v-supply = <&pm8941_l1>;
+ qcom,cdc-vdd-a-1p2v-voltage = <1225000 1225000>;
+ qcom,cdc-vdd-a-1p2v-current = <10000>;
+
+ cdc-vddcx-1-supply = <&pm8941_l1>;
+ qcom,cdc-vddcx-1-voltage = <1225000 1225000>;
+ qcom,cdc-vddcx-1-current = <10000>;
+
+ cdc-vddcx-2-supply = <&pm8941_l1>;
+ qcom,cdc-vddcx-2-voltage = <1225000 1225000>;
+ qcom,cdc-vddcx-2-current = <10000>;
+
+ qcom,cdc-micbias-ldoh-v = <0x3>;
+ qcom,cdc-micbias-cfilt1-mv = <1800>;
+ qcom,cdc-micbias-cfilt2-mv = <2700>;
+ qcom,cdc-micbias-cfilt3-mv = <1800>;
+ qcom,cdc-micbias1-cfilt-sel = <0x0>;
+ qcom,cdc-micbias2-cfilt-sel = <0x1>;
+ qcom,cdc-micbias3-cfilt-sel = <0x2>;
+ qcom,cdc-micbias4-cfilt-sel = <0x2>;
+
+ qcom,cdc-slim-ifd = "taiko-slim-ifd";
+ qcom,cdc-slim-ifd-elemental-addr = [00 00 A0 00 17 02];
+ };
};
spmi_bus: qcom,spmi@fc4c0000 {
@@ -467,7 +523,8 @@
reg = <0xfc880000 0x100>,
<0xfd485000 0x400>,
<0xfc820000 0x020>,
- <0xfc401680 0x004>;
+ <0xfc401680 0x004>,
+ <0xfc980008 0x004>;
vdd_mss-supply = <&pm8841_s3>;
qcom,firmware-name = "mba";
@@ -628,16 +685,18 @@
compatible = "qcom,qcedev";
reg = <0xfd440000 0x20000>,
<0xfd444000 0x8000>;
+ reg-names = "crypto-base","crypto-bam-base";
interrupts = <0 235 0>;
- qcom,bam-pipes = <0>;
+ qcom,bam-pipe-pair = <0>;
};
qcom,qcrypto@fd444000 {
compatible = "qcom,qcrypto";
reg = <0xfd440000 0x20000>,
<0xfd444000 0x8000>;
+ reg-names = "crypto-base","crypto-bam-base";
interrupts = <0 235 0>;
- qcom,bam-pipes = <1>;
+ qcom,bam-pipe-pair = <1>;
};
qcom,usbbam@f9304000 {
@@ -675,6 +734,15 @@
qcom,descriptor-fifo-size = <0x1400>;
};
};
+
+ qcom,msm-thermal {
+ compatible = "qcom,msm-thermal";
+ qcom,sensor-id = <0>;
+ qcom,poll-ms = <250>;
+ qcom,limit-temp = <60>;
+ qcom,temp-hysteresis = <10>;
+ qcom,freq-step = <2>;
+ };
};
/include/ "msm-pm8x41-rpm-regulator.dtsi"
diff --git a/arch/arm/boot/dts/msm9625.dts b/arch/arm/boot/dts/msm9625.dts
index deddc5f..42425ed 100644
--- a/arch/arm/boot/dts/msm9625.dts
+++ b/arch/arm/boot/dts/msm9625.dts
@@ -37,6 +37,8 @@
msmgpio: gpio@fd510000 {
compatible = "qcom,msm-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
reg = <0xfd510000 0x4000>;
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 1f2e285..3854403 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -356,6 +356,7 @@
CONFIG_IMX074_EEPROM=y
CONFIG_IMX091_EEPROM=y
CONFIG_MSM_GEMINI=y
+CONFIG_MSM_MERCURY=y
CONFIG_MSM_CSI20_HEADER=y
CONFIG_S5K3L1YX=y
CONFIG_IMX091=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 8c79847..06501ba 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -359,6 +359,7 @@
CONFIG_IMX074_EEPROM=y
CONFIG_IMX091_EEPROM=y
CONFIG_MSM_GEMINI=y
+CONFIG_MSM_MERCURY=y
CONFIG_MSM_CSI20_HEADER=y
CONFIG_S5K3L1YX=y
CONFIG_IMX091=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 6f4db42..c73c62e 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -51,6 +51,9 @@
CONFIG_MSM_TZ_LOG=y
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
CONFIG_MSM_OCMEM=y
+CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
+CONFIG_MSM_OCMEM_DEBUG=y
+CONFIG_MSM_OCMEM_POWER_DISABLE=y
CONFIG_MSM_MEMORY_DUMP=y
CONFIG_MSM_CACHE_ERP=y
CONFIG_MSM_L1_ERR_PANIC=y
@@ -66,7 +69,6 @@
CONFIG_HIGHMEM=y
CONFIG_VMALLOC_RESERVE=0x19000000
CONFIG_USE_OF=y
-CONFIG_ARM_APPENDED_DTB=y
CONFIG_ARM_ATAG_DTB_COMPAT=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
@@ -130,6 +132,7 @@
CONFIG_SERIAL_MSM_HSL=y
CONFIG_SERIAL_MSM_HSL_CONSOLE=y
CONFIG_DIAG_CHAR=y
+CONFIG_HVC_DCC=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_MSM=y
CONFIG_DCC_TTY=y
@@ -255,4 +258,3 @@
CONFIG_CRYPTO_DEV_QCEDEV=m
CONFIG_CRC_CCITT=y
CONFIG_LIBCRC32C=y
-CONFIG_MSM_BUS_SCALING=y
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index ca3e996..7d26726 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -541,7 +541,8 @@
dump_stack();
pr_info("\nsending IPI to all other CPUs:\n");
- smp_cross_call(&backtrace_mask, IPI_CPU_BACKTRACE);
+ if (!cpus_empty(backtrace_mask))
+ smp_cross_call(&backtrace_mask, IPI_CPU_BACKTRACE);
/* Wait for up to 10 seconds for all other CPUs to do the backtrace */
for (i = 0; i < 10 * 1000; i++) {
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index f026a94..5331f2c 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -2327,6 +2327,15 @@
related operations of OCMEM. Both local power management
and RPM assisted power management operations are supported.
+config MSM_OCMEM_POWER_DISABLE
+ bool "OCMEM Disable Power Control"
+ depends on MSM_OCMEM_DEBUG
+ help
+ Disable all OCMEM power management.
+ This keeps all OCMEM macros turned ON at all times thus
+ never allowing them to be turned OFF. Both local power
+ management and RPM assisted power modes are supported.
+
config MSM_RTB
bool "Register tracing"
help
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index ea7fb32..665b861 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -2277,11 +2277,13 @@
&msm8960_device_ebi1_ch0_erp,
&msm8960_device_ebi1_ch1_erp,
&epm_adc_device,
- &apq8064_qdss_device,
- &msm_etb_device,
- &msm_tpiu_device,
- &msm_funnel_device,
- &apq8064_etm_device,
+ &coresight_tpiu_device,
+ &coresight_etb_device,
+ &apq8064_coresight_funnel_device,
+ &coresight_etm0_device,
+ &coresight_etm1_device,
+ &coresight_etm2_device,
+ &coresight_etm3_device,
&apq_cpudai_slim_4_rx,
&apq_cpudai_slim_4_tx,
#ifdef CONFIG_MSM_GEMINI
@@ -2911,6 +2913,7 @@
static void __init apq8064_common_init(void)
{
u32 platform_version;
+ platform_device_register(&msm_gpio_device);
msm_tsens_early_init(&apq_tsens_pdata);
msm_thermal_init(&msm_thermal_pdata);
if (socinfo_init() < 0)
diff --git a/arch/arm/mach-msm/board-8930-gpiomux.c b/arch/arm/mach-msm/board-8930-gpiomux.c
index e0f012a..ff0a61f 100644
--- a/arch/arm/mach-msm/board-8930-gpiomux.c
+++ b/arch/arm/mach-msm/board-8930-gpiomux.c
@@ -688,6 +688,22 @@
},
};
+static struct gpiomux_setting gyro_int_line = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct msm_gpiomux_config msm8930_gyro_int_config[] __initdata = {
+ {
+ .gpio = 69, /* Gyro Interrupt Line */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gyro_int_line,
+ [GPIOMUX_ACTIVE] = &gyro_int_line,
+ },
+ },
+};
+
int __init msm8930_init_gpiomux(void)
{
int rc = msm_gpiomux_init(NR_GPIO_IRQS);
@@ -758,5 +774,9 @@
msm_gpiomux_install(msm8930_sd_det_config,
ARRAY_SIZE(msm8930_sd_det_config));
+ if (machine_is_msm8930_fluid() || machine_is_msm8930_mtp())
+ msm_gpiomux_install(msm8930_gyro_int_config,
+ ARRAY_SIZE(msm8930_gyro_int_config));
+
return 0;
}
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator.c
index d3a4960..d4bd18f 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator.c
@@ -99,6 +99,9 @@
REGULATOR_SUPPLY("cam_vdig", "4-0048"),
REGULATOR_SUPPLY("cam_vdig", "4-0020"),
};
+VREG_CONSUMERS(L13) = {
+ REGULATOR_SUPPLY("8038_l13", NULL),
+};
VREG_CONSUMERS(L14) = {
REGULATOR_SUPPLY("8038_l14", NULL),
REGULATOR_SUPPLY("pa_therm", "pm8xxx-adc"),
@@ -148,6 +151,9 @@
REGULATOR_SUPPLY("8038_l24", NULL),
REGULATOR_SUPPLY("riva_vddmx", "wcnss_wlan.0"),
};
+VREG_CONSUMERS(L25) = {
+ REGULATOR_SUPPLY("8038_l25", NULL),
+};
VREG_CONSUMERS(L26) = {
REGULATOR_SUPPLY("8038_l26", NULL),
};
@@ -492,6 +498,7 @@
RPM_LDO(L10, 0, 1, 0, 2900000, 2900000, NULL, 0, 0),
RPM_LDO(L11, 1, 1, 0, 1800000, 1800000, "8038_s4", 10000, 10000),
RPM_LDO(L12, 0, 1, 0, 1200000, 1200000, "8038_s2", 0, 0),
+ RPM_LDO(L13, 0, 0, 0, 2220000, 2220000, NULL, 0, 0),
RPM_LDO(L14, 0, 1, 0, 1800000, 1800000, NULL, 0, 0),
RPM_LDO(L15, 0, 1, 0, 1800000, 2950000, NULL, 0, 0),
RPM_LDO(L17, 0, 1, 0, 1800000, 2950000, NULL, 0, 0),
@@ -501,6 +508,7 @@
RPM_LDO(L22, 1, 1, 0, 1850000, 2950000, NULL, 10000, 10000),
RPM_LDO(L23, 1, 1, 1, 1800000, 1800000, "8038_s4", 0, 0),
RPM_LDO(L24, 0, 1, 1, 500000, 1150000, "8038_s2", 10000, 10000),
+ RPM_LDO(L25, 0, 0, 0, 1740000, 1740000, "8038_l13", 0, 0),
RPM_LDO(L26, 1, 1, 0, 1050000, 1050000, "8038_s2", 10000, 10000),
/* ID a_on pd ss supply */
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 0678461..4fce029 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -2239,14 +2239,11 @@
&msm8930_ion_dev,
#endif
&msm_device_tz_log,
-
-#ifdef CONFIG_MSM_QDSS
- &msm_qdss_device,
- &msm_etb_device,
- &msm_tpiu_device,
- &msm_funnel_device,
- &msm_etm_device,
-#endif
+ &coresight_tpiu_device,
+ &coresight_etb_device,
+ &coresight_funnel_device,
+ &coresight_etm0_device,
+ &coresight_etm1_device,
&msm_device_dspcrashd_8960,
&msm8960_device_watchdog,
#ifdef MSM8930_PHASE_2
@@ -2434,6 +2431,7 @@
static struct i2c_board_info __initdata mpu3050_i2c_boardinfo[] = {
{
I2C_BOARD_INFO("mpu3050", 0x68),
+ .irq = MSM_GPIO_TO_INT(MPU3050_INT_GPIO),
.platform_data = &mpu3050_gyro,
},
};
@@ -2575,6 +2573,7 @@
if (meminfo_init(SYS_MEMORY, SZ_256M) < 0)
pr_err("meminfo_init() failed!\n");
+ platform_device_register(&msm_gpio_device);
msm_tsens_early_init(&msm_tsens_pdata);
msm_thermal_init(&msm_thermal_pdata);
BUG_ON(msm_rpm_init(&msm8930_rpm_data));
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 25677c3..ad788bc 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2664,13 +2664,11 @@
&msm8960_rpm_log_device,
&msm8960_rpm_stat_device,
&msm_device_tz_log,
-#ifdef CONFIG_MSM_QDSS
- &msm_qdss_device,
- &msm_etb_device,
- &msm_tpiu_device,
- &msm_funnel_device,
- &msm_etm_device,
-#endif
+ &coresight_tpiu_device,
+ &coresight_etb_device,
+ &coresight_funnel_device,
+ &coresight_etm0_device,
+ &coresight_etm1_device,
&msm_device_dspcrashd_8960,
&msm8960_device_watchdog,
&msm8960_rtb_device,
@@ -3084,6 +3082,7 @@
if (meminfo_init(SYS_MEMORY, SZ_256M) < 0)
pr_err("meminfo_init() failed!\n");
+ platform_device_register(&msm_gpio_device);
msm_tsens_early_init(&msm_tsens_pdata);
msm_thermal_init(&msm_thermal_pdata);
BUG_ON(msm_rpm_init(&msm8960_rpm_data));
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 6fcc779..bf80262 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -101,13 +101,13 @@
},
},
{
- .gpio = 45, /* BLSP8 UART TX */
+ .gpio = 4, /* BLSP2 UART TX */
.settings = {
[GPIOMUX_SUSPENDED] = &gpio_uart_config,
},
},
{
- .gpio = 46, /* BLSP8 UART RX */
+ .gpio = 5, /* BLSP2 UART RX */
.settings = {
[GPIOMUX_SUSPENDED] = &gpio_uart_config,
},
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 1049bcb..388307b 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -26,6 +26,7 @@
#endif
#include <linux/regulator/machine.h>
#include <linux/regulator/krait-regulator.h>
+#include <linux/msm_thermal.h>
#include <asm/mach/map.h>
#include <asm/hardware/gic.h>
#include <mach/board.h>
@@ -434,6 +435,7 @@
else
msm_clock_init(&msm8974_clock_init_data);
msm8974_init_buses();
+ msm_thermal_device_init();
}
static struct of_device_id irq_match[] __initdata = {
@@ -461,8 +463,6 @@
}
static struct of_dev_auxdata msm_8974_auxdata_lookup[] __initdata = {
- OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF991F000, \
- "msm_serial_hsl.0", NULL),
OF_DEV_AUXDATA("qcom,hsusb-otg", 0xF9A55000, \
"msm_otg", NULL),
OF_DEV_AUXDATA("qcom,dwc-usb3-msm", 0xF9200000, \
@@ -487,6 +487,34 @@
OF_DEV_AUXDATA("qcom,pil-mba", 0xFC820000, "pil-mba", NULL),
OF_DEV_AUXDATA("qcom,pil-pronto", 0xFB21B000, \
"pil_pronto", NULL),
+ OF_DEV_AUXDATA("arm,coresight-tmc", 0xFC322000, \
+ "coresight-tmc-etr", NULL),
+ OF_DEV_AUXDATA("arm,coresight-tpiu", 0xFC318000, \
+ "coresight-tpiu", NULL),
+ OF_DEV_AUXDATA("qcom,coresight-replicator", 0xFC31C000, \
+ "coresight-replicator", NULL),
+ OF_DEV_AUXDATA("arm,coresight-tmc", 0xFC307000, \
+ "coresight-tmc-etf", NULL),
+ OF_DEV_AUXDATA("arm,coresight-funnel", 0xFC31B000, \
+ "coresight-funnel-merg", NULL),
+ OF_DEV_AUXDATA("arm,coresight-funnel", 0xFC319000, \
+ "coresight-funnel-in0", NULL),
+ OF_DEV_AUXDATA("arm,coresight-funnel", 0xFC31A000, \
+ "coresight-funnel-in1", NULL),
+ OF_DEV_AUXDATA("arm,coresight-funnel", 0xFC345000, \
+ "coresight-funnel-kpss", NULL),
+ OF_DEV_AUXDATA("arm,coresight-funnel", 0xFC364000, \
+ "coresight-funnel-mmss", NULL),
+ OF_DEV_AUXDATA("arm,coresight-stm", 0xFC321000, \
+ "coresight-stm", NULL),
+ OF_DEV_AUXDATA("arm,coresight-etm", 0xFC33C000, \
+ "coresight-etm0", NULL),
+ OF_DEV_AUXDATA("arm,coresight-etm", 0xFC33D000, \
+ "coresight-etm1", NULL),
+ OF_DEV_AUXDATA("arm,coresight-etm", 0xFC33E000, \
+ "coresight-etm2", NULL),
+ OF_DEV_AUXDATA("arm,coresight-etm", 0xFC33F000, \
+ "coresight-etm3", NULL),
OF_DEV_AUXDATA("qcom,msm-rng", 0xF9BFF000, \
"msm_rng", NULL),
OF_DEV_AUXDATA("qcom,qseecom", 0xFE806000, \
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index a312e2b..f885774 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -976,6 +976,7 @@
msm_android_usb_hsic_device.dev.platform_data;
msm9615_device_init();
+ platform_device_register(&msm_gpio_device);
msm9615_init_gpiomux();
msm9615_i2c_init();
regulator_suppress_info_printing();
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 50b1ac5..38f1170 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -10213,6 +10213,7 @@
#endif
pmic_reset_irq = PM8058_IRQ_BASE + PM8058_RESOUT_IRQ;
+ platform_device_register(&msm_gpio_device);
/*
* Initialize RPM first as other drivers and devices may need
* it for their initialization.
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 3b715a4..21b6c0a 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5176,11 +5176,13 @@
CLK_LOOKUP("dfab_clk", dfab_msmbus_clk.c, "msm_bus"),
CLK_LOOKUP("dfab_a_clk", dfab_msmbus_a_clk.c, "msm_bus"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, ""),
- CLK_LOOKUP("core_clk", qdss_clk.c, "msm_etb.0"),
- CLK_LOOKUP("core_clk", qdss_clk.c, "msm_tpiu.0"),
- CLK_LOOKUP("core_clk", qdss_clk.c, "msm_funnel.0"),
- CLK_LOOKUP("core_clk", qdss_clk.c, "msm_stm.0"),
- CLK_LOOKUP("core_clk", qdss_clk.c, "msm_etm.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tpiu.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etb.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.1"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.2"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.3"),
CLK_LOOKUP("ebi1_clk", ebi1_clk.c, ""),
CLK_LOOKUP("mmfpb_clk", mmfpb_clk.c, ""),
@@ -5515,11 +5517,13 @@
CLK_LOOKUP("dfab_clk", dfab_msmbus_clk.c, "msm_bus"),
CLK_LOOKUP("dfab_a_clk", dfab_msmbus_a_clk.c, "msm_bus"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, ""),
- CLK_LOOKUP("core_clk", qdss_clk.c, "msm_etb.0"),
- CLK_LOOKUP("core_clk", qdss_clk.c, "msm_tpiu.0"),
- CLK_LOOKUP("core_clk", qdss_clk.c, "msm_funnel.0"),
- CLK_LOOKUP("core_clk", qdss_clk.c, "msm_stm.0"),
- CLK_LOOKUP("core_clk", qdss_clk.c, "msm_etm.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tpiu.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etb.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.1"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.2"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.3"),
CLK_LOOKUP("ebi1_clk", ebi1_clk.c, NULL),
CLK_LOOKUP("mmfpb_clk", mmfpb_clk.c, NULL),
@@ -5861,11 +5865,13 @@
CLK_LOOKUP("dfab_clk", dfab_msmbus_clk.c, "msm_bus"),
CLK_LOOKUP("dfab_a_clk", dfab_msmbus_a_clk.c, "msm_bus"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, ""),
- CLK_LOOKUP("core_clk", qdss_clk.c, "msm_etb.0"),
- CLK_LOOKUP("core_clk", qdss_clk.c, "msm_tpiu.0"),
- CLK_LOOKUP("core_clk", qdss_clk.c, "msm_funnel.0"),
- CLK_LOOKUP("core_clk", qdss_clk.c, "msm_stm.0"),
- CLK_LOOKUP("core_clk", qdss_clk.c, "msm_etm.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-tpiu.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etb.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-funnel.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.0"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.1"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.2"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "coresight-etm.3"),
CLK_LOOKUP("ebi1_clk", ebi1_clk.c, NULL),
CLK_LOOKUP("mmfpb_clk", mmfpb_clk.c, NULL),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 007e63e..8ac1c88 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -18,6 +18,7 @@
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/clk.h>
+#include <linux/iopoll.h>
#include <mach/clk.h>
#include <mach/rpm-regulator-smd.h>
@@ -103,6 +104,7 @@
#define CLOCK_FRQ_MEASURE_CTL_REG 0x1884
#define CLOCK_FRQ_MEASURE_STATUS_REG 0x1888
#define GCC_XO_DIV4_CBCR_REG 0x10C8
+#define GCC_PLLTEST_PAD_CFG_REG 0x188C
#define APCS_GPLL_ENA_VOTE_REG 0x1480
#define MMSS_PLL_VOTE_APCS_REG 0x0100
#define MMSS_DEBUG_CLK_CTL_REG 0x0900
@@ -383,6 +385,8 @@
#define GP1_CBCR 0x1900
#define GP2_CBCR 0x1940
#define GP3_CBCR 0x1980
+#define AUDIO_CORE_GDSCR 0x7000
+#define AUDIO_CORE_IXFABRIC_CBCR 0x1B000
#define AUDIO_CORE_LPAIF_CODEC_SPKR_OSR_CBCR 0xA014
#define AUDIO_CORE_LPAIF_CODEC_SPKR_IBIT_CBCR 0xA018
#define AUDIO_CORE_LPAIF_CODEC_SPKR_EBIT_CBCR 0xA01C
@@ -485,9 +489,12 @@
#define OCMEMNOC_CBCR 0x50B4
#define LPASS_Q6SS_AHB_LFABIF_CBCR 0x22000
#define LPASS_Q6SS_XO_CBCR 0x26000
+#define LPASS_Q6_AXI_CBCR 0x11C0
+#define Q6SS_AHBM_CBCR 0x22004
#define MSS_XO_Q6_CBCR 0x108C
#define MSS_BUS_Q6_CBCR 0x10A4
#define MSS_CFG_AHB_CBCR 0x0280
+#define MSS_Q6_BIMC_AXI_CBCR 0x0284
#define APCS_CLOCK_BRANCH_ENA_VOTE 0x1484
#define APCS_CLOCK_SLEEP_ENA_VOTE 0x1488
@@ -756,6 +763,7 @@
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(bimc_acpu_a_clk, &bimc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(ocmemgx_gfx3d_clk, &ocmemgx_clk.c, LONG_MAX);
static DEFINE_CLK_VOTER(ocmemgx_msmbus_clk, &ocmemgx_clk.c, LONG_MAX);
static DEFINE_CLK_VOTER(ocmemgx_msmbus_a_clk, &ocmemgx_a_clk.c, LONG_MAX);
@@ -2284,6 +2292,17 @@
},
};
+static struct branch_clk gcc_mss_q6_bimc_axi_clk = {
+ .cbcr_reg = MSS_Q6_BIMC_AXI_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_mss_q6_bimc_axi_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_mss_q6_bimc_axi_clk.c),
+ },
+};
+
static struct clk_freq_tbl ftbl_mmss_axi_clk[] = {
F_MM( 19200000, cxo, 1, 0, 0),
F_MM(150000000, gpll0, 4, 0, 0),
@@ -3758,8 +3777,7 @@
static struct branch_clk mmss_mmssnoc_axi_clk = {
.cbcr_reg = MMSS_MMSSNOC_AXI_CBCR,
.parent = &axi_clk_src.c,
- /* The bus driver needs set_rate to go through to the parent */
- .has_sibling = 0,
+ .has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
.dbg_name = "mmss_mmssnoc_axi_clk",
@@ -3771,12 +3789,14 @@
static struct branch_clk mmss_s0_axi_clk = {
.cbcr_reg = MMSS_S0_AXI_CBCR,
.parent = &axi_clk_src.c,
- .has_sibling = 1,
+ /* The bus driver needs set_rate to go through to the parent */
+ .has_sibling = 0,
.base = &virt_bases[MMSS_BASE],
.c = {
.dbg_name = "mmss_s0_axi_clk",
.ops = &clk_ops_branch,
CLK_INIT(mmss_s0_axi_clk.c),
+ .depends = &mmss_mmssnoc_axi_clk.c,
},
};
@@ -3866,7 +3886,7 @@
static struct branch_clk oxili_gfx3d_clk = {
.cbcr_reg = OXILI_GFX3D_CBCR,
- .has_sibling = 1,
+ .parent = &ocmemgx_gfx3d_clk.c,
.base = &virt_bases[MMSS_BASE],
.c = {
.dbg_name = "oxili_gfx3d_clk",
@@ -3888,7 +3908,7 @@
};
static struct clk_freq_tbl ftbl_audio_core_slimbus_core_clock[] = {
- F_LPASS(28800000, lpapll0, 1, 15, 256),
+ F_LPASS(24576000, lpapll0, 4, 1, 5),
F_END
};
@@ -3932,7 +3952,7 @@
F_LPASS( 512000, lpapll0, 16, 1, 60),
F_LPASS( 768000, lpapll0, 16, 1, 40),
F_LPASS( 1024000, lpapll0, 16, 1, 30),
- F_LPASS( 1536000, lpapll0, 16, 1, 10),
+ F_LPASS( 1536000, lpapll0, 16, 1, 20),
F_LPASS( 2048000, lpapll0, 16, 1, 15),
F_LPASS( 3072000, lpapll0, 16, 1, 10),
F_LPASS( 4096000, lpapll0, 15, 1, 8),
@@ -4303,6 +4323,28 @@
},
};
+static struct branch_clk audio_core_ixfabric_clk = {
+ .cbcr_reg = AUDIO_CORE_IXFABRIC_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "audio_core_ixfabric_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(audio_core_ixfabric_clk.c),
+ },
+};
+
+static struct branch_clk gcc_lpass_q6_axi_clk = {
+ .cbcr_reg = LPASS_Q6_AXI_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_lpass_q6_axi_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_lpass_q6_axi_clk.c),
+ },
+};
+
static struct branch_clk q6ss_xo_clk = {
.cbcr_reg = LPASS_Q6SS_XO_CBCR,
.bcr_reg = LPASS_Q6SS_BCR,
@@ -4315,6 +4357,17 @@
},
};
+static struct branch_clk q6ss_ahbm_clk = {
+ .cbcr_reg = Q6SS_AHBM_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[LPASS_BASE],
+ .c = {
+ .dbg_name = "q6ss_ahbm_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(q6ss_ahbm_clk.c),
+ },
+};
+
static struct branch_clk mss_xo_q6_clk = {
.cbcr_reg = MSS_XO_Q6_CBCR,
.bcr_reg = MSS_Q6SS_BCR,
@@ -4425,6 +4478,8 @@
{&gcc_sdcc2_ahb_clk.c, GCC_BASE, 0x0071},
{&gcc_ocmem_noc_cfg_ahb_clk.c, GCC_BASE, 0x0029},
{&gcc_ce1_clk.c, GCC_BASE, 0x0138},
+ {&gcc_lpass_q6_axi_clk.c, GCC_BASE, 0x0160},
+ {&gcc_mss_q6_bimc_axi_clk.c, GCC_BASE, 0x0031},
{&mmss_mmssnoc_axi_clk.c, MMSS_BASE, 0x0004},
{&ocmemnoc_clk.c, MMSS_BASE, 0x0007},
{&ocmemcx_ocmemnoc_clk.c, MMSS_BASE, 0x0009},
@@ -4505,6 +4560,8 @@
{&audio_core_slimbus_lfabif_clk.c, LPASS_BASE, 0x003e},
{&q6ss_xo_clk.c, LPASS_BASE, 0x002b},
{&q6ss_ahb_lfabif_clk.c, LPASS_BASE, 0x001e},
+ {&q6ss_ahbm_clk.c, LPASS_BASE, 0x001d},
+ {&audio_core_ixfabric_clk.c, LPASS_BASE, 0x0059},
{&mss_bus_q6_clk.c, MSS_BASE, 0x003c},
{&mss_xo_q6_clk.c, MSS_BASE, 0x0007},
@@ -4563,12 +4620,12 @@
break;
case LPASS_BASE:
- clk_sel = 0x169;
+ clk_sel = 0x161;
regval = BVAL(11, 0, measure_mux[i].debug_mux);
writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
/* Activate debug clock output */
- regval |= BIT(16);
+ regval |= BIT(20);
writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
break;
@@ -4674,6 +4731,7 @@
ret = (raw_count_full * clk->multiplier);
}
+ 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);
@@ -4722,8 +4780,8 @@
CLK_LOOKUP("bus_clk", pnoc_sdcc4_clk.c, "msm_sdcc.4"),
CLK_DUMMY("xo", XO_CLK, NULL, OFF),
CLK_DUMMY("xo", XO_CLK, "pil_pronto", OFF),
- CLK_DUMMY("core_clk", BLSP2_UART_CLK, "msm_serial_hsl.0", OFF),
- CLK_DUMMY("iface_clk", BLSP2_UART_CLK, "msm_serial_hsl.0", OFF),
+ CLK_DUMMY("core_clk", BLSP2_UART_CLK, "f991f000.serial", OFF),
+ CLK_DUMMY("iface_clk", BLSP2_UART_CLK, "f991f000.serial", OFF),
CLK_DUMMY("core_clk", SDC1_CLK, NULL, OFF),
CLK_DUMMY("iface_clk", SDC1_P_CLK, NULL, OFF),
CLK_DUMMY("core_clk", SDC3_CLK, NULL, OFF),
@@ -4757,7 +4815,8 @@
CLK_LOOKUP("measure", measure_clk.c, "debug"),
CLK_LOOKUP("dma_bam_pclk", gcc_bam_dma_ahb_clk.c, "msm_sps"),
- CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "msm_serial_hsl.0"),
+ CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f991f000.serial"),
+ CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f991e000.serial"),
CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "spi_qsd.1"),
CLK_LOOKUP("core_clk", gcc_blsp1_qup1_i2c_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp1_qup1_spi_apps_clk.c, ""),
@@ -4772,8 +4831,8 @@
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_uart2_apps_clk.c, "f991e000.serial"),
+ CLK_LOOKUP("core_clk", gcc_blsp1_uart3_apps_clk.c, "f991f000.serial"),
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, ""),
@@ -4949,6 +5008,7 @@
/* LPASS clocks */
+ CLK_LOOKUP("bus_clk", audio_core_ixfabric_clk.c, ""),
CLK_LOOKUP("core_clk", audio_core_slimbus_core_clk.c, "fe12f000.slim"),
CLK_LOOKUP("iface_clk", audio_core_slimbus_lfabif_clk.c,
"fe12f000.slim"),
@@ -4972,7 +5032,7 @@
CLK_LOOKUP("osr_clk", audio_core_lpaif_quad_osr_clk.c, ""),
CLK_LOOKUP("ebit_clk", audio_core_lpaif_quad_ebit_clk.c, ""),
CLK_LOOKUP("ibit_clk", audio_core_lpaif_quad_ibit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_pcm0_clk_src.c,
+ CLK_LOOKUP("pcm_clk", audio_core_lpaif_pcm0_clk_src.c,
"msm-dai-q6.4106"),
CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm0_ebit_clk.c, ""),
CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm0_ibit_clk.c,
@@ -4986,12 +5046,16 @@
CLK_LOOKUP("core_oe_clk", audio_core_lpaif_pcmoe_clk.c,
"msm-dai-q6.4106"),
- CLK_LOOKUP("core_clk", mss_xo_q6_clk.c, "pil-q6v5-mss"),
- CLK_LOOKUP("bus_clk", mss_bus_q6_clk.c, "pil-q6v5-mss"),
- CLK_LOOKUP("bus_clk", gcc_mss_cfg_ahb_clk.c, ""),
- CLK_LOOKUP("mem_clk", gcc_boot_rom_ahb_clk.c, "pil-q6v5-mss"),
- CLK_LOOKUP("core_clk", q6ss_xo_clk.c, "pil-q6v5-lpass"),
- CLK_LOOKUP("bus_clk", q6ss_ahb_lfabif_clk.c, "pil-q6v5-lpass"),
+ CLK_LOOKUP("core_clk", mss_xo_q6_clk.c, "pil-q6v5-mss"),
+ CLK_LOOKUP("bus_clk", gcc_mss_q6_bimc_axi_clk.c, "pil-q6v5-mss"),
+ CLK_LOOKUP("iface_clk", gcc_mss_cfg_ahb_clk.c, "pil-q6v5-mss"),
+ CLK_LOOKUP("reg_clk", mss_bus_q6_clk.c, "pil-q6v5-mss"),
+ CLK_LOOKUP("mem_clk", gcc_boot_rom_ahb_clk.c, "pil-q6v5-mss"),
+
+ CLK_LOOKUP("core_clk", q6ss_xo_clk.c, "pil-q6v5-lpass"),
+ CLK_LOOKUP("bus_clk", gcc_lpass_q6_axi_clk.c, "pil-q6v5-lpass"),
+ CLK_LOOKUP("iface_clk", q6ss_ahb_lfabif_clk.c, "pil-q6v5-lpass"),
+ CLK_LOOKUP("reg_clk", q6ss_ahbm_clk.c, "pil-q6v5-lpass"),
CLK_LOOKUP("core_clk", gcc_prng_ahb_clk.c, "msm_rng"),
CLK_LOOKUP("dfab_clk", pnoc_sps_clk.c, "msm_sps"),
@@ -5021,8 +5085,8 @@
CLK_LOOKUP("ocmem_a_clk", ocmemgx_msmbus_a_clk.c, "msm_bus"),
CLK_LOOKUP("bus_clk", ocmemnoc_clk.c, "msm_ocmem_noc"),
CLK_LOOKUP("bus_a_clk", ocmemnoc_clk.c, "msm_ocmem_noc"),
- CLK_LOOKUP("bus_clk", mmss_mmssnoc_axi_clk.c, "msm_mmss_noc"),
- CLK_LOOKUP("bus_a_clk", mmss_mmssnoc_axi_clk.c, "msm_mmss_noc"),
+ CLK_LOOKUP("bus_clk", mmss_s0_axi_clk.c, "msm_mmss_noc"),
+ CLK_LOOKUP("bus_a_clk", mmss_s0_axi_clk.c, "msm_mmss_noc"),
CLK_LOOKUP("iface_clk", gcc_mmss_noc_cfg_ahb_clk.c, ""),
CLK_LOOKUP("iface_clk", gcc_ocmem_noc_cfg_ahb_clk.c, ""),
@@ -5220,9 +5284,24 @@
#define PLL_AUX_OUTPUT_BIT 1
#define PLL_AUX2_OUTPUT_BIT 2
+#define PWR_ON_MASK BIT(31)
+#define EN_REST_WAIT_MASK (0xF << 20)
+#define EN_FEW_WAIT_MASK (0xF << 16)
+#define CLK_DIS_WAIT_MASK (0xF << 12)
+#define SW_OVERRIDE_MASK BIT(2)
+#define HW_CONTROL_MASK BIT(1)
+#define SW_COLLAPSE_MASK BIT(0)
+
+/* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */
+#define EN_REST_WAIT_VAL (0x2 << 20)
+#define EN_FEW_WAIT_VAL (0x2 << 16)
+#define CLK_DIS_WAIT_VAL (0x2 << 12)
+#define GDSC_TIMEOUT_US 50000
+
static void __init reg_init(void)
{
- u32 regval;
+ u32 regval, status;
+ int ret;
if (!(readl_relaxed(GCC_REG_BASE(GPLL0_STATUS_REG))
& gpll0_clk_src.status_mask))
@@ -5252,6 +5331,31 @@
* register.
*/
writel_relaxed(0x0, GCC_REG_BASE(APCS_CLOCK_SLEEP_ENA_VOTE));
+
+ /*
+ * TODO: The following sequence enables the LPASS audio core GDSC.
+ * Remove when this becomes unnecessary.
+ */
+
+ /*
+ * Disable HW trigger: collapse/restore occur based on registers writes.
+ * Disable SW override: Use hardware state-machine for sequencing.
+ */
+ regval = readl_relaxed(LPASS_REG_BASE(AUDIO_CORE_GDSCR));
+ regval &= ~(HW_CONTROL_MASK | SW_OVERRIDE_MASK);
+
+ /* Configure wait time between states. */
+ regval &= ~(EN_REST_WAIT_MASK | EN_FEW_WAIT_MASK | CLK_DIS_WAIT_MASK);
+ regval |= EN_REST_WAIT_VAL | EN_FEW_WAIT_VAL | CLK_DIS_WAIT_VAL;
+ writel_relaxed(regval, LPASS_REG_BASE(AUDIO_CORE_GDSCR));
+
+ regval = readl_relaxed(LPASS_REG_BASE(AUDIO_CORE_GDSCR));
+ regval &= ~BIT(0);
+ writel_relaxed(regval, LPASS_REG_BASE(AUDIO_CORE_GDSCR));
+
+ ret = readl_poll_timeout(LPASS_REG_BASE(AUDIO_CORE_GDSCR), status,
+ status & PWR_ON_MASK, 50, GDSC_TIMEOUT_US);
+ WARN(ret, "LPASS Audio Core GDSC did not power on.\n");
}
static void __init msm8974_clock_post_init(void)
@@ -5272,6 +5376,11 @@
*/
clk_prepare_enable(&cxo_a_clk_src.c);
+ /* TODO: Temporarily enable a clock to allow access to LPASS core
+ * registers.
+ */
+ clk_prepare_enable(&audio_core_ixfabric_clk.c);
+
/*
* TODO: Temporarily enable NOC configuration AHB clocks. Remove when
* the bus driver is ready.
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index 207dbef..be69827 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -54,6 +54,23 @@
return (rc < 0) ? rc : iv.value * r->factor;
}
+static int clk_rpmrs_handoff(struct rpm_clk *r)
+{
+ struct msm_rpm_iv_pair iv = { .id = r->rpm_status_id, };
+ int rc = msm_rpm_get_status(&iv, 1);
+
+ if (rc < 0)
+ return rc;
+
+ if (!r->branch) {
+ r->last_set_khz = iv.value;
+ r->last_set_sleep_khz = iv.value;
+ r->c.rate = iv.value * r->factor;
+ }
+
+ return 0;
+}
+
static int clk_rpmrs_set_rate_smd(struct rpm_clk *r, uint32_t value,
uint32_t context, int noirq)
{
@@ -71,10 +88,16 @@
r->rpm_clk_id, &kvp, 1);
}
+static int clk_rpmrs_handoff_smd(struct rpm_clk *r)
+{
+ return 0;
+}
+
struct clk_rpmrs_data {
int (*set_rate_fn)(struct rpm_clk *r, uint32_t value,
uint32_t context, int noirq);
int (*get_rate_fn)(struct rpm_clk *r);
+ int (*handoff_fn)(struct rpm_clk *r);
int ctx_active_id;
int ctx_sleep_id;
};
@@ -82,12 +105,14 @@
struct clk_rpmrs_data clk_rpmrs_data = {
.set_rate_fn = clk_rpmrs_set_rate,
.get_rate_fn = clk_rpmrs_get_rate,
+ .handoff_fn = clk_rpmrs_handoff,
.ctx_active_id = MSM_RPM_CTX_SET_0,
.ctx_sleep_id = MSM_RPM_CTX_SET_SLEEP,
};
struct clk_rpmrs_data clk_rpmrs_data_smd = {
.set_rate_fn = clk_rpmrs_set_rate_smd,
+ .handoff_fn = clk_rpmrs_handoff_smd,
.ctx_active_id = MSM_RPM_CTX_ACTIVE_SET,
.ctx_sleep_id = MSM_RPM_CTX_SLEEP_SET,
};
@@ -257,7 +282,6 @@
static enum handoff rpm_clk_handoff(struct clk *clk)
{
struct rpm_clk *r = to_rpm_clk(clk);
- struct msm_rpm_iv_pair iv = { r->rpm_status_id };
int rc;
/*
@@ -266,16 +290,10 @@
* assume these clocks are enabled (unless the RPM call fails) so
* child clocks of these RPM clocks can still be handed off.
*/
- rc = msm_rpm_get_status(&iv, 1);
+ rc = r->rpmrs_data->handoff_fn(r);
if (rc < 0)
return HANDOFF_DISABLED_CLK;
- if (!r->branch) {
- r->last_set_khz = iv.value;
- r->last_set_sleep_khz = iv.value;
- clk->rate = iv.value * r->factor;
- }
-
return HANDOFF_ENABLED_CLK;
}
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 792bc1d..0d05df9 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -102,6 +102,15 @@
.bark_time = 11000,
.has_secure = true,
.needs_expired_enable = true,
+ .base = MSM_TMR0_BASE + WDT0_OFFSET,
+};
+
+static struct resource msm_watchdog_resources[] = {
+ {
+ .start = WDT0_ACCSCSSNBARK_INT,
+ .end = WDT0_ACCSCSSNBARK_INT,
+ .flags = IORESOURCE_IRQ,
+ },
};
struct platform_device msm8064_device_watchdog = {
@@ -110,6 +119,8 @@
.dev = {
.platform_data = &msm_watchdog_pdata,
},
+ .num_resources = ARRAY_SIZE(msm_watchdog_resources),
+ .resource = msm_watchdog_resources,
};
static struct resource msm_dmov_resource[] = {
@@ -2666,43 +2677,105 @@
.resource = msm_cache_erp_resources,
};
-#define MSM_QDSS_PHYS_BASE 0x01A00000
-#define MSM_ETM_PHYS_BASE (MSM_QDSS_PHYS_BASE + 0x1C000)
+#define CORESIGHT_PHYS_BASE 0x01A00000
+#define CORESIGHT_FUNNEL_PHYS_BASE (CORESIGHT_PHYS_BASE + 0x4000)
+#define CORESIGHT_ETM2_PHYS_BASE (CORESIGHT_PHYS_BASE + 0x1E000)
+#define CORESIGHT_ETM3_PHYS_BASE (CORESIGHT_PHYS_BASE + 0x1F000)
-#define QDSS_SOURCE(src_name, fpm) { .name = src_name, .fport_mask = fpm, }
-
-static struct qdss_source msm_qdss_sources[] = {
- QDSS_SOURCE("msm_etm", 0x33),
- QDSS_SOURCE("msm_oxili", 0x80),
-};
-
-static struct msm_qdss_platform_data qdss_pdata = {
- .src_table = msm_qdss_sources,
- .size = ARRAY_SIZE(msm_qdss_sources),
- .afamily = 1,
-};
-
-struct platform_device apq8064_qdss_device = {
- .name = "msm_qdss",
- .id = -1,
- .dev = {
- .platform_data = &qdss_pdata,
- },
-};
-
-static struct resource msm_etm_resources[] = {
+static struct resource coresight_funnel_resources[] = {
{
- .start = MSM_ETM_PHYS_BASE,
- .end = MSM_ETM_PHYS_BASE + (SZ_4K * 4) - 1,
+ .start = CORESIGHT_FUNNEL_PHYS_BASE,
+ .end = CORESIGHT_FUNNEL_PHYS_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
};
-struct platform_device apq8064_etm_device = {
- .name = "msm_etm",
+static const int coresight_funnel_outports[] = { 0, 1 };
+static const int coresight_funnel_child_ids[] = { 0, 1 };
+static const int coresight_funnel_child_ports[] = { 0, 0 };
+
+static struct coresight_platform_data coresight_funnel_pdata = {
+ .id = 2,
+ .name = "coresight-funnel",
+ .nr_inports = 4,
+ .outports = coresight_funnel_outports,
+ .child_ids = coresight_funnel_child_ids,
+ .child_ports = coresight_funnel_child_ports,
+ .nr_outports = ARRAY_SIZE(coresight_funnel_outports),
+};
+
+struct platform_device apq8064_coresight_funnel_device = {
+ .name = "coresight-funnel",
.id = 0,
- .num_resources = ARRAY_SIZE(msm_etm_resources),
- .resource = msm_etm_resources,
+ .num_resources = ARRAY_SIZE(coresight_funnel_resources),
+ .resource = coresight_funnel_resources,
+ .dev = {
+ .platform_data = &coresight_funnel_pdata,
+ },
+};
+
+static struct resource coresight_etm2_resources[] = {
+ {
+ .start = CORESIGHT_ETM2_PHYS_BASE,
+ .end = CORESIGHT_ETM2_PHYS_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static const int coresight_etm2_outports[] = { 0 };
+static const int coresight_etm2_child_ids[] = { 2 };
+static const int coresight_etm2_child_ports[] = { 4 };
+
+static struct coresight_platform_data coresight_etm2_pdata = {
+ .id = 6,
+ .name = "coresight-etm2",
+ .nr_inports = 1,
+ .outports = coresight_etm2_outports,
+ .child_ids = coresight_etm2_child_ids,
+ .child_ports = coresight_etm2_child_ports,
+ .nr_outports = ARRAY_SIZE(coresight_etm2_outports),
+};
+
+struct platform_device coresight_etm2_device = {
+ .name = "coresight-etm",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(coresight_etm2_resources),
+ .resource = coresight_etm2_resources,
+ .dev = {
+ .platform_data = &coresight_etm2_pdata,
+ },
+};
+
+static struct resource coresight_etm3_resources[] = {
+ {
+ .start = CORESIGHT_ETM3_PHYS_BASE,
+ .end = CORESIGHT_ETM3_PHYS_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static const int coresight_etm3_outports[] = { 0 };
+static const int coresight_etm3_child_ids[] = { 2 };
+static const int coresight_etm3_child_ports[] = { 5 };
+
+static struct coresight_platform_data coresight_etm3_pdata = {
+ .id = 7,
+ .name = "coresight-etm3",
+ .nr_inports = 3,
+ .outports = coresight_etm3_outports,
+ .child_ids = coresight_etm3_child_ids,
+ .child_ports = coresight_etm3_child_ports,
+ .nr_outports = ARRAY_SIZE(coresight_etm3_outports),
+};
+
+struct platform_device coresight_etm3_device = {
+ .name = "coresight-etm",
+ .id = 3,
+ .num_resources = ARRAY_SIZE(coresight_etm3_resources),
+ .resource = coresight_etm3_resources,
+ .dev = {
+ .platform_data = &coresight_etm3_pdata,
+ },
};
struct msm_iommu_domain_name apq8064_iommu_ctx_names[] = {
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 724eed8..8347580 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1331,6 +1331,15 @@
.pet_time = 10000,
.bark_time = 11000,
.has_secure = true,
+ .base = MSM_TMR0_BASE + WDT0_OFFSET,
+};
+
+static struct resource msm_watchdog_resources[] = {
+ {
+ .start = WDT0_ACCSCSSNBARK_INT,
+ .end = WDT0_ACCSCSSNBARK_INT,
+ .flags = IORESOURCE_IRQ,
+ },
};
struct platform_device msm8960_device_watchdog = {
@@ -1339,6 +1348,8 @@
.dev = {
.platform_data = &msm_watchdog_pdata,
},
+ .num_resources = ARRAY_SIZE(msm_watchdog_resources),
+ .resource = msm_watchdog_resources,
};
static struct resource msm_dmov_resource[] = {
@@ -3457,95 +3468,199 @@
#endif /* CONFIG_MSM_DSPS */
-#ifdef CONFIG_MSM_QDSS
+#define CORESIGHT_PHYS_BASE 0x01A00000
+#define CORESIGHT_TPIU_PHYS_BASE (CORESIGHT_PHYS_BASE + 0x3000)
+#define CORESIGHT_ETB_PHYS_BASE (CORESIGHT_PHYS_BASE + 0x1000)
+#define CORESIGHT_FUNNEL_PHYS_BASE (CORESIGHT_PHYS_BASE + 0x4000)
+#define CORESIGHT_STM_PHYS_BASE (CORESIGHT_PHYS_BASE + 0x6000)
+#define CORESIGHT_ETM0_PHYS_BASE (CORESIGHT_PHYS_BASE + 0x1C000)
+#define CORESIGHT_ETM1_PHYS_BASE (CORESIGHT_PHYS_BASE + 0x1D000)
-#define MSM_QDSS_PHYS_BASE 0x01A00000
-#define MSM_ETB_PHYS_BASE (MSM_QDSS_PHYS_BASE + 0x1000)
-#define MSM_TPIU_PHYS_BASE (MSM_QDSS_PHYS_BASE + 0x3000)
-#define MSM_FUNNEL_PHYS_BASE (MSM_QDSS_PHYS_BASE + 0x4000)
-#define MSM_ETM_PHYS_BASE (MSM_QDSS_PHYS_BASE + 0x1C000)
+#define CORESIGHT_STM_CHANNEL_PHYS_BASE (0x14000000 + 0x280000)
-#define QDSS_SOURCE(src_name, fpm) { .name = src_name, .fport_mask = fpm, }
-
-static struct qdss_source msm_qdss_sources[] = {
- QDSS_SOURCE("msm_etm", 0x3),
-};
-
-static struct msm_qdss_platform_data qdss_pdata = {
- .src_table = msm_qdss_sources,
- .size = ARRAY_SIZE(msm_qdss_sources),
- .afamily = 1,
-};
-
-struct platform_device msm_qdss_device = {
- .name = "msm_qdss",
- .id = -1,
- .dev = {
- .platform_data = &qdss_pdata,
- },
-};
-
-static struct resource msm_etb_resources[] = {
+static struct resource coresight_tpiu_resources[] = {
{
- .start = MSM_ETB_PHYS_BASE,
- .end = MSM_ETB_PHYS_BASE + SZ_4K - 1,
+ .start = CORESIGHT_TPIU_PHYS_BASE,
+ .end = CORESIGHT_TPIU_PHYS_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
};
-struct platform_device msm_etb_device = {
- .name = "msm_etb",
- .id = 0,
- .num_resources = ARRAY_SIZE(msm_etb_resources),
- .resource = msm_etb_resources,
+static struct coresight_platform_data coresight_tpiu_pdata = {
+ .id = 0,
+ .name = "coresight-tpiu",
+ .nr_inports = 1,
+ .nr_outports = 0,
};
-static struct resource msm_tpiu_resources[] = {
+struct platform_device coresight_tpiu_device = {
+ .name = "coresight-tpiu",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(coresight_tpiu_resources),
+ .resource = coresight_tpiu_resources,
+ .dev = {
+ .platform_data = &coresight_tpiu_pdata,
+ },
+};
+
+static struct resource coresight_etb_resources[] = {
{
- .start = MSM_TPIU_PHYS_BASE,
- .end = MSM_TPIU_PHYS_BASE + SZ_4K - 1,
+ .start = CORESIGHT_ETB_PHYS_BASE,
+ .end = CORESIGHT_ETB_PHYS_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
};
-struct platform_device msm_tpiu_device = {
- .name = "msm_tpiu",
- .id = 0,
- .num_resources = ARRAY_SIZE(msm_tpiu_resources),
- .resource = msm_tpiu_resources,
+static struct coresight_platform_data coresight_etb_pdata = {
+ .id = 1,
+ .name = "coresight-etb",
+ .nr_inports = 1,
+ .nr_outports = 0,
+ .default_sink = true,
};
-static struct resource msm_funnel_resources[] = {
+struct platform_device coresight_etb_device = {
+ .name = "coresight-etb",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(coresight_etb_resources),
+ .resource = coresight_etb_resources,
+ .dev = {
+ .platform_data = &coresight_etb_pdata,
+ },
+};
+
+static struct resource coresight_funnel_resources[] = {
{
- .start = MSM_FUNNEL_PHYS_BASE,
- .end = MSM_FUNNEL_PHYS_BASE + SZ_4K - 1,
+ .start = CORESIGHT_FUNNEL_PHYS_BASE,
+ .end = CORESIGHT_FUNNEL_PHYS_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
};
-struct platform_device msm_funnel_device = {
- .name = "msm_funnel",
- .id = 0,
- .num_resources = ARRAY_SIZE(msm_funnel_resources),
- .resource = msm_funnel_resources,
+static const int coresight_funnel_outports[] = { 0, 1 };
+static const int coresight_funnel_child_ids[] = { 0, 1 };
+static const int coresight_funnel_child_ports[] = { 0, 0 };
+
+static struct coresight_platform_data coresight_funnel_pdata = {
+ .id = 2,
+ .name = "coresight-funnel",
+ .nr_inports = 4,
+ .outports = coresight_funnel_outports,
+ .child_ids = coresight_funnel_child_ids,
+ .child_ports = coresight_funnel_child_ports,
+ .nr_outports = ARRAY_SIZE(coresight_funnel_outports),
};
-static struct resource msm_etm_resources[] = {
+struct platform_device coresight_funnel_device = {
+ .name = "coresight-funnel",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(coresight_funnel_resources),
+ .resource = coresight_funnel_resources,
+ .dev = {
+ .platform_data = &coresight_funnel_pdata,
+ },
+};
+
+static struct resource coresight_stm_resources[] = {
{
- .start = MSM_ETM_PHYS_BASE,
- .end = MSM_ETM_PHYS_BASE + (SZ_4K * 2) - 1,
+ .start = CORESIGHT_STM_PHYS_BASE,
+ .end = CORESIGHT_STM_PHYS_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = CORESIGHT_STM_CHANNEL_PHYS_BASE,
+ .end = CORESIGHT_STM_CHANNEL_PHYS_BASE + SZ_1M + SZ_512K - 1,
.flags = IORESOURCE_MEM,
},
};
-struct platform_device msm_etm_device = {
- .name = "msm_etm",
- .id = 0,
- .num_resources = ARRAY_SIZE(msm_etm_resources),
- .resource = msm_etm_resources,
+static const int coresight_stm_outports[] = { 0 };
+static const int coresight_stm_child_ids[] = { 2 };
+static const int coresight_stm_child_ports[] = { 2 };
+
+static struct coresight_platform_data coresight_stm_pdata = {
+ .id = 3,
+ .name = "coresight-stm",
+ .nr_inports = 0,
+ .outports = coresight_stm_outports,
+ .child_ids = coresight_stm_child_ids,
+ .child_ports = coresight_stm_child_ports,
+ .nr_outports = ARRAY_SIZE(coresight_stm_outports),
};
-#endif
+struct platform_device coresight_stm_device = {
+ .name = "coresight-stm",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(coresight_stm_resources),
+ .resource = coresight_stm_resources,
+ .dev = {
+ .platform_data = &coresight_stm_pdata,
+ },
+};
+
+static struct resource coresight_etm0_resources[] = {
+ {
+ .start = CORESIGHT_ETM0_PHYS_BASE,
+ .end = CORESIGHT_ETM0_PHYS_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static const int coresight_etm0_outports[] = { 0 };
+static const int coresight_etm0_child_ids[] = { 2 };
+static const int coresight_etm0_child_ports[] = { 0 };
+
+static struct coresight_platform_data coresight_etm0_pdata = {
+ .id = 4,
+ .name = "coresight-etm0",
+ .nr_inports = 0,
+ .outports = coresight_etm0_outports,
+ .child_ids = coresight_etm0_child_ids,
+ .child_ports = coresight_etm0_child_ports,
+ .nr_outports = ARRAY_SIZE(coresight_etm0_outports),
+};
+
+struct platform_device coresight_etm0_device = {
+ .name = "coresight-etm",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(coresight_etm0_resources),
+ .resource = coresight_etm0_resources,
+ .dev = {
+ .platform_data = &coresight_etm0_pdata,
+ },
+};
+
+static struct resource coresight_etm1_resources[] = {
+ {
+ .start = CORESIGHT_ETM1_PHYS_BASE,
+ .end = CORESIGHT_ETM1_PHYS_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static const int coresight_etm1_outports[] = { 0 };
+static const int coresight_etm1_child_ids[] = { 2 };
+static const int coresight_etm1_child_ports[] = { 1 };
+
+static struct coresight_platform_data coresight_etm1_pdata = {
+ .id = 5,
+ .name = "coresight-etm1",
+ .nr_inports = 0,
+ .outports = coresight_etm1_outports,
+ .child_ids = coresight_etm1_child_ids,
+ .child_ports = coresight_etm1_child_ports,
+ .nr_outports = ARRAY_SIZE(coresight_etm1_outports),
+};
+
+struct platform_device coresight_etm1_device = {
+ .name = "coresight-etm",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(coresight_etm1_resources),
+ .resource = coresight_etm1_resources,
+ .dev = {
+ .platform_data = &coresight_etm1_pdata,
+ },
+};
static struct resource msm_ebi1_ch0_erp_resources[] = {
{
@@ -3913,6 +4028,11 @@
},
};
+struct platform_device msm_gpio_device = {
+ .name = "msmgpio",
+ .id = -1,
+};
+
struct platform_device mdm_sglte_device = {
.name = "mdm2_modem",
.id = -1,
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 9f03878..c307714 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -70,6 +70,15 @@
.bark_time = 11000,
.has_secure = false,
.use_kernel_fiq = true,
+ .base = MSM_TMR_BASE + WDT0_OFFSET,
+};
+
+static struct resource msm_watchdog_resources[] = {
+ {
+ .start = WDT0_ACCSCSSNBARK_INT,
+ .end = WDT0_ACCSCSSNBARK_INT,
+ .flags = IORESOURCE_IRQ,
+ },
};
struct platform_device msm9615_device_watchdog = {
@@ -78,6 +87,8 @@
.dev = {
.platform_data = &msm_watchdog_pdata,
},
+ .num_resources = ARRAY_SIZE(msm_watchdog_resources),
+ .resource = msm_watchdog_resources,
};
static struct resource msm_dmov_resource[] = {
@@ -1372,6 +1383,10 @@
},
};
+struct platform_device msm_gpio_device = {
+ .name = "msmgpio",
+ .id = -1,
+};
void __init msm9615_device_init(void)
{
@@ -1382,7 +1397,6 @@
msm_rpmrs_levels[0].latency_us;
msm_android_usb_hsic_pdata.swfi_latency =
msm_rpmrs_levels[0].latency_us;
-
}
#define MSM_SHARED_RAM_PHYS 0x40000000
diff --git a/arch/arm/mach-msm/devices-fsm9xxx.c b/arch/arm/mach-msm/devices-fsm9xxx.c
index 5f4d940..639eeae 100644
--- a/arch/arm/mach-msm/devices-fsm9xxx.c
+++ b/arch/arm/mach-msm/devices-fsm9xxx.c
@@ -419,6 +419,15 @@
.bark_time = 11000,
.has_secure = false,
.has_vic = true,
+ .base = MSM_TMR_BASE + WDT1_OFFSET,
+};
+
+static struct resource msm_watchdog_resources[] = {
+ {
+ .start = INT_WDT1_ACCSCSSBARK,
+ .end = INT_WDT1_ACCSCSSBARK,
+ .flags = IORESOURCE_IRQ,
+ },
};
struct platform_device fsm9xxx_device_watchdog = {
@@ -427,5 +436,7 @@
.dev = {
.platform_data = &fsm_watchdog_pdata,
},
+ .num_resources = ARRAY_SIZE(msm_watchdog_resources),
+ .resource = msm_watchdog_resources,
};
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 9ea817f..9f31a18 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -100,6 +100,11 @@
#define MSM_UART9DM_PHYS (MSM_GSBI9_PHYS + 0x40000)
#define INT_UART9DM_IRQ GSBI9_UARTDM_IRQ
+struct platform_device msm_gpio_device = {
+ .name = "msmgpio",
+ .id = -1,
+};
+
static void charm_ap2mdm_kpdpwr_on(void)
{
gpio_direction_output(AP2MDM_PMIC_RESET_N, 0);
@@ -1991,6 +1996,15 @@
.pet_time = 10000,
.bark_time = 11000,
.has_secure = true,
+ .base = MSM_TMR0_BASE + WDT0_OFFSET,
+};
+
+static struct resource msm_watchdog_resources[] = {
+ {
+ .start = WDT0_ACCSCSSNBARK_INT,
+ .end = WDT0_ACCSCSSNBARK_INT,
+ .flags = IORESOURCE_IRQ,
+ },
};
struct platform_device msm8660_device_watchdog = {
@@ -1999,6 +2013,8 @@
.dev = {
.platform_data = &msm_watchdog_pdata,
},
+ .num_resources = ARRAY_SIZE(msm_watchdog_resources),
+ .resource = msm_watchdog_resources,
};
static struct resource msm_dmov_resource_adm0[] = {
@@ -2299,10 +2315,14 @@
#ifdef CONFIG_MSM_BUS_SCALING
.vidc_bus_client_pdata = &vidc_bus_client_data,
#endif
+#ifdef CONFIG_MSM_VIDC_CONTENT_PROTECTION
+ .cp_enabled = 1,
+#else
+ .cp_enabled = 0,
+#endif
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
.memtype = ION_CP_MM_HEAP_ID,
.enable_ion = 1,
- .cp_enabled = 1,
.secure_wb_heap = 1,
#else
.memtype = MEMTYPE_SMI_KERNEL,
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 84fe195..8e2ab7d 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -363,13 +363,14 @@
extern struct platform_device msm9615_device_watchdog;
extern struct platform_device fsm9xxx_device_watchdog;
-extern struct platform_device apq8064_qdss_device;
-extern struct platform_device msm_qdss_device;
-extern struct platform_device msm_etb_device;
-extern struct platform_device msm_tpiu_device;
-extern struct platform_device msm_funnel_device;
-extern struct platform_device msm_etm_device;
-extern struct platform_device apq8064_etm_device;
+extern struct platform_device coresight_tpiu_device;
+extern struct platform_device coresight_etb_device;
+extern struct platform_device coresight_funnel_device;
+extern struct platform_device apq8064_coresight_funnel_device;
+extern struct platform_device coresight_etm0_device;
+extern struct platform_device coresight_etm1_device;
+extern struct platform_device coresight_etm2_device;
+extern struct platform_device coresight_etm3_device;
#endif
extern struct platform_device msm_bus_8064_apps_fabric;
@@ -435,3 +436,5 @@
extern struct platform_device msm8930aa_device_acpuclk;
extern struct platform_device msm8960_device_acpuclk;
extern struct platform_device msm9615_device_acpuclk;
+
+extern struct platform_device msm_gpio_device;
diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c
index f8324ce..d1d9f4b 100644
--- a/arch/arm/mach-msm/hotplug.c
+++ b/arch/arm/mach-msm/hotplug.c
@@ -54,8 +54,8 @@
* OK, proper wakeup, we're done
*/
pen_release = -1;
- dmac_flush_range((void *)&pen_release,
- (void *)(&pen_release + sizeof(pen_release)));
+ dmac_flush_range((char *)&pen_release,
+ (char *)&pen_release + sizeof(pen_release));
break;
}
@@ -67,8 +67,8 @@
* possible, since we are currently running incoherently, and
* therefore cannot safely call printk() or anything else
*/
- dmac_inv_range((void *)&pen_release,
- (void *)(&pen_release + sizeof(pen_release)));
+ dmac_inv_range((char *)&pen_release,
+ (char *)&pen_release + sizeof(pen_release));
pr_debug("CPU%u: spurious wakeup call\n", cpu);
}
}
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h b/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h
index 684f9d3..47056a8 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h
@@ -100,6 +100,7 @@
RPM_VREG_ID_PM8038_L10,
RPM_VREG_ID_PM8038_L11,
RPM_VREG_ID_PM8038_L12,
+ RPM_VREG_ID_PM8038_L13,
RPM_VREG_ID_PM8038_L14,
RPM_VREG_ID_PM8038_L15,
RPM_VREG_ID_PM8038_L16,
@@ -111,6 +112,7 @@
RPM_VREG_ID_PM8038_L22,
RPM_VREG_ID_PM8038_L23,
RPM_VREG_ID_PM8038_L24,
+ RPM_VREG_ID_PM8038_L25,
RPM_VREG_ID_PM8038_L26,
RPM_VREG_ID_PM8038_L27,
RPM_VREG_ID_PM8038_S1,
@@ -154,6 +156,7 @@
};
/* Minimum high power mode loads in uA. */
+#define RPM_VREG_8930_LDO_5_HPM_MIN_LOAD 0
#define RPM_VREG_8930_LDO_50_HPM_MIN_LOAD 5000
#define RPM_VREG_8930_LDO_150_HPM_MIN_LOAD 10000
#define RPM_VREG_8930_LDO_300_HPM_MIN_LOAD 10000
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index 03a34d6..63b00c2 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -269,7 +269,11 @@
static int set_pmic_gang_phases(int phase_count)
{
- return msm_spm_apcs_set_phase(phase_count);
+ /*
+ * TODO : spm writes for phase control,
+ * pmic phase control is not working yet
+ */
+ return 0;
}
static int set_pmic_gang_voltage(int uV)
diff --git a/arch/arm/mach-msm/msm_watchdog.c b/arch/arm/mach-msm/msm_watchdog.c
index b471426..aca7667 100644
--- a/arch/arm/mach-msm/msm_watchdog.c
+++ b/arch/arm/mach-msm/msm_watchdog.c
@@ -37,22 +37,23 @@
#define TCSR_WDT_CFG 0x30
-#define WDT0_RST 0x38
-#define WDT0_EN 0x40
-#define WDT0_STS 0x44
-#define WDT0_BARK_TIME 0x4C
-#define WDT0_BITE_TIME 0x5C
+#define WDT_RST 0x0
+#define WDT_EN 0x8
+#define WDT_STS 0xC
+#define WDT_BARK_TIME 0x14
+#define WDT_BITE_TIME 0x24
#define WDT_HZ 32768
struct msm_watchdog_dump msm_dump_cpu_ctx;
-static void __iomem *msm_tmr0_base;
+static void __iomem *msm_wdt_base;
static unsigned long delay_time;
static unsigned long bark_time;
static unsigned long long last_pet;
static bool has_vic;
+static unsigned int msm_wdog_irq;
/*
* On the kernel command line specify
@@ -116,8 +117,8 @@
if (!enable)
return 0;
- __raw_writel(1, msm_tmr0_base + WDT0_RST);
- __raw_writel(0, msm_tmr0_base + WDT0_EN);
+ __raw_writel(1, msm_wdt_base + WDT_RST);
+ __raw_writel(0, msm_wdt_base + WDT_EN);
mb();
return 0;
}
@@ -127,8 +128,8 @@
if (!enable)
return 0;
- __raw_writel(1, msm_tmr0_base + WDT0_EN);
- __raw_writel(1, msm_tmr0_base + WDT0_RST);
+ __raw_writel(1, msm_wdt_base + WDT_EN);
+ __raw_writel(1, msm_wdt_base + WDT_RST);
mb();
return 0;
}
@@ -137,14 +138,14 @@
unsigned long event, void *ptr)
{
if (panic_timeout == 0) {
- __raw_writel(0, msm_tmr0_base + WDT0_EN);
+ __raw_writel(0, msm_wdt_base + WDT_EN);
mb();
} else {
__raw_writel(WDT_HZ * (panic_timeout + 4),
- msm_tmr0_base + WDT0_BARK_TIME);
+ msm_wdt_base + WDT_BARK_TIME);
__raw_writel(WDT_HZ * (panic_timeout + 4),
- msm_tmr0_base + WDT0_BITE_TIME);
- __raw_writel(1, msm_tmr0_base + WDT0_RST);
+ msm_wdt_base + WDT_BITE_TIME);
+ __raw_writel(1, msm_wdt_base + WDT_RST);
}
return NOTIFY_DONE;
}
@@ -162,14 +163,14 @@
{
struct wdog_disable_work_data *work_data =
container_of(work, struct wdog_disable_work_data, work);
- __raw_writel(0, msm_tmr0_base + WDT0_EN);
+ __raw_writel(0, msm_wdt_base + WDT_EN);
mb();
if (has_vic) {
- free_irq(WDT0_ACCSCSSNBARK_INT, 0);
+ free_irq(msm_wdog_irq, 0);
} else {
- disable_percpu_irq(WDT0_ACCSCSSNBARK_INT);
+ disable_percpu_irq(msm_wdog_irq);
if (!appsbark_fiq) {
- free_percpu_irq(WDT0_ACCSCSSNBARK_INT,
+ free_percpu_irq(msm_wdog_irq,
percpu_pdata);
free_percpu(percpu_pdata);
}
@@ -178,7 +179,7 @@
atomic_notifier_chain_unregister(&panic_notifier_list, &panic_blk);
cancel_delayed_work(&dogwork_struct);
/* may be suspended after the first write above */
- __raw_writel(0, msm_tmr0_base + WDT0_EN);
+ __raw_writel(0, msm_wdt_base + WDT_EN);
complete(&work_data->complete);
pr_info("MSM Watchdog deactivated.\n");
}
@@ -229,11 +230,11 @@
if (!enable)
return;
- slack = __raw_readl(msm_tmr0_base + WDT0_STS) >> 3;
+ slack = __raw_readl(msm_wdt_base + WDT_STS) >> 3;
slack = ((bark_time*WDT_HZ)/1000) - slack;
if (slack < min_slack_ticks)
min_slack_ticks = slack;
- __raw_writel(1, msm_tmr0_base + WDT0_RST);
+ __raw_writel(1, msm_wdt_base + WDT_RST);
time_ns = sched_clock();
slack_ns = (last_pet + bark_time_ns) - time_ns;
if (slack_ns < min_slack_ns)
@@ -329,7 +330,7 @@
int ret;
if (has_vic) {
- ret = request_irq(WDT0_ACCSCSSNBARK_INT, wdog_bark_handler, 0,
+ ret = request_irq(msm_wdog_irq, wdog_bark_handler, 0,
"apps_wdog_bark", NULL);
if (ret)
return;
@@ -344,7 +345,7 @@
}
msm_wdog_fiq_setup(stack);
- gic_set_irq_secure(WDT0_ACCSCSSNBARK_INT);
+ gic_set_irq_secure(msm_wdog_irq);
} else {
percpu_pdata = alloc_percpu(struct msm_watchdog_pdata *);
if (!percpu_pdata) {
@@ -354,7 +355,7 @@
}
/* Must request irq before sending scm command */
- ret = request_percpu_irq(WDT0_ACCSCSSNBARK_INT,
+ ret = request_percpu_irq(msm_wdog_irq,
wdog_bark_handler, "apps_wdog_bark", percpu_pdata);
if (ret) {
free_percpu(percpu_pdata);
@@ -364,20 +365,20 @@
configure_bark_dump();
- __raw_writel(timeout, msm_tmr0_base + WDT0_BARK_TIME);
- __raw_writel(timeout + 3*WDT_HZ, msm_tmr0_base + WDT0_BITE_TIME);
+ __raw_writel(timeout, msm_wdt_base + WDT_BARK_TIME);
+ __raw_writel(timeout + 3*WDT_HZ, msm_wdt_base + WDT_BITE_TIME);
schedule_delayed_work_on(0, &dogwork_struct, delay_time);
atomic_notifier_chain_register(&panic_notifier_list,
&panic_blk);
- __raw_writel(1, msm_tmr0_base + WDT0_EN);
- __raw_writel(1, msm_tmr0_base + WDT0_RST);
+ __raw_writel(1, msm_wdt_base + WDT_EN);
+ __raw_writel(1, msm_wdt_base + WDT_RST);
last_pet = sched_clock();
if (!has_vic)
- enable_percpu_irq(WDT0_ACCSCSSNBARK_INT, IRQ_TYPE_EDGE_RISING);
+ enable_percpu_irq(msm_wdog_irq, IRQ_TYPE_EDGE_RISING);
printk(KERN_INFO "MSM Watchdog Initialized\n");
@@ -400,7 +401,8 @@
appsbark_fiq = pdata->use_kernel_fiq;
}
- msm_tmr0_base = msm_timer_get_timer0_base();
+ msm_wdt_base = pdata->base;
+ msm_wdog_irq = platform_get_irq(pdev, 0);
/*
* This is only temporary till SBLs turn on the XPUs
diff --git a/arch/arm/mach-msm/msm_watchdog.h b/arch/arm/mach-msm/msm_watchdog.h
index 00ff0b6..5fb82ee 100644
--- a/arch/arm/mach-msm/msm_watchdog.h
+++ b/arch/arm/mach-msm/msm_watchdog.h
@@ -13,6 +13,10 @@
#ifndef __ARCH_ARM_MACH_MSM_MSM_WATCHDOG_H
#define __ARCH_ARM_MACH_MSM_MSM_WATCHDOG_H
+/* The base is just address of the WDT_RST register */
+#define WDT0_OFFSET 0x38
+#define WDT1_OFFSET 0x60
+
struct msm_watchdog_pdata {
/* pet interval period in ms */
unsigned int pet_time;
@@ -23,6 +27,7 @@
bool has_vic;
/* You have to be running in secure mode to use FIQ */
bool use_kernel_fiq;
+ void __iomem *base;
};
struct msm_watchdog_dump {
diff --git a/arch/arm/mach-msm/ocmem_core.c b/arch/arm/mach-msm/ocmem_core.c
index 019f59f..d8cfefc 100644
--- a/arch/arm/mach-msm/ocmem_core.c
+++ b/arch/arm/mach-msm/ocmem_core.c
@@ -383,6 +383,32 @@
return 0;
}
+#if defined(CONFIG_MSM_OCMEM_POWER_DISABLE)
+/* Initializes a region to be turned ON in wide mode */
+static int ocmem_region_set_default_state(unsigned int r_num)
+{
+ unsigned m_num = 0;
+
+ mutex_lock(®ion_ctrl_lock);
+
+ for (m_num = 0; m_num < num_banks; m_num++) {
+ apply_macro_vote(0, r_num, m_num, MACRO_ON);
+ aggregate_macro_state(r_num, m_num);
+ }
+
+ aggregate_region_state(r_num);
+ commit_region_state(r_num);
+
+ mutex_unlock(®ion_ctrl_lock);
+ return 0;
+}
+
+#else
+static int ocmem_region_set_default_state(unsigned int region_num)
+{
+ return 0;
+}
+#endif
#if defined(CONFIG_MSM_OCMEM_POWER_DEBUG)
@@ -489,6 +515,15 @@
REGION_DEFAULT_OFF -> REGION_DEFAULT_ON
**/
+#if defined(CONFIG_MSM_OCMEM_POWER_DISABLE)
+/* If power management is disabled leave the macro states as is */
+static int switch_power_state(int id, unsigned long offset, unsigned long len,
+ unsigned new_state)
+{
+ return 0;
+}
+
+#else
static int switch_power_state(int id, unsigned long offset, unsigned long len,
unsigned new_state)
{
@@ -579,6 +614,7 @@
WARN_ON(1);
return -EINVAL;
}
+#endif
/* Interfaces invoked from the scheduler */
int ocmem_memory_off(int id, unsigned long offset, unsigned long len)
@@ -700,6 +736,10 @@
goto hw_not_supported;
}
+ if (ocmem_region_set_default_state(i)) {
+ pr_err("Failed to initialize region %d\n", i);
+ goto hw_not_supported;
+ }
}
return 0;
hw_not_supported:
diff --git a/arch/arm/mach-msm/pil-mba.c b/arch/arm/mach-msm/pil-mba.c
index d0ba7d0..2176b26 100644
--- a/arch/arm/mach-msm/pil-mba.c
+++ b/arch/arm/mach-msm/pil-mba.c
@@ -37,7 +37,6 @@
#define STATUS_META_DATA_AUTH_SUCCESS 0x3
#define STATUS_AUTH_COMPLETE 0x4
-#define STATUS_ERROR_MASK BIT(31)
#define AUTH_TIMEOUT_US 10000000
#define PROXY_TIMEOUT_MS 10000
@@ -75,7 +74,7 @@
const u8 *metadata, size_t size)
{
struct mba_data *drv = dev_get_drvdata(pil->dev);
- u32 status;
+ s32 status;
int ret;
/* Copy metadata to assigned shared buffer location */
@@ -89,10 +88,14 @@
writel_relaxed(drv->metadata_phys, drv->reg_base + RMB_PMI_META_DATA);
writel_relaxed(CMD_META_DATA_READY, drv->reg_base + RMB_MBA_COMMAND);
ret = readl_poll_timeout(drv->reg_base + RMB_MBA_STATUS, status,
- status == STATUS_META_DATA_AUTH_SUCCESS,
+ status == STATUS_META_DATA_AUTH_SUCCESS || status < 0,
POLL_INTERVAL_US, AUTH_TIMEOUT_US);
- if (ret)
+ if (ret) {
dev_err(pil->dev, "MBA authentication timed out\n");
+ } else if (status < 0) {
+ dev_err(pil->dev, "MBA returned error %d\n", status);
+ ret = -EINVAL;
+ }
return ret;
}
@@ -101,6 +104,7 @@
size_t size)
{
struct mba_data *drv = dev_get_drvdata(pil->dev);
+ s32 status;
/* Begin image authentication */
if (drv->img_length == 0) {
@@ -111,28 +115,33 @@
drv->img_length += size;
writel_relaxed(drv->img_length, drv->reg_base + RMB_PMI_CODE_LENGTH);
- return readl_relaxed(drv->reg_base + RMB_MBA_STATUS)
- & STATUS_ERROR_MASK;
+ status = readl_relaxed(drv->reg_base + RMB_MBA_STATUS);
+ if (status < 0) {
+ dev_err(pil->dev, "MBA returned error %d\n", status);
+ return -EINVAL;
+ }
+
+ return 0;
}
static int pil_mba_auth(struct pil_desc *pil)
{
struct mba_data *drv = dev_get_drvdata(pil->dev);
int ret;
- u32 status;
+ s32 status;
/* Wait for all segments to be authenticated or an error to occur */
ret = readl_poll_timeout(drv->reg_base + RMB_MBA_STATUS, status,
- status == STATUS_AUTH_COMPLETE ||
- status & STATUS_ERROR_MASK,
+ status == STATUS_AUTH_COMPLETE || status < 0,
50, AUTH_TIMEOUT_US);
- if (ret)
- return ret;
+ if (ret) {
+ dev_err(pil->dev, "MBA authentication timed out\n");
+ } else if (status < 0) {
+ dev_err(pil->dev, "MBA returned error %d\n", status);
+ ret = -EINVAL;
+ }
- if (status & STATUS_ERROR_MASK)
- return -EINVAL;
-
- return 0;
+ return ret;
}
static int pil_mba_shutdown(struct pil_desc *pil)
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 311f8a7..44d8bc6 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -18,13 +18,56 @@
#include <linux/err.h>
#include <linux/of.h>
#include <linux/clk.h>
-
+#include <mach/clk.h>
#include "peripheral-loader.h"
#include "pil-q6v5.h"
#define QDSP6SS_RST_EVB 0x010
#define PROXY_TIMEOUT_MS 10000
+static int pil_lpass_enable_clks(struct q6v5_data *drv)
+{
+ int ret;
+
+ ret = clk_reset(drv->core_clk, CLK_RESET_DEASSERT);
+ if (ret)
+ goto err_reset;
+ ret = clk_prepare_enable(drv->core_clk);
+ if (ret)
+ goto err_core_clk;
+ ret = clk_prepare_enable(drv->ahb_clk);
+ if (ret)
+ goto err_ahb_clk;
+ ret = clk_prepare_enable(drv->axi_clk);
+ if (ret)
+ goto err_axi_clk;
+ ret = clk_prepare_enable(drv->reg_clk);
+ if (ret)
+ goto err_reg_clk;
+
+ return 0;
+
+err_reg_clk:
+ clk_disable_unprepare(drv->axi_clk);
+err_axi_clk:
+ clk_disable_unprepare(drv->ahb_clk);
+err_ahb_clk:
+ clk_disable_unprepare(drv->core_clk);
+err_core_clk:
+ clk_reset(drv->core_clk, CLK_RESET_ASSERT);
+err_reset:
+ return ret;
+}
+
+static void pil_lpass_disable_clks(struct q6v5_data *drv)
+{
+ clk_disable_unprepare(drv->reg_clk);
+ clk_disable_unprepare(drv->axi_clk);
+ clk_disable_unprepare(drv->ahb_clk);
+ clk_disable_unprepare(drv->core_clk);
+ clk_reset(drv->core_clk, CLK_RESET_ASSERT);
+}
+
static int pil_lpass_shutdown(struct pil_desc *pil)
{
struct q6v5_data *drv = dev_get_drvdata(pil->dev);
@@ -37,10 +80,10 @@
* performed during the shutdown succeed.
*/
if (drv->is_booted == false)
- pil_q6v5_enable_clks(pil);
+ pil_lpass_enable_clks(drv);
pil_q6v5_shutdown(pil);
- pil_q6v5_disable_clks(pil);
+ pil_lpass_disable_clks(drv);
drv->is_booted = false;
@@ -52,7 +95,7 @@
struct q6v5_data *drv = dev_get_drvdata(pil->dev);
int ret;
- ret = pil_q6v5_enable_clks(pil);
+ ret = pil_lpass_enable_clks(drv);
if (ret)
return ret;
@@ -62,7 +105,7 @@
ret = pil_q6v5_reset(pil);
if (ret) {
- pil_q6v5_disable_clks(pil);
+ pil_lpass_disable_clks(drv);
return ret;
}
@@ -96,6 +139,22 @@
desc->owner = THIS_MODULE;
desc->proxy_timeout = PROXY_TIMEOUT_MS;
+ drv->core_clk = devm_clk_get(&pdev->dev, "core_clk");
+ if (IS_ERR(drv->core_clk))
+ return PTR_ERR(drv->core_clk);
+
+ drv->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk");
+ if (IS_ERR(drv->ahb_clk))
+ return PTR_ERR(drv->ahb_clk);
+
+ drv->axi_clk = devm_clk_get(&pdev->dev, "bus_clk");
+ if (IS_ERR(drv->axi_clk))
+ return PTR_ERR(drv->axi_clk);
+
+ drv->reg_clk = devm_clk_get(&pdev->dev, "reg_clk");
+ if (IS_ERR(drv->reg_clk))
+ return PTR_ERR(drv->reg_clk);
+
drv->pil = msm_pil_register(desc);
if (IS_ERR(drv->pil))
return PTR_ERR(drv->pil);
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 5c9c3c4..6a30940 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -38,6 +38,9 @@
#define MSS_MODEM_HALT_BASE 0x200
#define MSS_NC_HALT_BASE 0x280
+/* MSS_CLAMP_IO Register Value */
+#define MSS_IO_UNCLAMP_ALL 0x40
+
/* RMB Status Register Values */
#define STATUS_PBL_SUCCESS 0x1
#define STATUS_XPU_UNLOCKED 0x1
@@ -71,6 +74,55 @@
return regulator_disable(drv->vreg);
}
+static int pil_mss_enable_clks(struct q6v5_data *drv)
+{
+ int ret;
+
+ ret = clk_prepare_enable(drv->ahb_clk);
+ if (ret)
+ goto err_ahb_clk;
+ ret = clk_reset(drv->core_clk, CLK_RESET_DEASSERT);
+ if (ret)
+ goto err_reset;
+ ret = clk_prepare_enable(drv->core_clk);
+ if (ret)
+ goto err_core_clk;
+ ret = clk_prepare_enable(drv->axi_clk);
+ if (ret)
+ goto err_axi_clk;
+ ret = clk_prepare_enable(drv->reg_clk);
+ if (ret)
+ goto err_reg_clk;
+ ret = clk_prepare_enable(drv->rom_clk);
+ if (ret)
+ goto err_rom_clk;
+
+ return 0;
+
+err_rom_clk:
+ clk_disable_unprepare(drv->reg_clk);
+err_reg_clk:
+ clk_disable_unprepare(drv->axi_clk);
+err_axi_clk:
+ clk_disable_unprepare(drv->core_clk);
+err_core_clk:
+ clk_reset(drv->core_clk, CLK_RESET_ASSERT);
+err_reset:
+ clk_disable_unprepare(drv->ahb_clk);
+err_ahb_clk:
+ return ret;
+}
+
+static void pil_mss_disable_clks(struct q6v5_data *drv)
+{
+ clk_disable_unprepare(drv->rom_clk);
+ clk_disable_unprepare(drv->reg_clk);
+ clk_disable_unprepare(drv->axi_clk);
+ clk_disable_unprepare(drv->core_clk);
+ clk_reset(drv->core_clk, CLK_RESET_ASSERT);
+ clk_disable_unprepare(drv->ahb_clk);
+}
+
static int wait_for_mba_ready(struct device *dev)
{
struct q6v5_data *drv = dev_get_drvdata(dev);
@@ -120,11 +172,11 @@
*/
if (drv->is_booted == false) {
pil_mss_power_up(pil->dev);
- pil_q6v5_enable_clks(pil);
+ pil_mss_enable_clks(drv);
}
pil_q6v5_shutdown(pil);
- pil_q6v5_disable_clks(pil);
+ pil_mss_disable_clks(drv);
pil_mss_power_down(pil->dev);
writel_relaxed(1, drv->restart_reg);
@@ -152,7 +204,7 @@
if (ret)
goto err_power;
- ret = pil_q6v5_enable_clks(pil);
+ ret = pil_mss_enable_clks(drv);
if (ret)
goto err_clks;
@@ -166,6 +218,9 @@
drv->reg_base + QDSP6SS_RST_EVB);
}
+ /* De-assert MSS IO clamps */
+ writel_relaxed(MSS_IO_UNCLAMP_ALL, drv->io_clamp_reg);
+
ret = pil_q6v5_reset(pil);
if (ret)
goto err_q6v5_reset;
@@ -184,7 +239,7 @@
err_auth:
pil_q6v5_shutdown(pil);
err_q6v5_reset:
- pil_q6v5_disable_clks(pil);
+ pil_mss_disable_clks(drv);
err_clks:
pil_mss_power_down(pil->dev);
err_power:
@@ -233,6 +288,12 @@
if (!drv->restart_reg)
return -ENOMEM;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 4);
+ drv->io_clamp_reg = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!drv->io_clamp_reg)
+ return -ENOMEM;
+
drv->vreg = devm_regulator_get(&pdev->dev, "vdd_mss");
if (IS_ERR(drv->vreg))
return PTR_ERR(drv->vreg);
@@ -247,9 +308,25 @@
return ret;
}
- drv->mem_clk = devm_clk_get(&pdev->dev, "mem_clk");
- if (IS_ERR(drv->mem_clk))
- return PTR_ERR(drv->mem_clk);
+ drv->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk");
+ if (IS_ERR(drv->ahb_clk))
+ return PTR_ERR(drv->ahb_clk);
+
+ drv->core_clk = devm_clk_get(&pdev->dev, "core_clk");
+ if (IS_ERR(drv->core_clk))
+ return PTR_ERR(drv->core_clk);
+
+ drv->axi_clk = devm_clk_get(&pdev->dev, "bus_clk");
+ if (IS_ERR(drv->axi_clk))
+ return PTR_ERR(drv->axi_clk);
+
+ drv->reg_clk = devm_clk_get(&pdev->dev, "reg_clk");
+ if (IS_ERR(drv->reg_clk))
+ return PTR_ERR(drv->reg_clk);
+
+ drv->rom_clk = devm_clk_get(&pdev->dev, "mem_clk");
+ if (IS_ERR(drv->rom_clk))
+ return PTR_ERR(drv->rom_clk);
drv->pil = msm_pil_register(desc);
if (IS_ERR(drv->pil))
diff --git a/arch/arm/mach-msm/pil-q6v5.c b/arch/arm/mach-msm/pil-q6v5.c
index a362a7e3..772031b 100644
--- a/arch/arm/mach-msm/pil-q6v5.c
+++ b/arch/arm/mach-msm/pil-q6v5.c
@@ -20,9 +20,7 @@
#include <linux/err.h>
#include <linux/of.h>
#include <linux/clk.h>
-
#include <mach/clk.h>
-
#include "peripheral-loader.h"
#include "pil-q6v5.h"
@@ -30,6 +28,7 @@
#define QDSP6SS_RESET 0x014
#define QDSP6SS_GFMUX_CTL 0x020
#define QDSP6SS_PWR_CTL 0x030
+#define QDSP6SS_CGC_OVERRIDE 0x034
/* AXI Halt Register Offsets */
#define AXI_HALTREQ 0x0
@@ -39,15 +38,15 @@
#define HALT_ACK_TIMEOUT_US 100000
/* QDSP6SS_RESET */
+#define Q6SS_STOP_CORE BIT(0)
#define Q6SS_CORE_ARES BIT(1)
-#define Q6SS_ETM_ISDB_ARES BIT(3)
-#define Q6SS_STOP_CORE BIT(4)
+#define Q6SS_BUS_ARES_ENA BIT(2)
/* QDSP6SS_GFMUX_CTL */
#define Q6SS_CLK_ENA BIT(1)
/* QDSP6SS_PWR_CTL */
-#define Q6SS_L2DATA_SLP_NRET_N BIT(0)
+#define Q6SS_L2DATA_SLP_NRET_N (BIT(0)|BIT(1)|BIT(2))
#define Q6SS_L2TAG_SLP_NRET_N BIT(16)
#define Q6SS_ETB_SLP_NRET_N BIT(17)
#define Q6SS_L2DATA_STBY_N BIT(18)
@@ -55,6 +54,10 @@
#define Q6SS_CLAMP_IO BIT(20)
#define QDSS_BHS_ON BIT(21)
+/* QDSP6SS_CGC_OVERRIDE */
+#define Q6SS_CORE_CLK_EN BIT(0)
+#define Q6SS_CORE_RCLK_EN BIT(1)
+
int pil_q6v5_make_proxy_votes(struct pil_desc *pil)
{
int ret;
@@ -107,50 +110,6 @@
}
EXPORT_SYMBOL(pil_q6v5_init_image);
-int pil_q6v5_enable_clks(struct pil_desc *pil)
-{
- struct q6v5_data *drv = dev_get_drvdata(pil->dev);
- int ret;
-
- ret = clk_reset(drv->core_clk, CLK_RESET_DEASSERT);
- if (ret)
- goto err_reset;
- ret = clk_prepare_enable(drv->core_clk);
- if (ret)
- goto err_core_clk;
- ret = clk_prepare_enable(drv->bus_clk);
- if (ret)
- goto err_bus_clk;
- if (drv->mem_clk) {
- ret = clk_prepare_enable(drv->mem_clk);
- if (ret)
- goto err_mem_clk;
- }
-
- return 0;
-
-err_mem_clk:
- clk_disable_unprepare(drv->bus_clk);
-err_bus_clk:
- clk_disable_unprepare(drv->core_clk);
-err_core_clk:
- clk_reset(drv->core_clk, CLK_RESET_ASSERT);
-err_reset:
- return ret;
-}
-EXPORT_SYMBOL(pil_q6v5_enable_clks);
-
-void pil_q6v5_disable_clks(struct pil_desc *pil)
-{
- struct q6v5_data *drv = dev_get_drvdata(pil->dev);
-
- clk_disable_unprepare(drv->bus_clk);
- clk_disable_unprepare(drv->core_clk);
- clk_disable_unprepare(drv->mem_clk);
- clk_reset(drv->core_clk, CLK_RESET_ASSERT);
-}
-EXPORT_SYMBOL(pil_q6v5_disable_clks);
-
void pil_q6v5_shutdown(struct pil_desc *pil)
{
u32 val;
@@ -174,7 +133,7 @@
/* Assert Q6 resets */
val = readl_relaxed(drv->reg_base + QDSP6SS_RESET);
- val = (Q6SS_CORE_ARES | Q6SS_ETM_ISDB_ARES);
+ val = (Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENA);
writel_relaxed(val, drv->reg_base + QDSP6SS_RESET);
/* Kill power at block headswitch (affects LPASS only) */
@@ -191,7 +150,7 @@
/* Assert resets, stop core */
val = readl_relaxed(drv->reg_base + QDSP6SS_RESET);
- val |= (Q6SS_CORE_ARES | Q6SS_ETM_ISDB_ARES | Q6SS_STOP_CORE);
+ val |= (Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENA | Q6SS_STOP_CORE);
writel_relaxed(val, drv->reg_base + QDSP6SS_RESET);
/* Enable power block headswitch (only affects LPASS) */
@@ -211,9 +170,15 @@
writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
/* Bring core out of reset */
- val = Q6SS_STOP_CORE;
+ val = readl_relaxed(drv->reg_base + QDSP6SS_RESET);
+ val &= ~Q6SS_CORE_ARES;
writel_relaxed(val, drv->reg_base + QDSP6SS_RESET);
+ /* Disable clock gating for core and rclk */
+ val = readl_relaxed(drv->reg_base + QDSP6SS_CGC_OVERRIDE);
+ val |= Q6SS_CORE_RCLK_EN | Q6SS_CORE_CLK_EN;
+ writel_relaxed(val, drv->reg_base + QDSP6SS_CGC_OVERRIDE);
+
/* Turn on core clock */
val = readl_relaxed(drv->reg_base + QDSP6SS_GFMUX_CTL);
val |= Q6SS_CLK_ENA;
@@ -266,14 +231,6 @@
if (IS_ERR(drv->xo))
return ERR_CAST(drv->xo);
- drv->bus_clk = devm_clk_get(&pdev->dev, "bus_clk");
- if (IS_ERR(drv->bus_clk))
- return ERR_CAST(drv->bus_clk);
-
- drv->core_clk = devm_clk_get(&pdev->dev, "core_clk");
- if (IS_ERR(drv->core_clk))
- return ERR_CAST(drv->core_clk);
-
desc->dev = &pdev->dev;
return desc;
diff --git a/arch/arm/mach-msm/pil-q6v5.h b/arch/arm/mach-msm/pil-q6v5.h
index e0d7a20..03f93fa 100644
--- a/arch/arm/mach-msm/pil-q6v5.h
+++ b/arch/arm/mach-msm/pil-q6v5.h
@@ -21,13 +21,16 @@
struct q6v5_data {
void __iomem *reg_base;
- struct clk *xo;
- struct clk *bus_clk;
- struct clk *core_clk;
- struct clk *mem_clk;
+ struct clk *xo; /* XO clock source */
+ struct clk *ahb_clk; /* PIL access to registers */
+ struct clk *axi_clk; /* CPU access to memory */
+ struct clk *core_clk; /* CPU core */
+ struct clk *reg_clk; /* CPU access registers */
+ struct clk *rom_clk; /* Boot ROM */
void __iomem *axi_halt_base;
void __iomem *rmb_base;
void __iomem *restart_reg;
+ void __iomem *io_clamp_reg;
unsigned long start_addr;
struct regulator *vreg;
bool is_booted;
@@ -42,8 +45,6 @@
size_t size);
void pil_q6v5_shutdown(struct pil_desc *pil);
int pil_q6v5_reset(struct pil_desc *pil);
-int pil_q6v5_enable_clks(struct pil_desc *pil);
-void pil_q6v5_disable_clks(struct pil_desc *pil);
struct pil_desc *pil_q6v5_init(struct platform_device *pdev);
#endif
diff --git a/arch/arm/mach-msm/pil-venus.c b/arch/arm/mach-msm/pil-venus.c
index 6a0aeaa..49c39ec 100644
--- a/arch/arm/mach-msm/pil-venus.c
+++ b/arch/arm/mach-msm/pil-venus.c
@@ -228,12 +228,6 @@
writel_relaxed(drv->fw_sz, wrapper_base +
VENUS_WRAPPER_VBIF_SS_SEC_FW_END_ADDR);
- rc = iommu_attach_device(drv->iommu_fw_domain, drv->iommu_fw_ctx);
- if (rc) {
- dev_err(pil->dev, "venus fw iommu attach failed\n");
- goto err_iommu_attach;
- }
-
/* Enable all Venus internal clocks */
writel_relaxed(0, wrapper_base + VENUS_WRAPPER_CLOCK_CONFIG);
writel_relaxed(0, wrapper_base + VENUS_WRAPPER_CPU_CLOCK_CONFIG);
@@ -247,6 +241,12 @@
*/
udelay(1);
+ rc = iommu_attach_device(drv->iommu_fw_domain, drv->iommu_fw_ctx);
+ if (rc) {
+ dev_err(pil->dev, "venus fw iommu attach failed\n");
+ goto err_iommu_attach;
+ }
+
/* Map virtual addr space 0 - fw_sz to firmware physical addr space */
rc = msm_iommu_map_contig_buffer(pa, drv->venus_domain_num, 0,
drv->fw_sz, SZ_4K, 0, &iova);
@@ -285,19 +285,6 @@
venus_clock_prepare_enable(pil->dev);
- /* Halt AXI and AXI OCMEM VBIF Access */
- reg = readl_relaxed(vbif_base + VENUS_VBIF_AXI_HALT_CTRL0);
- reg |= VENUS_VBIF_AXI_HALT_CTRL0_HALT_REQ;
- writel_relaxed(reg, vbif_base + VENUS_VBIF_AXI_HALT_CTRL0);
-
- /* Request for AXI bus port halt */
- rc = readl_poll_timeout(vbif_base + VENUS_VBIF_AXI_HALT_CTRL1,
- reg, reg & VENUS_VBIF_AXI_HALT_CTRL1_HALT_ACK,
- POLL_INTERVAL_US,
- VENUS_VBIF_AXI_HALT_ACK_TIMEOUT_US);
- if (rc)
- dev_err(pil->dev, "Port halt timeout\n");
-
/* Assert the reset to ARM9 */
reg = readl_relaxed(wrapper_base + VENUS_WRAPPER_SW_RESET);
reg |= BIT(4);
@@ -311,6 +298,19 @@
iommu_detach_device(drv->iommu_fw_domain, drv->iommu_fw_ctx);
+ /* Halt AXI and AXI OCMEM VBIF Access */
+ reg = readl_relaxed(vbif_base + VENUS_VBIF_AXI_HALT_CTRL0);
+ reg |= VENUS_VBIF_AXI_HALT_CTRL0_HALT_REQ;
+ writel_relaxed(reg, vbif_base + VENUS_VBIF_AXI_HALT_CTRL0);
+
+ /* Request for AXI bus port halt */
+ rc = readl_poll_timeout(vbif_base + VENUS_VBIF_AXI_HALT_CTRL1,
+ reg, reg & VENUS_VBIF_AXI_HALT_CTRL1_HALT_ACK,
+ POLL_INTERVAL_US,
+ VENUS_VBIF_AXI_HALT_ACK_TIMEOUT_US);
+ if (rc)
+ dev_err(pil->dev, "Port halt timeout\n");
+
venus_clock_disable_unprepare(pil->dev);
regulator_disable(drv->gdsc);
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index a11ca95..28b7748 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -120,6 +120,29 @@
return 0;
}
+static int __cpuinit krait_release_secondary_p3(unsigned long base, int cpu)
+{
+ void *base_ptr = ioremap_nocache(base + (cpu * 0x10000), SZ_4K);
+ if (!base_ptr)
+ return -ENODEV;
+
+ writel_relaxed(0x021, base_ptr+0x04);
+ mb();
+ udelay(2);
+
+ writel_relaxed(0x020, base_ptr+0x04);
+ mb();
+ udelay(2);
+
+ writel_relaxed(0x000, base_ptr+0x04);
+ mb();
+
+ writel_relaxed(0x080, base_ptr+0x04);
+ mb();
+ iounmap(base_ptr);
+ return 0;
+}
+
static int __cpuinit release_secondary(unsigned int cpu)
{
BUG_ON(cpu >= get_core_count());
@@ -134,6 +157,9 @@
cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab())
return krait_release_secondary(0x02088000, cpu);
+ if (cpu_is_msm8974())
+ return krait_release_secondary_p3(0xf9088000, cpu);
+
WARN(1, "unknown CPU case in release_secondary\n");
return -EINVAL;
}
@@ -205,8 +231,8 @@
if (pen_release == -1)
break;
- dmac_inv_range((void *)&pen_release,
- (void *)(&pen_release+sizeof(pen_release)));
+ dmac_inv_range((char *)&pen_release,
+ (char *)&pen_release + sizeof(pen_release));
udelay(10);
}
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
index 1092c77..5c1e7ce 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
@@ -20,7 +20,7 @@
#include <mach/qdsp6v2/audio_acdb.h>
-#define MAX_NETWORKS 12
+#define MAX_NETWORKS 15
struct sidetone_atomic_cal {
atomic_t enable;
diff --git a/arch/arm/mach-msm/rpm-regulator-8930.c b/arch/arm/mach-msm/rpm-regulator-8930.c
index 0de67b1..3878e22 100644
--- a/arch/arm/mach-msm/rpm-regulator-8930.c
+++ b/arch/arm/mach-msm/rpm-regulator-8930.c
@@ -71,6 +71,11 @@
VOLTAGE_RANGE( 750000, 1537500, 12500),
};
+static struct vreg_range ln_ldo_ranges[] = {
+ VOLTAGE_RANGE( 690000, 1110000, 60000),
+ VOLTAGE_RANGE(1380000, 2220000, 120000),
+};
+
static struct vreg_range smps_ranges[] = {
VOLTAGE_RANGE( 375000, 737500, 12500),
VOLTAGE_RANGE( 750000, 1487500, 12500),
@@ -90,6 +95,7 @@
static struct vreg_set_points pldo_set_points = SET_POINTS(pldo_ranges);
static struct vreg_set_points nldo_set_points = SET_POINTS(nldo_ranges);
static struct vreg_set_points nldo1200_set_points = SET_POINTS(nldo1200_ranges);
+static struct vreg_set_points ln_ldo_set_points = SET_POINTS(ln_ldo_ranges);
static struct vreg_set_points smps_set_points = SET_POINTS(smps_ranges);
static struct vreg_set_points ftsmps_set_points = SET_POINTS(ftsmps_ranges);
static struct vreg_set_points corner_set_points = SET_POINTS(corner_ranges);
@@ -98,6 +104,7 @@
&pldo_set_points,
&nldo_set_points,
&nldo1200_set_points,
+ &ln_ldo_set_points,
&smps_set_points,
&ftsmps_set_points,
&corner_set_points,
@@ -173,6 +180,7 @@
LDO(L10, "8038_l10", "8038_l10_pc", pldo, LDO_600, 0),
LDO(L11, "8038_l11", "8038_l11_pc", pldo, LDO_600, 0),
LDO(L12, "8038_l12", "8038_l12_pc", nldo, LDO_300, 1),
+ LDO(L13, "8038_l13", NULL, ln_ldo, LDO_5, 0),
LDO(L14, "8038_l14", "8038_l14_pc", pldo, LDO_50, 0),
LDO(L15, "8038_l15", "8038_l15_pc", pldo, LDO_150, 0),
LDO(L16, "8038_l16", NULL, nldo1200, LDO_1200, 1),
@@ -184,6 +192,7 @@
LDO(L22, "8038_l22", "8038_l22_pc", pldo, LDO_50, 0),
LDO(L23, "8038_l23", "8038_l23_pc", pldo, LDO_50, 0),
LDO(L24, "8038_l24", NULL, nldo1200, LDO_1200, 1),
+ LDO(L25, "8038_l25", NULL, ln_ldo, LDO_5, 0),
LDO(L26, "8038_l26", "8038_l26_pc", nldo, LDO_150, 1),
LDO(L27, "8038_l27", NULL, nldo1200, LDO_1200, 1),
@@ -237,8 +246,12 @@
{
int real_id = 0;
- if (id >= RPM_VREG_ID_PM8038_L2_PC && id <= RPM_VREG_ID_PM8038_L15_PC)
+ if (id >= RPM_VREG_ID_PM8038_L2_PC && id <= RPM_VREG_ID_PM8038_L12_PC)
real_id = id - RPM_VREG_ID_PM8038_L2_PC;
+ else if (id >= RPM_VREG_ID_PM8038_L14_PC
+ && id <= RPM_VREG_ID_PM8038_L15_PC)
+ real_id = id - RPM_VREG_ID_PM8038_L14_PC
+ + RPM_VREG_ID_PM8038_L14;
else if (id >= RPM_VREG_ID_PM8038_L17_PC
&& id <= RPM_VREG_ID_PM8038_L18_PC)
real_id = id - RPM_VREG_ID_PM8038_L17_PC
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index b6fb52a..57f41ca 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -250,8 +250,8 @@
#endif
}
-#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
-static void __init arm_bootmem_free_apnm(unsigned long max_low,
+#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
+static void __init arm_bootmem_free_hmnm(unsigned long max_low,
unsigned long max_high)
{
unsigned long max_zone_pfns[MAX_NR_ZONES];
@@ -267,7 +267,7 @@
unsigned long start = memblock_region_memory_base_pfn(reg);
unsigned long end = memblock_region_memory_end_pfn(reg);
- add_active_range(0, start, end);
+ memblock_set_node(PFN_PHYS(start), PFN_PHYS(end - start), 0);
}
free_area_init_nodes(max_zone_pfns);
}
@@ -491,8 +491,8 @@
*/
sparse_init();
-#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
- arm_bootmem_free_apnm(max_low, max_high);
+#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
+ arm_bootmem_free_hmnm(max_low, max_high);
#else
/*
* Now free the memory - free_area_init_node needs
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 121bf7c9..5c04693 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -4,7 +4,7 @@
*
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
* Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
- * Copyright (c) 2000-2001, 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2000-2001, 2010-2012, Code Aurora Forum. All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify
@@ -51,6 +51,7 @@
static bool reset = 0;
static struct hci_uart_proto *hup[HCI_UART_MAX_PROTO];
+static void hci_uart_tty_wakeup_action(unsigned long data);
int hci_uart_register_proto(struct hci_uart_proto *p)
{
@@ -276,6 +277,8 @@
tty->receive_room = 65536;
spin_lock_init(&hu->rx_lock);
+ tasklet_init(&hu->tty_wakeup_task, hci_uart_tty_wakeup_action,
+ (unsigned long)hu);
/* Flush any pending characters in the driver and line discipline. */
@@ -309,6 +312,8 @@
if (hdev)
hci_uart_close(hdev);
+ tasklet_kill(&hu->tty_wakeup_task);
+
if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
hu->proto->close(hu);
if (hdev) {
@@ -323,6 +328,8 @@
*
* Callback for transmit wakeup. Called when low level
* device driver can accept more send data.
+ * This callback gets called from the isr context so
+ * schedule the send data operation to tasklet.
*
* Arguments: tty pointer to associated tty instance data
* Return Value: None
@@ -330,12 +337,26 @@
static void hci_uart_tty_wakeup(struct tty_struct *tty)
{
struct hci_uart *hu = (void *)tty->disc_data;
+ tasklet_schedule(&hu->tty_wakeup_task);
+}
+
+/* hci_uart_tty_wakeup_action()
+ *
+ * Scheduled action to transmit data when low level device
+ * driver can accept more data.
+ */
+static void hci_uart_tty_wakeup_action(unsigned long data)
+{
+ struct hci_uart *hu = (struct hci_uart *)data;
+ struct tty_struct *tty;
BT_DBG("");
if (!hu)
return;
+ tty = hu->tty;
+
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
if (tty != hu->tty)
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index dc48239..123fc24 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -4,7 +4,7 @@
*
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
* Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org>
- * Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2000-2001, 2010, 2012 Code Aurora Forum. All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify
@@ -66,6 +66,7 @@
unsigned long hdev_flags;
struct hci_uart_proto *proto;
+ struct tasklet_struct tty_wakeup_task;
void *priv;
struct sk_buff *tx_skb;
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index 4d34362..6f3b79b 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -421,6 +421,7 @@
break;
case MDP_Y_CRCB_H2V1:
case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H1V2:
p->num_planes = 2;
p->plane_size[0] = w * h;
p->plane_size[1] = w * h;
@@ -651,9 +652,12 @@
int bpp;
uint32_t dst_format;
- if (info->src.format == MDP_YCRYCB_H2V1)
- dst_format = MDP_Y_CRCB_H2V1;
- else
+ if (info->src.format == MDP_YCRYCB_H2V1) {
+ if (info->rotations & MDP_ROT_90)
+ dst_format = MDP_Y_CRCB_H1V2;
+ else
+ dst_format = MDP_Y_CRCB_H2V1;
+ } else
return -EINVAL;
if (info->dst.format != dst_format)
@@ -1286,7 +1290,10 @@
info.dst.format = info.src.format;
break;
case MDP_YCRYCB_H2V1:
- info.dst.format = MDP_Y_CRCB_H2V1;
+ if (info.rotations & MDP_ROT_90)
+ info.dst.format = MDP_Y_CRCB_H1V2;
+ else
+ info.dst.format = MDP_Y_CRCB_H2V1;
break;
case MDP_Y_CB_CR_H2V2:
case MDP_Y_CBCR_H2V2_TILE:
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 2ee2093..bded488 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -1,2 +1,3 @@
-obj-$(CONFIG_MSM_QDSS) += coresight.o coresight-etb.o coresight-tpiu.o coresight-funnel.o coresight-stm.o coresight-etm.o
+obj-$(CONFIG_OF) += of_coresight.o
+obj-$(CONFIG_MSM_QDSS) += coresight.o coresight-tmc.o coresight-tpiu.o coresight-etb.o coresight-funnel.o coresight-replicator.o coresight-stm.o coresight-etm.o
diff --git a/drivers/coresight/coresight-etb.c b/drivers/coresight/coresight-etb.c
index 2bffae5..56cee06 100644
--- a/drivers/coresight/coresight-etb.c
+++ b/drivers/coresight/coresight-etb.c
@@ -23,8 +23,9 @@
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/delay.h>
-#include <linux/mutex.h>
+#include <linux/spinlock.h>
#include <linux/clk.h>
+#include <linux/of_coresight.h>
#include <linux/coresight.h>
#include "coresight-priv.h"
@@ -32,6 +33,17 @@
#define etb_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
#define etb_readl(drvdata, off) __raw_readl(drvdata->base + off)
+#define ETB_LOCK(drvdata) \
+do { \
+ mb(); \
+ etb_writel(drvdata, 0x0, CORESIGHT_LAR); \
+} while (0)
+#define ETB_UNLOCK(drvdata) \
+do { \
+ etb_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
+ mb(); \
+} while (0)
+
#define ETB_RAM_DEPTH_REG (0x004)
#define ETB_STATUS_REG (0x00C)
#define ETB_RAM_READ_DATA_REG (0x010)
@@ -50,42 +62,29 @@
#define ETB_ITATBCTR1 (0xEF4)
#define ETB_ITATBCTR0 (0xEF8)
-
#define BYTES_PER_WORD 4
#define ETB_SIZE_WORDS 4096
#define FRAME_SIZE_WORDS 4
-#define ETB_LOCK() \
-do { \
- mb(); \
- etb_writel(drvdata, 0x0, CORESIGHT_LAR); \
-} while (0)
-#define ETB_UNLOCK() \
-do { \
- etb_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
- mb(); \
-} while (0)
-
struct etb_drvdata {
- uint8_t *buf;
- void __iomem *base;
- bool enabled;
- bool reading;
- spinlock_t spinlock;
- atomic_t in_use;
- struct device *dev;
- struct kobject *kobj;
- struct clk *clk;
- uint32_t trigger_cntr;
+ void __iomem *base;
+ struct device *dev;
+ struct coresight_device *csdev;
+ struct miscdevice miscdev;
+ struct clk *clk;
+ spinlock_t spinlock;
+ bool reading;
+ atomic_t in_use;
+ uint8_t *buf;
+ bool enable;
+ uint32_t trigger_cntr;
};
-static struct etb_drvdata *drvdata;
-
-static void __etb_enable(void)
+static void __etb_enable(struct etb_drvdata *drvdata)
{
int i;
- ETB_UNLOCK();
+ ETB_UNLOCK(drvdata);
etb_writel(drvdata, 0x0, ETB_RAM_WRITE_POINTER);
for (i = 0; i < ETB_SIZE_WORDS; i++)
@@ -98,11 +97,12 @@
etb_writel(drvdata, BIT(13) | BIT(0), ETB_FFCR);
etb_writel(drvdata, BIT(0), ETB_CTL_REG);
- ETB_LOCK();
+ ETB_LOCK(drvdata);
}
-int etb_enable(void)
+static int etb_enable(struct coresight_device *csdev)
{
+ struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
int ret;
unsigned long flags;
@@ -111,25 +111,24 @@
return ret;
spin_lock_irqsave(&drvdata->spinlock, flags);
- __etb_enable();
- drvdata->enabled = true;
- dev_info(drvdata->dev, "ETB enabled\n");
+ __etb_enable(drvdata);
+ drvdata->enable = true;
spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ dev_info(drvdata->dev, "ETB enabled\n");
return 0;
}
-static void __etb_disable(void)
+static void __etb_disable(struct etb_drvdata *drvdata)
{
int count;
uint32_t ffcr;
- ETB_UNLOCK();
+ ETB_UNLOCK(drvdata);
ffcr = etb_readl(drvdata, ETB_FFCR);
ffcr |= (BIT(12) | BIT(6));
etb_writel(drvdata, ffcr, ETB_FFCR);
-
for (count = TIMEOUT_US; BVAL(etb_readl(drvdata, ETB_FFCR), 6) != 0
&& count > 0; count--)
udelay(1);
@@ -137,30 +136,16 @@
etb_readl(drvdata, ETB_FFCR));
etb_writel(drvdata, 0x0, ETB_CTL_REG);
-
for (count = TIMEOUT_US; BVAL(etb_readl(drvdata, ETB_FFSR), 1) != 1
&& count > 0; count--)
udelay(1);
WARN(count == 0, "timeout while disabling DRVDATA, ETB_FFSR: %#x\n",
etb_readl(drvdata, ETB_FFSR));
- ETB_LOCK();
+ ETB_LOCK(drvdata);
}
-void etb_disable(void)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&drvdata->spinlock, flags);
- __etb_disable();
- drvdata->enabled = false;
- dev_info(drvdata->dev, "ETB disabled\n");
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
- clk_disable_unprepare(drvdata->clk);
-}
-
-static void __etb_dump(void)
+static void __etb_dump(struct etb_drvdata *drvdata)
{
int i;
uint8_t *buf_ptr;
@@ -170,7 +155,7 @@
uint32_t frame_off;
uint32_t frame_endoff;
- ETB_UNLOCK();
+ ETB_UNLOCK(drvdata);
read_ptr = etb_readl(drvdata, ETB_RAM_READ_POINTER);
write_ptr = etb_readl(drvdata, ETB_RAM_WRITE_POINTER);
@@ -211,26 +196,69 @@
etb_writel(drvdata, read_ptr, ETB_RAM_READ_POINTER);
- ETB_LOCK();
+ ETB_LOCK(drvdata);
}
-void etb_dump(void)
+static void etb_disable(struct coresight_device *csdev)
+{
+ struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+ unsigned long flags;
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ __etb_disable(drvdata);
+ __etb_dump(drvdata);
+ drvdata->enable = false;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ clk_disable_unprepare(drvdata->clk);
+
+ dev_info(drvdata->dev, "ETB disabled\n");
+}
+
+static void etb_abort(struct coresight_device *csdev)
+{
+ struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+ unsigned long flags;
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ __etb_disable(drvdata);
+ __etb_dump(drvdata);
+ drvdata->enable = false;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_info(drvdata->dev, "ETB aborted\n");
+}
+
+static const struct coresight_ops_sink etb_sink_ops = {
+ .enable = etb_enable,
+ .disable = etb_disable,
+ .abort = etb_abort,
+};
+
+static const struct coresight_ops etb_cs_ops = {
+ .sink_ops = &etb_sink_ops,
+};
+
+static void etb_dump(struct etb_drvdata *drvdata)
{
unsigned long flags;
spin_lock_irqsave(&drvdata->spinlock, flags);
- if (drvdata->enabled) {
- __etb_disable();
- __etb_dump();
- __etb_enable();
-
- dev_info(drvdata->dev, "ETB dumped\n");
+ if (drvdata->enable) {
+ __etb_disable(drvdata);
+ __etb_dump(drvdata);
+ __etb_enable(drvdata);
}
spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_info(drvdata->dev, "ETB dumped\n");
}
static int etb_open(struct inode *inode, struct file *file)
{
+ struct etb_drvdata *drvdata = container_of(file->private_data,
+ struct etb_drvdata, miscdev);
+
if (atomic_cmpxchg(&drvdata->in_use, 0, 1))
return -EBUSY;
@@ -241,8 +269,11 @@
static ssize_t etb_read(struct file *file, char __user *data,
size_t len, loff_t *ppos)
{
+ struct etb_drvdata *drvdata = container_of(file->private_data,
+ struct etb_drvdata, miscdev);
+
if (drvdata->reading == false) {
- etb_dump();
+ etb_dump(drvdata);
drvdata->reading = true;
}
@@ -258,38 +289,35 @@
dev_dbg(drvdata->dev, "%s: %d bytes copied, %d bytes left\n",
__func__, len, (int) (ETB_SIZE_WORDS * BYTES_PER_WORD - *ppos));
-
return len;
}
static int etb_release(struct inode *inode, struct file *file)
{
- drvdata->reading = false;
+ struct etb_drvdata *drvdata = container_of(file->private_data,
+ struct etb_drvdata, miscdev);
+ drvdata->reading = false;
atomic_set(&drvdata->in_use, 0);
dev_dbg(drvdata->dev, "%s: released\n", __func__);
-
return 0;
}
static const struct file_operations etb_fops = {
- .owner = THIS_MODULE,
- .open = etb_open,
- .read = etb_read,
- .release = etb_release,
-};
-
-static struct miscdevice etb_misc = {
- .name = "msm_etb",
- .minor = MISC_DYNAMIC_MINOR,
- .fops = &etb_fops,
+ .owner = THIS_MODULE,
+ .open = etb_open,
+ .read = etb_read,
+ .release = etb_release,
+ .llseek = no_llseek,
};
static ssize_t etb_show_trigger_cntr(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->trigger_cntr;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -297,6 +325,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -308,120 +337,105 @@
static DEVICE_ATTR(trigger_cntr, S_IRUGO | S_IWUSR, etb_show_trigger_cntr,
etb_store_trigger_cntr);
-static int __devinit etb_sysfs_init(void)
-{
- int ret;
+static struct attribute *etb_attrs[] = {
+ &dev_attr_trigger_cntr.attr,
+ NULL,
+};
- drvdata->kobj = kobject_create_and_add("etb", qdss_get_modulekobj());
- if (!drvdata->kobj) {
- dev_err(drvdata->dev, "failed to create ETB sysfs kobject\n");
- ret = -ENOMEM;
- goto err_create;
- }
+static struct attribute_group etb_attr_grp = {
+ .attrs = etb_attrs,
+};
- ret = sysfs_create_file(drvdata->kobj, &dev_attr_trigger_cntr.attr);
- if (ret) {
- dev_err(drvdata->dev, "failed to create ETB sysfs trigger_cntr"
- " attribute\n");
- goto err_file;
- }
-
- return 0;
-err_file:
- kobject_put(drvdata->kobj);
-err_create:
- return ret;
-}
-
-static void __devexit etb_sysfs_exit(void)
-{
- sysfs_remove_file(drvdata->kobj, &dev_attr_trigger_cntr.attr);
- kobject_put(drvdata->kobj);
-}
+static const struct attribute_group *etb_attr_grps[] = {
+ &etb_attr_grp,
+ NULL,
+};
static int __devinit etb_probe(struct platform_device *pdev)
{
int ret;
+ struct device *dev = &pdev->dev;
+ struct coresight_platform_data *pdata;
+ struct etb_drvdata *drvdata;
struct resource *res;
+ struct coresight_desc *desc;
- drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
- if (!drvdata) {
- ret = -ENOMEM;
- goto err_kzalloc_drvdata;
+ if (pdev->dev.of_node) {
+ pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ pdev->dev.platform_data = pdata;
}
+ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+ drvdata->dev = &pdev->dev;
+ platform_set_drvdata(pdev, drvdata);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- ret = -EINVAL;
- goto err_res;
- }
+ if (!res)
+ return -ENODEV;
- drvdata->base = ioremap_nocache(res->start, resource_size(res));
- if (!drvdata->base) {
- ret = -EINVAL;
- goto err_ioremap;
- }
-
- drvdata->dev = &pdev->dev;
+ drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!drvdata->base)
+ return -ENOMEM;
spin_lock_init(&drvdata->spinlock);
- drvdata->clk = clk_get(drvdata->dev, "core_clk");
- if (IS_ERR(drvdata->clk)) {
- ret = PTR_ERR(drvdata->clk);
- goto err_clk_get;
- }
+ drvdata->clk = devm_clk_get(dev, "core_clk");
+ if (IS_ERR(drvdata->clk))
+ return PTR_ERR(drvdata->clk);
ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
if (ret)
- goto err_clk_rate;
+ return ret;
- ret = misc_register(&etb_misc);
+ drvdata->buf = devm_kzalloc(dev, ETB_SIZE_WORDS * BYTES_PER_WORD,
+ GFP_KERNEL);
+ if (!drvdata->buf)
+ return -ENOMEM;
+
+ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+ desc->type = CORESIGHT_DEV_TYPE_SINK;
+ desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
+ desc->ops = &etb_cs_ops;
+ desc->pdata = pdev->dev.platform_data;
+ desc->dev = &pdev->dev;
+ desc->groups = etb_attr_grps;
+ desc->owner = THIS_MODULE;
+ drvdata->csdev = coresight_register(desc);
+ if (IS_ERR(drvdata->csdev))
+ return PTR_ERR(drvdata->csdev);
+
+ drvdata->miscdev.name = ((struct coresight_platform_data *)
+ (pdev->dev.platform_data))->name;
+ drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
+ drvdata->miscdev.fops = &etb_fops;
+ ret = misc_register(&drvdata->miscdev);
if (ret)
- goto err_misc;
+ goto err;
- drvdata->buf = kzalloc(ETB_SIZE_WORDS * BYTES_PER_WORD, GFP_KERNEL);
- if (!drvdata->buf) {
- ret = -ENOMEM;
- goto err_alloc;
- }
-
- etb_sysfs_init();
-
- dev_info(drvdata->dev, "ETB initialized\n");
+ dev_info(dev, "ETB initialized\n");
return 0;
-
-err_alloc:
- misc_deregister(&etb_misc);
-err_misc:
-err_clk_rate:
- clk_put(drvdata->clk);
-err_clk_get:
- iounmap(drvdata->base);
-err_ioremap:
-err_res:
- kfree(drvdata);
-err_kzalloc_drvdata:
- dev_err(drvdata->dev, "ETB init failed\n");
+err:
+ coresight_unregister(drvdata->csdev);
return ret;
}
static int __devexit etb_remove(struct platform_device *pdev)
{
- if (drvdata->enabled)
- etb_disable();
- etb_sysfs_exit();
- kfree(drvdata->buf);
- misc_deregister(&etb_misc);
- clk_put(drvdata->clk);
- iounmap(drvdata->base);
- kfree(drvdata);
+ struct etb_drvdata *drvdata = platform_get_drvdata(pdev);
+ misc_deregister(&drvdata->miscdev);
+ coresight_unregister(drvdata->csdev);
return 0;
}
static struct of_device_id etb_match[] = {
- {.compatible = "qcom,msm-etb"},
+ {.compatible = "arm,coresight-etb"},
{}
};
@@ -429,7 +443,7 @@
.probe = etb_probe,
.remove = __devexit_p(etb_remove),
.driver = {
- .name = "msm_etb",
+ .name = "coresight-etb",
.owner = THIS_MODULE,
.of_match_table = etb_match,
},
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index b3d2a16..e805c7f 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -26,17 +26,30 @@
#include <linux/pm_qos.h>
#include <linux/sysfs.h>
#include <linux/stat.h>
+#include <linux/mutex.h>
#include <linux/clk.h>
+#include <linux/of_coresight.h>
#include <linux/coresight.h>
#include <asm/sections.h>
#include <mach/socinfo.h>
#include "coresight-priv.h"
-#define etm_writel(drvdata, cpu, val, off) \
- __raw_writel((val), drvdata->base + (SZ_4K * cpu) + off)
-#define etm_readl(drvdata, cpu, off) \
- __raw_readl(drvdata->base + (SZ_4K * cpu) + off)
+#define etm_writel(drvdata, val, off) \
+ __raw_writel((val), drvdata->base + off)
+#define etm_readl(drvdata, off) \
+ __raw_readl(drvdata->base + off)
+
+#define ETM_LOCK(drvdata) \
+do { \
+ mb(); \
+ etm_writel(drvdata, 0x0, CORESIGHT_LAR); \
+} while (0)
+#define ETM_UNLOCK(drvdata) \
+do { \
+ etm_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
+ mb(); \
+} while (0)
/*
* Device registers:
@@ -119,7 +132,7 @@
#define ETM_SEQ_STATE_MAX_VAL (0x2)
-enum {
+enum etm_addr_type {
ETM_ADDR_TYPE_NONE,
ETM_ADDR_TYPE_SINGLE,
ETM_ADDR_TYPE_RANGE,
@@ -127,42 +140,24 @@
ETM_ADDR_TYPE_STOP,
};
-#define ETM_LOCK(cpu) \
-do { \
- mb(); \
- etm_writel(drvdata, cpu, 0x0, CORESIGHT_LAR); \
-} while (0)
-#define ETM_UNLOCK(cpu) \
-do { \
- etm_writel(drvdata, cpu, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
- mb(); \
-} while (0)
-
-
-#ifdef MODULE_PARAM_PREFIX
-#undef MODULE_PARAM_PREFIX
-#endif
-#define MODULE_PARAM_PREFIX "coresight."
-
#ifdef CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE
-static int etm_boot_enable = 1;
+static int boot_enable = 1;
#else
-static int etm_boot_enable;
+static int boot_enable;
#endif
module_param_named(
- etm_boot_enable, etm_boot_enable, int, S_IRUGO
+ boot_enable, boot_enable, int, S_IRUGO
);
struct etm_drvdata {
void __iomem *base;
- bool enabled;
+ struct device *dev;
+ struct coresight_device *csdev;
+ struct clk *clk;
+ struct mutex mutex;
struct wake_lock wake_lock;
struct pm_qos_request qos_req;
- struct qdss_source *src;
- struct mutex mutex;
- struct device *dev;
- struct kobject *kobj;
- struct clk *clk;
+ int cpu;
uint8_t arch;
uint8_t nr_addr_cmp;
uint8_t nr_cntr;
@@ -200,9 +195,6 @@
uint32_t timestamp_event;
};
-static struct etm_drvdata *drvdata;
-
-
/* ETM clock is derived from the processor clock and gets enabled on a
* logical OR of below items on Krait (pass2 onwards):
* 1.CPMR[ETMCLKEN] is 1
@@ -218,115 +210,107 @@
* clock vote in the driver and the save-restore code uses 1. above
* for its vote
*/
-static void etm_set_pwrdwn(int cpu)
+static void etm_set_pwrdwn(struct etm_drvdata *drvdata)
{
uint32_t etmcr;
- etmcr = etm_readl(drvdata, cpu, ETMCR);
+ etmcr = etm_readl(drvdata, ETMCR);
etmcr |= BIT(0);
- etm_writel(drvdata, cpu, etmcr, ETMCR);
+ etm_writel(drvdata, etmcr, ETMCR);
}
-static void etm_clr_pwrdwn(int cpu)
+static void etm_clr_pwrdwn(struct etm_drvdata *drvdata)
{
uint32_t etmcr;
- etmcr = etm_readl(drvdata, cpu, ETMCR);
+ etmcr = etm_readl(drvdata, ETMCR);
etmcr &= ~BIT(0);
- etm_writel(drvdata, cpu, etmcr, ETMCR);
+ etm_writel(drvdata, etmcr, ETMCR);
}
-static void etm_set_prog(int cpu)
+static void etm_set_prog(struct etm_drvdata *drvdata)
{
uint32_t etmcr;
int count;
- etmcr = etm_readl(drvdata, cpu, ETMCR);
+ etmcr = etm_readl(drvdata, ETMCR);
etmcr |= BIT(10);
- etm_writel(drvdata, cpu, etmcr, ETMCR);
-
- for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, cpu, ETMSR), 1) != 1
+ etm_writel(drvdata, etmcr, ETMCR);
+ for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 1
&& count > 0; count--)
udelay(1);
WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
- etm_readl(drvdata, cpu, ETMSR));
+ etm_readl(drvdata, ETMSR));
}
-static void etm_clr_prog(int cpu)
+static void etm_clr_prog(struct etm_drvdata *drvdata)
{
uint32_t etmcr;
int count;
- etmcr = etm_readl(drvdata, cpu, ETMCR);
+ etmcr = etm_readl(drvdata, ETMCR);
etmcr &= ~BIT(10);
- etm_writel(drvdata, cpu, etmcr, ETMCR);
-
- for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, cpu, ETMSR), 1) != 0
+ etm_writel(drvdata, etmcr, ETMCR);
+ for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 0
&& count > 0; count--)
udelay(1);
WARN(count == 0, "timeout while clearing prog bit, ETMSR: %#x\n",
- etm_readl(drvdata, cpu, ETMSR));
+ etm_readl(drvdata, ETMSR));
}
-static void __etm_enable(int cpu)
+static void __etm_enable(struct etm_drvdata *drvdata)
{
int i;
- ETM_UNLOCK(cpu);
+ ETM_UNLOCK(drvdata);
/* Vote for ETM power/clock enable */
- etm_clr_pwrdwn(cpu);
- etm_set_prog(cpu);
+ etm_clr_pwrdwn(drvdata);
+ etm_set_prog(drvdata);
- etm_writel(drvdata, cpu, drvdata->ctrl | BIT(10), ETMCR);
- etm_writel(drvdata, cpu, drvdata->trigger_event, ETMTRIGGER);
- etm_writel(drvdata, cpu, drvdata->startstop_ctrl, ETMTSSCR);
- etm_writel(drvdata, cpu, drvdata->enable_event, ETMTEEVR);
- etm_writel(drvdata, cpu, drvdata->enable_ctrl1, ETMTECR1);
- etm_writel(drvdata, cpu, drvdata->fifofull_level, ETMFFLR);
+ etm_writel(drvdata, drvdata->ctrl | BIT(10), ETMCR);
+ etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER);
+ etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR);
+ etm_writel(drvdata, drvdata->enable_event, ETMTEEVR);
+ etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1);
+ etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR);
for (i = 0; i < drvdata->nr_addr_cmp; i++) {
- etm_writel(drvdata, cpu, drvdata->addr_val[i], ETMACVRn(i));
- etm_writel(drvdata, cpu, drvdata->addr_acctype[i], ETMACTRn(i));
+ etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i));
+ etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i));
}
for (i = 0; i < drvdata->nr_cntr; i++) {
- etm_writel(drvdata, cpu, drvdata->cntr_rld_val[i],
- ETMCNTRLDVRn(i));
- etm_writel(drvdata, cpu, drvdata->cntr_event[i], ETMCNTENRn(i));
- etm_writel(drvdata, cpu, drvdata->cntr_rld_event[i],
+ etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i));
+ etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i));
+ etm_writel(drvdata, drvdata->cntr_rld_event[i],
ETMCNTRLDEVRn(i));
- etm_writel(drvdata, cpu, drvdata->cntr_val[i], ETMCNTVRn(i));
+ etm_writel(drvdata, drvdata->cntr_val[i], ETMCNTVRn(i));
}
- etm_writel(drvdata, cpu, drvdata->seq_12_event, ETMSQ12EVR);
- etm_writel(drvdata, cpu, drvdata->seq_21_event, ETMSQ21EVR);
- etm_writel(drvdata, cpu, drvdata->seq_23_event, ETMSQ23EVR);
- etm_writel(drvdata, cpu, drvdata->seq_31_event, ETMSQ31EVR);
- etm_writel(drvdata, cpu, drvdata->seq_32_event, ETMSQ32EVR);
- etm_writel(drvdata, cpu, drvdata->seq_13_event, ETMSQ13EVR);
- etm_writel(drvdata, cpu, drvdata->seq_curr_state, ETMSQR);
+ etm_writel(drvdata, drvdata->seq_12_event, ETMSQ12EVR);
+ etm_writel(drvdata, drvdata->seq_21_event, ETMSQ21EVR);
+ etm_writel(drvdata, drvdata->seq_23_event, ETMSQ23EVR);
+ etm_writel(drvdata, drvdata->seq_31_event, ETMSQ31EVR);
+ etm_writel(drvdata, drvdata->seq_32_event, ETMSQ32EVR);
+ etm_writel(drvdata, drvdata->seq_13_event, ETMSQ13EVR);
+ etm_writel(drvdata, drvdata->seq_curr_state, ETMSQR);
for (i = 0; i < drvdata->nr_ext_out; i++)
- etm_writel(drvdata, cpu, 0x0000406F, ETMEXTOUTEVRn(i));
+ etm_writel(drvdata, 0x0000406F, ETMEXTOUTEVRn(i));
for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
- etm_writel(drvdata, cpu, drvdata->ctxid_val[i], ETMCIDCVRn(i));
- etm_writel(drvdata, cpu, drvdata->ctxid_mask, ETMCIDCMR);
- etm_writel(drvdata, cpu, drvdata->sync_freq, ETMSYNCFR);
- etm_writel(drvdata, cpu, 0x00000000, ETMEXTINSELR);
- etm_writel(drvdata, cpu, drvdata->timestamp_event, ETMTSEVR);
- etm_writel(drvdata, cpu, 0x00000000, ETMAUXCR);
- etm_writel(drvdata, cpu, cpu+1, ETMTRACEIDR);
- etm_writel(drvdata, cpu, 0x00000000, ETMVMIDCVR);
+ etm_writel(drvdata, drvdata->ctxid_val[i], ETMCIDCVRn(i));
+ etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR);
+ etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR);
+ etm_writel(drvdata, 0x00000000, ETMEXTINSELR);
+ etm_writel(drvdata, drvdata->timestamp_event, ETMTSEVR);
+ etm_writel(drvdata, 0x00000000, ETMAUXCR);
+ etm_writel(drvdata, drvdata->cpu + 1, ETMTRACEIDR);
+ etm_writel(drvdata, 0x00000000, ETMVMIDCVR);
- etm_clr_prog(cpu);
- ETM_LOCK(cpu);
+ etm_clr_prog(drvdata);
+ ETM_LOCK(drvdata);
}
-static int etm_enable(void)
+static int etm_enable(struct coresight_device *csdev)
{
- int ret, cpu;
-
- if (drvdata->enabled) {
- dev_err(drvdata->dev, "ETM tracing already enabled\n");
- ret = -EPERM;
- goto err;
- }
+ struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+ int ret;
wake_lock(&drvdata->wake_lock);
/* 1. causes all online cpus to come out of idle PC
@@ -342,52 +326,37 @@
if (ret)
goto err_clk;
- ret = qdss_enable(drvdata->src);
- if (ret)
- goto err_qdss;
-
- for_each_online_cpu(cpu)
- __etm_enable(cpu);
-
- drvdata->enabled = true;
+ mutex_lock(&drvdata->mutex);
+ __etm_enable(drvdata);
+ mutex_unlock(&drvdata->mutex);
pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
wake_unlock(&drvdata->wake_lock);
dev_info(drvdata->dev, "ETM tracing enabled\n");
return 0;
-
-err_qdss:
- clk_disable_unprepare(drvdata->clk);
err_clk:
pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
wake_unlock(&drvdata->wake_lock);
-err:
return ret;
}
-static void __etm_disable(int cpu)
+static void __etm_disable(struct etm_drvdata *drvdata)
{
- ETM_UNLOCK(cpu);
- etm_set_prog(cpu);
+ ETM_UNLOCK(drvdata);
+ etm_set_prog(drvdata);
/* program trace enable to low by using always false event */
- etm_writel(drvdata, cpu, 0x6F | BIT(14), ETMTEEVR);
+ etm_writel(drvdata, 0x6F | BIT(14), ETMTEEVR);
/* Vote for ETM power/clock disable */
- etm_set_pwrdwn(cpu);
- ETM_LOCK(cpu);
+ etm_set_pwrdwn(drvdata);
+ ETM_LOCK(drvdata);
}
-static int etm_disable(void)
+static void etm_disable(struct coresight_device *csdev)
{
- int ret, cpu;
-
- if (!drvdata->enabled) {
- dev_err(drvdata->dev, "ETM tracing already disabled\n");
- ret = -EPERM;
- goto err;
- }
+ struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
wake_lock(&drvdata->wake_lock);
/* 1. causes all online cpus to come out of idle PC
@@ -399,12 +368,9 @@
*/
pm_qos_update_request(&drvdata->qos_req, 0);
- for_each_online_cpu(cpu)
- __etm_disable(cpu);
-
- drvdata->enabled = false;
-
- qdss_disable(drvdata->src);
+ mutex_lock(&drvdata->mutex);
+ __etm_disable(drvdata);
+ mutex_unlock(&drvdata->mutex);
clk_disable_unprepare(drvdata->clk);
@@ -412,55 +378,23 @@
wake_unlock(&drvdata->wake_lock);
dev_info(drvdata->dev, "ETM tracing disabled\n");
- return 0;
-err:
- return ret;
}
-/* Memory mapped writes to clear os lock not supported */
-static void etm_os_unlock(void *unused)
-{
- unsigned long value = 0x0;
+static const struct coresight_ops_source etm_source_ops = {
+ .enable = etm_enable,
+ .disable = etm_disable,
+};
- asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
- asm("isb\n\t");
-}
-
-static ssize_t etm_show_enabled(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- unsigned long val = drvdata->enabled;
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t etm_store_enabled(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t size)
-{
- int ret = 0;
- unsigned long val;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
-
- mutex_lock(&drvdata->mutex);
- if (val)
- ret = etm_enable();
- else
- ret = etm_disable();
- mutex_unlock(&drvdata->mutex);
-
- if (ret)
- return ret;
- return size;
-}
-static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, etm_show_enabled,
- etm_store_enabled);
+static const struct coresight_ops etm_cs_ops = {
+ .source_ops = &etm_source_ops,
+};
static ssize_t etm_show_nr_addr_cmp(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->nr_addr_cmp;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
static DEVICE_ATTR(nr_addr_cmp, S_IRUGO, etm_show_nr_addr_cmp, NULL);
@@ -468,7 +402,9 @@
static ssize_t etm_show_nr_cntr(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->nr_cntr;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
static DEVICE_ATTR(nr_cntr, S_IRUGO, etm_show_nr_cntr, NULL);
@@ -476,7 +412,9 @@
static ssize_t etm_show_nr_ctxid_cmp(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->nr_ctxid_cmp;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
static DEVICE_ATTR(nr_ctxid_cmp, S_IRUGO, etm_show_nr_ctxid_cmp, NULL);
@@ -484,7 +422,9 @@
static ssize_t etm_show_reset(struct device *dev, struct device_attribute *attr,
char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->reset;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -493,6 +433,7 @@
struct device_attribute *attr, const char *buf,
size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
int i;
unsigned long val;
@@ -536,7 +477,11 @@
for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
drvdata->ctxid_val[i] = 0x0;
drvdata->ctxid_mask = 0x0;
- drvdata->sync_freq = 0x80;
+ /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
+ if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
+ drvdata->sync_freq = 0x100;
+ else
+ drvdata->sync_freq = 0x80;
drvdata->timestamp_event = 0x406F;
}
mutex_unlock(&drvdata->mutex);
@@ -547,13 +492,16 @@
static ssize_t etm_show_mode(struct device *dev, struct device_attribute *attr,
char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->mode;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
static ssize_t etm_store_mode(struct device *dev, struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -581,6 +529,7 @@
drvdata->ctrl |= BIT(28);
else
drvdata->ctrl &= ~BIT(28);
+
if (drvdata->mode & ETM_MODE_CTXID)
drvdata->ctrl |= (BIT(14) | BIT(15));
else
@@ -594,7 +543,9 @@
static ssize_t etm_show_trigger_event(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->trigger_event;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -602,6 +553,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -616,7 +568,9 @@
static ssize_t etm_show_enable_event(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->enable_event;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -624,6 +578,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -638,7 +593,9 @@
static ssize_t etm_show_fifofull_level(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->fifofull_level;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -646,6 +603,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -660,7 +618,9 @@
static ssize_t etm_show_addr_idx(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->addr_idx;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -668,6 +628,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -689,6 +650,7 @@
static ssize_t etm_show_addr_single(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
uint8_t idx;
@@ -709,6 +671,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
uint8_t idx;
@@ -734,6 +697,7 @@
static ssize_t etm_show_addr_range(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val1, val2;
uint8_t idx;
@@ -761,6 +725,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val1, val2;
uint8_t idx;
@@ -798,6 +763,7 @@
static ssize_t etm_show_addr_start(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
uint8_t idx;
@@ -818,6 +784,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
uint8_t idx;
@@ -845,6 +812,7 @@
static ssize_t etm_show_addr_stop(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
uint8_t idx;
@@ -865,6 +833,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
uint8_t idx;
@@ -892,6 +861,7 @@
static ssize_t etm_show_addr_acctype(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
mutex_lock(&drvdata->mutex);
@@ -904,6 +874,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -920,7 +891,9 @@
static ssize_t etm_show_cntr_idx(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->addr_idx;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -928,6 +901,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -949,7 +923,9 @@
static ssize_t etm_show_cntr_rld_val(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
+
mutex_lock(&drvdata->mutex);
val = drvdata->cntr_rld_val[drvdata->cntr_idx];
mutex_unlock(&drvdata->mutex);
@@ -960,6 +936,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -976,6 +953,7 @@
static ssize_t etm_show_cntr_event(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
mutex_lock(&drvdata->mutex);
@@ -988,6 +966,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -1004,6 +983,7 @@
static ssize_t etm_show_cntr_rld_event(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
mutex_lock(&drvdata->mutex);
@@ -1016,6 +996,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -1032,6 +1013,7 @@
static ssize_t etm_show_cntr_val(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
mutex_lock(&drvdata->mutex);
@@ -1044,6 +1026,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -1060,7 +1043,9 @@
static ssize_t etm_show_seq_12_event(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->seq_12_event;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1068,6 +1053,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -1082,7 +1068,9 @@
static ssize_t etm_show_seq_21_event(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->seq_21_event;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1090,6 +1078,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -1104,7 +1093,9 @@
static ssize_t etm_show_seq_23_event(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->seq_23_event;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1112,6 +1103,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -1126,7 +1118,9 @@
static ssize_t etm_show_seq_31_event(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->seq_31_event;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1134,6 +1128,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -1148,7 +1143,9 @@
static ssize_t etm_show_seq_32_event(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->seq_32_event;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1156,6 +1153,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -1170,7 +1168,9 @@
static ssize_t etm_show_seq_13_event(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->seq_13_event;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1178,6 +1178,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -1192,7 +1193,9 @@
static ssize_t etm_show_seq_curr_state(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->seq_curr_state;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1200,6 +1203,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -1216,7 +1220,9 @@
static ssize_t etm_show_ctxid_idx(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->ctxid_idx;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1224,6 +1230,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -1245,6 +1252,7 @@
static ssize_t etm_show_ctxid_val(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
mutex_lock(&drvdata->mutex);
@@ -1257,6 +1265,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -1273,7 +1282,9 @@
static ssize_t etm_show_ctxid_mask(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->ctxid_mask;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1281,6 +1292,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -1295,6 +1307,7 @@
static ssize_t etm_show_sync_freq(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->sync_freq;
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1303,6 +1316,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -1318,7 +1332,9 @@
struct device_attribute *attr,
char *buf)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->timestamp_event;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -1326,6 +1342,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -1376,39 +1393,18 @@
.attrs = etm_attrs,
};
-static int __devinit etm_sysfs_init(void)
+static const struct attribute_group *etm_attr_grps[] = {
+ &etm_attr_grp,
+ NULL,
+};
+
+/* Memory mapped writes to clear os lock not supported */
+static void etm_os_unlock(void *unused)
{
- int ret;
+ unsigned long value = 0x0;
- drvdata->kobj = kobject_create_and_add("etm", qdss_get_modulekobj());
- if (!drvdata->kobj) {
- dev_err(drvdata->dev, "failed to create ETM sysfs kobject\n");
- ret = -ENOMEM;
- goto err_create;
- }
-
- ret = sysfs_create_file(drvdata->kobj, &dev_attr_enabled.attr);
- if (ret) {
- dev_err(drvdata->dev, "failed to create ETM sysfs enabled"
- " attribute\n");
- goto err_file;
- }
-
- if (sysfs_create_group(drvdata->kobj, &etm_attr_grp))
- dev_err(drvdata->dev, "failed to create ETM sysfs group\n");
-
- return 0;
-err_file:
- kobject_put(drvdata->kobj);
-err_create:
- return ret;
-}
-
-static void __devexit etm_sysfs_exit(void)
-{
- sysfs_remove_group(drvdata->kobj, &etm_attr_grp);
- sysfs_remove_file(drvdata->kobj, &dev_attr_enabled.attr);
- kobject_put(drvdata->kobj);
+ asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
+ asm("isb\n\t");
}
static bool __devinit etm_arch_supported(uint8_t arch)
@@ -1422,34 +1418,32 @@
return true;
}
-static int __devinit etm_init_arch_data(void)
+static int __devinit etm_init_arch_data(struct etm_drvdata *drvdata)
{
int ret;
- /* use cpu 0 for setup */
- int cpu = 0;
uint32_t etmidr;
uint32_t etmccr;
/* Unlock OS lock first to allow memory mapped reads and writes */
etm_os_unlock(NULL);
smp_call_function(etm_os_unlock, NULL, 1);
- ETM_UNLOCK(cpu);
+ ETM_UNLOCK(drvdata);
/* Vote for ETM power/clock enable */
- etm_clr_pwrdwn(cpu);
+ etm_clr_pwrdwn(drvdata);
/* Set prog bit. It will be set from reset but this is included to
* ensure it is set
*/
- etm_set_prog(cpu);
+ etm_set_prog(drvdata);
/* find all capabilities */
- etmidr = etm_readl(drvdata, cpu, ETMIDR);
+ etmidr = etm_readl(drvdata, ETMIDR);
drvdata->arch = BMVAL(etmidr, 4, 11);
if (etm_arch_supported(drvdata->arch) == false) {
ret = -EINVAL;
goto err;
}
- etmccr = etm_readl(drvdata, cpu, ETMCCR);
+ etmccr = etm_readl(drvdata, ETMCCR);
drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
@@ -1457,15 +1451,15 @@
drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
/* Vote for ETM power/clock disable */
- etm_set_pwrdwn(cpu);
- ETM_LOCK(cpu);
+ etm_set_pwrdwn(drvdata);
+ ETM_LOCK(drvdata);
return 0;
err:
return ret;
}
-static void __devinit etm_init_default_data(void)
+static void __devinit etm_init_default_data(struct etm_drvdata *drvdata)
{
int i;
@@ -1489,7 +1483,11 @@
drvdata->seq_31_event = 0x406F;
drvdata->seq_32_event = 0x406F;
drvdata->seq_13_event = 0x406F;
- drvdata->sync_freq = 0x80;
+ /* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
+ if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
+ drvdata->sync_freq = 0x100;
+ else
+ drvdata->sync_freq = 0x80;
drvdata->timestamp_event = 0x406F;
/* Overrides for Krait pass1 */
@@ -1511,112 +1509,108 @@
static int __devinit etm_probe(struct platform_device *pdev)
{
int ret;
+ struct device *dev = &pdev->dev;
+ struct coresight_platform_data *pdata;
+ struct etm_drvdata *drvdata;
struct resource *res;
+ static int etm_count;
+ struct coresight_desc *desc;
- drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
- if (!drvdata) {
- ret = -ENOMEM;
- goto err_kzalloc_drvdata;
+ if (pdev->dev.of_node) {
+ pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ pdev->dev.platform_data = pdata;
}
+ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+ drvdata->dev = &pdev->dev;
+ platform_set_drvdata(pdev, drvdata);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- ret = -EINVAL;
- goto err_res;
- }
+ if (!res)
+ return -ENODEV;
- drvdata->base = ioremap_nocache(res->start, resource_size(res));
- if (!drvdata->base) {
- ret = -EINVAL;
- goto err_ioremap;
- }
-
- drvdata->dev = &pdev->dev;
+ drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!drvdata->base)
+ return -ENOMEM;
mutex_init(&drvdata->mutex);
- wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "msm_etm");
+ wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "coresight-etm");
pm_qos_add_request(&drvdata->qos_req, PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
- drvdata->src = qdss_get("msm_etm");
- if (IS_ERR(drvdata->src)) {
- ret = PTR_ERR(drvdata->src);
- goto err_qdssget;
- }
- drvdata->clk = clk_get(drvdata->dev, "core_clk");
+ drvdata->clk = devm_clk_get(dev, "core_clk");
if (IS_ERR(drvdata->clk)) {
ret = PTR_ERR(drvdata->clk);
- goto err_clk_get;
+ goto err0;
}
ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
if (ret)
- goto err_clk_rate;
+ goto err0;
+
+ drvdata->cpu = etm_count++;
ret = clk_prepare_enable(drvdata->clk);
if (ret)
- goto err_clk_enable;
+ goto err0;
- ret = etm_init_arch_data();
+ ret = etm_init_arch_data(drvdata);
if (ret)
- goto err_arch;
-
- etm_init_default_data();
-
- ret = etm_sysfs_init();
- if (ret)
- goto err_sysfs;
-
- drvdata->enabled = false;
+ goto err1;
+ etm_init_default_data(drvdata);
clk_disable_unprepare(drvdata->clk);
- dev_info(drvdata->dev, "ETM initialized\n");
+ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+ if (!desc) {
+ ret = -ENOMEM;
+ goto err0;
+ }
+ desc->type = CORESIGHT_DEV_TYPE_SOURCE;
+ desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
+ desc->ops = &etm_cs_ops;
+ desc->pdata = pdev->dev.platform_data;
+ desc->dev = &pdev->dev;
+ desc->groups = etm_attr_grps;
+ desc->owner = THIS_MODULE;
+ drvdata->csdev = coresight_register(desc);
+ if (IS_ERR(drvdata->csdev)) {
+ ret = PTR_ERR(drvdata->csdev);
+ goto err0;
+ }
- if (etm_boot_enable)
- etm_enable();
+ dev_info(dev, "ETM initialized\n");
+
+ if (boot_enable)
+ coresight_enable(drvdata->csdev);
return 0;
-
-err_sysfs:
-err_arch:
+err1:
clk_disable_unprepare(drvdata->clk);
-err_clk_enable:
-err_clk_rate:
- clk_put(drvdata->clk);
-err_clk_get:
- qdss_put(drvdata->src);
-err_qdssget:
+err0:
pm_qos_remove_request(&drvdata->qos_req);
wake_lock_destroy(&drvdata->wake_lock);
mutex_destroy(&drvdata->mutex);
- iounmap(drvdata->base);
-err_ioremap:
-err_res:
- kfree(drvdata);
-err_kzalloc_drvdata:
- dev_err(drvdata->dev, "ETM init failed\n");
return ret;
}
static int __devexit etm_remove(struct platform_device *pdev)
{
- if (drvdata->enabled)
- etm_disable();
- etm_sysfs_exit();
- clk_put(drvdata->clk);
- qdss_put(drvdata->src);
+ struct etm_drvdata *drvdata = platform_get_drvdata(pdev);
+
+ coresight_unregister(drvdata->csdev);
pm_qos_remove_request(&drvdata->qos_req);
wake_lock_destroy(&drvdata->wake_lock);
mutex_destroy(&drvdata->mutex);
- iounmap(drvdata->base);
- kfree(drvdata);
-
return 0;
}
static struct of_device_id etm_match[] = {
- {.compatible = "qcom,msm-etm"},
+ {.compatible = "arm,coresight-etm"},
{}
};
@@ -1624,7 +1618,7 @@
.probe = etm_probe,
.remove = __devexit_p(etm_remove),
.driver = {
- .name = "msm_etm",
+ .name = "coresight-etm",
.owner = THIS_MODULE,
.of_match_table = etm_match,
},
diff --git a/drivers/coresight/coresight-funnel.c b/drivers/coresight/coresight-funnel.c
index 79a27f4..3d5c0c2 100644
--- a/drivers/coresight/coresight-funnel.c
+++ b/drivers/coresight/coresight-funnel.c
@@ -20,113 +20,118 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/clk.h>
+#include <linux/of_coresight.h>
#include <linux/coresight.h>
#include "coresight-priv.h"
-#define funnel_writel(drvdata, id, val, off) \
- __raw_writel((val), drvdata->base + (SZ_4K * id) + off)
-#define funnel_readl(drvdata, id, off) \
- __raw_readl(drvdata->base + (SZ_4K * id) + off)
+#define funnel_writel(drvdata, val, off) \
+ __raw_writel((val), drvdata->base + off)
+#define funnel_readl(drvdata, off) \
+ __raw_readl(drvdata->base + off)
-#define FUNNEL_FUNCTL (0x000)
-#define FUNNEL_PRICTL (0x004)
-#define FUNNEL_ITATBDATA0 (0xEEC)
-#define FUNNEL_ITATBCTR2 (0xEF0)
-#define FUNNEL_ITATBCTR1 (0xEF4)
-#define FUNNEL_ITATBCTR0 (0xEF8)
-
-
-#define FUNNEL_LOCK(id) \
+#define FUNNEL_LOCK(drvdata) \
do { \
mb(); \
- funnel_writel(drvdata, id, 0x0, CORESIGHT_LAR); \
+ funnel_writel(drvdata, 0x0, CORESIGHT_LAR); \
} while (0)
-#define FUNNEL_UNLOCK(id) \
+#define FUNNEL_UNLOCK(drvdata) \
do { \
- funnel_writel(drvdata, id, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
+ funnel_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
mb(); \
} while (0)
-#define FUNNEL_HOLDTIME_MASK (0xF00)
-#define FUNNEL_HOLDTIME_SHFT (0x8)
-#define FUNNEL_HOLDTIME (0x7 << FUNNEL_HOLDTIME_SHFT)
+#define FUNNEL_FUNCTL (0x000)
+#define FUNNEL_PRICTL (0x004)
+#define FUNNEL_ITATBDATA0 (0xEEC)
+#define FUNNEL_ITATBCTR2 (0xEF0)
+#define FUNNEL_ITATBCTR1 (0xEF4)
+#define FUNNEL_ITATBCTR0 (0xEF8)
+
+#define FUNNEL_HOLDTIME_MASK (0xF00)
+#define FUNNEL_HOLDTIME_SHFT (0x8)
+#define FUNNEL_HOLDTIME (0x7 << FUNNEL_HOLDTIME_SHFT)
struct funnel_drvdata {
- void __iomem *base;
- bool enabled;
- struct mutex mutex;
- struct device *dev;
- struct kobject *kobj;
- struct clk *clk;
- uint32_t priority;
+ void __iomem *base;
+ struct device *dev;
+ struct coresight_device *csdev;
+ struct clk *clk;
+ uint32_t priority;
};
-static struct funnel_drvdata *drvdata;
-
-static void __funnel_enable(uint8_t id, uint32_t port_mask)
+static void __funnel_enable(struct funnel_drvdata *drvdata, int port)
{
uint32_t functl;
- FUNNEL_UNLOCK(id);
+ FUNNEL_UNLOCK(drvdata);
- functl = funnel_readl(drvdata, id, FUNNEL_FUNCTL);
+ functl = funnel_readl(drvdata, FUNNEL_FUNCTL);
functl &= ~FUNNEL_HOLDTIME_MASK;
functl |= FUNNEL_HOLDTIME;
- functl |= port_mask;
- funnel_writel(drvdata, id, functl, FUNNEL_FUNCTL);
- funnel_writel(drvdata, id, drvdata->priority, FUNNEL_PRICTL);
+ functl |= (1 << port);
+ funnel_writel(drvdata, functl, FUNNEL_FUNCTL);
+ funnel_writel(drvdata, drvdata->priority, FUNNEL_PRICTL);
- FUNNEL_LOCK(id);
+ FUNNEL_LOCK(drvdata);
}
-int funnel_enable(uint8_t id, uint32_t port_mask)
+static int funnel_enable(struct coresight_device *csdev, int inport,
+ int outport)
{
+ struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
int ret;
ret = clk_prepare_enable(drvdata->clk);
if (ret)
return ret;
- mutex_lock(&drvdata->mutex);
- __funnel_enable(id, port_mask);
- drvdata->enabled = true;
- dev_info(drvdata->dev, "FUNNEL port mask 0x%lx enabled\n",
- (unsigned long) port_mask);
- mutex_unlock(&drvdata->mutex);
+ __funnel_enable(drvdata, inport);
+ dev_info(drvdata->dev, "FUNNEL inport %d enabled\n", inport);
return 0;
}
-static void __funnel_disable(uint8_t id, uint32_t port_mask)
+static void __funnel_disable(struct funnel_drvdata *drvdata, int inport)
{
uint32_t functl;
- FUNNEL_UNLOCK(id);
+ FUNNEL_UNLOCK(drvdata);
- functl = funnel_readl(drvdata, id, FUNNEL_FUNCTL);
- functl &= ~port_mask;
- funnel_writel(drvdata, id, functl, FUNNEL_FUNCTL);
+ functl = funnel_readl(drvdata, FUNNEL_FUNCTL);
+ functl &= ~(1 << inport);
+ funnel_writel(drvdata, functl, FUNNEL_FUNCTL);
- FUNNEL_LOCK(id);
+ FUNNEL_LOCK(drvdata);
}
-void funnel_disable(uint8_t id, uint32_t port_mask)
+static void funnel_disable(struct coresight_device *csdev, int inport,
+ int outport)
{
- mutex_lock(&drvdata->mutex);
- __funnel_disable(id, port_mask);
- drvdata->enabled = false;
- dev_info(drvdata->dev, "FUNNEL port mask 0x%lx disabled\n",
- (unsigned long) port_mask);
- mutex_unlock(&drvdata->mutex);
+ struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+ __funnel_disable(drvdata, inport);
clk_disable_unprepare(drvdata->clk);
+
+ dev_info(drvdata->dev, "FUNNEL inport %d disabled\n", inport);
}
+static const struct coresight_ops_link funnel_link_ops = {
+ .enable = funnel_enable,
+ .disable = funnel_disable,
+};
+
+static const struct coresight_ops funnel_cs_ops = {
+ .link_ops = &funnel_link_ops,
+};
+
static ssize_t funnel_show_priority(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->priority;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -134,6 +139,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -145,107 +151,86 @@
static DEVICE_ATTR(priority, S_IRUGO | S_IWUSR, funnel_show_priority,
funnel_store_priority);
-static int __devinit funnel_sysfs_init(void)
-{
- int ret;
+static struct attribute *funnel_attrs[] = {
+ &dev_attr_priority.attr,
+ NULL,
+};
- drvdata->kobj = kobject_create_and_add("funnel", qdss_get_modulekobj());
- if (!drvdata->kobj) {
- dev_err(drvdata->dev, "failed to create FUNNEL sysfs kobject\n");
- ret = -ENOMEM;
- goto err_create;
- }
+static struct attribute_group funnel_attr_grp = {
+ .attrs = funnel_attrs,
+};
- ret = sysfs_create_file(drvdata->kobj, &dev_attr_priority.attr);
- if (ret) {
- dev_err(drvdata->dev, "failed to create FUNNEL sysfs priority"
- " attribute\n");
- goto err_file;
- }
-
- return 0;
-err_file:
- kobject_put(drvdata->kobj);
-err_create:
- return ret;
-}
-
-static void __devexit funnel_sysfs_exit(void)
-{
- sysfs_remove_file(drvdata->kobj, &dev_attr_priority.attr);
- kobject_put(drvdata->kobj);
-}
+static const struct attribute_group *funnel_attr_grps[] = {
+ &funnel_attr_grp,
+ NULL,
+};
static int __devinit funnel_probe(struct platform_device *pdev)
{
int ret;
+ struct device *dev = &pdev->dev;
+ struct coresight_platform_data *pdata;
+ struct funnel_drvdata *drvdata;
struct resource *res;
+ struct coresight_desc *desc;
- drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
- if (!drvdata) {
- ret = -ENOMEM;
- goto err_kzalloc_drvdata;
+ if (pdev->dev.of_node) {
+ pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ pdev->dev.platform_data = pdata;
}
+ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+ drvdata->dev = &pdev->dev;
+ platform_set_drvdata(pdev, drvdata);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- ret = -EINVAL;
- goto err_res;
- }
+ if (!res)
+ return -ENODEV;
- drvdata->base = ioremap_nocache(res->start, resource_size(res));
- if (!drvdata->base) {
- ret = -EINVAL;
- goto err_ioremap;
- }
+ drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!drvdata->base)
+ return -ENOMEM;
- drvdata->dev = &pdev->dev;
-
- mutex_init(&drvdata->mutex);
-
- drvdata->clk = clk_get(drvdata->dev, "core_clk");
- if (IS_ERR(drvdata->clk)) {
- ret = PTR_ERR(drvdata->clk);
- goto err_clk_get;
- }
+ drvdata->clk = devm_clk_get(dev, "core_clk");
+ if (IS_ERR(drvdata->clk))
+ return PTR_ERR(drvdata->clk);
ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
if (ret)
- goto err_clk_rate;
+ return ret;
- funnel_sysfs_init();
+ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+ desc->type = CORESIGHT_DEV_TYPE_LINK;
+ desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG;
+ desc->ops = &funnel_cs_ops;
+ desc->pdata = pdev->dev.platform_data;
+ desc->dev = &pdev->dev;
+ desc->groups = funnel_attr_grps;
+ desc->owner = THIS_MODULE;
+ drvdata->csdev = coresight_register(desc);
+ if (IS_ERR(drvdata->csdev))
+ return PTR_ERR(drvdata->csdev);
- dev_info(drvdata->dev, "FUNNEL initialized\n");
+ dev_info(dev, "FUNNEL initialized\n");
return 0;
-
-err_clk_rate:
- clk_put(drvdata->clk);
-err_clk_get:
- mutex_destroy(&drvdata->mutex);
- iounmap(drvdata->base);
-err_ioremap:
-err_res:
- kfree(drvdata);
-err_kzalloc_drvdata:
- dev_err(drvdata->dev, "FUNNEL init failed\n");
- return ret;
}
static int __devexit funnel_remove(struct platform_device *pdev)
{
- if (drvdata->enabled)
- funnel_disable(0x0, 0xFF);
- funnel_sysfs_exit();
- clk_put(drvdata->clk);
- mutex_destroy(&drvdata->mutex);
- iounmap(drvdata->base);
- kfree(drvdata);
+ struct funnel_drvdata *drvdata = platform_get_drvdata(pdev);
+ coresight_unregister(drvdata->csdev);
return 0;
}
static struct of_device_id funnel_match[] = {
- {.compatible = "qcom,msm-funnel"},
+ {.compatible = "arm,coresight-funnel"},
{}
};
@@ -253,7 +238,7 @@
.probe = funnel_probe,
.remove = __devexit_p(funnel_remove),
.driver = {
- .name = "msm_funnel",
+ .name = "coresight-funnel",
.owner = THIS_MODULE,
.of_match_table = funnel_match,
},
diff --git a/drivers/coresight/coresight-priv.h b/drivers/coresight/coresight-priv.h
index dab854c..a28a3a5 100644
--- a/drivers/coresight/coresight-priv.h
+++ b/drivers/coresight/coresight-priv.h
@@ -36,13 +36,4 @@
#define BMVAL(val, lsb, msb) ((val & BM(lsb, msb)) >> lsb)
#define BVAL(val, n) ((val & BIT(n)) >> n)
-int etb_enable(void);
-void etb_disable(void);
-void etb_dump(void);
-void tpiu_disable(void);
-int funnel_enable(uint8_t id, uint32_t port_mask);
-void funnel_disable(uint8_t id, uint32_t port_mask);
-
-struct kobject *qdss_get_modulekobj(void);
-
#endif
diff --git a/drivers/coresight/coresight-replicator.c b/drivers/coresight/coresight-replicator.c
new file mode 100644
index 0000000..fec76c5
--- /dev/null
+++ b/drivers/coresight/coresight-replicator.c
@@ -0,0 +1,211 @@
+/* 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/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/of_coresight.h>
+#include <linux/coresight.h>
+
+#include "coresight-priv.h"
+
+#define replicator_writel(drvdata, val, off) \
+ __raw_writel((val), drvdata->base + off)
+#define replicator_readl(drvdata, off) \
+ __raw_readl(drvdata->base + off)
+
+#define REPLICATOR_LOCK(drvdata) \
+do { \
+ mb(); \
+ replicator_writel(drvdata, 0x0, CORESIGHT_LAR); \
+} while (0)
+#define REPLICATOR_UNLOCK(drvdata) \
+do { \
+ replicator_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
+ mb(); \
+} while (0)
+
+#define REPLICATOR_IDFILTER0 (0x000)
+#define REPLICATOR_IDFILTER1 (0x004)
+#define REPLICATOR_ITATBCTR0 (0xEFC)
+#define REPLICATOR_ITATBCTR1 (0xEF8)
+
+struct replicator_drvdata {
+ void __iomem *base;
+ struct device *dev;
+ struct coresight_device *csdev;
+ struct clk *clk;
+};
+
+static void __replicator_enable(struct replicator_drvdata *drvdata, int outport)
+{
+ REPLICATOR_UNLOCK(drvdata);
+
+ if (outport == 0) {
+ replicator_writel(drvdata, 0x0, REPLICATOR_IDFILTER0);
+ replicator_writel(drvdata, 0xFF, REPLICATOR_IDFILTER1);
+ } else {
+ replicator_writel(drvdata, 0x0, REPLICATOR_IDFILTER1);
+ replicator_writel(drvdata, 0xFF, REPLICATOR_IDFILTER0);
+ }
+
+ REPLICATOR_LOCK(drvdata);
+}
+
+static int replicator_enable(struct coresight_device *csdev, int inport,
+ int outport)
+{
+ struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+ int ret;
+
+ ret = clk_prepare_enable(drvdata->clk);
+ if (ret)
+ return ret;
+
+ __replicator_enable(drvdata, outport);
+
+ dev_info(drvdata->dev, "REPLICATOR enabled\n");
+ return 0;
+}
+
+static void __replicator_disable(struct replicator_drvdata *drvdata,
+ int outport)
+{
+ REPLICATOR_UNLOCK(drvdata);
+
+ if (outport == 0)
+ replicator_writel(drvdata, 0xFF, REPLICATOR_IDFILTER0);
+ else
+ replicator_writel(drvdata, 0xFF, REPLICATOR_IDFILTER1);
+
+ REPLICATOR_LOCK(drvdata);
+}
+
+static void replicator_disable(struct coresight_device *csdev, int inport,
+ int outport)
+{
+ struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+ __replicator_disable(drvdata, outport);
+
+ clk_disable_unprepare(drvdata->clk);
+
+ dev_info(drvdata->dev, "REPLICATOR disabled\n");
+}
+
+static const struct coresight_ops_link replicator_link_ops = {
+ .enable = replicator_enable,
+ .disable = replicator_disable,
+};
+
+static const struct coresight_ops replicator_cs_ops = {
+ .link_ops = &replicator_link_ops,
+};
+
+static int __devinit replicator_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct device *dev = &pdev->dev;
+ struct coresight_platform_data *pdata;
+ struct replicator_drvdata *drvdata;
+ struct resource *res;
+ struct coresight_desc *desc;
+
+ if (pdev->dev.of_node) {
+ pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ pdev->dev.platform_data = pdata;
+ }
+
+ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+ drvdata->dev = &pdev->dev;
+ platform_set_drvdata(pdev, drvdata);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!drvdata->base)
+ return -ENOMEM;
+
+ drvdata->clk = devm_clk_get(dev, "core_clk");
+ if (IS_ERR(drvdata->clk))
+ return PTR_ERR(drvdata->clk);
+
+ ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
+ if (ret)
+ return ret;
+
+ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+ desc->type = CORESIGHT_DEV_TYPE_LINK;
+ desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT;
+ desc->ops = &replicator_cs_ops;
+ desc->pdata = pdev->dev.platform_data;
+ desc->dev = &pdev->dev;
+ desc->owner = THIS_MODULE;
+ drvdata->csdev = coresight_register(desc);
+ if (IS_ERR(drvdata->csdev))
+ return PTR_ERR(drvdata->csdev);
+
+ dev_info(dev, "REPLICATOR initialized\n");
+ return 0;
+}
+
+static int __devexit replicator_remove(struct platform_device *pdev)
+{
+ struct replicator_drvdata *drvdata = platform_get_drvdata(pdev);
+
+ coresight_unregister(drvdata->csdev);
+ return 0;
+}
+
+static struct of_device_id replicator_match[] = {
+ {.compatible = "qcom,coresight-replicator"},
+ {}
+};
+
+static struct platform_driver replicator_driver = {
+ .probe = replicator_probe,
+ .remove = __devexit_p(replicator_remove),
+ .driver = {
+ .name = "coresight-replicator",
+ .owner = THIS_MODULE,
+ .of_match_table = replicator_match,
+ },
+};
+
+static int __init replicator_init(void)
+{
+ return platform_driver_register(&replicator_driver);
+}
+module_init(replicator_init);
+
+static void __exit replicator_exit(void)
+{
+ platform_driver_unregister(&replicator_driver);
+}
+module_exit(replicator_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Replicator driver");
diff --git a/drivers/coresight/coresight-stm.c b/drivers/coresight/coresight-stm.c
index 6387947..e366918 100644
--- a/drivers/coresight/coresight-stm.c
+++ b/drivers/coresight/coresight-stm.c
@@ -22,22 +22,69 @@
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
+#include <linux/delay.h>
#include <linux/clk.h>
+#include <linux/of_coresight.h>
#include <linux/coresight.h>
#include <linux/coresight-stm.h>
#include <asm/unaligned.h>
#include "coresight-priv.h"
-#define stm_writel(drvdata, val, off) \
- __raw_writel((val), drvdata->base + off)
-#define stm_readl(drvdata, val, off) \
- __raw_readl(drvdata->base + off)
+#define stm_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
+#define stm_readl(drvdata, off) __raw_readl(drvdata->base + off)
+
+#define STM_LOCK(drvdata) \
+do { \
+ mb(); \
+ stm_writel(drvdata, 0x0, CORESIGHT_LAR); \
+} while (0)
+#define STM_UNLOCK(drvdata) \
+do { \
+ stm_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
+ mb(); \
+} while (0)
+
+#define STMDMASTARTR (0xC04)
+#define STMDMASTOPR (0xC08)
+#define STMDMASTATR (0xC0C)
+#define STMDMACTLR (0xC10)
+#define STMDMAIDR (0xCFC)
+#define STMHEER (0xD00)
+#define STMHETER (0xD20)
+#define STMHEMCR (0xD64)
+#define STMHEMASTR (0xDF4)
+#define STMHEFEAT1R (0xDF8)
+#define STMHEIDR (0xDFC)
+#define STMSPER (0xE00)
+#define STMSPTER (0xE20)
+#define STMSPSCR (0xE60)
+#define STMSPMSCR (0xE64)
+#define STMSPOVERRIDER (0xE68)
+#define STMSPMOVERRIDER (0xE6C)
+#define STMSPTRIGCSR (0xE70)
+#define STMTCSR (0xE80)
+#define STMTSSTIMR (0xE84)
+#define STMTSFREQR (0xE8C)
+#define STMSYNCR (0xE90)
+#define STMAUXCR (0xE94)
+#define STMSPFEAT1R (0xEA0)
+#define STMSPFEAT2R (0xEA4)
+#define STMSPFEAT3R (0xEA8)
+#define STMITTRIGGER (0xEE8)
+#define STMITATBDATA0 (0xEEC)
+#define STMITATBCTR2 (0xEF0)
+#define STMITATBID (0xEF4)
+#define STMITATBCTR0 (0xEF8)
#define NR_STM_CHANNEL (32)
#define BYTES_PER_CHANNEL (256)
+#define STM_TRACE_BUF_SIZE (1024)
-enum {
+#define OST_START_TOKEN (0x30)
+#define OST_VERSION (0x1)
+
+enum stm_pkt_type {
STM_PKT_TYPE_DATA = 0x98,
STM_PKT_TYPE_FLAG = 0xE8,
STM_PKT_TYPE_TRIG = 0xF8,
@@ -47,45 +94,24 @@
STM_OPTION_MARKED = 0x10,
};
-#define STM_TRACE_BUF_SIZE (1024)
-
-#define OST_START_TOKEN (0x30)
-#define OST_VERSION (0x1)
-
-#define stm_channel_addr(ch) \
- (drvdata->chs.base + (ch * BYTES_PER_CHANNEL))
+#define stm_channel_addr(drvdata, ch) (drvdata->chs.base + \
+ (ch * BYTES_PER_CHANNEL))
#define stm_channel_off(type, opts) (type & ~opts)
-#define STM_LOCK() \
-do { \
- mb(); \
- stm_writel(drvdata, 0x0, CORESIGHT_LAR); \
-} while (0)
-#define STM_UNLOCK() \
-do { \
- stm_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
- mb(); \
-} while (0)
-
-#define STMSPER (0xE00)
-#define STMSPTER (0xE20)
-#define STMTCSR (0xE80)
-#define STMSYNCR (0xE90)
-
#ifdef CONFIG_MSM_QDSS_STM_DEFAULT_ENABLE
-static int stm_boot_enable = 1;
+static int boot_enable = 1;
#else
-static int stm_boot_enable;
+static int boot_enable;
#endif
module_param_named(
- stm_boot_enable, stm_boot_enable, int, S_IRUGO
+ boot_enable, boot_enable, int, S_IRUGO
);
-static int stm_boot_nr_channel;
+static int boot_nr_channel;
module_param_named(
- stm_boot_nr_channel, stm_boot_nr_channel, int, S_IRUGO
+ boot_nr_channel, boot_nr_channel, int, S_IRUGO
);
struct channel_space {
@@ -95,99 +121,202 @@
struct stm_drvdata {
void __iomem *base;
- bool enabled;
- struct qdss_source *src;
struct device *dev;
- struct kobject *kobj;
+ struct coresight_device *csdev;
+ struct miscdevice miscdev;
struct clk *clk;
- uint32_t entity;
+ spinlock_t spinlock;
struct channel_space chs;
+ bool enable;
+ uint32_t entity;
};
-static struct stm_drvdata *drvdata;
+static struct stm_drvdata *stmdrvdata;
-static void __stm_enable(void)
+static int stm_hwevent_isenable(struct stm_drvdata *drvdata)
{
- STM_UNLOCK();
+ int ret = 0;
- stm_writel(drvdata, 0x80, STMSYNCR);
- stm_writel(drvdata, 0xFFFFFFFF, STMSPTER);
- stm_writel(drvdata, 0xFFFFFFFF, STMSPER);
- stm_writel(drvdata, 0x30003, STMTCSR);
+ spin_lock(&drvdata->spinlock);
+ if (drvdata->enable)
+ if (BVAL(stm_readl(drvdata, STMHEMCR), 0))
+ ret = stm_readl(drvdata, STMHEER) == 0 ? 0 : 1;
+ spin_unlock(&drvdata->spinlock);
- STM_LOCK();
-}
-
-static int stm_enable(void)
-{
- int ret;
-
- if (drvdata->enabled) {
- dev_err(drvdata->dev, "STM tracing already enabled\n");
- ret = -EINVAL;
- goto err;
- }
-
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- goto err_clk;
-
- ret = qdss_enable(drvdata->src);
- if (ret)
- goto err_qdss;
-
- __stm_enable();
-
- drvdata->enabled = true;
-
- dev_info(drvdata->dev, "STM tracing enabled\n");
- return 0;
-
-err_qdss:
- clk_disable_unprepare(drvdata->clk);
-err_clk:
-err:
return ret;
}
-static void __stm_disable(void)
+static void __stm_hwevent_enable(struct stm_drvdata *drvdata)
{
- STM_UNLOCK();
+ STM_UNLOCK(drvdata);
- stm_writel(drvdata, 0x30000, STMTCSR);
+ stm_writel(drvdata, 0x0, STMHETER);
+ stm_writel(drvdata, 0xFFFFFFFF, STMHEER);
+ stm_writel(drvdata, 0x5, STMHEMCR);
+
+ STM_LOCK(drvdata);
+}
+
+static int stm_hwevent_enable(struct stm_drvdata *drvdata)
+{
+ int ret = 0;
+
+ spin_lock(&drvdata->spinlock);
+ if (drvdata->enable)
+ __stm_hwevent_enable(drvdata);
+ else
+ ret = -EINVAL;
+ spin_unlock(&drvdata->spinlock);
+
+ return ret;
+}
+
+static int stm_port_isenable(struct stm_drvdata *drvdata)
+{
+ int ret = 0;
+
+ spin_lock(&drvdata->spinlock);
+ if (drvdata->enable)
+ ret = stm_readl(drvdata, STMSPER) == 0 ? 0 : 1;
+ spin_unlock(&drvdata->spinlock);
+
+ return ret;
+}
+
+static void __stm_port_enable(struct stm_drvdata *drvdata)
+{
+ STM_UNLOCK(drvdata);
+
+ stm_writel(drvdata, 0xFFFFFFFF, STMSPTER);
+ stm_writel(drvdata, 0xFFFFFFFF, STMSPER);
+
+ STM_LOCK(drvdata);
+}
+
+static int stm_port_enable(struct stm_drvdata *drvdata)
+{
+ int ret = 0;
+
+ spin_lock(&drvdata->spinlock);
+ if (drvdata->enable)
+ __stm_port_enable(drvdata);
+ else
+ ret = -EINVAL;
+ spin_unlock(&drvdata->spinlock);
+
+ return ret;
+}
+
+static void __stm_enable(struct stm_drvdata *drvdata)
+{
+ __stm_hwevent_enable(drvdata);
+ __stm_port_enable(drvdata);
+
+ STM_UNLOCK(drvdata);
+
+ stm_writel(drvdata, 0x80, STMSYNCR);
+ /* SYNCEN is read-only and HWTEN is not implemented */
+ stm_writel(drvdata, 0x30003, STMTCSR);
+
+ STM_LOCK(drvdata);
+}
+
+static int stm_enable(struct coresight_device *csdev)
+{
+ struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+ int ret;
+
+ ret = clk_prepare_enable(drvdata->clk);
+ if (ret)
+ return ret;
+
+ spin_lock(&drvdata->spinlock);
+ __stm_enable(drvdata);
+ drvdata->enable = true;
+ spin_unlock(&drvdata->spinlock);
+
+ dev_info(drvdata->dev, "STM tracing enabled\n");
+ return 0;
+}
+
+static void __stm_hwevent_disable(struct stm_drvdata *drvdata)
+{
+ STM_UNLOCK(drvdata);
+
+ stm_writel(drvdata, 0x0, STMHETER);
+ stm_writel(drvdata, 0x0, STMHEER);
+ stm_writel(drvdata, 0x0, STMHEMCR);
+
+ STM_LOCK(drvdata);
+}
+
+static void stm_hwevent_disable(struct stm_drvdata *drvdata)
+{
+ spin_lock(&drvdata->spinlock);
+ if (drvdata->enable)
+ __stm_hwevent_disable(drvdata);
+ spin_unlock(&drvdata->spinlock);
+}
+
+static void __stm_port_disable(struct stm_drvdata *drvdata)
+{
+ STM_UNLOCK(drvdata);
+
stm_writel(drvdata, 0x0, STMSPER);
stm_writel(drvdata, 0x0, STMSPTER);
- STM_LOCK();
+ STM_LOCK(drvdata);
}
-static int stm_disable(void)
+static void stm_port_disable(struct stm_drvdata *drvdata)
{
- int ret;
+ spin_lock(&drvdata->spinlock);
+ if (drvdata->enable)
+ __stm_port_disable(drvdata);
+ spin_unlock(&drvdata->spinlock);
+}
- if (!drvdata->enabled) {
- dev_err(drvdata->dev, "STM tracing already disabled\n");
- ret = -EINVAL;
- goto err;
- }
+static void __stm_disable(struct stm_drvdata *drvdata)
+{
+ STM_UNLOCK(drvdata);
- __stm_disable();
+ stm_writel(drvdata, 0x30000, STMTCSR);
- drvdata->enabled = false;
+ STM_LOCK(drvdata);
- qdss_disable(drvdata->src);
+ __stm_hwevent_disable(drvdata);
+ __stm_port_disable(drvdata);
+}
+
+static void stm_disable(struct coresight_device *csdev)
+{
+ struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+ spin_lock(&drvdata->spinlock);
+ __stm_disable(drvdata);
+ drvdata->enable = false;
+ spin_unlock(&drvdata->spinlock);
+
+ /* Wait for 100ms so that pending data has been written to HW */
+ msleep(100);
clk_disable_unprepare(drvdata->clk);
dev_info(drvdata->dev, "STM tracing disabled\n");
- return 0;
-
-err:
- return ret;
}
+static const struct coresight_ops_source stm_source_ops = {
+ .enable = stm_enable,
+ .disable = stm_disable,
+};
+
+static const struct coresight_ops stm_cs_ops = {
+ .source_ops = &stm_source_ops,
+};
+
static uint32_t stm_channel_alloc(uint32_t off)
{
+ struct stm_drvdata *drvdata = stmdrvdata;
uint32_t ch;
do {
@@ -201,6 +330,8 @@
static void stm_channel_free(uint32_t ch)
{
+ struct stm_drvdata *drvdata = stmdrvdata;
+
clear_bit(ch, drvdata->chs.bitmap);
}
@@ -301,13 +432,14 @@
static inline int __stm_trace(uint32_t options, uint8_t entity_id,
uint8_t proto_id, const void *data, uint32_t size)
{
+ struct stm_drvdata *drvdata = stmdrvdata;
int len = 0;
uint32_t ch;
unsigned long ch_addr;
/* allocate channel and get the channel address */
ch = stm_channel_alloc(0);
- ch_addr = (unsigned long)stm_channel_addr(ch);
+ ch_addr = (unsigned long)stm_channel_addr(drvdata, ch);
/* send the ost header */
len += stm_trace_ost_header(ch_addr, options, entity_id, proto_id, data,
@@ -344,21 +476,25 @@
int stm_trace(uint32_t options, uint8_t entity_id, uint8_t proto_id,
const void *data, uint32_t size)
{
+ struct stm_drvdata *drvdata = stmdrvdata;
+
/* we don't support sizes more than 24bits (0 to 23) */
- if (!(drvdata->enabled && (drvdata->entity & entity_id) &&
+ if (!(drvdata && drvdata->enable && (drvdata->entity & entity_id) &&
(size < 0x1000000)))
return 0;
return __stm_trace(options, entity_id, proto_id, data, size);
}
-EXPORT_SYMBOL(stm_trace);
+EXPORT_SYMBOL_GPL(stm_trace);
static ssize_t stm_write(struct file *file, const char __user *data,
size_t size, loff_t *ppos)
{
+ struct stm_drvdata *drvdata = container_of(file->private_data,
+ struct stm_drvdata, miscdev);
char *buf;
- if (!drvdata->enabled)
+ if (!drvdata->enable)
return -EINVAL;
if (!(drvdata->entity & OST_ENTITY_DEV_NODE))
@@ -386,49 +522,81 @@
static const struct file_operations stm_fops = {
.owner = THIS_MODULE,
+ .open = nonseekable_open,
.write = stm_write,
.llseek = no_llseek,
};
-static struct miscdevice stm_misc = {
- .name = "msm_stm",
- .minor = MISC_DYNAMIC_MINOR,
- .fops = &stm_fops,
-};
-
-static ssize_t stm_show_enabled(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t stm_show_hwevent_enable(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- unsigned long val = drvdata->enabled;
+ struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long val = stm_hwevent_isenable(drvdata);
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
-static ssize_t stm_store_enabled(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t size)
+static ssize_t stm_store_hwevent_enable(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
{
- int ret = 0;
+ struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
+ int ret = 0;
if (sscanf(buf, "%lx", &val) != 1)
return -EINVAL;
if (val)
- ret = stm_enable();
+ ret = stm_hwevent_enable(drvdata);
else
- ret = stm_disable();
+ stm_hwevent_disable(drvdata);
if (ret)
return ret;
return size;
}
-static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, stm_show_enabled,
- stm_store_enabled);
+static DEVICE_ATTR(hwevent_enable, S_IRUGO | S_IWUSR, stm_show_hwevent_enable,
+ stm_store_hwevent_enable);
+
+static ssize_t stm_show_port_enable(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long val = stm_port_isenable(drvdata);
+
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t stm_store_port_enable(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long val;
+ int ret = 0;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ if (val)
+ ret = stm_port_enable(drvdata);
+ else
+ stm_port_disable(drvdata);
+
+ if (ret)
+ return ret;
+ return size;
+}
+static DEVICE_ATTR(port_enable, S_IRUGO | S_IWUSR, stm_show_port_enable,
+ stm_store_port_enable);
static ssize_t stm_show_entity(struct device *dev,
struct device_attribute *attr, char *buf)
{
+ struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val = drvdata->entity;
+
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
@@ -436,6 +604,7 @@
struct device_attribute *attr,
const char *buf, size_t size)
{
+ struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
unsigned long val;
if (sscanf(buf, "%lx", &val) != 1)
@@ -447,167 +616,131 @@
static DEVICE_ATTR(entity, S_IRUGO | S_IWUSR, stm_show_entity,
stm_store_entity);
-static int __devinit stm_sysfs_init(void)
-{
- int ret;
+static struct attribute *stm_attrs[] = {
+ &dev_attr_hwevent_enable.attr,
+ &dev_attr_port_enable.attr,
+ &dev_attr_entity.attr,
+ NULL,
+};
- drvdata->kobj = kobject_create_and_add("stm", qdss_get_modulekobj());
- if (!drvdata->kobj) {
- dev_err(drvdata->dev, "failed to create STM sysfs kobject\n");
- ret = -ENOMEM;
- goto err_create;
- }
+static struct attribute_group stm_attr_grp = {
+ .attrs = stm_attrs,
+};
- ret = sysfs_create_file(drvdata->kobj, &dev_attr_enabled.attr);
- if (ret) {
- dev_err(drvdata->dev, "failed to create STM sysfs enabled attr\n");
- goto err_file;
- }
-
- if (sysfs_create_file(drvdata->kobj, &dev_attr_entity.attr))
- dev_err(drvdata->dev, "failed to create STM sysfs entity attr\n");
-
- return 0;
-err_file:
- kobject_put(drvdata->kobj);
-err_create:
- return ret;
-}
-
-static void __devexit stm_sysfs_exit(void)
-{
- sysfs_remove_file(drvdata->kobj, &dev_attr_entity.attr);
- sysfs_remove_file(drvdata->kobj, &dev_attr_enabled.attr);
- kobject_put(drvdata->kobj);
-}
+static const struct attribute_group *stm_attr_grps[] = {
+ &stm_attr_grp,
+ NULL,
+};
static int __devinit stm_probe(struct platform_device *pdev)
{
int ret;
+ struct device *dev = &pdev->dev;
+ struct coresight_platform_data *pdata;
+ struct stm_drvdata *drvdata;
struct resource *res;
size_t res_size, bitmap_size;
+ struct coresight_desc *desc;
- drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
- if (!drvdata) {
- ret = -ENOMEM;
- goto err_kzalloc_drvdata;
+ if (pdev->dev.of_node) {
+ pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ pdev->dev.platform_data = pdata;
}
+ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+ /* Store the driver data pointer for use in exported functions */
+ stmdrvdata = drvdata;
+ drvdata->dev = &pdev->dev;
+ platform_set_drvdata(pdev, drvdata);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- ret = -EINVAL;
- goto err_res0;
- }
+ if (!res)
+ return -ENODEV;
- drvdata->base = ioremap_nocache(res->start, resource_size(res));
- if (!drvdata->base) {
- ret = -EINVAL;
- goto err_ioremap0;
- }
+ drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!drvdata->base)
+ return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!res) {
- ret = -EINVAL;
- goto err_res1;
- }
+ if (!res)
+ return -ENODEV;
- if (stm_boot_nr_channel) {
- res_size = min((resource_size_t)(stm_boot_nr_channel *
+ if (boot_nr_channel) {
+ res_size = min((resource_size_t)(boot_nr_channel *
BYTES_PER_CHANNEL), resource_size(res));
- bitmap_size = stm_boot_nr_channel * sizeof(long);
+ bitmap_size = boot_nr_channel * sizeof(long);
} else {
res_size = min((resource_size_t)(NR_STM_CHANNEL *
BYTES_PER_CHANNEL), resource_size(res));
bitmap_size = NR_STM_CHANNEL * sizeof(long);
}
+ drvdata->chs.base = devm_ioremap(dev, res->start, res_size);
+ if (!drvdata->chs.base)
+ return -ENOMEM;
+ drvdata->chs.bitmap = devm_kzalloc(dev, bitmap_size, GFP_KERNEL);
+ if (!drvdata->chs.bitmap)
+ return -ENOMEM;
- drvdata->chs.bitmap = kzalloc(bitmap_size, GFP_KERNEL);
- if (!drvdata->chs.bitmap) {
- ret = -ENOMEM;
- goto err_bitmap;
- }
+ spin_lock_init(&drvdata->spinlock);
- drvdata->chs.base = ioremap_nocache(res->start, res_size);
- if (!drvdata->chs.base) {
- ret = -EINVAL;
- goto err_ioremap1;
- }
-
- drvdata->dev = &pdev->dev;
-
- ret = misc_register(&stm_misc);
- if (ret)
- goto err_misc;
-
- drvdata->src = qdss_get("msm_stm");
- if (IS_ERR(drvdata->src)) {
- ret = PTR_ERR(drvdata->src);
- goto err_qdssget;
- }
-
- drvdata->clk = clk_get(drvdata->dev, "core_clk");
- if (IS_ERR(drvdata->clk)) {
- ret = PTR_ERR(drvdata->clk);
- goto err_clk_get;
- }
+ drvdata->clk = devm_clk_get(dev, "core_clk");
+ if (IS_ERR(drvdata->clk))
+ return PTR_ERR(drvdata->clk);
ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
if (ret)
- goto err_clk_rate;
+ return ret;
drvdata->entity = OST_ENTITY_ALL;
- ret = stm_sysfs_init();
- if (ret)
- goto err_sysfs;
+ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+ desc->type = CORESIGHT_DEV_TYPE_SOURCE;
+ desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE;
+ desc->ops = &stm_cs_ops;
+ desc->pdata = pdev->dev.platform_data;
+ desc->dev = &pdev->dev;
+ desc->groups = stm_attr_grps;
+ desc->owner = THIS_MODULE;
+ drvdata->csdev = coresight_register(desc);
+ if (IS_ERR(drvdata->csdev))
+ return PTR_ERR(drvdata->csdev);
- if (stm_boot_enable)
- stm_enable();
+ drvdata->miscdev.name = ((struct coresight_platform_data *)
+ (pdev->dev.platform_data))->name;
+ drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
+ drvdata->miscdev.fops = &stm_fops;
+ ret = misc_register(&drvdata->miscdev);
+ if (ret)
+ goto err;
dev_info(drvdata->dev, "STM initialized\n");
+
+ if (boot_enable)
+ coresight_enable(drvdata->csdev);
+
return 0;
-
-err_sysfs:
-err_clk_rate:
- clk_put(drvdata->clk);
-err_clk_get:
- qdss_put(drvdata->src);
-err_qdssget:
- misc_deregister(&stm_misc);
-err_misc:
- iounmap(drvdata->chs.base);
-err_ioremap1:
- kfree(drvdata->chs.bitmap);
-err_bitmap:
-err_res1:
- iounmap(drvdata->base);
-err_ioremap0:
-err_res0:
- kfree(drvdata);
-err_kzalloc_drvdata:
-
- dev_err(drvdata->dev, "STM init failed\n");
+err:
+ coresight_unregister(drvdata->csdev);
return ret;
}
static int __devexit stm_remove(struct platform_device *pdev)
{
- if (drvdata->enabled)
- stm_disable();
- stm_sysfs_exit();
- clk_put(drvdata->clk);
- qdss_put(drvdata->src);
- misc_deregister(&stm_misc);
- iounmap(drvdata->chs.base);
- kfree(drvdata->chs.bitmap);
- iounmap(drvdata->base);
- kfree(drvdata);
+ struct stm_drvdata *drvdata = platform_get_drvdata(pdev);
+ misc_deregister(&drvdata->miscdev);
+ coresight_unregister(drvdata->csdev);
return 0;
}
static struct of_device_id stm_match[] = {
- {.compatible = "qcom,msm-stm"},
+ {.compatible = "arm,coresight-stm"},
{}
};
@@ -615,7 +748,7 @@
.probe = stm_probe,
.remove = __devexit_p(stm_remove),
.driver = {
- .name = "msm_stm",
+ .name = "coresight-stm",
.owner = THIS_MODULE,
.of_match_table = stm_match,
},
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
new file mode 100644
index 0000000..1c85aff
--- /dev/null
+++ b/drivers/coresight/coresight-tmc.c
@@ -0,0 +1,790 @@
+/* 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/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/memory_alloc.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <linux/of_coresight.h>
+#include <linux/coresight.h>
+#include <mach/memory.h>
+
+#include "coresight-priv.h"
+
+#define tmc_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
+#define tmc_readl(drvdata, off) __raw_readl(drvdata->base + off)
+
+#define TMC_LOCK(drvdata) \
+do { \
+ mb(); \
+ tmc_writel(drvdata, 0x0, CORESIGHT_LAR); \
+} while (0)
+#define TMC_UNLOCK(drvdata) \
+do { \
+ tmc_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
+ mb(); \
+} while (0)
+
+#define TMC_RSZ (0x004)
+#define TMC_STS (0x00C)
+#define TMC_RRD (0x010)
+#define TMC_RRP (0x014)
+#define TMC_RWP (0x018)
+#define TMC_TRG (0x01C)
+#define TMC_CTL (0x020)
+#define TMC_RWD (0x024)
+#define TMC_MODE (0x028)
+#define TMC_LBUFLEVEL (0x02C)
+#define TMC_CBUFLEVEL (0x030)
+#define TMC_BUFWM (0x034)
+#define TMC_RRPHI (0x038)
+#define TMC_RWPHI (0x03C)
+#define TMC_AXICTL (0x110)
+#define TMC_DBALO (0x118)
+#define TMC_DBAHI (0x11C)
+#define TMC_FFSR (0x300)
+#define TMC_FFCR (0x304)
+#define TMC_PSCR (0x308)
+#define TMC_ITMISCOP0 (0xEE0)
+#define TMC_ITTRFLIN (0xEE8)
+#define TMC_ITATBDATA0 (0xEEC)
+#define TMC_ITATBCTR2 (0xEF0)
+#define TMC_ITATBCTR1 (0xEF4)
+#define TMC_ITATBCTR0 (0xEF8)
+
+#define BYTES_PER_WORD 4
+
+enum tmc_config_type {
+ TMC_CONFIG_TYPE_ETB,
+ TMC_CONFIG_TYPE_ETR,
+ TMC_CONFIG_TYPE_ETF,
+};
+
+enum tmc_mode {
+ TMC_MODE_CIRCULAR_BUFFER,
+ TMC_MODE_SOFTWARE_FIFO,
+ TMC_MODE_HARDWARE_FIFO,
+};
+
+enum tmc_mem_intf_width {
+ TMC_MEM_INTF_WIDTH_32BITS = 0x2,
+ TMC_MEM_INTF_WIDTH_64BITS = 0x3,
+ TMC_MEM_INTF_WIDTH_128BITS = 0x4,
+ TMC_MEM_INTF_WIDTH_256BITS = 0x5,
+};
+
+struct tmc_drvdata {
+ void __iomem *base;
+ struct device *dev;
+ struct coresight_device *csdev;
+ struct miscdevice miscdev;
+ struct clk *clk;
+ spinlock_t spinlock;
+ int read_count;
+ bool reading;
+ char *buf;
+ unsigned long paddr;
+ void __iomem *vaddr;
+ uint32_t size;
+ bool enable;
+ enum tmc_config_type config_type;
+ uint32_t trigger_cntr;
+};
+
+static void tmc_wait_for_ready(struct tmc_drvdata *drvdata)
+{
+ int count;
+
+ /* Ensure formatter, unformatter and hardware fifo are empty */
+ for (count = TIMEOUT_US; BVAL(tmc_readl(drvdata, TMC_STS), 2) != 1
+ && count > 0; count--)
+ udelay(1);
+ WARN(count == 0, "timeout while waiting for TMC ready, TMC_STS: %#x\n",
+ tmc_readl(drvdata, TMC_STS));
+}
+
+static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
+{
+ int count;
+ uint32_t ffcr;
+
+ ffcr = tmc_readl(drvdata, TMC_FFCR);
+ ffcr |= BIT(12);
+ tmc_writel(drvdata, ffcr, TMC_FFCR);
+ ffcr |= BIT(6);
+ tmc_writel(drvdata, ffcr, TMC_FFCR);
+ /* Ensure flush completes */
+ for (count = TIMEOUT_US; BVAL(tmc_readl(drvdata, TMC_FFCR), 6) != 0
+ && count > 0; count--)
+ udelay(1);
+ WARN(count == 0, "timeout while flushing TMC, TMC_FFCR: %#x\n",
+ tmc_readl(drvdata, TMC_FFCR));
+
+ tmc_wait_for_ready(drvdata);
+}
+
+static void __tmc_enable(struct tmc_drvdata *drvdata)
+{
+ tmc_writel(drvdata, 0x1, TMC_CTL);
+}
+
+static void __tmc_disable(struct tmc_drvdata *drvdata)
+{
+ tmc_writel(drvdata, 0x0, TMC_CTL);
+}
+
+static void __tmc_etb_enable(struct tmc_drvdata *drvdata)
+{
+ /* Zero out the memory to help with debug */
+ memset(drvdata->buf, 0, drvdata->size);
+
+ TMC_UNLOCK(drvdata);
+
+ tmc_writel(drvdata, TMC_MODE_CIRCULAR_BUFFER, TMC_MODE);
+ tmc_writel(drvdata, 0x133, TMC_FFCR);
+ tmc_writel(drvdata, drvdata->trigger_cntr, TMC_TRG);
+ __tmc_enable(drvdata);
+
+ TMC_LOCK(drvdata);
+}
+
+static void __tmc_etr_enable(struct tmc_drvdata *drvdata)
+{
+ uint32_t axictl;
+
+ /* Zero out the memory to help with debug */
+ memset(drvdata->vaddr, 0, drvdata->size);
+
+ TMC_UNLOCK(drvdata);
+
+ tmc_writel(drvdata, drvdata->size / BYTES_PER_WORD, TMC_RSZ);
+ tmc_writel(drvdata, TMC_MODE_CIRCULAR_BUFFER, TMC_MODE);
+
+ axictl = tmc_readl(drvdata, TMC_AXICTL);
+ axictl |= (0xF << 8);
+ tmc_writel(drvdata, axictl, TMC_AXICTL);
+ axictl &= ~(0x1 << 7);
+ tmc_writel(drvdata, axictl, TMC_AXICTL);
+ axictl = (axictl & ~0x3) | 0x2;
+ tmc_writel(drvdata, axictl, TMC_AXICTL);
+
+ tmc_writel(drvdata, drvdata->paddr, TMC_DBALO);
+ tmc_writel(drvdata, 0x0, TMC_DBAHI);
+ tmc_writel(drvdata, 0x133, TMC_FFCR);
+ __tmc_enable(drvdata);
+
+ TMC_LOCK(drvdata);
+}
+
+static void __tmc_etf_enable(struct tmc_drvdata *drvdata)
+{
+ TMC_UNLOCK(drvdata);
+
+ tmc_writel(drvdata, TMC_MODE_HARDWARE_FIFO, TMC_MODE);
+ tmc_writel(drvdata, 0x3, TMC_FFCR);
+ tmc_writel(drvdata, 0x0, TMC_BUFWM);
+ __tmc_enable(drvdata);
+
+ TMC_LOCK(drvdata);
+}
+
+static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
+{
+ int ret;
+ unsigned long flags;
+
+ ret = clk_prepare_enable(drvdata->clk);
+ if (ret)
+ return ret;
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ if (drvdata->reading) {
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ clk_disable_unprepare(drvdata->clk);
+ return -EBUSY;
+ }
+
+ if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+ __tmc_etb_enable(drvdata);
+ } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+ __tmc_etr_enable(drvdata);
+ } else {
+ if (mode == TMC_MODE_CIRCULAR_BUFFER)
+ __tmc_etb_enable(drvdata);
+ else
+ __tmc_etf_enable(drvdata);
+ }
+ drvdata->enable = true;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_info(drvdata->dev, "TMC enabled\n");
+ return 0;
+}
+
+static int tmc_enable_sink(struct coresight_device *csdev)
+{
+ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+ return tmc_enable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
+}
+
+static int tmc_enable_link(struct coresight_device *csdev, int inport,
+ int outport)
+{
+ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+ return tmc_enable(drvdata, TMC_MODE_HARDWARE_FIFO);
+}
+
+static void __tmc_etb_dump(struct tmc_drvdata *drvdata)
+{
+ enum tmc_mem_intf_width memwidth;
+ uint8_t memwords;
+ char *bufp;
+ uint32_t read_data;
+ int i;
+
+ memwidth = BMVAL(tmc_readl(drvdata, CORESIGHT_DEVID), 8, 10);
+ if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
+ memwords = 1;
+ else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
+ memwords = 2;
+ else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
+ memwords = 4;
+ else
+ memwords = 8;
+
+ bufp = drvdata->buf;
+ while (1) {
+ for (i = 0; i < memwords; i++) {
+ read_data = tmc_readl(drvdata, TMC_RRD);
+ if (read_data == 0xFFFFFFFF)
+ return;
+ memcpy(bufp, &read_data, BYTES_PER_WORD);
+ bufp += BYTES_PER_WORD;
+ }
+ }
+}
+
+static void __tmc_etb_disable(struct tmc_drvdata *drvdata)
+{
+ TMC_UNLOCK(drvdata);
+
+ tmc_flush_and_stop(drvdata);
+ __tmc_etb_dump(drvdata);
+ __tmc_disable(drvdata);
+
+ TMC_LOCK(drvdata);
+}
+
+static void __tmc_etr_dump(struct tmc_drvdata *drvdata)
+{
+ uint32_t rwp, rwphi;
+
+ rwp = tmc_readl(drvdata, TMC_RWP);
+ rwphi = tmc_readl(drvdata, TMC_RWPHI);
+
+ if (BVAL(tmc_readl(drvdata, TMC_STS), 0))
+ drvdata->buf = drvdata->vaddr + rwp;
+ else
+ drvdata->buf = drvdata->vaddr;
+}
+
+static void __tmc_etr_disable(struct tmc_drvdata *drvdata)
+{
+ TMC_UNLOCK(drvdata);
+
+ tmc_flush_and_stop(drvdata);
+ __tmc_etr_dump(drvdata);
+ __tmc_disable(drvdata);
+
+ TMC_LOCK(drvdata);
+}
+
+static void __tmc_etf_disable(struct tmc_drvdata *drvdata)
+{
+ TMC_UNLOCK(drvdata);
+
+ tmc_flush_and_stop(drvdata);
+ __tmc_disable(drvdata);
+
+ TMC_LOCK(drvdata);
+}
+
+static void tmc_disable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ if (drvdata->reading)
+ goto out;
+
+ if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+ __tmc_etb_disable(drvdata);
+ } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+ __tmc_etr_disable(drvdata);
+ } else {
+ if (mode == TMC_MODE_CIRCULAR_BUFFER)
+ __tmc_etb_disable(drvdata);
+ else
+ __tmc_etf_disable(drvdata);
+ }
+out:
+ drvdata->enable = false;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ clk_disable_unprepare(drvdata->clk);
+
+ dev_info(drvdata->dev, "TMC disabled\n");
+}
+
+static void tmc_disable_sink(struct coresight_device *csdev)
+{
+ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+ tmc_disable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
+}
+
+static void tmc_disable_link(struct coresight_device *csdev, int inport,
+ int outport)
+{
+ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+ tmc_disable(drvdata, TMC_MODE_HARDWARE_FIFO);
+}
+
+static void tmc_abort(struct coresight_device *csdev)
+{
+ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+ unsigned long flags;
+ enum tmc_mode mode;
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ if (drvdata->reading)
+ goto out0;
+
+ if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+ __tmc_etb_disable(drvdata);
+ } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+ __tmc_etr_disable(drvdata);
+ } else {
+ mode = tmc_readl(drvdata, TMC_MODE);
+ if (mode == TMC_MODE_CIRCULAR_BUFFER)
+ __tmc_etb_disable(drvdata);
+ else
+ goto out1;
+ }
+out0:
+ drvdata->enable = false;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_info(drvdata->dev, "TMC aborted\n");
+ return;
+out1:
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+}
+
+static const struct coresight_ops_sink tmc_sink_ops = {
+ .enable = tmc_enable_sink,
+ .disable = tmc_disable_sink,
+ .abort = tmc_abort,
+};
+
+static const struct coresight_ops_link tmc_link_ops = {
+ .enable = tmc_enable_link,
+ .disable = tmc_disable_link,
+};
+
+static const struct coresight_ops tmc_etb_cs_ops = {
+ .sink_ops = &tmc_sink_ops,
+};
+
+static const struct coresight_ops tmc_etr_cs_ops = {
+ .sink_ops = &tmc_sink_ops,
+};
+
+static const struct coresight_ops tmc_etf_cs_ops = {
+ .sink_ops = &tmc_sink_ops,
+ .link_ops = &tmc_link_ops,
+};
+
+static int tmc_read_prepare(struct tmc_drvdata *drvdata)
+{
+ int ret;
+ unsigned long flags;
+ enum tmc_mode mode;
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ if (!drvdata->enable)
+ goto out;
+
+ if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+ __tmc_etb_disable(drvdata);
+ } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+ __tmc_etr_disable(drvdata);
+ } else {
+ mode = tmc_readl(drvdata, TMC_MODE);
+ if (mode == TMC_MODE_CIRCULAR_BUFFER) {
+ __tmc_etb_disable(drvdata);
+ } else {
+ ret = -ENODEV;
+ goto err;
+ }
+ }
+out:
+ drvdata->reading = true;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_info(drvdata->dev, "TMC read start\n");
+ return 0;
+err:
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ return ret;
+}
+
+static void tmc_read_unprepare(struct tmc_drvdata *drvdata)
+{
+ unsigned long flags;
+ enum tmc_mode mode;
+
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ if (!drvdata->enable)
+ goto out;
+
+ if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+ __tmc_etb_enable(drvdata);
+ } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+ __tmc_etr_enable(drvdata);
+ } else {
+ mode = tmc_readl(drvdata, TMC_MODE);
+ if (mode == TMC_MODE_CIRCULAR_BUFFER)
+ __tmc_etb_enable(drvdata);
+ }
+out:
+ drvdata->reading = false;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_info(drvdata->dev, "TMC read end\n");
+}
+
+static int tmc_open(struct inode *inode, struct file *file)
+{
+ struct tmc_drvdata *drvdata = container_of(file->private_data,
+ struct tmc_drvdata, miscdev);
+ int ret = 0;
+
+ if (drvdata->read_count++)
+ goto out;
+
+ ret = tmc_read_prepare(drvdata);
+ if (ret)
+ return ret;
+out:
+ nonseekable_open(inode, file);
+
+ dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
+ return 0;
+}
+
+static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
+ loff_t *ppos)
+{
+ struct tmc_drvdata *drvdata = container_of(file->private_data,
+ struct tmc_drvdata, miscdev);
+ char *bufp = drvdata->buf + *ppos;
+
+ if (*ppos + len > drvdata->size)
+ len = drvdata->size - *ppos;
+
+ if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+ if (bufp == (char *)(drvdata->vaddr + drvdata->size))
+ bufp = drvdata->vaddr;
+ if ((bufp + len) > (char *)(drvdata->vaddr + drvdata->size))
+ len = (char *)(drvdata->vaddr + drvdata->size) - bufp;
+ }
+
+ if (copy_to_user(data, bufp, len)) {
+ dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
+ return -EFAULT;
+ }
+
+ *ppos += len;
+
+ dev_dbg(drvdata->dev, "%s: %d bytes copied, %d bytes left\n",
+ __func__, len, (int) (drvdata->size - *ppos));
+ return len;
+}
+
+static int tmc_release(struct inode *inode, struct file *file)
+{
+ struct tmc_drvdata *drvdata = container_of(file->private_data,
+ struct tmc_drvdata, miscdev);
+
+ if (--drvdata->read_count) {
+ if (drvdata->read_count < 0) {
+ WARN_ONCE(1, "mismatched close\n");
+ drvdata->read_count = 0;
+ }
+ goto out;
+ }
+
+ tmc_read_unprepare(drvdata);
+out:
+ dev_dbg(drvdata->dev, "%s: released\n", __func__);
+ return 0;
+}
+
+static const struct file_operations tmc_fops = {
+ .owner = THIS_MODULE,
+ .open = tmc_open,
+ .read = tmc_read,
+ .release = tmc_release,
+ .llseek = no_llseek,
+};
+
+static ssize_t tmc_show_trigger_cntr(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long val = drvdata->trigger_cntr;
+
+ return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t tmc_store_trigger_cntr(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
+ unsigned long val;
+
+ if (sscanf(buf, "%lx", &val) != 1)
+ return -EINVAL;
+
+ drvdata->trigger_cntr = val;
+ return size;
+}
+static DEVICE_ATTR(trigger_cntr, S_IRUGO | S_IWUSR, tmc_show_trigger_cntr,
+ tmc_store_trigger_cntr);
+
+static struct attribute *tmc_attrs[] = {
+ &dev_attr_trigger_cntr.attr,
+ NULL,
+};
+
+static struct attribute_group tmc_attr_grp = {
+ .attrs = tmc_attrs,
+};
+
+static const struct attribute_group *tmc_etb_attr_grps[] = {
+ &tmc_attr_grp,
+ NULL,
+};
+
+static const struct attribute_group *tmc_etr_attr_grps[] = {
+ &tmc_attr_grp,
+ NULL,
+};
+
+static const struct attribute_group *tmc_etf_attr_grps[] = {
+ &tmc_attr_grp,
+ NULL,
+};
+
+static int __devinit tmc_probe(struct platform_device *pdev)
+{
+ int ret;
+ uint32_t devid;
+ struct device *dev = &pdev->dev;
+ struct coresight_platform_data *pdata;
+ struct tmc_drvdata *drvdata;
+ struct resource *res;
+ struct coresight_desc *desc;
+
+ if (pdev->dev.of_node) {
+ pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ pdev->dev.platform_data = pdata;
+ }
+
+ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+ drvdata->dev = &pdev->dev;
+ platform_set_drvdata(pdev, drvdata);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!drvdata->base)
+ return -ENOMEM;
+
+ spin_lock_init(&drvdata->spinlock);
+
+ drvdata->clk = devm_clk_get(dev, "core_clk");
+ if (IS_ERR(drvdata->clk))
+ return PTR_ERR(drvdata->clk);
+
+ ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(drvdata->clk);
+ if (ret)
+ return ret;
+
+ devid = tmc_readl(drvdata, CORESIGHT_DEVID);
+ drvdata->config_type = BMVAL(devid, 6, 7);
+
+ if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
+ drvdata->size = SZ_1M;
+ else
+ drvdata->size = tmc_readl(drvdata, TMC_RSZ) * BYTES_PER_WORD;
+
+ clk_disable_unprepare(drvdata->clk);
+
+ if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+ drvdata->paddr = allocate_contiguous_ebi_nomap(drvdata->size,
+ SZ_4K);
+ if (!drvdata->paddr)
+ return -ENOMEM;
+ drvdata->vaddr = devm_ioremap(dev, drvdata->paddr,
+ drvdata->size);
+ if (!drvdata->vaddr) {
+ ret = -ENOMEM;
+ goto err0;
+ }
+ memset(drvdata->vaddr, 0, drvdata->size);
+ } else {
+ drvdata->buf = devm_kzalloc(dev, drvdata->size, GFP_KERNEL);
+ if (!drvdata->buf)
+ return -ENOMEM;
+ }
+
+ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+ if (!desc) {
+ ret = -ENOMEM;
+ goto err0;
+ }
+ if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+ desc->type = CORESIGHT_DEV_TYPE_SINK;
+ desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
+ desc->ops = &tmc_etb_cs_ops;
+ desc->pdata = pdev->dev.platform_data;
+ desc->dev = &pdev->dev;
+ desc->groups = tmc_etb_attr_grps;
+ desc->owner = THIS_MODULE;
+ drvdata->csdev = coresight_register(desc);
+ if (IS_ERR(drvdata->csdev)) {
+ ret = PTR_ERR(drvdata->csdev);
+ goto err0;
+ }
+ } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+ desc->type = CORESIGHT_DEV_TYPE_SINK;
+ desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
+ desc->ops = &tmc_etr_cs_ops;
+ desc->pdata = pdev->dev.platform_data;
+ desc->dev = &pdev->dev;
+ desc->groups = tmc_etr_attr_grps;
+ desc->owner = THIS_MODULE;
+ drvdata->csdev = coresight_register(desc);
+ if (IS_ERR(drvdata->csdev)) {
+ ret = PTR_ERR(drvdata->csdev);
+ goto err0;
+ }
+ } else {
+ desc->type = CORESIGHT_DEV_TYPE_LINKSINK;
+ desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
+ desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO;
+ desc->ops = &tmc_etf_cs_ops;
+ desc->pdata = pdev->dev.platform_data;
+ desc->dev = &pdev->dev;
+ desc->groups = tmc_etf_attr_grps;
+ desc->owner = THIS_MODULE;
+ drvdata->csdev = coresight_register(desc);
+ if (IS_ERR(drvdata->csdev)) {
+ ret = PTR_ERR(drvdata->csdev);
+ goto err0;
+ }
+ }
+
+ drvdata->miscdev.name = ((struct coresight_platform_data *)
+ (pdev->dev.platform_data))->name;
+ drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
+ drvdata->miscdev.fops = &tmc_fops;
+ ret = misc_register(&drvdata->miscdev);
+ if (ret)
+ goto err1;
+
+ dev_info(dev, "TMC initialized\n");
+ return 0;
+err1:
+ coresight_unregister(drvdata->csdev);
+err0:
+ free_contiguous_memory_by_paddr(drvdata->paddr);
+ return ret;
+}
+
+static int __devexit tmc_remove(struct platform_device *pdev)
+{
+ struct tmc_drvdata *drvdata = platform_get_drvdata(pdev);
+
+ misc_deregister(&drvdata->miscdev);
+ coresight_unregister(drvdata->csdev);
+ free_contiguous_memory_by_paddr(drvdata->paddr);
+ return 0;
+}
+
+static struct of_device_id tmc_match[] = {
+ {.compatible = "arm,coresight-tmc"},
+ {}
+};
+
+static struct platform_driver tmc_driver = {
+ .probe = tmc_probe,
+ .remove = __devexit_p(tmc_remove),
+ .driver = {
+ .name = "coresight-tmc",
+ .owner = THIS_MODULE,
+ .of_match_table = tmc_match,
+ },
+};
+
+static int __init tmc_init(void)
+{
+ return platform_driver_register(&tmc_driver);
+}
+module_init(tmc_init);
+
+static void __exit tmc_exit(void)
+{
+ platform_driver_unregister(&tmc_driver);
+}
+module_exit(tmc_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Trace Memory Controller driver");
diff --git a/drivers/coresight/coresight-tpiu.c b/drivers/coresight/coresight-tpiu.c
index c0bcfdd..290ae7f 100644
--- a/drivers/coresight/coresight-tpiu.c
+++ b/drivers/coresight/coresight-tpiu.c
@@ -19,6 +19,7 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/clk.h>
+#include <linux/of_coresight.h>
#include <linux/coresight.h>
#include "coresight-priv.h"
@@ -26,135 +27,182 @@
#define tpiu_writel(drvdata, val, off) __raw_writel((val), drvdata->base + off)
#define tpiu_readl(drvdata, off) __raw_readl(drvdata->base + off)
-#define TPIU_SUPP_PORTSZ (0x000)
-#define TPIU_CURR_PORTSZ (0x004)
-#define TPIU_SUPP_TRIGMODES (0x100)
-#define TPIU_TRIG_CNTRVAL (0x104)
-#define TPIU_TRIG_MULT (0x108)
-#define TPIU_SUPP_TESTPATM (0x200)
-#define TPIU_CURR_TESTPATM (0x204)
-#define TPIU_TEST_PATREPCNTR (0x208)
-#define TPIU_FFSR (0x300)
-#define TPIU_FFCR (0x304)
-#define TPIU_FSYNC_CNTR (0x308)
-#define TPIU_EXTCTL_INPORT (0x400)
-#define TPIU_EXTCTL_OUTPORT (0x404)
-#define TPIU_ITTRFLINACK (0xEE4)
-#define TPIU_ITTRFLIN (0xEE8)
-#define TPIU_ITATBDATA0 (0xEEC)
-#define TPIU_ITATBCTR2 (0xEF0)
-#define TPIU_ITATBCTR1 (0xEF4)
-#define TPIU_ITATBCTR0 (0xEF8)
-
-
-#define TPIU_LOCK() \
+#define TPIU_LOCK(drvdata) \
do { \
mb(); \
tpiu_writel(drvdata, 0x0, CORESIGHT_LAR); \
} while (0)
-#define TPIU_UNLOCK() \
+#define TPIU_UNLOCK(drvdata) \
do { \
tpiu_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR); \
mb(); \
} while (0)
+#define TPIU_SUPP_PORTSZ (0x000)
+#define TPIU_CURR_PORTSZ (0x004)
+#define TPIU_SUPP_TRIGMODES (0x100)
+#define TPIU_TRIG_CNTRVAL (0x104)
+#define TPIU_TRIG_MULT (0x108)
+#define TPIU_SUPP_TESTPATM (0x200)
+#define TPIU_CURR_TESTPATM (0x204)
+#define TPIU_TEST_PATREPCNTR (0x208)
+#define TPIU_FFSR (0x300)
+#define TPIU_FFCR (0x304)
+#define TPIU_FSYNC_CNTR (0x308)
+#define TPIU_EXTCTL_INPORT (0x400)
+#define TPIU_EXTCTL_OUTPORT (0x404)
+#define TPIU_ITTRFLINACK (0xEE4)
+#define TPIU_ITTRFLIN (0xEE8)
+#define TPIU_ITATBDATA0 (0xEEC)
+#define TPIU_ITATBCTR2 (0xEF0)
+#define TPIU_ITATBCTR1 (0xEF4)
+#define TPIU_ITATBCTR0 (0xEF8)
+
struct tpiu_drvdata {
- void __iomem *base;
- bool enabled;
- struct device *dev;
- struct clk *clk;
+ void __iomem *base;
+ struct device *dev;
+ struct coresight_device *csdev;
+ struct clk *clk;
};
-static struct tpiu_drvdata *drvdata;
-
-static void __tpiu_disable(void)
+static void __tpiu_enable(struct tpiu_drvdata *drvdata)
{
- TPIU_UNLOCK();
+ TPIU_UNLOCK(drvdata);
+
+ /* TODO: fill this up */
+
+ TPIU_LOCK(drvdata);
+}
+
+static int tpiu_enable(struct coresight_device *csdev)
+{
+ struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+ int ret;
+
+ ret = clk_prepare_enable(drvdata->clk);
+ if (ret)
+ return ret;
+
+ __tpiu_enable(drvdata);
+
+ dev_info(drvdata->dev, "TPIU enabled\n");
+ return 0;
+}
+
+static void __tpiu_disable(struct tpiu_drvdata *drvdata)
+{
+ TPIU_UNLOCK(drvdata);
tpiu_writel(drvdata, 0x3000, TPIU_FFCR);
tpiu_writel(drvdata, 0x3040, TPIU_FFCR);
- TPIU_LOCK();
+ TPIU_LOCK(drvdata);
}
-void tpiu_disable(void)
+static void tpiu_disable(struct coresight_device *csdev)
{
- __tpiu_disable();
- drvdata->enabled = false;
+ struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+ __tpiu_disable(drvdata);
+
+ clk_disable_unprepare(drvdata->clk);
+
dev_info(drvdata->dev, "TPIU disabled\n");
}
+static void tpiu_abort(struct coresight_device *csdev)
+{
+ struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+ __tpiu_disable(drvdata);
+
+ dev_info(drvdata->dev, "TPIU aborted\n");
+}
+
+static const struct coresight_ops_sink tpiu_sink_ops = {
+ .enable = tpiu_enable,
+ .disable = tpiu_disable,
+ .abort = tpiu_abort,
+};
+
+static const struct coresight_ops tpiu_cs_ops = {
+ .sink_ops = &tpiu_sink_ops,
+};
+
static int __devinit tpiu_probe(struct platform_device *pdev)
{
int ret;
+ struct device *dev = &pdev->dev;
+ struct coresight_platform_data *pdata;
+ struct tpiu_drvdata *drvdata;
struct resource *res;
+ struct coresight_desc *desc;
- drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
- if (!drvdata) {
- ret = -ENOMEM;
- goto err_kzalloc_drvdata;
+ if (pdev->dev.of_node) {
+ pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ pdev->dev.platform_data = pdata;
}
+ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+ drvdata->dev = &pdev->dev;
+ platform_set_drvdata(pdev, drvdata);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- ret = -EINVAL;
- goto err_res;
- }
+ if (!res)
+ return -ENODEV;
- drvdata->base = ioremap_nocache(res->start, resource_size(res));
- if (!drvdata->base) {
- ret = -EINVAL;
- goto err_ioremap;
- }
+ drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+ if (!drvdata->base)
+ return -ENOMEM;
- drvdata->dev = &pdev->dev;
-
- drvdata->clk = clk_get(drvdata->dev, "core_clk");
- if (IS_ERR(drvdata->clk)) {
- ret = PTR_ERR(drvdata->clk);
- goto err_clk_get;
- }
+ drvdata->clk = devm_clk_get(dev, "core_clk");
+ if (IS_ERR(drvdata->clk))
+ return PTR_ERR(drvdata->clk);
ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
if (ret)
- goto err_clk_rate;
+ return ret;
- /* Disable tpiu to support older targets that need this */
ret = clk_prepare_enable(drvdata->clk);
if (ret)
- goto err_clk_enable;
- __tpiu_disable();
+ return ret;
+
+ /* Disable tpiu to support older targets that need this */
+ __tpiu_disable(drvdata);
+
clk_disable_unprepare(drvdata->clk);
- dev_info(drvdata->dev, "TPIU initialized\n");
- return 0;
+ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+ desc->type = CORESIGHT_DEV_TYPE_SINK;
+ desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_PORT;
+ desc->ops = &tpiu_cs_ops;
+ desc->pdata = pdev->dev.platform_data;
+ desc->dev = &pdev->dev;
+ desc->owner = THIS_MODULE;
+ drvdata->csdev = coresight_register(desc);
+ if (IS_ERR(drvdata->csdev))
+ return PTR_ERR(drvdata->csdev);
-err_clk_enable:
-err_clk_rate:
- clk_put(drvdata->clk);
-err_clk_get:
- iounmap(drvdata->base);
-err_ioremap:
-err_res:
- kfree(drvdata);
-err_kzalloc_drvdata:
- dev_err(drvdata->dev, "TPIU init failed\n");
- return ret;
+ dev_info(dev, "TPIU initialized\n");
+ return 0;
}
static int __devexit tpiu_remove(struct platform_device *pdev)
{
- if (drvdata->enabled)
- tpiu_disable();
- clk_put(drvdata->clk);
- iounmap(drvdata->base);
- kfree(drvdata);
+ struct tpiu_drvdata *drvdata = platform_get_drvdata(pdev);
+ coresight_unregister(drvdata->csdev);
return 0;
}
static struct of_device_id tpiu_match[] = {
- {.compatible = "qcom,msm-tpiu"},
+ {.compatible = "arm,coresight-tpiu"},
{}
};
@@ -162,7 +210,7 @@
.probe = tpiu_probe,
.remove = __devexit_p(tpiu_remove),
.driver = {
- .name = "msm_tpiu",
+ .name = "coresight-tpiu",
.owner = THIS_MODULE,
.of_match_table = tpiu_match,
},
diff --git a/drivers/coresight/coresight.c b/drivers/coresight/coresight.c
index a17ac9a..f76d303 100644
--- a/drivers/coresight/coresight.c
+++ b/drivers/coresight/coresight.c
@@ -26,17 +26,13 @@
#include "coresight-priv.h"
-
#define NO_SINK (-1)
-#define MAX_STR_LEN (65535)
-
static int curr_sink = NO_SINK;
static LIST_HEAD(coresight_orph_conns);
static LIST_HEAD(coresight_devs);
static DEFINE_SEMAPHORE(coresight_mutex);
-
static int coresight_find_link_inport(struct coresight_device *csdev)
{
int i;
@@ -343,7 +339,7 @@
up(&coresight_mutex);
return ret;
}
-EXPORT_SYMBOL(coresight_enable);
+EXPORT_SYMBOL_GPL(coresight_enable);
void coresight_disable(struct coresight_device *csdev)
{
@@ -366,7 +362,29 @@
out:
up(&coresight_mutex);
}
-EXPORT_SYMBOL(coresight_disable);
+EXPORT_SYMBOL_GPL(coresight_disable);
+
+void coresight_abort(void)
+{
+ struct coresight_device *cd;
+
+ if (down_trylock(&coresight_mutex)) {
+ pr_err("coresight: abort could not be processed\n");
+ return;
+ }
+ if (curr_sink == NO_SINK)
+ goto out;
+
+ list_for_each_entry(cd, &coresight_devs, dev_link) {
+ if (cd->id == curr_sink) {
+ if (cd->enable && cd->ops->sink_ops->abort)
+ cd->ops->sink_ops->abort(cd);
+ }
+ }
+out:
+ up(&coresight_mutex);
+}
+EXPORT_SYMBOL_GPL(coresight_abort);
static ssize_t coresight_show_type(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -626,7 +644,7 @@
err_kzalloc_csdev:
return ERR_PTR(ret);
}
-EXPORT_SYMBOL(coresight_register);
+EXPORT_SYMBOL_GPL(coresight_register);
void coresight_unregister(struct coresight_device *csdev)
{
@@ -638,7 +656,7 @@
put_device(&csdev->dev);
}
}
-EXPORT_SYMBOL(coresight_unregister);
+EXPORT_SYMBOL_GPL(coresight_unregister);
static int __init coresight_init(void)
{
@@ -653,300 +671,3 @@
module_exit(coresight_exit);
MODULE_LICENSE("GPL v2");
-/*
- * Exclusion rules for structure fields.
- *
- * S: qdss.sources_mutex protected.
- * I: qdss.sink_mutex protected.
- * C: qdss.clk_mutex protected.
- */
-struct qdss_ctx {
- struct kobject *modulekobj;
- uint8_t afamily;
- struct list_head sources; /* S: sources list */
- struct mutex sources_mutex;
- uint8_t sink_count; /* I: sink count */
- struct mutex sink_mutex;
- uint8_t max_clk;
- struct clk *clk;
-};
-
-static struct qdss_ctx qdss;
-
-/**
- * qdss_get - get the qdss source handle
- * @name: name of the qdss source
- *
- * Searches the sources list to get the qdss source handle for this source.
- *
- * CONTEXT:
- * Typically called from init or probe functions
- *
- * RETURNS:
- * pointer to struct qdss_source on success, %NULL on failure
- */
-struct qdss_source *qdss_get(const char *name)
-{
- struct qdss_source *src, *source = NULL;
-
- mutex_lock(&qdss.sources_mutex);
- list_for_each_entry(src, &qdss.sources, link) {
- if (src->name) {
- if (strncmp(src->name, name, MAX_STR_LEN))
- continue;
- source = src;
- break;
- }
- }
- mutex_unlock(&qdss.sources_mutex);
-
- return source ? source : ERR_PTR(-ENOENT);
-}
-EXPORT_SYMBOL(qdss_get);
-
-/**
- * qdss_put - release the qdss source handle
- * @name: name of the qdss source
- *
- * CONTEXT:
- * Typically called from driver remove or exit functions
- */
-void qdss_put(struct qdss_source *src)
-{
-}
-EXPORT_SYMBOL(qdss_put);
-
-/**
- * qdss_enable - enable qdss for the source
- * @src: handle for the source making the call
- *
- * Enables qdss block (relevant funnel ports and sink) if not already
- * enabled, otherwise increments the reference count
- *
- * CONTEXT:
- * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
- *
- * RETURNS:
- * 0 on success, non-zero on failure
- */
-int qdss_enable(struct qdss_source *src)
-{
- if (!src)
- return -EINVAL;
-
- if (qdss.afamily) {
- mutex_lock(&qdss.sink_mutex);
- if (qdss.sink_count == 0) {
- tpiu_disable();
- /* enable ETB first to avoid losing any trace data */
- etb_enable();
- }
- qdss.sink_count++;
- mutex_unlock(&qdss.sink_mutex);
- }
-
- funnel_enable(0x0, src->fport_mask);
- return 0;
-}
-EXPORT_SYMBOL(qdss_enable);
-
-/**
- * qdss_disable - disable qdss for the source
- * @src: handle for the source making the call
- *
- * Disables qdss block (relevant funnel ports and sink) if the reference count
- * is one, otherwise decrements the reference count
- *
- * CONTEXT:
- * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
- */
-void qdss_disable(struct qdss_source *src)
-{
- if (!src)
- return;
-
- if (qdss.afamily) {
- mutex_lock(&qdss.sink_mutex);
- if (WARN(qdss.sink_count == 0, "qdss is unbalanced\n"))
- goto out;
- if (qdss.sink_count == 1) {
- etb_dump();
- etb_disable();
- }
- qdss.sink_count--;
- mutex_unlock(&qdss.sink_mutex);
- }
-
- funnel_disable(0x0, src->fport_mask);
- return;
-out:
- mutex_unlock(&qdss.sink_mutex);
-}
-EXPORT_SYMBOL(qdss_disable);
-
-/**
- * qdss_disable_sink - force disable the current qdss sink(s)
- *
- * Force disable the current qdss sink(s) to stop the sink from accepting any
- * trace generated subsequent to this call. This function should only be used
- * as a way to stop the sink from getting polluted with trace data that is
- * uninteresting after an event of interest has occured.
- *
- * CONTEXT:
- * Can be called from atomic or non-atomic context.
- */
-void qdss_disable_sink(void)
-{
- if (qdss.afamily) {
- etb_dump();
- etb_disable();
- }
-}
-EXPORT_SYMBOL(qdss_disable_sink);
-
-struct kobject *qdss_get_modulekobj(void)
-{
- return qdss.modulekobj;
-}
-
-#define QDSS_ATTR(name) \
-static struct kobj_attribute name##_attr = \
- __ATTR(name, S_IRUGO | S_IWUSR, name##_show, name##_store)
-
-static ssize_t max_clk_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- unsigned long val;
-
- if (sscanf(buf, "%lx", &val) != 1)
- return -EINVAL;
-
- qdss.max_clk = val;
- return n;
-}
-static ssize_t max_clk_show(struct kobject *kobj,
- struct kobj_attribute *attr,
- char *buf)
-{
- unsigned long val = qdss.max_clk;
- return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-QDSS_ATTR(max_clk);
-
-static void __devinit qdss_add_sources(struct qdss_source *srcs, size_t num)
-{
- mutex_lock(&qdss.sources_mutex);
- while (num--) {
- list_add_tail(&srcs->link, &qdss.sources);
- srcs++;
- }
- mutex_unlock(&qdss.sources_mutex);
-}
-
-static int __init qdss_sysfs_init(void)
-{
- int ret;
-
- qdss.modulekobj = kset_find_obj(module_kset, KBUILD_MODNAME);
- if (!qdss.modulekobj) {
- pr_err("failed to find QDSS sysfs module kobject\n");
- ret = -ENOENT;
- goto err;
- }
-
- ret = sysfs_create_file(qdss.modulekobj, &max_clk_attr.attr);
- if (ret) {
- pr_err("failed to create QDSS sysfs max_clk attribute\n");
- goto err;
- }
-
- return 0;
-err:
- return ret;
-}
-
-static void __devexit qdss_sysfs_exit(void)
-{
- sysfs_remove_file(qdss.modulekobj, &max_clk_attr.attr);
-}
-
-static int __devinit qdss_probe(struct platform_device *pdev)
-{
- int ret = 0;
- struct msm_qdss_platform_data *pdata;
-
- mutex_init(&qdss.sources_mutex);
- mutex_init(&qdss.sink_mutex);
-
- INIT_LIST_HEAD(&qdss.sources);
-
- pdata = pdev->dev.platform_data;
- if (!pdata)
- goto err_pdata;
-
- qdss.afamily = pdata->afamily;
- qdss_add_sources(pdata->src_table, pdata->size);
-
- pr_info("QDSS arch initialized\n");
- return 0;
-err_pdata:
- mutex_destroy(&qdss.sink_mutex);
- mutex_destroy(&qdss.sources_mutex);
- pr_err("QDSS init failed\n");
- return ret;
-}
-
-static int __devexit qdss_remove(struct platform_device *pdev)
-{
- qdss_sysfs_exit();
- mutex_destroy(&qdss.sink_mutex);
- mutex_destroy(&qdss.sources_mutex);
-
- return 0;
-}
-
-static struct of_device_id qdss_match[] = {
- {.compatible = "qcom,msm-qdss"},
- {}
-};
-
-static struct platform_driver qdss_driver = {
- .probe = qdss_probe,
- .remove = __devexit_p(qdss_remove),
- .driver = {
- .name = "msm_qdss",
- .owner = THIS_MODULE,
- .of_match_table = qdss_match,
- },
-};
-
-static int __init qdss_init(void)
-{
- return platform_driver_register(&qdss_driver);
-}
-arch_initcall(qdss_init);
-
-static int __init qdss_module_init(void)
-{
- int ret;
-
- ret = qdss_sysfs_init();
- if (ret)
- goto err_sysfs;
-
- pr_info("QDSS module initialized\n");
- return 0;
-err_sysfs:
- return ret;
-}
-module_init(qdss_module_init);
-
-static void __exit qdss_exit(void)
-{
- platform_driver_unregister(&qdss_driver);
-}
-module_exit(qdss_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Qualcomm Debug SubSystem Driver");
diff --git a/drivers/coresight/of_coresight.c b/drivers/coresight/of_coresight.c
new file mode 100644
index 0000000..5c2c525
--- /dev/null
+++ b/drivers/coresight/of_coresight.c
@@ -0,0 +1,99 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/coresight.h>
+
+struct coresight_platform_data *of_get_coresight_platform_data(
+ struct device *dev, struct device_node *node)
+{
+ int i, ret = 0;
+ uint32_t outports_len = 0;
+ struct device_node *child_node;
+ struct coresight_platform_data *pdata;
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ ret = of_property_read_u32(node, "coresight-id", &pdata->id);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ret = of_property_read_string(node, "coresight-name", &pdata->name);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ret = of_property_read_u32(node, "coresight-nr-inports",
+ &pdata->nr_inports);
+ if (ret)
+ return ERR_PTR(ret);
+
+ pdata->nr_outports = 0;
+ if (of_get_property(node, "coresight-outports", &outports_len))
+ pdata->nr_outports = outports_len/sizeof(uint32_t);
+
+ if (pdata->nr_outports) {
+ pdata->outports = devm_kzalloc(dev, pdata->nr_outports *
+ sizeof(*pdata->outports),
+ GFP_KERNEL);
+ if (!pdata->outports)
+ return ERR_PTR(-ENOMEM);
+
+ ret = of_property_read_u32_array(node, "coresight-outports",
+ (u32 *)pdata->outports,
+ pdata->nr_outports);
+ if (ret)
+ return ERR_PTR(ret);
+
+ pdata->child_ids = devm_kzalloc(dev, pdata->nr_outports *
+ sizeof(*pdata->child_ids),
+ GFP_KERNEL);
+ if (!pdata->child_ids)
+ return ERR_PTR(-ENOMEM);
+
+ for (i = 0; i < pdata->nr_outports; i++) {
+ child_node = of_parse_phandle(node,
+ "coresight-child-list",
+ i);
+ if (!child_node)
+ return ERR_PTR(-EINVAL);
+
+ ret = of_property_read_u32(child_node, "coresight-id",
+ (u32 *)&pdata->child_ids[i]);
+ of_node_put(child_node);
+ if (ret)
+ return ERR_PTR(ret);
+ }
+
+ pdata->child_ports = devm_kzalloc(dev, pdata->nr_outports *
+ sizeof(*pdata->child_ports),
+ GFP_KERNEL);
+ if (!pdata->child_ports)
+ return ERR_PTR(-ENOMEM);
+
+ ret = of_property_read_u32_array(node, "coresight-child-ports",
+ (u32 *)pdata->child_ports,
+ pdata->nr_outports);
+ if (ret)
+ return ERR_PTR(ret);
+ }
+
+ pdata->default_sink = of_property_read_bool(node,
+ "coresight-default-sink");
+ return pdata;
+}
+EXPORT_SYMBOL_GPL(of_get_coresight_platform_data);
diff --git a/drivers/gpio/gpio-msm-common.c b/drivers/gpio/gpio-msm-common.c
index bdb8171..46f6460 100644
--- a/drivers/gpio/gpio-msm-common.c
+++ b/drivers/gpio/gpio-msm-common.c
@@ -23,6 +23,7 @@
#include <linux/irqdomain.h>
#include <linux/of.h>
#include <linux/err.h>
+#include <linux/platform_device.h>
#include <asm/mach/irq.h>
@@ -402,59 +403,6 @@
.irq_disable = msm_gpio_irq_disable,
};
-/*
- * This lock class tells lockdep that GPIO irqs are in a different
- * category than their parent, so it won't report false recursion.
- */
-static struct lock_class_key msm_gpio_lock_class;
-
-/* TODO: This should be a real platform_driver */
-static int __devinit msm_gpio_probe(void)
-{
- int ret;
-#ifndef CONFIG_OF
- int irq, i;
-#endif
-
- spin_lock_init(&tlmm_lock);
- bitmap_zero(msm_gpio.enabled_irqs, NR_MSM_GPIOS);
- bitmap_zero(msm_gpio.wake_irqs, NR_MSM_GPIOS);
- bitmap_zero(msm_gpio.dual_edge_irqs, NR_MSM_GPIOS);
- ret = gpiochip_add(&msm_gpio.gpio_chip);
- if (ret < 0)
- return ret;
-
-#ifndef CONFIG_OF
- for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
- irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
- irq_set_lockdep_class(irq, &msm_gpio_lock_class);
- irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
- handle_level_irq);
- set_irq_flags(irq, IRQF_VALID);
- }
-#endif
- ret = request_irq(TLMM_MSM_SUMMARY_IRQ, msm_summary_irq_handler,
- IRQF_TRIGGER_HIGH, "msmgpio", NULL);
- if (ret) {
- pr_err("Request_irq failed for TLMM_MSM_SUMMARY_IRQ - %d\n",
- ret);
- return ret;
- }
- return 0;
-}
-
-static int __devexit msm_gpio_remove(void)
-{
- int ret = gpiochip_remove(&msm_gpio.gpio_chip);
-
- if (ret < 0)
- return ret;
-
- irq_set_handler(TLMM_MSM_SUMMARY_IRQ, NULL);
-
- return 0;
-}
-
#ifdef CONFIG_PM
static int msm_gpio_suspend(void)
{
@@ -518,22 +466,6 @@
.resume = msm_gpio_resume,
};
-static int __init msm_gpio_init(void)
-{
- msm_gpio_probe();
- register_syscore_ops(&msm_gpio_syscore_ops);
- return 0;
-}
-
-static void __exit msm_gpio_exit(void)
-{
- unregister_syscore_ops(&msm_gpio_syscore_ops);
- msm_gpio_remove();
-}
-
-postcore_initcall(msm_gpio_init);
-module_exit(msm_gpio_exit);
-
static void msm_tlmm_set_field(const struct tlmm_field_cfg *configs,
unsigned id, unsigned width, unsigned val)
{
@@ -594,6 +526,89 @@
}
EXPORT_SYMBOL(msm_gpio_install_direct_irq);
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parent, so it won't report false recursion.
+ */
+static struct lock_class_key msm_gpio_lock_class;
+
+static int __devinit msm_gpio_probe(struct platform_device *pdev)
+{
+ int ret;
+#ifndef CONFIG_OF
+ int irq, i;
+#endif
+ msm_gpio.gpio_chip.dev = &pdev->dev;
+ spin_lock_init(&tlmm_lock);
+ bitmap_zero(msm_gpio.enabled_irqs, NR_MSM_GPIOS);
+ bitmap_zero(msm_gpio.wake_irqs, NR_MSM_GPIOS);
+ bitmap_zero(msm_gpio.dual_edge_irqs, NR_MSM_GPIOS);
+ ret = gpiochip_add(&msm_gpio.gpio_chip);
+ if (ret < 0)
+ return ret;
+
+#ifndef CONFIG_OF
+ for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
+ irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
+ irq_set_lockdep_class(irq, &msm_gpio_lock_class);
+ irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
+ handle_level_irq);
+ set_irq_flags(irq, IRQF_VALID);
+ }
+#endif
+ ret = request_irq(TLMM_MSM_SUMMARY_IRQ, msm_summary_irq_handler,
+ IRQF_TRIGGER_HIGH, "msmgpio", NULL);
+ if (ret) {
+ pr_err("Request_irq failed for TLMM_MSM_SUMMARY_IRQ - %d\n",
+ ret);
+ return ret;
+ }
+ register_syscore_ops(&msm_gpio_syscore_ops);
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static struct of_device_id msm_gpio_of_match[] __devinitdata = {
+ {.compatible = "qcom,msm-gpio", },
+ { },
+};
+#endif
+
+static int __devexit msm_gpio_remove(struct platform_device *pdev)
+{
+ int ret;
+
+ unregister_syscore_ops(&msm_gpio_syscore_ops);
+ ret = gpiochip_remove(&msm_gpio.gpio_chip);
+ if (ret < 0)
+ return ret;
+ irq_set_handler(TLMM_MSM_SUMMARY_IRQ, NULL);
+
+ return 0;
+}
+
+static struct platform_driver msm_gpio_driver = {
+ .probe = msm_gpio_probe,
+ .remove = __devexit_p(msm_gpio_remove),
+ .driver = {
+ .name = "msmgpio",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(msm_gpio_of_match),
+ },
+};
+
+static void __exit msm_gpio_exit(void)
+{
+ platform_driver_unregister(&msm_gpio_driver);
+}
+module_exit(msm_gpio_exit);
+
+static int __init msm_gpio_init(void)
+{
+ return platform_driver_register(&msm_gpio_driver);
+}
+postcore_initcall(msm_gpio_init);
+
#ifdef CONFIG_OF
static int msm_gpio_irq_domain_xlate(struct irq_domain *d,
struct device_node *controller,
diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c
index bbcba81..ccbbd67 100644
--- a/drivers/gpio/qpnp-pin.c
+++ b/drivers/gpio/qpnp-pin.c
@@ -46,10 +46,10 @@
/* mpp peripheral type and subtype values */
#define Q_MPP_TYPE 0x11
-#define Q_MPP_SUBTYPE_4CH_NO_ANA_OUT 0x1
-#define Q_MPP_SUBTYPE_4CH_NO_SINK 0x2
-#define Q_MPP_SUBTYPE_4CH_FULL_FUNC 0x3
-#define Q_MPP_SUBTYPE_8CH_FULL_FUNC 0x7
+#define Q_MPP_SUBTYPE_4CH_NO_ANA_OUT 0x3
+#define Q_MPP_SUBTYPE_4CH_NO_SINK 0x5
+#define Q_MPP_SUBTYPE_4CH_FULL_FUNC 0x2
+#define Q_MPP_SUBTYPE_8CH_FULL_FUNC 0x4
/* control register base address offsets */
#define Q_REG_MODE_CTL 0x40
diff --git a/drivers/gpu/msm/Makefile b/drivers/gpu/msm/Makefile
index 6cdb5f1..c7ed329 100644
--- a/drivers/gpu/msm/Makefile
+++ b/drivers/gpu/msm/Makefile
@@ -35,6 +35,7 @@
msm_z180-y += \
z180.o \
+ z180_postmortem.o \
z180_trace.o
msm_kgsl_core-objs = $(msm_kgsl_core-y)
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index f7d1e59..6a894c8 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -32,8 +32,6 @@
#include "adreno.h"
#include "adreno_pm4types.h"
-#include "adreno_debugfs.h"
-#include "adreno_postmortem.h"
#include "a2xx_reg.h"
#include "a3xx_reg.h"
@@ -1639,7 +1637,7 @@
* Trigger an automatic dump of the state to
* the console
*/
- adreno_postmortem_dump(device, 0);
+ kgsl_postmortem_dump(device, 0);
/*
* Make a GPU snapshot. For now, do it after the PM dump so we
@@ -2452,6 +2450,7 @@
.drawctxt_create = adreno_drawctxt_create,
.drawctxt_destroy = adreno_drawctxt_destroy,
.setproperty = adreno_setproperty,
+ .postmortem_dump = adreno_dump,
};
static struct platform_driver adreno_platform_driver = {
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 279e7ed..b923049e 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -49,6 +49,8 @@
#define ADRENO_DEFAULT_PWRSCALE_POLICY NULL
#endif
+void adreno_debugfs_init(struct kgsl_device *device);
+
#define ADRENO_ISTORE_START 0x5000 /* Istore offset */
#define ADRENO_NUM_CTX_SWITCH_ALLOWED_BEFORE_DRAW 50
@@ -166,6 +168,8 @@
void adreno_regwrite(struct kgsl_device *device, unsigned int offsetwords,
unsigned int value);
+int adreno_dump(struct kgsl_device *device, int manual);
+
struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device,
unsigned int pt_base,
unsigned int gpuaddr,
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index e3c9a18..bb3da40 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -18,67 +18,11 @@
#include <linux/io.h>
#include "kgsl.h"
-#include "adreno_postmortem.h"
#include "adreno.h"
#include "a2xx_reg.h"
unsigned int kgsl_cff_dump_enable;
-int adreno_pm_regs_enabled;
-int adreno_pm_ib_enabled;
-
-static struct dentry *pm_d_debugfs;
-
-static int pm_dump_set(void *data, u64 val)
-{
- struct kgsl_device *device = data;
-
- if (val) {
- mutex_lock(&device->mutex);
- adreno_postmortem_dump(device, 1);
- mutex_unlock(&device->mutex);
- }
-
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(pm_dump_fops,
- NULL,
- pm_dump_set, "%llu\n");
-
-static int pm_regs_enabled_set(void *data, u64 val)
-{
- adreno_pm_regs_enabled = val ? 1 : 0;
- return 0;
-}
-
-static int pm_regs_enabled_get(void *data, u64 *val)
-{
- *val = adreno_pm_regs_enabled;
- return 0;
-}
-
-static int pm_ib_enabled_set(void *data, u64 val)
-{
- adreno_pm_ib_enabled = val ? 1 : 0;
- return 0;
-}
-
-static int pm_ib_enabled_get(void *data, u64 *val)
-{
- *val = adreno_pm_ib_enabled;
- return 0;
-}
-
-
-DEFINE_SIMPLE_ATTRIBUTE(pm_regs_enabled_fops,
- pm_regs_enabled_get,
- pm_regs_enabled_set, "%llu\n");
-
-DEFINE_SIMPLE_ATTRIBUTE(pm_ib_enabled_fops,
- pm_ib_enabled_get,
- pm_ib_enabled_set, "%llu\n");
-
static int kgsl_cff_dump_enable_set(void *data, u64 val)
{
@@ -116,23 +60,9 @@
&adreno_dev->wait_timeout);
debugfs_create_u32("ib_check", 0644, device->d_debugfs,
&adreno_dev->ib_check_level);
-
/* By Default enable fast hang detection */
adreno_dev->fast_hang_detect = 1;
debugfs_create_u32("fast_hang_detect", 0644, device->d_debugfs,
&adreno_dev->fast_hang_detect);
- /* Create post mortem control files */
-
- pm_d_debugfs = debugfs_create_dir("postmortem", device->d_debugfs);
-
- if (IS_ERR(pm_d_debugfs))
- return;
-
- debugfs_create_file("dump", 0600, pm_d_debugfs, device,
- &pm_dump_fops);
- debugfs_create_file("regs_enabled", 0644, pm_d_debugfs, device,
- &pm_regs_enabled_fops);
- debugfs_create_file("ib_enabled", 0644, pm_d_debugfs, device,
- &pm_ib_enabled_fops);
}
diff --git a/drivers/gpu/msm/adreno_debugfs.h b/drivers/gpu/msm/adreno_debugfs.h
deleted file mode 100644
index 5f8d89a..0000000
--- a/drivers/gpu/msm/adreno_debugfs.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Copyright (c) 2002,2008-2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-#ifndef __ADRENO_DEBUGFS_H
-#define __ADRENO_DEBUGFS_H
-
-#ifdef CONFIG_DEBUG_FS
-
-int adreno_debugfs_init(struct kgsl_device *device);
-
-extern int adreno_pm_regs_enabled;
-extern int adreno_pm_ib_enabled;
-
-static inline int is_adreno_pm_regs_enabled(void)
-{
- return adreno_pm_regs_enabled;
-}
-
-static inline int is_adreno_pm_ib_enabled(void)
-{
- return adreno_pm_ib_enabled;
-}
-
-#else
-static inline int adreno_debugfs_init(struct kgsl_device *device)
-{
- return 0;
-}
-
-static inline int kgsl_pmregs_enabled(void)
-{
- /* If debugfs is turned off, then always print registers */
- return 1;
-}
-#endif
-
-#endif /* __ADRENO_DEBUGFS_H */
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 3cc4bcf..2038c10 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -19,8 +19,6 @@
#include "adreno.h"
#include "adreno_pm4types.h"
#include "adreno_ringbuffer.h"
-#include "adreno_postmortem.h"
-#include "adreno_debugfs.h"
#include "kgsl_cffdump.h"
#include "kgsl_pwrctrl.h"
@@ -678,7 +676,7 @@
"MH_INTERRUPT: MASK = %08X | STATUS = %08X\n", r1, r2);
}
-static int adreno_dump(struct kgsl_device *device)
+int adreno_dump(struct kgsl_device *device, int manual)
{
unsigned int cp_ib1_base, cp_ib1_bufsz;
unsigned int cp_ib2_base, cp_ib2_bufsz;
@@ -834,7 +832,7 @@
cp_rb_base, cp_rb_rptr, cp_rb_wptr, read_idx);
adreno_dump_rb(device, rb_copy, num_item<<2, read_idx, rb_count);
- if (is_adreno_pm_ib_enabled()) {
+ if (device->pm_ib_enabled) {
for (read_idx = NUM_DWORDS_OF_RINGBUFFER_HISTORY;
read_idx >= 0; --read_idx) {
uint32_t this_cmd = rb_copy[read_idx];
@@ -865,7 +863,7 @@
}
/* Dump the registers if the user asked for it */
- if (is_adreno_pm_regs_enabled()) {
+ if (device->pm_regs_enabled) {
if (adreno_is_a20x(adreno_dev))
adreno_dump_regs(device, a200_registers,
a200_registers_count);
@@ -885,85 +883,3 @@
end:
return result;
}
-
-/**
- * adreno_postmortem_dump - Dump the current GPU state
- * @device - A pointer to the KGSL device to dump
- * @manual - A flag that indicates if this was a manually triggered
- * dump (from debugfs). If zero, then this is assumed to be a
- * dump automaticlaly triggered from a hang
-*/
-
-int adreno_postmortem_dump(struct kgsl_device *device, int manual)
-{
- bool saved_nap;
- struct kgsl_pwrctrl *pwr = &device->pwrctrl;
-
- BUG_ON(device == NULL);
-
- kgsl_cffdump_hang(device->id);
-
- /* For a manual dump, make sure that the system is idle */
-
- if (manual) {
- if (device->active_cnt != 0) {
- mutex_unlock(&device->mutex);
- wait_for_completion(&device->suspend_gate);
- mutex_lock(&device->mutex);
- }
-
- if (device->state == KGSL_STATE_ACTIVE)
- kgsl_idle(device, KGSL_TIMEOUT_DEFAULT);
-
- }
- KGSL_LOG_DUMP(device, "POWER: FLAGS = %08lX | ACTIVE POWERLEVEL = %08X",
- pwr->power_flags, pwr->active_pwrlevel);
-
- KGSL_LOG_DUMP(device, "POWER: INTERVAL TIMEOUT = %08X ",
- pwr->interval_timeout);
-
- KGSL_LOG_DUMP(device, "GRP_CLK = %lu ",
- kgsl_get_clkrate(pwr->grp_clks[0]));
-
- KGSL_LOG_DUMP(device, "BUS CLK = %lu ",
- kgsl_get_clkrate(pwr->ebi1_clk));
-
- /* Disable the idle timer so we don't get interrupted */
- del_timer_sync(&device->idle_timer);
- mutex_unlock(&device->mutex);
- flush_workqueue(device->work_queue);
- mutex_lock(&device->mutex);
-
- /* Turn off napping to make sure we have the clocks full
- attention through the following process */
- saved_nap = device->pwrctrl.nap_allowed;
- device->pwrctrl.nap_allowed = false;
-
- /* Force on the clocks */
- kgsl_pwrctrl_wake(device);
-
- /* Disable the irq */
- kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
-
- adreno_dump(device);
-
- /* Restore nap mode */
- device->pwrctrl.nap_allowed = saved_nap;
-
- /* On a manual trigger, turn on the interrupts and put
- the clocks to sleep. They will recover themselves
- on the next event. For a hang, leave things as they
- are until recovery kicks in. */
-
- if (manual) {
- kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
-
- /* try to go into a sleep mode until the next event */
- kgsl_pwrctrl_request_state(device, KGSL_STATE_SLEEP);
- kgsl_pwrctrl_sleep(device);
- }
-
- KGSL_DRV_ERR(device, "Dump Finished\n");
-
- return 0;
-}
diff --git a/drivers/gpu/msm/adreno_postmortem.h b/drivers/gpu/msm/adreno_postmortem.h
deleted file mode 100644
index b677800..0000000
--- a/drivers/gpu/msm/adreno_postmortem.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __ADRENO_POSTMORTEM_H
-#define __ADRENO_POSTMORTEM_H
-
-struct kgsl_device;
-
-int adreno_postmortem_dump(struct kgsl_device *device, int manual);
-
-#endif /* __ADRENO_POSTMORTEM_H */
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 49786ba..ca9e335 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -22,7 +22,6 @@
#include "adreno.h"
#include "adreno_pm4types.h"
#include "adreno_ringbuffer.h"
-#include "adreno_debugfs.h"
#include "a2xx_reg.h"
#include "a3xx_reg.h"
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 62e1521..3d83508 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -649,6 +649,7 @@
struct kgsl_device, display_off);
KGSL_PWR_WARN(device, "early suspend start\n");
mutex_lock(&device->mutex);
+ device->pwrctrl.restore_slumber = true;
kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER);
kgsl_pwrctrl_sleep(device);
mutex_unlock(&device->mutex);
@@ -677,7 +678,7 @@
struct kgsl_device, display_off);
KGSL_PWR_WARN(device, "late resume start\n");
mutex_lock(&device->mutex);
- device->pwrctrl.restore_slumber = 0;
+ device->pwrctrl.restore_slumber = false;
if (device->pwrscale.policy == NULL)
kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_TURBO);
kgsl_pwrctrl_wake(device);
@@ -2176,7 +2177,7 @@
static long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
{
struct kgsl_device_private *dev_priv = filep->private_data;
- unsigned int nr = _IOC_NR(cmd);
+ unsigned int nr;
kgsl_ioctl_func_t func;
int lock, ret;
char ustack[64];
@@ -2192,6 +2193,8 @@
else if (cmd == IOCTL_KGSL_CMDSTREAM_READTIMESTAMP_OLD)
cmd = IOCTL_KGSL_CMDSTREAM_READTIMESTAMP;
+ nr = _IOC_NR(cmd);
+
if (cmd & (IOC_IN | IOC_OUT)) {
if (_IOC_SIZE(cmd) < sizeof(ustack))
uptr = ustack;
@@ -2216,7 +2219,20 @@
}
if (nr < ARRAY_SIZE(kgsl_ioctl_funcs) &&
- kgsl_ioctl_funcs[nr].func != NULL) {
+ kgsl_ioctl_funcs[nr].func != NULL) {
+
+ /*
+ * Make sure that nobody tried to send us a malformed ioctl code
+ * with a valid NR but bogus flags
+ */
+
+ if (kgsl_ioctl_funcs[nr].cmd != cmd) {
+ KGSL_DRV_ERR(dev_priv->device,
+ "Malformed ioctl code %08x\n", cmd);
+ ret = -ENOIOCTLCMD;
+ goto done;
+ }
+
func = kgsl_ioctl_funcs[nr].func;
lock = kgsl_ioctl_funcs[nr].lock;
} else {
@@ -2570,6 +2586,83 @@
}
EXPORT_SYMBOL(kgsl_device_platform_probe);
+int kgsl_postmortem_dump(struct kgsl_device *device, int manual)
+{
+ bool saved_nap;
+ struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+
+ BUG_ON(device == NULL);
+
+ kgsl_cffdump_hang(device->id);
+
+ /* For a manual dump, make sure that the system is idle */
+
+ if (manual) {
+ if (device->active_cnt != 0) {
+ mutex_unlock(&device->mutex);
+ wait_for_completion(&device->suspend_gate);
+ mutex_lock(&device->mutex);
+ }
+
+ if (device->state == KGSL_STATE_ACTIVE)
+ kgsl_idle(device, KGSL_TIMEOUT_DEFAULT);
+
+ }
+ KGSL_LOG_DUMP(device, "|%s| Dump Started\n", device->name);
+ KGSL_LOG_DUMP(device, "POWER: FLAGS = %08lX | ACTIVE POWERLEVEL = %08X",
+ pwr->power_flags, pwr->active_pwrlevel);
+
+ KGSL_LOG_DUMP(device, "POWER: INTERVAL TIMEOUT = %08X ",
+ pwr->interval_timeout);
+
+ KGSL_LOG_DUMP(device, "GRP_CLK = %lu ",
+ kgsl_get_clkrate(pwr->grp_clks[0]));
+
+ KGSL_LOG_DUMP(device, "BUS CLK = %lu ",
+ kgsl_get_clkrate(pwr->ebi1_clk));
+
+ /* Disable the idle timer so we don't get interrupted */
+ del_timer_sync(&device->idle_timer);
+ mutex_unlock(&device->mutex);
+ flush_workqueue(device->work_queue);
+ mutex_lock(&device->mutex);
+
+ /* Turn off napping to make sure we have the clocks full
+ attention through the following process */
+ saved_nap = device->pwrctrl.nap_allowed;
+ device->pwrctrl.nap_allowed = false;
+
+ /* Force on the clocks */
+ kgsl_pwrctrl_wake(device);
+
+ /* Disable the irq */
+ kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
+
+ /*Call the device specific postmortem dump function*/
+ device->ftbl->postmortem_dump(device, manual);
+
+ /* Restore nap mode */
+ device->pwrctrl.nap_allowed = saved_nap;
+
+ /* On a manual trigger, turn on the interrupts and put
+ the clocks to sleep. They will recover themselves
+ on the next event. For a hang, leave things as they
+ are until recovery kicks in. */
+
+ if (manual) {
+ kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
+
+ /* try to go into a sleep mode until the next event */
+ kgsl_pwrctrl_request_state(device, KGSL_STATE_SLEEP);
+ kgsl_pwrctrl_sleep(device);
+ }
+
+ KGSL_LOG_DUMP(device, "|%s| Dump Finished\n", device->name);
+
+ return 0;
+}
+EXPORT_SYMBOL(kgsl_postmortem_dump);
+
void kgsl_device_platform_remove(struct kgsl_device *device)
{
kgsl_device_snapshot_close(device);
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 8a3345b..ac04c56 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -173,6 +173,7 @@
#endif
void kgsl_mem_entry_destroy(struct kref *kref);
+int kgsl_postmortem_dump(struct kgsl_device *device, int manual);
struct kgsl_mem_entry *kgsl_get_mem_entry(unsigned int ptbase,
unsigned int gpuaddr, unsigned int size);
diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c
index 328dd95..545d2b3 100644
--- a/drivers/gpu/msm/kgsl_debugfs.c
+++ b/drivers/gpu/msm/kgsl_debugfs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2008-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2008-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
@@ -22,6 +22,60 @@
#define KGSL_LOG_LEVEL_MAX 7
struct dentry *kgsl_debugfs_dir;
+static struct dentry *pm_d_debugfs;
+
+static int pm_dump_set(void *data, u64 val)
+{
+ struct kgsl_device *device = data;
+
+ if (val) {
+ mutex_lock(&device->mutex);
+ kgsl_postmortem_dump(device, 1);
+ mutex_unlock(&device->mutex);
+ }
+
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(pm_dump_fops,
+ NULL,
+ pm_dump_set, "%llu\n");
+
+static int pm_regs_enabled_set(void *data, u64 val)
+{
+ struct kgsl_device *device = data;
+ device->pm_regs_enabled = val ? 1 : 0;
+ return 0;
+}
+
+static int pm_regs_enabled_get(void *data, u64 *val)
+{
+ struct kgsl_device *device = data;
+ *val = device->pm_regs_enabled;
+ return 0;
+}
+
+static int pm_ib_enabled_set(void *data, u64 val)
+{
+ struct kgsl_device *device = data;
+ device->pm_ib_enabled = val ? 1 : 0;
+ return 0;
+}
+
+static int pm_ib_enabled_get(void *data, u64 *val)
+{
+ struct kgsl_device *device = data;
+ *val = device->pm_ib_enabled;
+ return 0;
+}
+
+
+DEFINE_SIMPLE_ATTRIBUTE(pm_regs_enabled_fops,
+ pm_regs_enabled_get,
+ pm_regs_enabled_set, "%llu\n");
+
+DEFINE_SIMPLE_ATTRIBUTE(pm_ib_enabled_fops,
+ pm_ib_enabled_get,
+ pm_ib_enabled_set, "%llu\n");
static inline int kgsl_log_set(unsigned int *log_val, void *data, u64 val)
{
@@ -75,6 +129,21 @@
&mem_log_fops);
debugfs_create_file("log_level_pwr", 0644, device->d_debugfs, device,
&pwr_log_fops);
+
+ /* Create postmortem dump control files */
+
+ pm_d_debugfs = debugfs_create_dir("postmortem", device->d_debugfs);
+
+ if (IS_ERR(pm_d_debugfs))
+ return;
+
+ debugfs_create_file("dump", 0600, pm_d_debugfs, device,
+ &pm_dump_fops);
+ debugfs_create_file("regs_enabled", 0644, pm_d_debugfs, device,
+ &pm_regs_enabled_fops);
+ debugfs_create_file("ib_enabled", 0644, pm_d_debugfs, device,
+ &pm_ib_enabled_fops);
+
}
void kgsl_core_debugfs_init(void)
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 0336a20..d0932ef 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -110,6 +110,7 @@
int (*setproperty) (struct kgsl_device *device,
enum kgsl_property_type type, void *value,
unsigned int sizebytes);
+ int (*postmortem_dump) (struct kgsl_device *device, int manual);
};
/* MH register values */
@@ -196,6 +197,10 @@
struct work_struct ts_expired_ws;
struct list_head events;
s64 on_time;
+
+ /* Postmortem Control switches */
+ int pm_regs_enabled;
+ int pm_ib_enabled;
};
void kgsl_timestamp_expired(struct work_struct *work);
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index c02274d..8e6c5c0 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -24,7 +24,6 @@
#include "kgsl_mmu.h"
#include "kgsl_device.h"
#include "kgsl_sharedmem.h"
-#include "adreno_postmortem.h"
#define KGSL_MMU_ALIGN_SHIFT 13
#define KGSL_MMU_ALIGN_MASK (~((1 << KGSL_MMU_ALIGN_SHIFT) - 1))
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 6d4d4d3..4b5021d 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -800,14 +800,12 @@
case KGSL_STATE_ACTIVE:
if (!device->ftbl->isidle(device)) {
kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
- device->pwrctrl.restore_slumber = true;
return -EBUSY;
}
/* fall through */
case KGSL_STATE_NAP:
case KGSL_STATE_SLEEP:
del_timer_sync(&device->idle_timer);
- device->pwrctrl.restore_slumber = true;
device->ftbl->suspend_context(device);
device->ftbl->stop(device);
_sleep_accounting(device);
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 3504dfc..9037f3c 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -25,9 +25,6 @@
#define DRIVER_VERSION_MAJOR 3
#define DRIVER_VERSION_MINOR 1
-#define Z180_DEVICE(device) \
- KGSL_CONTAINER_OF(device, struct z180_device, dev)
-
#define GSL_VGC_INT_MASK \
(REG_VGC_IRQSTATUS__MH_MASK | \
REG_VGC_IRQSTATUS__G2D_MASK | \
@@ -41,16 +38,12 @@
#define VGV3_CONTROL_MARKADD_FSHIFT 0
#define VGV3_CONTROL_MARKADD_FMASK 0xfff
-#define Z180_PACKET_SIZE 15
#define Z180_MARKER_SIZE 10
#define Z180_CALL_CMD 0x1000
#define Z180_MARKER_CMD 0x8000
#define Z180_STREAM_END_CMD 0x9000
#define Z180_STREAM_PACKET 0x7C000176
#define Z180_STREAM_PACKET_CALL 0x7C000275
-#define Z180_PACKET_COUNT 8
-#define Z180_RB_SIZE (Z180_PACKET_SIZE*Z180_PACKET_COUNT \
- *sizeof(uint32_t))
#define NUMTEXUNITS 4
#define TEXUNITREGCOUNT 25
@@ -846,6 +839,7 @@
else if (timeout == 0) {
status = -ETIMEDOUT;
kgsl_pwrctrl_set_state(device, KGSL_STATE_HUNG);
+ kgsl_postmortem_dump(device, 0);
} else
status = timeout;
@@ -936,6 +930,7 @@
.drawctxt_create = NULL,
.drawctxt_destroy = z180_drawctxt_destroy,
.ioctl = NULL,
+ .postmortem_dump = z180_dump,
};
static struct platform_device_id z180_id_table[] = {
diff --git a/drivers/gpu/msm/z180.h b/drivers/gpu/msm/z180.h
index e5c5ef3..6e81a9d 100644
--- a/drivers/gpu/msm/z180.h
+++ b/drivers/gpu/msm/z180.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,13 @@
#define DEVICE_2D0_NAME "kgsl-2d0"
#define DEVICE_2D1_NAME "kgsl-2d1"
+#define Z180_PACKET_SIZE 15
+#define Z180_PACKET_COUNT 8
+#define Z180_RB_SIZE (Z180_PACKET_SIZE*Z180_PACKET_COUNT \
+ *sizeof(uint32_t))
+#define Z180_DEVICE(device) \
+ KGSL_CONTAINER_OF(device, struct z180_device, dev)
+
#define Z180_DEFAULT_PWRSCALE_POLICY NULL
struct z180_ringbuffer {
@@ -34,4 +41,6 @@
spinlock_t cmdwin_lock;
};
+int z180_dump(struct kgsl_device *, int);
+
#endif /* __Z180_H */
diff --git a/drivers/gpu/msm/z180_postmortem.c b/drivers/gpu/msm/z180_postmortem.c
new file mode 100644
index 0000000..a9b0c50
--- /dev/null
+++ b/drivers/gpu/msm/z180_postmortem.c
@@ -0,0 +1,229 @@
+/* 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 "kgsl.h"
+#include "kgsl_device.h"
+#include "z180.h"
+#include "z180_reg.h"
+
+#define Z180_STREAM_PACKET_CALL 0x7C000275
+
+/* Postmortem Dump formatted Output parameters */
+
+/* Number of Words per dump data line */
+#define WORDS_PER_LINE 8
+
+/* Number of spaces per dump data line */
+#define NUM_SPACES (WORDS_PER_LINE - 1)
+
+/*
+ * Output dump data is formatted as string, hence number of chars
+ * per line for line string allocation
+ */
+#define CHARS_PER_LINE \
+ ((WORDS_PER_LINE * (2*sizeof(unsigned int))) + NUM_SPACES + 1)
+
+/* Z180 registers (byte offsets) to be dumped */
+static const unsigned int regs_to_dump[] = {
+ ADDR_VGC_VERSION,
+ ADDR_VGC_SYSSTATUS,
+ ADDR_VGC_IRQSTATUS,
+ ADDR_VGC_IRQENABLE,
+ ADDR_VGC_IRQ_ACTIVE_CNT,
+ ADDR_VGC_CLOCKEN,
+ ADDR_VGC_MH_DATA_ADDR,
+ ADDR_VGC_GPR0,
+ ADDR_VGC_GPR1,
+ ADDR_VGC_BUSYCNT,
+ ADDR_VGC_FIFOFREE,
+};
+
+/**
+ * z180_dump_regs - Dumps all of Z180 external registers. Prints the word offset
+ * of the register in each output line.
+ * @device: kgsl_device pointer to the Z180 core
+ */
+static void z180_dump_regs(struct kgsl_device *device)
+{
+ unsigned int i;
+ unsigned int reg_val;
+
+ KGSL_LOG_DUMP(device, "Z180 Register Dump\n");
+ for (i = 0; i < ARRAY_SIZE(regs_to_dump); i++) {
+ kgsl_regread(device,
+ regs_to_dump[i]/sizeof(unsigned int), ®_val);
+ KGSL_LOG_DUMP(device, "REG: %04X: %08X\n",
+ regs_to_dump[i]/sizeof(unsigned int), reg_val);
+ }
+}
+
+/**
+ * z180_dump_ringbuffer - Dumps the Z180 core's ringbuffer contents
+ * @device: kgsl_device pointer to the z180 core
+ */
+static void z180_dump_ringbuffer(struct kgsl_device *device)
+{
+ unsigned int rb_size;
+ unsigned int *rb_hostptr;
+ unsigned int rb_words;
+ unsigned int rb_gpuaddr;
+ struct z180_device *z180_dev = Z180_DEVICE(device);
+ unsigned int i;
+ char linebuf[CHARS_PER_LINE];
+
+ KGSL_LOG_DUMP(device, "Z180 ringbuffer dump\n");
+
+ rb_hostptr = (unsigned int *) z180_dev->ringbuffer.cmdbufdesc.hostptr;
+
+ rb_size = Z180_RB_SIZE;
+ rb_gpuaddr = z180_dev->ringbuffer.cmdbufdesc.gpuaddr;
+
+ rb_words = rb_size/sizeof(unsigned int);
+
+ KGSL_LOG_DUMP(device, "ringbuffer size: %u\n", rb_size);
+
+ KGSL_LOG_DUMP(device, "rb_words: %d\n", rb_words);
+
+ for (i = 0; i < rb_words; i += WORDS_PER_LINE) {
+ hex_dump_to_buffer(rb_hostptr+i,
+ rb_size - i*sizeof(unsigned int),
+ WORDS_PER_LINE*sizeof(unsigned int),
+ sizeof(unsigned int), linebuf,
+ sizeof(linebuf), false);
+ KGSL_LOG_DUMP(device, "RB: %04X: %s\n",
+ rb_gpuaddr + i*sizeof(unsigned int), linebuf);
+ }
+}
+
+
+static void z180_dump_ib(struct kgsl_device *device)
+{
+ unsigned int rb_size;
+ unsigned int *rb_hostptr;
+ unsigned int rb_words;
+ unsigned int rb_gpuaddr;
+ unsigned int ib_gpuptr = 0;
+ unsigned int ib_size = 0;
+ void *ib_hostptr = NULL;
+ int rb_slot_num = -1;
+ struct z180_device *z180_dev = Z180_DEVICE(device);
+ struct kgsl_mem_entry *entry = NULL;
+ unsigned int pt_base;
+ unsigned int i;
+ unsigned int j;
+ char linebuf[CHARS_PER_LINE];
+ unsigned int current_ib_slot;
+ unsigned int len;
+ unsigned int rowsize;
+ KGSL_LOG_DUMP(device, "Z180 IB dump\n");
+
+ rb_hostptr = (unsigned int *) z180_dev->ringbuffer.cmdbufdesc.hostptr;
+
+ rb_size = Z180_RB_SIZE;
+ rb_gpuaddr = z180_dev->ringbuffer.cmdbufdesc.gpuaddr;
+
+ rb_words = rb_size/sizeof(unsigned int);
+
+ KGSL_LOG_DUMP(device, "Ringbuffer size (bytes): %u\n", rb_size);
+
+ KGSL_LOG_DUMP(device, "rb_words: %d\n", rb_words);
+
+ pt_base = kgsl_mmu_get_current_ptbase(&device->mmu);
+
+ /* Dump the current IB */
+ for (i = 0; i < rb_words; i++) {
+ if (rb_hostptr[i] == Z180_STREAM_PACKET_CALL) {
+
+ rb_slot_num++;
+ current_ib_slot =
+ z180_dev->current_timestamp % Z180_PACKET_COUNT;
+ if (rb_slot_num != current_ib_slot)
+ continue;
+
+ ib_gpuptr = rb_hostptr[i+1];
+
+ entry = kgsl_get_mem_entry(pt_base, ib_gpuptr, 1);
+
+ if (entry == NULL) {
+ KGSL_LOG_DUMP(device,
+ "IB mem entry not found for ringbuffer slot#: %d\n",
+ rb_slot_num);
+ continue;
+ }
+
+ ib_hostptr = kgsl_memdesc_map(&entry->memdesc);
+
+ if (ib_hostptr == NULL) {
+ KGSL_LOG_DUMP(device,
+ "Could not map IB to kernel memory, Ringbuffer Slot: %d\n",
+ rb_slot_num);
+ continue;
+ }
+
+ ib_size = entry->memdesc.size;
+ KGSL_LOG_DUMP(device,
+ "IB size: %dbytes, IB size in words: %d\n",
+ ib_size,
+ ib_size/sizeof(unsigned int));
+
+ for (j = 0; j < ib_size; j += WORDS_PER_LINE) {
+ len = ib_size - j*sizeof(unsigned int);
+ rowsize = WORDS_PER_LINE*sizeof(unsigned int);
+ hex_dump_to_buffer(ib_hostptr+j, len, rowsize,
+ sizeof(unsigned int), linebuf,
+ sizeof(linebuf), false);
+ KGSL_LOG_DUMP(device, "IB%d: %04X: %s\n",
+ rb_slot_num,
+ (rb_gpuaddr +
+ j*sizeof(unsigned int)),
+ linebuf);
+ }
+ KGSL_LOG_DUMP(device, "IB Dump Finished\n");
+ }
+ }
+}
+
+
+/**
+ * z180_dump - Dumps the Z180 ringbuffer and registers (and IBs if asked for)
+ * for postmortem
+ * analysis.
+ * @device: kgsl_device pointer to the Z180 core
+ */
+int z180_dump(struct kgsl_device *device, int manual)
+{
+ struct z180_device *z180_dev = Z180_DEVICE(device);
+
+ mb();
+
+ KGSL_LOG_DUMP(device, "Retired Timestamp: %d\n", z180_dev->timestamp);
+ KGSL_LOG_DUMP(device,
+ "Current Timestamp: %d\n", z180_dev->current_timestamp);
+
+ /* Dump ringbuffer */
+ z180_dump_ringbuffer(device);
+
+ /* Dump registers */
+ z180_dump_regs(device);
+
+ /* Dump IBs, if asked for */
+ if (device->pm_ib_enabled)
+ z180_dump_ib(device);
+
+ /* Get the stack trace if the dump was automatic */
+ if (!manual)
+ BUG_ON(1);
+
+ return 0;
+}
+
diff --git a/drivers/gpu/msm/z180_reg.h b/drivers/gpu/msm/z180_reg.h
index 5b6c001..07d60b9 100644
--- a/drivers/gpu/msm/z180_reg.h
+++ b/drivers/gpu/msm/z180_reg.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -45,5 +45,12 @@
#define ADDR_VGV3_NEXTADDR 0x0075
#define ADDR_VGV3_NEXTCMD 0x0076
#define ADDR_VGV3_WRITEADDR 0x0072
+#define ADDR_VGC_VERSION 0x400
+#define ADDR_VGC_SYSSTATUS 0x410
+#define ADDR_VGC_CLOCKEN 0x508
+#define ADDR_VGC_GPR0 0x520
+#define ADDR_VGC_GPR1 0x528
+#define ADDR_VGC_BUSYCNT 0x530
+#define ADDR_VGC_FIFOFREE 0x7c0
#endif /* __Z180_REG_H */
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index e24eeaf..c122270 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -111,7 +111,7 @@
struct qpnp_vadc_amux *adc_channel_list;
struct qpnp_adc_properties *adc_prop;
struct qpnp_adc_amux_properties *amux_prop;
- int count_adc_channel_list = 0, decimation, rc = 0;
+ int count_adc_channel_list = 0, decimation, rc = 0, i = 0;
if (!node)
return -EINVAL;
@@ -133,7 +133,7 @@
return -ENOMEM;
}
adc_channel_list = devm_kzalloc(&spmi->dev,
- (sizeof(struct qpnp_vadc_amux) * count_adc_channel_list),
+ sizeof(struct qpnp_vadc_amux) * count_adc_channel_list,
GFP_KERNEL);
if (!adc_channel_list) {
dev_err(&spmi->dev, "Unable to allocate memory\n");
@@ -148,9 +148,12 @@
return -ENOMEM;
}
+ adc_qpnp->adc_channels = adc_channel_list;
+ adc_qpnp->amux_prop = amux_prop;
+
for_each_child_of_node(node, child) {
int channel_num, scaling, post_scaling, hw_settle_time;
- int fast_avg_setup, calib_type, i = 0, rc;
+ int fast_avg_setup, calib_type, rc;
const char *calibration_param, *channel_name;
channel_name = of_get_property(child,
@@ -216,8 +219,6 @@
adc_channel_list[i].fast_avg_setup = fast_avg_setup;
i++;
}
- adc_qpnp->adc_channels = adc_channel_list;
- adc_qpnp->amux_prop = amux_prop;
/* Get the ADC VDD reference voltage and ADC bit resolution */
rc = of_property_read_u32(node, "qcom,adc-vdd-reference",
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 95da3b9..b689255 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -142,7 +142,7 @@
int rc;
rc = spmi_ext_register_readl(iadc->adc->spmi->ctrl, iadc->adc->slave,
- reg, data, 1);
+ (iadc->adc->offset + reg), data, 1);
if (rc < 0) {
pr_err("qpnp iadc read reg %d failed with %d\n", reg, rc);
return rc;
@@ -159,7 +159,7 @@
buf = &data;
rc = spmi_ext_register_writel(iadc->adc->spmi->ctrl, iadc->adc->slave,
- reg, buf, 1);
+ (iadc->adc->offset + reg), buf, 1);
if (rc < 0) {
pr_err("qpnp iadc write reg %d failed with %d\n", reg, rc);
return rc;
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 8d6d411..9e8a2e2 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -37,6 +37,7 @@
#define QPNP_VADC_STATUS1_MEAS_INTERVAL_EN_STS BIT(2)
#define QPNP_VADC_STATUS1_REQ_STS BIT(1)
#define QPNP_VADC_STATUS1_EOC BIT(0)
+#define QPNP_VADC_STATUS1_REQ_STS_EOC_MASK 0x3
#define QPNP_VADC_STATUS2 0x9
#define QPNP_VADC_STATUS2_CONV_SEQ_STATE 6
#define QPNP_VADC_STATUS2_FIFO_NOT_EMPTY_FLAG BIT(1)
@@ -112,7 +113,7 @@
int rc;
rc = spmi_ext_register_readl(vadc->adc->spmi->ctrl, vadc->adc->slave,
- reg, data, 1);
+ (vadc->adc->offset + reg), data, 1);
if (rc < 0) {
pr_err("qpnp adc read reg %d failed with %d\n", reg, rc);
return rc;
@@ -130,7 +131,7 @@
buf = &data;
rc = spmi_ext_register_writel(vadc->adc->spmi->ctrl, vadc->adc->slave,
- reg, buf, 1);
+ (vadc->adc->offset + reg), buf, 1);
if (rc < 0) {
pr_err("qpnp adc write reg %d failed with %d\n", reg, rc);
return rc;
@@ -200,61 +201,87 @@
int32_t qpnp_vadc_configure(
struct qpnp_adc_amux_properties *chan_prop)
{
+ struct qpnp_vadc_drv *vadc = qpnp_vadc;
u8 decimation = 0, conv_sequence = 0, conv_sequence_trig = 0;
+ u8 mode_ctrl = 0;
int rc = 0;
- rc = qpnp_vadc_write_reg(QPNP_VADC_INT_EN_SET,
+ if (vadc->vadc_init_calib) {
+ /* Configure interrupt if calibration is complete */
+ rc = qpnp_vadc_write_reg(QPNP_VADC_INT_EN_SET,
QPNP_VADC_INT_EOC_BIT);
+ if (rc < 0) {
+ pr_err("Configure error for interrupt setup\n");
+ return rc;
+ }
+ }
+
+ /* Mode selection */
+ rc = qpnp_vadc_read_reg(QPNP_VADC_MODE_CTL, &mode_ctrl);
if (rc < 0) {
- pr_err("qpnp adc configure error for interrupt setup\n");
+ pr_err("Mode configure read error\n");
+ return rc;
+ }
+ mode_ctrl |= chan_prop->mode_sel << QPNP_VADC_OP_MODE_SHIFT;
+ rc = qpnp_vadc_write_reg(QPNP_VADC_MODE_CTL, mode_ctrl);
+ if (rc < 0) {
+ pr_err("Mode configure write error\n");
return rc;
}
- rc = qpnp_vadc_write_reg(QPNP_VADC_MODE_CTL, chan_prop->mode_sel);
- if (rc < 0) {
- pr_err("qpnp adc configure error for mode selection\n");
+ rc = qpnp_vadc_enable(true);
+ if (rc)
return rc;
- }
+ /* Channel selection */
rc = qpnp_vadc_write_reg(QPNP_VADC_ADC_CH_SEL_CTL,
chan_prop->amux_channel);
if (rc < 0) {
- pr_err("qpnp adc configure error for channel selection\n");
+ pr_err("Channel configure error\n");
return rc;
}
+ /* Digital parameter setup */
+ rc = qpnp_vadc_read_reg(QPNP_VADC_ADC_DIG_PARAM, &decimation);
+ if (rc < 0) {
+ pr_err("Digital parameter configure read error\n");
+ return rc;
+ }
decimation |= chan_prop->decimation <<
QPNP_VADC_ADC_DIG_DEC_RATIO_SEL_SHIFT;
rc = qpnp_vadc_write_reg(QPNP_VADC_ADC_DIG_PARAM, decimation);
if (rc < 0) {
- pr_err("qpnp adc configure error for digital parameter setup\n");
+ pr_err("Digital parameter configure write error\n");
return rc;
}
+ /* HW settling time delay */
rc = qpnp_vadc_write_reg(QPNP_VADC_HW_SETTLE_DELAY,
chan_prop->hw_settle_time);
if (rc < 0) {
- pr_err("qpnp adc configure error for hw settling time setup\n");
+ pr_err("HW settling time setup error\n");
return rc;
}
if (chan_prop->mode_sel == (ADC_OP_NORMAL_MODE <<
QPNP_VADC_OP_MODE_SHIFT)) {
+ /* Normal measurement mode */
rc = qpnp_vadc_write_reg(QPNP_VADC_FAST_AVG_CTL,
chan_prop->fast_avg_setup);
if (rc < 0) {
- pr_err("qpnp adc fast averaging configure error\n");
+ pr_err("Fast averaging configure error\n");
return rc;
}
} else if (chan_prop->mode_sel == (ADC_OP_CONVERSION_SEQUENCER <<
QPNP_VADC_OP_MODE_SHIFT)) {
+ /* Conversion sequence mode */
conv_sequence = ((ADC_SEQ_HOLD_100US <<
QPNP_VADC_CONV_SEQ_HOLDOFF_SHIFT) |
ADC_CONV_SEQ_TIMEOUT_5MS);
rc = qpnp_vadc_write_reg(QPNP_VADC_CONV_SEQ_CTL,
conv_sequence);
if (rc < 0) {
- pr_err("qpnp adc conversion sequence error\n");
+ pr_err("Conversion sequence error\n");
return rc;
}
@@ -264,14 +291,15 @@
rc = qpnp_vadc_write_reg(QPNP_VADC_CONV_SEQ_TRIG_CTL,
conv_sequence_trig);
if (rc < 0) {
- pr_err("qpnp adc conversion trigger error\n");
+ pr_err("Conversion trigger error\n");
return rc;
}
}
+ /* Request conversion */
rc = qpnp_vadc_write_reg(QPNP_VADC_CONV_REQ, QPNP_VADC_CONV_REQ_SET);
if (rc < 0) {
- pr_err("qpnp adc request conversion failed\n");
+ pr_err("Request conversion failed\n");
return rc;
}
@@ -282,29 +310,34 @@
static int32_t qpnp_vadc_read_conversion_result(int32_t *data)
{
uint8_t rslt_lsb, rslt_msb;
- int rc = 0;
+ int rc = 0, status = 0;
- rc = qpnp_vadc_read_reg(QPNP_VADC_DATA0, &rslt_lsb);
- if (rc < 0) {
- pr_err("qpnp adc result read failed for data0 with %d\n", rc);
- return rc;
+ status = qpnp_vadc_read_reg(QPNP_VADC_DATA0, &rslt_lsb);
+ if (status < 0) {
+ pr_err("qpnp adc result read failed for data0\n");
+ goto fail;
}
- rc = qpnp_vadc_read_reg(QPNP_VADC_DATA1, &rslt_msb);
- if (rc < 0) {
- pr_err("qpnp adc result read failed for data1 with %d\n", rc);
- return rc;
+ status = qpnp_vadc_read_reg(QPNP_VADC_DATA1, &rslt_msb);
+ if (status < 0) {
+ pr_err("qpnp adc result read failed for data1\n");
+ goto fail;
}
*data = (rslt_msb << 8) | rslt_lsb;
- rc = qpnp_vadc_check_result(data);
- if (rc < 0) {
+ status = qpnp_vadc_check_result(data);
+ if (status < 0) {
pr_err("VADC data check failed\n");
- return rc;
+ goto fail;
}
- return 0;
+fail:
+ rc = qpnp_vadc_enable(false);
+ if (rc)
+ return rc;
+
+ return status;
}
static int32_t qpnp_vadc_read_status(int mode_sel)
@@ -393,6 +426,7 @@
rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
if (rc < 0)
return rc;
+ status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
usleep_range(QPNP_VADC_CONV_TIME_MIN,
QPNP_VADC_CONV_TIME_MAX);
}
@@ -414,11 +448,13 @@
goto calib_fail;
}
+ status1 = 0;
while (status1 != (~QPNP_VADC_STATUS1_REQ_STS |
QPNP_VADC_STATUS1_EOC)) {
rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
if (rc < 0)
return rc;
+ status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
usleep_range(QPNP_VADC_CONV_TIME_MIN,
QPNP_VADC_CONV_TIME_MAX);
}
@@ -449,11 +485,13 @@
goto calib_fail;
}
+ status1 = 0;
while (status1 != (~QPNP_VADC_STATUS1_REQ_STS |
QPNP_VADC_STATUS1_EOC)) {
rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
if (rc < 0)
return rc;
+ status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
usleep_range(QPNP_VADC_CONV_TIME_MIN,
QPNP_VADC_CONV_TIME_MAX);
}
@@ -475,11 +513,13 @@
goto calib_fail;
}
+ status1 = 0;
while (status1 != (~QPNP_VADC_STATUS1_REQ_STS |
QPNP_VADC_STATUS1_EOC)) {
rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
if (rc < 0)
return rc;
+ status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
usleep_range(QPNP_VADC_CONV_TIME_MIN,
QPNP_VADC_CONV_TIME_MAX);
}
@@ -508,7 +548,7 @@
struct qpnp_vadc_result *result)
{
struct qpnp_vadc_drv *vadc = qpnp_vadc;
- int rc, scale_type, amux_prescaling;
+ int rc = 0, scale_type, amux_prescaling;
if (!vadc->vadc_init_calib) {
rc = qpnp_vadc_calib_device();
@@ -521,10 +561,6 @@
mutex_lock(&vadc->adc->adc_lock);
- rc = qpnp_vadc_enable(true);
- if (rc)
- goto fail_unlock;
-
vadc->adc->amux_prop->amux_channel = channel;
vadc->adc->amux_prop->decimation =
vadc->adc->adc_channels[channel].adc_decimation;
@@ -541,15 +577,15 @@
<< QPNP_VADC_OP_MODE_SHIFT);
else {
pr_err("Invalid trigger channel:%d\n", trigger_channel);
- goto fail;
+ goto fail_unlock;
}
vadc->adc->amux_prop->trigger_channel = trigger_channel;
rc = qpnp_vadc_configure(vadc->adc->amux_prop);
if (rc) {
- pr_info("qpnp vadc configure failed with %d\n", rc);
- goto fail;
+ pr_err("qpnp vadc configure failed with %d\n", rc);
+ goto fail_unlock;
}
wait_for_completion(&vadc->adc->adc_rslt_completion);
@@ -557,13 +593,13 @@
if (trigger_channel < ADC_SEQ_NONE) {
rc = qpnp_vadc_read_status(vadc->adc->amux_prop->mode_sel);
if (rc)
- pr_info("Conversion sequence timed out - %d\n", rc);
+ pr_debug("Conversion sequence timed out - %d\n", rc);
}
rc = qpnp_vadc_read_conversion_result(&result->adc_code);
if (rc) {
- pr_info("qpnp vadc read adc code failed with %d\n", rc);
- goto fail;
+ pr_err("qpnp vadc read adc code failed with %d\n", rc);
+ goto fail_unlock;
}
amux_prescaling = vadc->adc->adc_channels[channel].chan_path_prescaling;
@@ -576,17 +612,12 @@
scale_type = vadc->adc->adc_channels[channel].adc_scale_fn;
if (scale_type >= SCALE_NONE) {
rc = -EBADF;
- goto fail;
+ goto fail_unlock;
}
vadc_scale_fn[scale_type].chan(result->adc_code,
vadc->adc->adc_prop, vadc->adc->amux_prop->chan_prop, result);
-fail:
- rc = qpnp_vadc_enable(false);
- if (rc)
- pr_err("Disable ADC failed during configuration\n");
-
fail_unlock:
mutex_unlock(&vadc->adc->adc_lock);
@@ -649,7 +680,7 @@
return 0;
hwmon_err_sens:
- pr_info("Init HWMON failed for qpnp_adc with %d\n", rc);
+ pr_err("Init HWMON failed for qpnp_adc with %d\n", rc);
return rc;
}
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
index 8b6e172..d3da652 100644
--- a/drivers/input/misc/mpu3050.c
+++ b/drivers/input/misc/mpu3050.c
@@ -40,6 +40,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
+#include <linux/gpio.h>
#include <linux/input/mpu3050.h>
#include <linux/regulator/consumer.h>
@@ -50,6 +51,8 @@
#define MPU3050_MIN_VALUE -32768
#define MPU3050_MAX_VALUE 32767
+#define MPU3050_MIN_POLL_INTERVAL 1
+#define MPU3050_MAX_POLL_INTERVAL 250
#define MPU3050_DEFAULT_POLL_INTERVAL 200
#define MPU3050_DEFAULT_FS_RANGE 3
@@ -90,8 +93,10 @@
#define MPU3050_DLPF_CFG_MASK 0x07
/* INT_CFG */
#define MPU3050_RAW_RDY_EN 0x01
-#define MPU3050_MPU_RDY_EN 0x02
-#define MPU3050_LATCH_INT_EN 0x04
+#define MPU3050_MPU_RDY_EN 0x04
+#define MPU3050_LATCH_INT_EN 0x20
+#define MPU3050_OPEN_DRAIN 0x40
+#define MPU3050_ACTIVE_LOW 0x80
/* PWR_MGM */
#define MPU3050_PWR_MGM_PLL_X 0x01
#define MPU3050_PWR_MGM_PLL_Y 0x02
@@ -117,6 +122,7 @@
struct mpu3050_gyro_platform_data *platform_data;
struct delayed_work input_work;
u32 use_poll;
+ u32 poll_interval;
};
struct sensor_regulator {
@@ -190,6 +196,78 @@
}
/**
+ * mpu3050_attr_get_polling_rate - get the sampling rate
+ */
+static ssize_t mpu3050_attr_get_polling_rate(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int val;
+ struct mpu3050_sensor *sensor = dev_get_drvdata(dev);
+ val = sensor ? sensor->poll_interval : 0;
+ return snprintf(buf, 8, "%d\n", val);
+}
+
+/**
+ * mpu3050_attr_set_polling_rate - set the sampling rate
+ */
+static ssize_t mpu3050_attr_set_polling_rate(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct mpu3050_sensor *sensor = dev_get_drvdata(dev);
+ unsigned long interval_ms;
+
+ if (kstrtoul(buf, 10, &interval_ms))
+ return -EINVAL;
+ if ((interval_ms < MPU3050_MIN_POLL_INTERVAL) ||
+ (interval_ms > MPU3050_MAX_POLL_INTERVAL))
+ return -EINVAL;
+
+ if (sensor)
+ sensor->poll_interval = interval_ms;
+
+ /* Output frequency divider. The poll interval */
+ i2c_smbus_write_byte_data(sensor->client, MPU3050_SMPLRT_DIV,
+ interval_ms - 1);
+
+ return size;
+}
+
+static struct device_attribute attributes[] = {
+
+ __ATTR(pollrate_ms, 0666,
+ mpu3050_attr_get_polling_rate,
+ mpu3050_attr_set_polling_rate),
+};
+
+static int create_sysfs_interfaces(struct device *dev)
+{
+ int i;
+ int err;
+ for (i = 0; i < ARRAY_SIZE(attributes); i++) {
+ err = device_create_file(dev, attributes + i);
+ if (err)
+ goto error;
+ }
+ return 0;
+
+error:
+ for ( ; i >= 0; i--)
+ device_remove_file(dev, attributes + i);
+ dev_err(dev, "%s:Unable to create interface\n", __func__);
+ return err;
+}
+
+static int remove_sysfs_interfaces(struct device *dev)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(attributes); i++)
+ device_remove_file(dev, attributes + i);
+ return 0;
+}
+
+/**
* mpu3050_xyz_read_reg - read the axes values
* @buffer: provide register addr and get register
* @length: length of register
@@ -284,20 +362,20 @@
struct mpu3050_sensor *sensor = input_get_drvdata(input);
int error;
- pm_runtime_get(sensor->dev);
+ pm_runtime_get_sync(sensor->dev);
/* Enable interrupts */
error = i2c_smbus_write_byte_data(sensor->client, MPU3050_INT_CFG,
- MPU3050_LATCH_INT_EN |
- MPU3050_RAW_RDY_EN |
- MPU3050_MPU_RDY_EN);
+ MPU3050_ACTIVE_LOW |
+ MPU3050_OPEN_DRAIN |
+ MPU3050_RAW_RDY_EN);
if (error < 0) {
pm_runtime_put(sensor->dev);
return error;
}
if (sensor->use_poll)
schedule_delayed_work(&sensor->input_work,
- msecs_to_jiffies(MPU3050_DEFAULT_POLL_INTERVAL));
+ msecs_to_jiffies(sensor->poll_interval));
return 0;
}
@@ -366,7 +444,7 @@
if (sensor->use_poll)
schedule_delayed_work(&sensor->input_work,
- msecs_to_jiffies(MPU3050_DEFAULT_POLL_INTERVAL));
+ msecs_to_jiffies(sensor->poll_interval));
}
/**
@@ -399,7 +477,7 @@
/* Output frequency divider. The poll interval */
ret = i2c_smbus_write_byte_data(client, MPU3050_SMPLRT_DIV,
- MPU3050_DEFAULT_POLL_INTERVAL - 1);
+ sensor->poll_interval - 1);
if (ret < 0)
return ret;
@@ -444,6 +522,18 @@
sensor->dev = &client->dev;
sensor->idev = idev;
sensor->platform_data = client->dev.platform_data;
+ i2c_set_clientdata(client, sensor);
+ if (sensor->platform_data) {
+ u32 interval = sensor->platform_data->poll_interval;
+
+ if ((interval < MPU3050_MIN_POLL_INTERVAL) ||
+ (interval > MPU3050_MAX_POLL_INTERVAL))
+ sensor->poll_interval = MPU3050_DEFAULT_POLL_INTERVAL;
+ else
+ sensor->poll_interval = interval;
+ } else {
+ sensor->poll_interval = MPU3050_DEFAULT_POLL_INTERVAL;
+ }
mpu3050_set_power_mode(client, 1);
msleep(10);
@@ -485,14 +575,34 @@
goto err_pm_set_suspended;
if (client->irq == 0) {
- INIT_DELAYED_WORK(&sensor->input_work, mpu3050_input_work_fn);
sensor->use_poll = 1;
+ INIT_DELAYED_WORK(&sensor->input_work, mpu3050_input_work_fn);
} else {
sensor->use_poll = 0;
+ if (gpio_is_valid(sensor->platform_data->gpio_int)) {
+ /* configure interrupt gpio */
+ ret = gpio_request(sensor->platform_data->gpio_int,
+ "gyro_gpio_int");
+ if (ret) {
+ pr_err("%s: unable to request interrupt gpio %d\n",
+ __func__,
+ sensor->platform_data->gpio_int);
+ goto err_pm_set_suspended;
+ }
+
+ ret = gpio_direction_input(
+ sensor->platform_data->gpio_int);
+ if (ret) {
+ pr_err("%s: unable to set direction for gpio %d\n",
+ __func__, sensor->platform_data->gpio_int);
+ goto err_free_gpio;
+ }
+ }
+
error = request_threaded_irq(client->irq,
NULL, mpu3050_interrupt_thread,
- IRQF_TRIGGER_RISING,
+ IRQF_TRIGGER_FALLING,
"mpu3050", sensor);
if (error) {
dev_err(&client->dev,
@@ -508,14 +618,26 @@
goto err_free_irq;
}
+ error = create_sysfs_interfaces(&client->dev);
+ if (error < 0) {
+ dev_err(&client->dev, "failed to create sysfs\n");
+ goto err_input_cleanup;
+ }
+
pm_runtime_enable(&client->dev);
pm_runtime_set_autosuspend_delay(&client->dev, MPU3050_AUTO_DELAY);
return 0;
+err_input_cleanup:
+ input_unregister_device(idev);
err_free_irq:
if (client->irq > 0)
free_irq(client->irq, sensor);
+err_free_gpio:
+ if ((client->irq > 0) &&
+ (gpio_is_valid(sensor->platform_data->gpio_int)))
+ gpio_free(sensor->platform_data->gpio_int);
err_pm_set_suspended:
pm_runtime_set_suspended(&client->dev);
err_free_mem:
@@ -537,8 +659,12 @@
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
- free_irq(client->irq, sensor);
+ if (client->irq)
+ free_irq(client->irq, sensor);
+
+ remove_sysfs_interfaces(&client->dev);
input_unregister_device(sensor->idev);
+
kfree(sensor);
return 0;
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tsif.c b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tsif.c
index bd1ecfe..74a0dbe 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tsif.c
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tsif.c
@@ -26,8 +26,8 @@
#define DMX_TSIF_MAX_SECTION_FILTER_NUM 64
/* When TSIF driver notifies demux that new packets are received */
-#define DMX_TSIF_PACKETS_IN_CHUNK_DEF 16
-#define DMX_TSIF_CHUNKS_IN_BUF 8
+#define DMX_TSIF_PACKETS_IN_CHUNK_DEF 512
+#define DMX_TSIF_CHUNKS_IN_BUF 16
#define DMX_TSIF_TIME_LIMIT 10000
/* TSIF_DRIVER_MODE: 3 means manual control from debugfs. use 1 normally. */
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
index fd94e80..372c612 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
@@ -47,18 +47,20 @@
#define TSPP_RAW_TTS_SIZE 192
-/* Size of single descriptor.
- * Assuming 20MBit/sec stream, with 200 packets
- * per descriptor there would be about 68 descriptors.
- * Meanning about 68 interrupts per second.
+/* Size of single descriptor. Using max descriptor size (170 packets).
+ * Assuming 20MBit/sec stream, with 170 packets
+ * per descriptor there would be about 82 descriptors,
+ * Meanning about 82 notifications per second.
*/
-#define TSPP_BUFFER_SIZE (TSPP_RAW_TTS_SIZE * 200)
+#define MAX_BAM_DESCRIPTOR_SIZE (32*1024 - 1)
+#define TSPP_BUFFER_SIZE \
+ ((MAX_BAM_DESCRIPTOR_SIZE / TSPP_RAW_TTS_SIZE) * TSPP_RAW_TTS_SIZE)
/* Number of descriptors, total size: TSPP_BUFFER_SIZE*TSPP_BUFFER_COUNT */
-#define TSPP_BUFFER_COUNT (16)
+#define TSPP_BUFFER_COUNT (32)
/* When TSPP notifies demux that new packets are received */
-#define TSPP_NOTIFICATION_SIZE (TSPP_RAW_TTS_SIZE * 100)
+#define TSPP_NOTIFICATION_SIZE 1
/* Channel timeout in msec */
#define TSPP_CHANNEL_TIMEOUT 16
@@ -232,7 +234,7 @@
* @channel_id: Channel with new TS packets
* @user: user-data holding TSIF number
*/
-static void mpq_tspp_callback(u32 channel_id, void *user)
+static void mpq_tspp_callback(int channel_id, void *user)
{
int tsif = (int)user;
struct work_struct *work;
diff --git a/drivers/media/video/msm_vidc/msm_smem.c b/drivers/media/video/msm_vidc/msm_smem.c
index 76e3592..ff12a5c 100644
--- a/drivers/media/video/msm_vidc/msm_smem.c
+++ b/drivers/media/video/msm_vidc/msm_smem.c
@@ -108,8 +108,6 @@
unsigned long iova = 0;
unsigned long buffer_size = 0;
int rc = 0;
- if (size == 0)
- goto skip_mem_alloc;
flags = flags | ION_HEAP(ION_CP_MM_HEAP_ID);
if (align < 4096)
align = 4096;
@@ -147,7 +145,6 @@
fail_map:
ion_free(client->clnt, hndl);
fail_shared_mem_alloc:
-skip_mem_alloc:
return rc;
}
@@ -236,12 +233,15 @@
struct smem_client *client;
int rc = 0;
struct msm_smem *mem;
-
client = clt;
if (!client) {
pr_err("Invalid client passed\n");
return NULL;
}
+ if (!size) {
+ pr_err("No need to allocate memory of size: %d\n", size);
+ return NULL;
+ }
mem = kzalloc(sizeof(*mem), GFP_KERNEL);
if (!mem) {
pr_err("Failed to allocate shared mem\n");
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index a683315..c87211a 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -440,15 +440,16 @@
if (fmt) {
f->fmt.pix_mp.pixelformat = fmt->fourcc;
if (inst->in_reconfig == true) {
- inst->height = inst->reconfig_height;
- inst->width = inst->reconfig_width;
+ inst->prop.height = inst->reconfig_height;
+ inst->prop.width = inst->reconfig_width;
}
- f->fmt.pix_mp.height = inst->height;
- f->fmt.pix_mp.width = inst->width;
+ f->fmt.pix_mp.height = inst->prop.height;
+ f->fmt.pix_mp.width = inst->prop.width;
f->fmt.pix_mp.num_planes = fmt->num_planes;
for (i = 0; i < fmt->num_planes; ++i) {
f->fmt.pix_mp.plane_fmt[i].sizeimage =
- fmt->get_frame_size(i, inst->height, inst->width);
+ fmt->get_frame_size(i, inst->prop.height,
+ inst->prop.width);
}
} else {
pr_err("Buf type not recognized, type = %d\n",
@@ -584,7 +585,7 @@
*num_buffers = MIN_NUM_OUTPUT_BUFFERS;
for (i = 0; i < *num_planes; i++) {
sizes[i] = inst->fmts[OUTPUT_PORT]->get_frame_size(
- i, inst->height, inst->width);
+ i, inst->prop.height, inst->prop.width);
}
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index f030163..14baf79 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/video/msm_vidc/msm_venc.c
@@ -1201,7 +1201,7 @@
inst->fmts[OUTPUT_PORT] = &venc_formats[0];
inst->prop.height = DEFAULT_HEIGHT;
inst->prop.width = DEFAULT_WIDTH;
- inst->prop.height = 30;
+ inst->prop.fps = 30;
return rc;
}
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 6835467..b07c63b 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -1126,7 +1126,7 @@
pr_err("inst: %p is already in state: %d\n", inst, inst->state);
goto exit;
}
- ocmem_sz = get_ocmem_requirement(inst->height, inst->width);
+ ocmem_sz = get_ocmem_requirement(inst->prop.height, inst->prop.width);
rc = msm_comm_alloc_ocmem(inst->core, ocmem_sz);
if (rc)
pr_warn("Failed to allocate OCMEM. Performance will be impacted\n");
@@ -1490,10 +1490,13 @@
struct list_head *ptr, *next;
struct vidc_buffer_addr_info buffer_info;
unsigned long flags;
+ struct hal_buffer_requirements *scratch_buf =
+ &inst->buff_req.buffer[HAL_BUFFER_INTERNAL_SCRATCH];
int i;
+
pr_debug("scratch: num = %d, size = %d\n",
- inst->buff_req.buffer[6].buffer_count_actual,
- inst->buff_req.buffer[6].buffer_size);
+ scratch_buf->buffer_count_actual,
+ scratch_buf->buffer_size);
spin_lock_irqsave(&inst->lock, flags);
if (!list_empty(&inst->internalbufs)) {
list_for_each_safe(ptr, next, &inst->internalbufs) {
@@ -1505,40 +1508,44 @@
}
}
spin_unlock_irqrestore(&inst->lock, flags);
-
-
- for (i = 0; i < inst->buff_req.buffer[6].buffer_count_actual;
+ if (scratch_buf->buffer_size) {
+ for (i = 0; i < scratch_buf->buffer_count_actual;
i++) {
- handle = msm_smem_alloc(inst->mem_client,
- inst->buff_req.buffer[6].buffer_size, 1, 0,
+ handle = msm_smem_alloc(inst->mem_client,
+ scratch_buf->buffer_size, 1, 0,
inst->core->resources.io_map[NS_MAP].domain, 0);
- if (!handle) {
- pr_err("Failed to allocate scratch memory\n");
- rc = -ENOMEM;
- goto err_no_mem;
- }
- binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
- if (!binfo) {
- pr_err("Out of memory\n");
- rc = -ENOMEM;
- goto err_no_mem;
- }
- binfo->handle = handle;
- spin_lock_irqsave(&inst->lock, flags);
- list_add_tail(&binfo->list, &inst->internalbufs);
- spin_unlock_irqrestore(&inst->lock, flags);
- buffer_info.buffer_size =
- inst->buff_req.buffer[6].buffer_size;
- buffer_info.buffer_type = HAL_BUFFER_INTERNAL_SCRATCH;
- buffer_info.num_buffers = 1;
- buffer_info.align_device_addr = handle->device_addr;
- rc = vidc_hal_session_set_buffers((void *) inst->session,
- &buffer_info);
- if (rc) {
- pr_err("vidc_hal_session_set_buffers failed");
- break;
+ if (!handle) {
+ pr_err("Failed to allocate scratch memory\n");
+ rc = -ENOMEM;
+ goto err_no_mem;
+ }
+ binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
+ if (!binfo) {
+ pr_err("Out of memory\n");
+ rc = -ENOMEM;
+ goto fail_kzalloc;
+ }
+ binfo->handle = handle;
+ buffer_info.buffer_size = scratch_buf->buffer_size;
+ buffer_info.buffer_type = HAL_BUFFER_INTERNAL_SCRATCH;
+ buffer_info.num_buffers = 1;
+ buffer_info.align_device_addr = handle->device_addr;
+ rc = vidc_hal_session_set_buffers(
+ (void *) inst->session, &buffer_info);
+ if (rc) {
+ pr_err("vidc_hal_session_set_buffers failed");
+ goto fail_set_buffers;
+ }
+ spin_lock_irqsave(&inst->lock, flags);
+ list_add_tail(&binfo->list, &inst->internalbufs);
+ spin_unlock_irqrestore(&inst->lock, flags);
}
}
+ return rc;
+fail_set_buffers:
+ kfree(binfo);
+fail_kzalloc:
+ msm_smem_free(inst->mem_client, handle);
err_no_mem:
return rc;
}
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index 992f39c..8c11de8 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_internal.h
@@ -201,8 +201,6 @@
int session_type;
void *session;
struct session_prop prop;
- u32 width;
- u32 height;
int state;
const struct msm_vidc_format *fmts[MAX_PORT_NUM];
struct vb2_queue vb2_bufq[MAX_PORT_NUM];
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index f1f1c69..9f2ead4 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -273,10 +273,10 @@
#ifdef TOP_FIELD_FIX
writel_iowmb(0x00000000 | vp_act->top_field << 0, VCAP_VP_CTRL);
- writel_iowmb(0x00030000 | vp_act->top_field << 0, VCAP_VP_CTRL);
+ writel_iowmb(0x00010000 | vp_act->top_field << 0, VCAP_VP_CTRL);
#else
writel_iowmb(0x00000000 | top_field, VCAP_VP_CTRL);
- writel_iowmb(0x00030000 | top_field, VCAP_VP_CTRL);
+ writel_iowmb(0x00010000 | top_field, VCAP_VP_CTRL);
#endif
enable_irq(dev->vpirq->start);
writel_iowmb(irq, VCAP_VP_INT_CLEAR);
@@ -420,58 +420,84 @@
int init_motion_buf(struct vcap_client_data *c_data)
{
+ int rc;
struct vcap_dev *dev = c_data->dev;
- void *buf;
- unsigned long motion_base_addr;
- uint32_t size = ((c_data->vp_out_fmt.width + 63) >> 6) *
+ struct ion_handle *handle = NULL;
+ unsigned long paddr, ionflag = 0;
+ void *vaddr;
+ size_t len;
+ size_t size = ((c_data->vp_out_fmt.width + 63) >> 6) *
((c_data->vp_out_fmt.height + 7) >> 3) * 16;
- if (c_data->vid_vp_action.bufMotion) {
+ if (c_data->vid_vp_action.motionHandle) {
pr_err("Motion buffer has already been created");
return -ENOEXEC;
}
- buf = kzalloc(size, GFP_KERNEL);
- if (!buf)
+ handle = ion_alloc(dev->ion_client, size, SZ_4K,
+ ION_HEAP(ION_CP_MM_HEAP_ID));
+ if (IS_ERR_OR_NULL(handle)) {
+ pr_err("%s: ion_alloc failed\n", __func__);
return -ENOMEM;
+ }
+ rc = ion_phys(dev->ion_client, handle, &paddr, &len);
+ if (rc < 0) {
+ pr_err("%s: ion_phys failed\n", __func__);
+ ion_free(dev->ion_client, handle);
+ return rc;
+ }
- c_data->vid_vp_action.bufMotion = buf;
- motion_base_addr = virt_to_phys(buf);
- writel_iowmb(motion_base_addr, VCAP_VP_MOTION_EST_ADDR);
+ rc = ion_handle_get_flags(dev->ion_client, handle, &ionflag);
+ if (rc) {
+ pr_err("%s: get flags ion handle failed\n", __func__);
+ ion_free(dev->ion_client, handle);
+ return rc;
+ }
+
+ vaddr = ion_map_kernel(dev->ion_client, handle, ionflag);
+ if (IS_ERR(vaddr)) {
+ pr_err("%s: Map motion buffer failed\n", __func__);
+ ion_free(dev->ion_client, handle);
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ memset(vaddr, 0, size);
+ c_data->vid_vp_action.motionHandle = handle;
+
+ vaddr = NULL;
+ ion_unmap_kernel(dev->ion_client, handle);
+
+ writel_iowmb(paddr, VCAP_VP_MOTION_EST_ADDR);
return 0;
}
void deinit_motion_buf(struct vcap_client_data *c_data)
{
struct vcap_dev *dev = c_data->dev;
- void *buf;
-
- if (!c_data->vid_vp_action.bufMotion) {
+ if (!c_data->vid_vp_action.motionHandle) {
pr_err("Motion buffer has not been created");
return;
}
- buf = c_data->vid_vp_action.bufMotion;
-
writel_iowmb(0x00000000, VCAP_VP_MOTION_EST_ADDR);
- c_data->vid_vp_action.bufMotion = NULL;
- kfree(buf);
+ ion_free(dev->ion_client, c_data->vid_vp_action.motionHandle);
+ c_data->vid_vp_action.motionHandle = NULL;
return;
}
int init_nr_buf(struct vcap_client_data *c_data)
{
struct vcap_dev *dev = c_data->dev;
- struct nr_buffer *buf;
- uint32_t frame_size, tot_size, rc;
+ struct ion_handle *handle = NULL;
+ size_t frame_size, tot_size, len;
+ unsigned long paddr;
+ int rc;
- if (c_data->vid_vp_action.bufNR.vaddr) {
+ if (c_data->vid_vp_action.bufNR.nr_handle) {
pr_err("NR buffer has already been created");
return -ENOEXEC;
}
- buf = &c_data->vid_vp_action.bufNR;
- if (!buf)
- return -ENOMEM;
frame_size = c_data->vp_in_fmt.width * c_data->vp_in_fmt.height;
if (c_data->vp_in_fmt.pixfmt == V4L2_PIX_FMT_NV16)
@@ -479,19 +505,30 @@
else
tot_size = frame_size / 2 * 3;
- buf->vaddr = kzalloc(tot_size, GFP_KERNEL);
- if (!buf->vaddr)
+ handle = ion_alloc(dev->ion_client, tot_size, SZ_4K,
+ ION_HEAP(ION_CP_MM_HEAP_ID));
+ if (IS_ERR_OR_NULL(handle)) {
+ pr_err("%s: ion_alloc failed\n", __func__);
return -ENOMEM;
+ }
+ rc = ion_phys(dev->ion_client, handle, &paddr, &len);
+ if (rc < 0) {
+ pr_err("%s: ion_phys failed\n", __func__);
+ ion_free(dev->ion_client, handle);
+ return rc;
+ }
+
+ c_data->vid_vp_action.bufNR.nr_handle = handle;
update_nr_value(c_data);
- buf->paddr = virt_to_phys(buf->vaddr);
+ c_data->vid_vp_action.bufNR.paddr = paddr;
rc = readl_relaxed(VCAP_VP_NR_CONFIG2);
- rc |= 0x02D00001;
+ rc |= (((c_data->vp_out_fmt.width / 16) << 20) | 0x1);
writel_relaxed(rc, VCAP_VP_NR_CONFIG2);
- writel_relaxed(buf->paddr, VCAP_VP_NR_T2_Y_BASE_ADDR);
- writel_relaxed(buf->paddr + frame_size, VCAP_VP_NR_T2_C_BASE_ADDR);
- buf->nr_pos = NRT2_BUF;
+ writel_relaxed(paddr, VCAP_VP_NR_T2_Y_BASE_ADDR);
+ writel_relaxed(paddr + frame_size, VCAP_VP_NR_T2_C_BASE_ADDR);
+ c_data->vid_vp_action.bufNR.nr_pos = NRT2_BUF;
return 0;
}
@@ -501,20 +538,19 @@
struct nr_buffer *buf;
uint32_t rc;
- if (!c_data->vid_vp_action.bufNR.vaddr) {
+ if (!c_data->vid_vp_action.bufNR.nr_handle) {
pr_err("NR buffer has not been created");
return;
}
-
buf = &c_data->vid_vp_action.bufNR;
rc = readl_relaxed(VCAP_VP_NR_CONFIG2);
- rc &= !(0x02D00001);
+ rc &= !(0x0FF00001);
writel_relaxed(rc, VCAP_VP_NR_CONFIG2);
- kfree(buf->vaddr);
+ ion_free(dev->ion_client, buf->nr_handle);
+ buf->nr_handle = NULL;
buf->paddr = 0;
- buf->vaddr = NULL;
return;
}
@@ -592,18 +628,26 @@
{
struct vcap_dev *dev = c_data->dev;
unsigned int width, height;
+ struct ion_handle *handle = NULL;
unsigned long paddr;
- void *temp;
+ size_t len;
uint32_t reg;
int rc = 0;
dprintk(2, "%s: Start VP dummy event\n", __func__);
- temp = kzalloc(0x1200, GFP_KERNEL);
- if (!temp) {
- pr_err("%s: Failed to alloc mem", __func__);
+ handle = ion_alloc(dev->ion_client, 0x1200, SZ_4K,
+ ION_HEAP(ION_CP_MM_HEAP_ID));
+ if (IS_ERR_OR_NULL(handle)) {
+ pr_err("%s: ion_alloc failed\n", __func__);
return -ENOMEM;
}
- paddr = virt_to_phys(temp);
+
+ rc = ion_phys(dev->ion_client, handle, &paddr, &len);
+ if (rc < 0) {
+ pr_err("%s: ion_phys failed\n", __func__);
+ ion_free(dev->ion_client, handle);
+ return rc;
+ }
width = c_data->vp_out_fmt.width;
height = c_data->vp_out_fmt.height;
@@ -626,7 +670,7 @@
writel_relaxed(0x01100101, VCAP_VP_INTERRUPT_ENABLE);
writel_iowmb(0x00000000, VCAP_VP_CTRL);
- writel_iowmb(0x00030000, VCAP_VP_CTRL);
+ writel_iowmb(0x00010000, VCAP_VP_CTRL);
enable_irq(dev->vpirq->start);
rc = wait_event_interruptible_timeout(dev->vp_dummy_waitq,
@@ -650,7 +694,7 @@
c_data->vp_out_fmt.width = width;
c_data->vp_out_fmt.height = height;
- kfree(temp);
+ ion_free(dev->ion_client, handle);
dprintk(2, "%s: Exit VP dummy event\n", __func__);
return rc;
@@ -748,10 +792,10 @@
writel_relaxed(0x01100101, VCAP_VP_INTERRUPT_ENABLE);
#ifdef TOP_FIELD_FIX
writel_iowmb(0x00000000 | vp_act->top_field << 0, VCAP_VP_CTRL);
- writel_iowmb(0x00030000 | vp_act->top_field << 0, VCAP_VP_CTRL);
+ writel_iowmb(0x00010000 | vp_act->top_field << 0, VCAP_VP_CTRL);
#else
writel_iowmb(0x00000000 | top_field, VCAP_VP_CTRL);
- writel_iowmb(0x00030000 | top_field, VCAP_VP_CTRL);
+ writel_iowmb(0x00010000 | top_field, VCAP_VP_CTRL);
#endif
atomic_set(&c_data->dev->vp_enabled, 1);
enable_irq(dev->vpirq->start);
@@ -795,10 +839,10 @@
writel_relaxed(0x01100101, VCAP_VP_INTERRUPT_ENABLE);
#ifdef TOP_FIELD_FIX
writel_iowmb(0x00000000 | vp_act->top_field << 0, VCAP_VP_CTRL);
- writel_iowmb(0x00030000 | vp_act->top_field << 0, VCAP_VP_CTRL);
+ writel_iowmb(0x00010000 | vp_act->top_field << 0, VCAP_VP_CTRL);
#else
writel_iowmb(0x00000000 | top_field, VCAP_VP_CTRL);
- writel_iowmb(0x00030000 | top_field, VCAP_VP_CTRL);
+ writel_iowmb(0x00010000 | top_field, VCAP_VP_CTRL);
#endif
atomic_set(&c_data->dev->vp_enabled, 1);
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 6d82e11..05707fd 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of_gpio.h>
#include <linux/slab.h>
#include <linux/mfd/core.h>
#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
@@ -320,10 +321,12 @@
wcd9xxx_bring_up(wcd9xxx);
- ret = wcd9xxx_irq_init(wcd9xxx);
- if (ret) {
- pr_err("IRQ initialization failed\n");
- goto err;
+ if (wcd9xxx->irq != -1) {
+ ret = wcd9xxx_irq_init(wcd9xxx);
+ if (ret) {
+ pr_err("IRQ initialization failed\n");
+ goto err;
+ }
}
wcd9xxx->idbyte_0 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_0);
@@ -497,10 +500,15 @@
goto err;
}
- for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++)
- wcd9xxx->supplies[i].supply = pdata->regulator[i].name;
+ wcd9xxx->num_of_supplies = 0;
+ for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+ if (pdata->regulator[i].name) {
+ wcd9xxx->supplies[i].supply = pdata->regulator[i].name;
+ wcd9xxx->num_of_supplies++;
+ }
+ }
- ret = regulator_bulk_get(wcd9xxx->dev, ARRAY_SIZE(pdata->regulator),
+ ret = regulator_bulk_get(wcd9xxx->dev, wcd9xxx->num_of_supplies,
wcd9xxx->supplies);
if (ret != 0) {
dev_err(wcd9xxx->dev, "Failed to get supplies: err = %d\n",
@@ -508,7 +516,7 @@
goto err_supplies;
}
- for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+ for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
ret = regulator_set_voltage(wcd9xxx->supplies[i].consumer,
pdata->regulator[i].min_uV, pdata->regulator[i].max_uV);
if (ret) {
@@ -528,7 +536,7 @@
}
}
- ret = regulator_bulk_enable(ARRAY_SIZE(pdata->regulator),
+ ret = regulator_bulk_enable(wcd9xxx->num_of_supplies,
wcd9xxx->supplies);
if (ret != 0) {
dev_err(wcd9xxx->dev, "Failed to enable supplies: err = %d\n",
@@ -538,13 +546,13 @@
return ret;
err_configure:
- for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+ for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
pdata->regulator[i].max_uV);
regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
}
err_get:
- regulator_bulk_free(ARRAY_SIZE(pdata->regulator), wcd9xxx->supplies);
+ regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
err_supplies:
kfree(wcd9xxx->supplies);
err:
@@ -556,14 +564,14 @@
{
int i;
- regulator_bulk_disable(ARRAY_SIZE(pdata->regulator),
+ regulator_bulk_disable(wcd9xxx->num_of_supplies,
wcd9xxx->supplies);
- for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+ for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
pdata->regulator[i].max_uV);
regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
}
- regulator_bulk_free(ARRAY_SIZE(pdata->regulator), wcd9xxx->supplies);
+ regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
kfree(wcd9xxx->supplies);
}
@@ -792,6 +800,252 @@
return 0;
}
+#define CODEC_DT_MAX_PROP_SIZE 40
+static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
+ struct wcd9xxx_regulator *vreg, const char *vreg_name)
+{
+ int len, ret = 0;
+ const __be32 *prop;
+ char prop_name[CODEC_DT_MAX_PROP_SIZE];
+ struct device_node *regnode = NULL;
+ u32 prop_val;
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "%s-supply",
+ vreg_name);
+ regnode = of_parse_phandle(dev->of_node, prop_name, 0);
+
+ if (!regnode) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ prop_name, dev->of_node->full_name);
+ return -ENODEV;
+ }
+ vreg->name = vreg_name;
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+ "qcom,%s-voltage", vreg_name);
+ prop = of_get_property(dev->of_node, prop_name, &len);
+
+ if (!prop || (len != (2 * sizeof(__be32)))) {
+ dev_err(dev, "%s %s property\n",
+ prop ? "invalid format" : "no", prop_name);
+ return -ENODEV;
+ } else {
+ vreg->min_uV = be32_to_cpup(&prop[0]);
+ vreg->max_uV = be32_to_cpup(&prop[1]);
+ }
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+ "qcom,%s-current", vreg_name);
+
+ ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+ if (ret) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ prop_name, dev->of_node->full_name);
+ return -ENODEV;
+ }
+ vreg->optimum_uA = prop_val;
+
+ dev_info(dev, "%s: vol=[%d %d]uV, curr=[%d]uA\n", vreg->name,
+ vreg->min_uV, vreg->max_uV, vreg->optimum_uA);
+ return 0;
+}
+
+static int wcd9xxx_dt_parse_micbias_info(struct device *dev,
+ struct wcd9xxx_micbias_setting *micbias)
+{
+ int ret = 0;
+ char prop_name[CODEC_DT_MAX_PROP_SIZE];
+ u32 prop_val;
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+ "qcom,cdc-micbias-ldoh-v");
+ ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+ if (ret) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ prop_name, dev->of_node->full_name);
+ return -ENODEV;
+ }
+ micbias->ldoh_v = (u8)prop_val;
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+ "qcom,cdc-micbias-cfilt1-mv");
+ ret = of_property_read_u32(dev->of_node, prop_name,
+ &micbias->cfilt1_mv);
+ if (ret) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ prop_name, dev->of_node->full_name);
+ return -ENODEV;
+ }
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+ "qcom,cdc-micbias-cfilt2-mv");
+ ret = of_property_read_u32(dev->of_node, prop_name,
+ &micbias->cfilt2_mv);
+ if (ret) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ prop_name, dev->of_node->full_name);
+ return -ENODEV;
+ }
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+ "qcom,cdc-micbias-cfilt3-mv");
+ ret = of_property_read_u32(dev->of_node, prop_name,
+ &micbias->cfilt3_mv);
+ if (ret) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ prop_name, dev->of_node->full_name);
+ return -ENODEV;
+ }
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+ "qcom,cdc-micbias1-cfilt-sel");
+ ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+ if (ret) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ prop_name, dev->of_node->full_name);
+ return -ENODEV;
+ }
+ micbias->bias1_cfilt_sel = (u8)prop_val;
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+ "qcom,cdc-micbias2-cfilt-sel");
+ ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+ if (ret) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ prop_name, dev->of_node->full_name);
+ return -ENODEV;
+ }
+ micbias->bias2_cfilt_sel = (u8)prop_val;
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+ "qcom,cdc-micbias3-cfilt-sel");
+ ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+ if (ret) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ prop_name, dev->of_node->full_name);
+ return -ENODEV;
+ }
+ micbias->bias3_cfilt_sel = (u8)prop_val;
+
+ snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+ "qcom,cdc-micbias4-cfilt-sel");
+ ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+ if (ret) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ prop_name, dev->of_node->full_name);
+ return -ENODEV;
+ }
+ micbias->bias4_cfilt_sel = (u8)prop_val;
+
+ dev_dbg(dev, "ldoh_v %u cfilt1_mv %u cfilt2_mv %u cfilt3_mv %u",
+ (u32)micbias->ldoh_v, (u32)micbias->cfilt1_mv,
+ (u32)micbias->cfilt2_mv, (u32)micbias->cfilt3_mv);
+
+ dev_dbg(dev, "bias1_cfilt_sel %u bias2_cfilt_sel %u\n",
+ (u32)micbias->bias1_cfilt_sel, (u32)micbias->bias2_cfilt_sel);
+
+ dev_dbg(dev, "bias3_cfilt_sel %u bias4_cfilt_sel %u\n",
+ (u32)micbias->bias3_cfilt_sel, (u32)micbias->bias4_cfilt_sel);
+
+ return 0;
+}
+
+static int wcd9xxx_dt_parse_slim_interface_dev_info(struct device *dev,
+ struct slim_device *slim_ifd)
+{
+ int ret = 0;
+ struct property *prop;
+
+ ret = of_property_read_string(dev->of_node, "qcom,cdc-slim-ifd",
+ &slim_ifd->name);
+ if (ret) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ "qcom,cdc-slim-ifd-dev", dev->of_node->full_name);
+ return -ENODEV;
+ }
+ prop = of_find_property(dev->of_node,
+ "qcom,cdc-slim-ifd-elemental-addr", NULL);
+ if (!prop) {
+ dev_err(dev, "Looking up %s property in node %s failed",
+ "qcom,cdc-slim-ifd-elemental-addr",
+ dev->of_node->full_name);
+ return -ENODEV;
+ } else if (prop->length != 6) {
+ dev_err(dev, "invalid codec slim ifd addr. addr length = %d\n",
+ prop->length);
+ return -ENODEV;
+ }
+ memcpy(slim_ifd->e_addr, prop->value, 6);
+
+ return 0;
+}
+
+static char *taiko_supplies[] = {
+ "cdc-vdd-buck", "cdc-vdd-tx-h", "cdc-vdd-rx-h", "cdc-vddpx-1",
+ "cdc-vdd-a-1p2v", "cdc-vddcx-1", "cdc-vddcx-2",
+};
+
+static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev)
+{
+ struct wcd9xxx_pdata *pdata;
+ int ret, i;
+ char **codec_supplies;
+ u32 num_of_supplies = 0;
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(dev,
+ "could not allocate memory for platform data\n");
+ return NULL;
+ }
+
+ if (!strcmp(dev_name(dev), "taiko-slim-pgd")) {
+ codec_supplies = taiko_supplies;
+ num_of_supplies = ARRAY_SIZE(taiko_supplies);
+ } else {
+ dev_err(dev, "%s unsupported device %s\n",
+ __func__, dev_name(dev));
+ goto err;
+ }
+
+ if (num_of_supplies > ARRAY_SIZE(pdata->regulator)) {
+ dev_err(dev, "%s: Num of supplies %u > max supported %u\n",
+ __func__, num_of_supplies, ARRAY_SIZE(pdata->regulator));
+
+ goto err;
+ }
+
+ for (i = 0; i < num_of_supplies; i++) {
+ ret = wcd9xxx_dt_parse_vreg_info(dev, &pdata->regulator[i],
+ codec_supplies[i]);
+ if (ret)
+ goto err;
+ }
+
+ ret = wcd9xxx_dt_parse_micbias_info(dev, &pdata->micbias);
+ if (ret)
+ goto err;
+
+ pdata->reset_gpio = of_get_named_gpio(dev->of_node,
+ "qcom,cdc-reset-gpio", 0);
+ if (pdata->reset_gpio < 0) {
+ dev_err(dev, "Looking up %s property in node %s failed %d\n",
+ "qcom, cdc-reset-gpio", dev->of_node->full_name,
+ pdata->reset_gpio);
+ goto err;
+ }
+ pdata->irq = -1;
+
+ ret = wcd9xxx_dt_parse_slim_interface_dev_info(dev,
+ &pdata->slimbus_slave_device);
+ if (ret)
+ goto err;
+ return pdata;
+err:
+ devm_kfree(dev, pdata);
+ return NULL;
+}
+
static int wcd9xxx_slim_probe(struct slim_device *slim)
{
struct wcd9xxx *wcd9xxx;
@@ -799,8 +1053,15 @@
int ret = 0;
int sgla_retry_cnt;
- dev_info(&slim->dev, "Initialized slim device %s\n", slim->name);
- pdata = slim->dev.platform_data;
+ if (slim->dev.of_node) {
+ dev_info(&slim->dev, "Platform data from device tree\n");
+ pdata = wcd9xxx_populate_dt_pdata(&slim->dev);
+ slim->dev.platform_data = pdata;
+
+ } else {
+ dev_info(&slim->dev, "Platform data from board file\n");
+ pdata = slim->dev.platform_data;
+ }
if (!pdata) {
dev_err(&slim->dev, "Error, no platform data\n");
@@ -1103,7 +1364,7 @@
};
static const struct slim_device_id taiko_slimtest_id[] = {
- {"taiko-slim", 0},
+ {"taiko-slim-pgd", 0},
{}
};
diff --git a/drivers/mfd/wcd9xxx-slimslave.c b/drivers/mfd/wcd9xxx-slimslave.c
index 5f839a8..71c68ac 100644
--- a/drivers/mfd/wcd9xxx-slimslave.c
+++ b/drivers/mfd/wcd9xxx-slimslave.c
@@ -555,18 +555,18 @@
__func__, i, ch_num[i], idx, i, sph[i], grph);
}
- /* slim_disconnect_port */
- ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
- if (ret < 0) {
- pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
- __func__, ret);
- }
/* slim_control_ch (REMOVE) */
ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_REMOVE, true);
if (ret < 0) {
pr_err("%s: slim_control_ch failed ret[%d]\n", __func__, ret);
goto err;
}
+ /* slim_disconnect_port */
+ ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
+ if (ret < 0) {
+ pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
+ __func__, ret);
+ }
for (i = 0; i < ch_cnt; i++) {
idx = (ch_num[i] - BASE_CH_NUM - sh_ch.rx_port_start_offset);
rx[idx].grph = 0;
diff --git a/drivers/regulator/qpnp-regulator.c b/drivers/regulator/qpnp-regulator.c
index 8d592fb..0e836c7 100644
--- a/drivers/regulator/qpnp-regulator.c
+++ b/drivers/regulator/qpnp-regulator.c
@@ -268,8 +268,8 @@
};
static struct qpnp_voltage_range ftsmps_ranges[] = {
- VOLTAGE_RANGE(0, 80000, 350000, 1355000, 5000),
- VOLTAGE_RANGE(1, 160000, 1360000, 2710000, 10000),
+ VOLTAGE_RANGE(0, 0, 350000, 1275000, 5000),
+ VOLTAGE_RANGE(1, 0, 1280000, 2040000, 10000),
};
static struct qpnp_voltage_range boost_ranges[] = {
@@ -982,16 +982,26 @@
static int qpnp_regulator_match(struct qpnp_regulator *vreg)
{
const struct qpnp_regulator_mapping *mapping;
+ struct device_node *node = vreg->spmi_dev->dev.of_node;
int rc, i;
u8 raw_type[2], type, subtype;
+ u32 type_reg[2];
- rc = qpnp_vreg_read(vreg, QPNP_COMMON_REG_TYPE, raw_type, 2);
- if (rc) {
- vreg_err(vreg, "could not read type register, rc=%d\n", rc);
- return rc;
+ rc = of_property_read_u32_array(node, "qcom,force-type",
+ type_reg, 2);
+ if (!rc) {
+ type = type_reg[0];
+ subtype = type_reg[1];
+ } else {
+ rc = qpnp_vreg_read(vreg, QPNP_COMMON_REG_TYPE, raw_type, 2);
+ if (rc) {
+ vreg_err(vreg,
+ "could not read type register, rc=%d\n", rc);
+ return rc;
+ }
+ type = raw_type[0];
+ subtype = raw_type[1];
}
- type = raw_type[0];
- subtype = raw_type[1];
rc = -ENODEV;
for (i = 0; i < ARRAY_SIZE(supported_regulators); i++) {
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index b2d2f74..d082273 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -75,7 +75,7 @@
config THERMAL_MONITOR
bool "Monitor thermal state and limit CPU Frequency"
- depends on THERMAL_TSENS8960
+ depends on THERMAL_TSENS8960 || THERMAL_TSENS8974
depends on CPU_FREQ_MSM
default n
help
diff --git a/drivers/tty/n_smux.c b/drivers/tty/n_smux.c
index 32e52d0..1385e08 100644
--- a/drivers/tty/n_smux.c
+++ b/drivers/tty/n_smux.c
@@ -274,6 +274,7 @@
struct mutex mutex_lha0;
int is_initialized;
+ int platform_devs_registered;
int in_reset;
int ld_open_count;
struct tty_struct *tty;
@@ -3377,14 +3378,18 @@
/* re-register platform devices */
SMUX_DBG("%s: ssr - after power-up\n", __func__);
mutex_lock(&smux.mutex_lha0);
- for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
- SMUX_DBG("%s: register pdev '%s'\n",
+ if (smux.ld_open_count > 0
+ && !smux.platform_devs_registered) {
+ for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
+ SMUX_DBG("%s: register pdev '%s'\n",
__func__, smux_devs[i].name);
- smux_devs[i].dev.release = smux_pdev_release;
- tmp = platform_device_register(&smux_devs[i]);
- if (tmp)
- pr_err("%s: error %d registering device %s\n",
+ smux_devs[i].dev.release = smux_pdev_release;
+ tmp = platform_device_register(&smux_devs[i]);
+ if (tmp)
+ pr_err("%s: error %d registering device %s\n",
__func__, tmp, smux_devs[i].name);
+ }
+ smux.platform_devs_registered = 1;
}
mutex_unlock(&smux.mutex_lha0);
return NOTIFY_DONE;
@@ -3396,30 +3401,34 @@
/* Cleanup channels */
smux_flush_workqueues();
mutex_lock(&smux.mutex_lha0);
- smux_lch_purge();
- if (smux.tty)
- tty_driver_flush_buffer(smux.tty);
+ if (smux.ld_open_count > 0) {
+ smux_lch_purge();
+ if (smux.tty)
+ tty_driver_flush_buffer(smux.tty);
- /* Unregister platform devices */
- for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
- SMUX_DBG("%s: unregister pdev '%s'\n",
- __func__, smux_devs[i].name);
- platform_device_unregister(&smux_devs[i]);
+ /* Unregister platform devices */
+ if (smux.platform_devs_registered) {
+ for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
+ SMUX_DBG("%s: unregister pdev '%s'\n",
+ __func__, smux_devs[i].name);
+ platform_device_unregister(&smux_devs[i]);
+ }
+ smux.platform_devs_registered = 0;
+ }
+
+ /* Power-down UART */
+ spin_lock_irqsave(&smux.tx_lock_lha2, flags);
+ if (smux.power_state != SMUX_PWR_OFF) {
+ SMUX_PWR("%s: SSR - turning off UART\n", __func__);
+ smux.power_state = SMUX_PWR_OFF;
+ power_off_uart = 1;
+ }
+ smux.powerdown_enabled = 0;
+ spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
+
+ if (power_off_uart)
+ smux_uart_power_off_atomic();
}
-
- /* Power-down UART */
- spin_lock_irqsave(&smux.tx_lock_lha2, flags);
- if (smux.power_state != SMUX_PWR_OFF) {
- SMUX_PWR("%s: SSR - turning off UART\n", __func__);
- smux.power_state = SMUX_PWR_OFF;
- power_off_uart = 1;
- }
- smux.powerdown_enabled = 0;
- spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
-
- if (power_off_uart)
- smux_uart_power_off_atomic();
-
smux.tx_activity_flag = 0;
smux.rx_activity_flag = 0;
smux.rx_state = SMUX_RX_IDLE;
@@ -3493,6 +3502,7 @@
pr_err("%s: error %d registering device %s\n",
__func__, tmp, smux_devs[i].name);
}
+ smux.platform_devs_registered = 1;
mutex_unlock(&smux.mutex_lha0);
return 0;
}
@@ -3519,10 +3529,13 @@
smux_lch_purge();
/* Unregister platform devices */
- for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
- SMUX_DBG("%s: unregister pdev '%s'\n",
- __func__, smux_devs[i].name);
- platform_device_unregister(&smux_devs[i]);
+ if (smux.platform_devs_registered) {
+ for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
+ SMUX_DBG("%s: unregister pdev '%s'\n",
+ __func__, smux_devs[i].name);
+ platform_device_unregister(&smux_devs[i]);
+ }
+ smux.platform_devs_registered = 0;
}
/* Schedule UART power-up if it's down */
@@ -3668,6 +3681,7 @@
smux.ld_open_count = 0;
smux.in_reset = 0;
smux.is_initialized = 1;
+ smux.platform_devs_registered = 0;
smux_byte_loopback = 0;
spin_lock_init(&smux.tx_lock_lha2);
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index 414a7b9..1d0b6d4 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -607,6 +607,7 @@
struct usb_cdc_notification *event;
unsigned long flags;
int ret;
+ struct rmnet_ctrl_pkt *cpkt;
pr_debug("%s:dev:%p portno#%d\n", __func__, dev, dev->port_num);
@@ -633,6 +634,14 @@
ret = usb_ep_queue(dev->notify, dev->notify_req, GFP_ATOMIC);
if (ret) {
atomic_dec(&dev->notify_count);
+ spin_lock_irqsave(&dev->lock, flags);
+ cpkt = list_first_entry(&dev->cpkt_resp_q,
+ struct rmnet_ctrl_pkt, list);
+ if (cpkt) {
+ list_del(&cpkt->list);
+ rmnet_free_ctrl_pkt(cpkt);
+ }
+ spin_unlock_irqrestore(&dev->lock, flags);
pr_debug("ep enqueue error %d\n", ret);
}
}
@@ -768,6 +777,8 @@
{
struct f_rmnet *dev = req->context;
int status = req->status;
+ unsigned long flags;
+ struct rmnet_ctrl_pkt *cpkt;
pr_debug("%s: dev:%p port#%d\n", __func__, dev, dev->port_num);
@@ -790,6 +801,14 @@
status = usb_ep_queue(dev->notify, req, GFP_ATOMIC);
if (status) {
atomic_dec(&dev->notify_count);
+ spin_lock_irqsave(&dev->lock, flags);
+ cpkt = list_first_entry(&dev->cpkt_resp_q,
+ struct rmnet_ctrl_pkt, list);
+ if (cpkt) {
+ list_del(&cpkt->list);
+ rmnet_free_ctrl_pkt(cpkt);
+ }
+ spin_unlock_irqrestore(&dev->lock, flags);
pr_debug("ep enqueue error %d\n", status);
}
break;
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 0e1267b..355990a 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -847,9 +847,13 @@
/* Ensure that above operation is completed before turning off clocks */
mb();
- if (!motg->pdata->core_clk_always_on_workaround) {
+ /* Consider clocks on workaround flag only in case of bus suspend */
+ if (!(phy->state == OTG_STATE_B_PERIPHERAL &&
+ test_bit(A_BUS_SUSPEND, &motg->inputs)) ||
+ !motg->pdata->core_clk_always_on_workaround) {
clk_disable_unprepare(motg->pclk);
clk_disable_unprepare(motg->core_clk);
+ motg->lpm_flags |= CLOCKS_DOWN;
}
/* usb phy no more require TCXO clock, hence vote for TCXO disable */
@@ -917,9 +921,10 @@
motg->lpm_flags &= ~XO_SHUTDOWN;
}
- if (!motg->pdata->core_clk_always_on_workaround) {
+ if (motg->lpm_flags & CLOCKS_DOWN) {
clk_prepare_enable(motg->core_clk);
clk_prepare_enable(motg->pclk);
+ motg->lpm_flags &= ~CLOCKS_DOWN;
}
if (motg->lpm_flags & PHY_PWR_COLLAPSED) {
@@ -2726,10 +2731,14 @@
pr_debug("OTG IRQ: in LPM\n");
disable_irq_nosync(irq);
motg->async_int = 1;
- if (atomic_read(&motg->pm_suspended))
+ if (atomic_read(&motg->pm_suspended)) {
motg->sm_work_pending = true;
- else
+ if ((otg->phy->state == OTG_STATE_A_SUSPEND) ||
+ (otg->phy->state == OTG_STATE_A_WAIT_BCON))
+ set_bit(A_BUS_REQ, &motg->inputs);
+ } else {
pm_request_resume(otg->phy->dev);
+ }
return IRQ_HANDLED;
}
@@ -3388,7 +3397,7 @@
static int __init msm_otg_probe(struct platform_device *pdev)
{
- int ret = 0;
+ int ret = 0, disable_lpm = 0;
struct resource *res;
struct msm_otg *motg;
struct usb_phy *phy;
@@ -3406,6 +3415,8 @@
dev_err(&pdev->dev, "devices setup failed\n");
return ret;
}
+ /* LPM not supported on targets using DT */
+ disable_lpm = 1;
} else if (!pdev->dev.platform_data) {
dev_err(&pdev->dev, "No platform data given. Bailing out\n");
return -ENODEV;
@@ -3661,7 +3672,8 @@
wake_lock(&motg->wlock);
pm_runtime_set_active(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
+ if (!disable_lpm)
+ pm_runtime_enable(&pdev->dev);
if (motg->pdata->bus_scale_table) {
motg->bus_perf_client =
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index 46ef7b4..0976fc6 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -1452,21 +1452,21 @@
len += ret;
if (len && (format & TOP_AND_BOTTOM))
- ret = snprintf(buf + len, PAGE_SIZE, ":%s",
+ ret = snprintf(buf + len, PAGE_SIZE - len, ":%s",
single_video_3d_format_2string(
format & TOP_AND_BOTTOM));
else
- ret = snprintf(buf + len, PAGE_SIZE, "%s",
+ ret = snprintf(buf + len, PAGE_SIZE - len, "%s",
single_video_3d_format_2string(
format & TOP_AND_BOTTOM));
len += ret;
if (len && (format & SIDE_BY_SIDE_HALF))
- ret = snprintf(buf + len, PAGE_SIZE, ":%s",
+ ret = snprintf(buf + len, PAGE_SIZE - len, ":%s",
single_video_3d_format_2string(
format & SIDE_BY_SIDE_HALF));
else
- ret = snprintf(buf + len, PAGE_SIZE, "%s",
+ ret = snprintf(buf + len, PAGE_SIZE - len, "%s",
single_video_3d_format_2string(
format & SIDE_BY_SIDE_HALF));
len += ret;
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index ee73eea..d911b62 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -1510,10 +1510,13 @@
#ifdef CONFIG_FB_MSM_NO_MDP_PIPE_CTRL
-static void mdp_clk_off(void)
+/*
+ * mdp_clk_disable_unprepare(void) called from thread context
+ */
+static void mdp_clk_disable_unprepare(void)
{
mb();
- vsync_clk_disable();
+ vsync_clk_disable_unprepare();
if (mdp_clk != NULL)
clk_disable_unprepare(mdp_clk);
@@ -1525,8 +1528,10 @@
clk_disable_unprepare(mdp_lut_clk);
}
-
-static void mdp_clk_on(void)
+/*
+ * mdp_clk_prepare_enable(void) called from thread context
+ */
+static void mdp_clk_prepare_enable(void)
{
if (mdp_clk != NULL)
clk_prepare_enable(mdp_clk);
@@ -1537,9 +1542,12 @@
if (mdp_lut_clk != NULL)
clk_prepare_enable(mdp_lut_clk);
- vsync_clk_enable();
+ vsync_clk_prepare_enable();
}
+/*
+ * mdp_clk_ctrl: called from thread context
+ */
void mdp_clk_ctrl(int on)
{
static int mdp_clk_cnt;
@@ -1547,13 +1555,13 @@
mutex_lock(&mdp_suspend_mutex);
if (on) {
if (mdp_clk_cnt == 0)
- mdp_clk_on();
+ mdp_clk_prepare_enable();
mdp_clk_cnt++;
} else {
if (mdp_clk_cnt) {
mdp_clk_cnt--;
if (mdp_clk_cnt == 0)
- mdp_clk_off();
+ mdp_clk_disable_unprepare();
}
}
mutex_unlock(&mdp_suspend_mutex);
@@ -2398,8 +2406,7 @@
if (!(mdp_pdata->cont_splash_enabled))
mdp4_hw_init();
#else
- if (!(mdp_pdata->cont_splash_enabled))
- mdp_hw_init();
+ mdp_hw_init();
#endif
#ifdef CONFIG_FB_MSM_OVERLAY
@@ -2591,6 +2598,7 @@
else {
printk(KERN_ERR "Invalid Selection of destination panel\n");
rc = -ENODEV;
+ mdp_clk_ctrl(0);
goto mdp_probe_err;
}
@@ -2638,6 +2646,7 @@
else {
printk(KERN_ERR "Invalid Selection of destination panel\n");
rc = -ENODEV;
+ mdp_clk_ctrl(0);
goto mdp_probe_err;
}
INIT_WORK(&mfd->dma_update_worker,
@@ -2737,6 +2746,7 @@
pr_err("%s: writeback panel not supprted\n",
__func__);
platform_device_put(msm_fb_dev);
+ mdp_clk_ctrl(0);
return -ENODEV;
}
pdata->on = mdp4_overlay_writeback_on;
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index 12bd1d4..76d06a0 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -831,8 +831,8 @@
void mdp3_vsync_irq_disable(int intr, int term);
#ifdef MDP_HW_VSYNC
-void vsync_clk_enable(void);
-void vsync_clk_disable(void);
+void vsync_clk_prepare_enable(void);
+void vsync_clk_disable_unprepare(void);
void mdp_hw_vsync_clk_enable(struct msm_fb_data_type *mfd);
void mdp_hw_vsync_clk_disable(struct msm_fb_data_type *mfd);
void mdp_vsync_clk_disable(void);
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 72e7c8f..767332a 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -665,24 +665,17 @@
uint32 mdp4_rgb_igc_lut_cvt(uint32 ndx);
void mdp4_vg_qseed_init(int);
int mdp4_overlay_blt(struct fb_info *info, struct msmfb_overlay_blt *req);
-int mdp4_overlay_blt_offset(struct fb_info *info,
- struct msmfb_overlay_blt *req);
-
#ifdef CONFIG_FB_MSM_MIPI_DSI
-int mdp4_dsi_overlay_blt_start(struct msm_fb_data_type *mfd);
-int mdp4_dsi_overlay_blt_stop(struct msm_fb_data_type *mfd);
+void mdp4_dsi_cmd_blt_start(struct msm_fb_data_type *mfd);
+void mdp4_dsi_cmd_blt_stop(struct msm_fb_data_type *mfd);
void mdp4_dsi_video_blt_start(struct msm_fb_data_type *mfd);
void mdp4_dsi_video_blt_stop(struct msm_fb_data_type *mfd);
-void mdp4_dsi_overlay_blt(struct msm_fb_data_type *mfd,
- struct msmfb_overlay_blt *req);
-int mdp4_dsi_overlay_blt_offset(struct msm_fb_data_type *mfd,
+void mdp4_dsi_cmd_overlay_blt(struct msm_fb_data_type *mfd,
struct msmfb_overlay_blt *req);
void mdp4_dsi_video_overlay_blt(struct msm_fb_data_type *mfd,
struct msmfb_overlay_blt *req);
-int mdp4_dsi_video_overlay_blt_offset(struct msm_fb_data_type *mfd,
- struct msmfb_overlay_blt *req);
void mdp4_dsi_video_base_swap(int cndx, struct mdp4_overlay_pipe *pipe);
#ifdef CONFIG_FB_MSM_MDP40
@@ -726,10 +719,9 @@
struct msm_fb_data_type *mfd, struct msmfb_overlay_blt *req)
{
}
-static inline int mdp4_dsi_video_overlay_blt_offset(
+static inline void mdp4_dsi_cmd_overlay_blt(
struct msm_fb_data_type *mfd, struct msmfb_overlay_blt *req)
{
- return -ENODEV;
}
static inline void mdp4_dsi_video_base_swap(int cndx,
struct mdp4_overlay_pipe *pipe)
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index ee4cb4e..9fe5214 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -154,7 +154,6 @@
pr_err("%s: Error, mixer=%d iommu fndx=%d\n",
__func__, mixer, flist->fndx);
mdp4_stat.iommu_drop++;
- mutex_unlock(&iommu_mutex);
return;
}
@@ -476,14 +475,18 @@
dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
- if (mfd->panel_info.bpp == 18) {
+ if ((mfd->panel_info.type == MIPI_CMD_PANEL) ||
+ (mfd->panel_info.type == MIPI_VIDEO_PANEL)) {
+ dma2_cfg_reg |= DMA_DSTC0G_8BITS | /* 888 24BPP */
+ DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
+ } else if (mfd->panel_info.bpp == 18) {
dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 666 18BPP */
DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
} else if (mfd->panel_info.bpp == 16) {
dma2_cfg_reg |= DMA_DSTC0G_6BITS | /* 565 16BPP */
DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
} else {
- dma2_cfg_reg |= DMA_DSTC0G_8BITS | /* 888 16BPP */
+ dma2_cfg_reg |= DMA_DSTC0G_8BITS | /* 888 24BPP */
DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
}
@@ -1663,6 +1666,12 @@
bspipe = ctrl->stage[mixer][MDP4_MIXER_STAGE_BASE];
+ /*
+ * bspipe is clone here
+ * get real pipe
+ */
+ bspipe = mdp4_overlay_ndx2pipe(bspipe->pipe_ndx);
+
/* save original base layer */
ctrl->baselayer[mixer] = bspipe;
@@ -2091,17 +2100,18 @@
num = pipe->pipe_num;
ndx = pipe->pipe_ndx;
mixer = pipe->mixer_num;
- iom = pipe->iommu;
mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 0);
- memset(pipe, 0, sizeof(*pipe));
+ iom = pipe->iommu;
+ memset(pipe, 0, sizeof(*pipe));
pipe->pipe_type = ptype;
pipe->pipe_num = num;
pipe->pipe_ndx = ndx;
pipe->mixer_num = mixer;
pipe->iommu = iom;
+
}
static int mdp4_overlay_validate_downscale(struct mdp_overlay *req,
@@ -2516,7 +2526,7 @@
return -EINTR;
if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
- mdp4_dsi_overlay_blt(mfd, req);
+ mdp4_dsi_cmd_overlay_blt(mfd, req);
else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
mdp4_dsi_video_overlay_blt(mfd, req);
else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
@@ -2644,49 +2654,6 @@
}
}
-static void mdp4_overlay_update_blt_mode(struct msm_fb_data_type *mfd)
-{
- if (mfd->use_ov0_blt == mfd->ov0_blt_state)
- return;
-
- if (mfd->use_ov0_blt) {
- if (mfd->panel_info.type == LCDC_PANEL ||
- mfd->panel_info.type == LVDS_PANEL)
- mdp4_lcdc_overlay_blt_start(mfd);
- else if (mfd->panel_info.type == MIPI_VIDEO_PANEL)
- mdp4_dsi_video_blt_start(mfd);
- else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
- mdp4_dsi_overlay_blt_start(mfd);
- else if (ctrl->panel_mode & MDP4_PANEL_MDDI)
- mdp4_mddi_overlay_blt_start(mfd);
- } else {
- if (mfd->panel_info.type == LCDC_PANEL ||
- mfd->panel_info.type == LVDS_PANEL)
- mdp4_lcdc_overlay_blt_stop(mfd);
- else if (mfd->panel_info.type == MIPI_VIDEO_PANEL)
- mdp4_dsi_video_blt_stop(mfd);
- else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
- mdp4_dsi_overlay_blt_stop(mfd);
- else if (ctrl->panel_mode & MDP4_PANEL_MDDI)
- mdp4_mddi_overlay_blt_stop(mfd);
- }
- mfd->ov0_blt_state = mfd->use_ov0_blt;
-}
-
-static void mdp4_overlay1_update_blt_mode(struct msm_fb_data_type *mfd)
-{
- if (mfd->ov1_blt_state == mfd->use_ov1_blt)
- return;
- if (mfd->use_ov1_blt) {
- mdp4_dtv_overlay_blt_start(mfd);
- pr_debug("%s overlay1 writeback is enabled\n", __func__);
- } else {
- mdp4_dtv_overlay_blt_stop(mfd);
- pr_debug("%s overlay1 writeback is disabled\n", __func__);
- }
- mfd->ov1_blt_state = mfd->use_ov1_blt;
-}
-
static u32 mdp4_overlay_blt_enable(struct mdp_overlay *req,
struct msm_fb_data_type *mfd, uint32 perf_level)
{
@@ -2914,12 +2881,10 @@
}
mfd->use_ov0_blt &= ~(1 << (pipe->pipe_ndx-1));
- mdp4_overlay_update_blt_mode(mfd);
} else { /* mixer1, DTV, ATV */
if (ctrl->panel_mode & MDP4_PANEL_DTV) {
mdp4_overlay_dtv_unset(mfd, pipe);
mfd->use_ov1_blt &= ~(1 << (pipe->pipe_ndx-1));
- mdp4_overlay1_update_blt_mode(mfd);
}
}
@@ -2950,16 +2915,22 @@
int mdp4_overlay_vsync_ctrl(struct fb_info *info, int enable)
{
+ int cmd;
+
+ if (enable)
+ cmd = 1;
+ else
+ cmd = 0;
+
if (!hdmi_prim_display && info->node == 0) {
if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
- mdp4_dsi_video_vsync_ctrl(0, enable);
+ mdp4_dsi_video_vsync_ctrl(0, cmd);
else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
- mdp4_dsi_cmd_vsync_ctrl(0, enable);
+ mdp4_dsi_cmd_vsync_ctrl(0, cmd);
else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
- mdp4_lcdc_vsync_ctrl(0, enable);
- } else if (hdmi_prim_display || info->node == 1) {
- mdp4_dtv_vsync_ctrl(0, enable);
- }
+ mdp4_lcdc_vsync_ctrl(0, cmd);
+ } else if (hdmi_prim_display || info->node == 1)
+ mdp4_dtv_vsync_ctrl(0, cmd);
return 0;
}
@@ -3176,12 +3147,6 @@
}
}
- if (mfd->use_ov0_blt)
- mdp4_overlay_update_blt_mode(mfd);
-
- if (mfd->use_ov1_blt)
- mdp4_overlay1_update_blt_mode(mfd);
-
if (ctrl->panel_mode & MDP4_PANEL_MDDI)
goto mddi;
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 7998d8b..e1fa02e 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -39,7 +39,7 @@
static int vsync_start_y_adjust = 4;
#define MAX_CONTROLLER 1
-#define VSYNC_EXPIRE_TICK 2
+#define VSYNC_EXPIRE_TICK 4
#define BACKLIGHT_MAX 4
struct backlight {
@@ -54,24 +54,34 @@
int inited;
int update_ndx;
int expire_tick;
- uint32 dmap_intr_tot;
+ int blt_wait;
+ u32 ov_koff;
+ u32 ov_done;
+ u32 dmap_koff;
+ u32 dmap_done;
uint32 rdptr_intr_tot;
uint32 rdptr_sirq_tot;
atomic_t suspend;
- int dmap_wait_cnt;
int wait_vsync_cnt;
- int commit_cnt;
+ int blt_change;
+ int blt_free;
+ int blt_end;
+ int fake_vsync;
struct mutex update_lock;
+ struct completion ov_comp;
struct completion dmap_comp;
struct completion vsync_comp;
- spinlock_t dmap_spin_lock;
spinlock_t spin_lock;
+ struct msm_fb_data_type *mfd;
struct mdp4_overlay_pipe *base_pipe;
struct vsync_update vlist[2];
struct backlight blight;
- int vsync_irq_enabled;
+ int vsync_enabled;
+ int clk_enabled;
+ int clk_control;
ktime_t vsync_time;
struct work_struct vsync_work;
+ struct work_struct clk_work;
} vsync_ctrl_db[MAX_CONTROLLER];
static void vsync_irq_enable(int intr, int term)
@@ -80,7 +90,6 @@
spin_lock_irqsave(&mdp_spin_lock, flag);
/* no need to clrear other interrupts for comamnd mode */
- outp32(MDP_INTR_CLEAR, INTR_PRIMARY_RDPTR);
mdp_intr_mask |= intr;
outp32(MDP_INTR_ENABLE, mdp_intr_mask);
mdp_enable_irq(term);
@@ -161,30 +170,7 @@
return cnt;
}
-void mdp4_blt_dmap_cfg(struct mdp4_overlay_pipe *pipe)
-{
- uint32 off, addr;
- int bpp;
-
- if (pipe->ov_blt_addr == 0)
- return;
-
-#ifdef BLT_RGB565
- bpp = 2; /* overlay ouput is RGB565 */
-#else
- bpp = 3; /* overlay ouput is RGB888 */
-#endif
- off = 0;
- if (pipe->blt_dmap_done & 0x01)
- off = pipe->src_height * pipe->src_width * bpp;
- addr = pipe->dma_blt_addr + off;
-
- /* dmap */
- MDP_OUTP(MDP_BASE + 0x90008, addr);
-}
-
-
-void mdp4_blt_overlay0_cfg(struct mdp4_overlay_pipe *pipe)
+static void mdp4_dsi_cmd_blt_ov_update(struct mdp4_overlay_pipe *pipe)
{
uint32 off, addr;
int bpp;
@@ -199,7 +185,7 @@
bpp = 3; /* overlay ouput is RGB888 */
#endif
off = 0;
- if (pipe->blt_ov_done & 0x01)
+ if (pipe->ov_cnt & 0x01)
off = pipe->src_height * pipe->src_width * bpp;
addr = pipe->ov_blt_addr + off;
/* overlay 0 */
@@ -208,32 +194,91 @@
outpdw(overlay_base + 0x001c, addr);
}
-static void vsync_commit_kickoff_dmap(struct mdp4_overlay_pipe *pipe)
+static void mdp4_dsi_cmd_blt_dmap_update(struct mdp4_overlay_pipe *pipe)
{
- if (mipi_dsi_ctrl_lock(1)) {
- mdp4_stat.kickoff_dmap++;
- pipe->blt_dmap_koff++;
- vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
- outpdw(MDP_BASE + 0x000c, 0); /* kickoff dmap engine */
- mb();
- }
+ uint32 off, addr;
+ int bpp;
+
+ if (pipe->ov_blt_addr == 0)
+ return;
+
+#ifdef BLT_RGB565
+ bpp = 2; /* overlay ouput is RGB565 */
+#else
+ bpp = 3; /* overlay ouput is RGB888 */
+#endif
+ off = 0;
+ if (pipe->dmap_cnt & 0x01)
+ off = pipe->src_height * pipe->src_width * bpp;
+ addr = pipe->dma_blt_addr + off;
+
+ /* dmap */
+ MDP_OUTP(MDP_BASE + 0x90008, addr);
}
-static void vsync_commit_kickoff_ov0(struct mdp4_overlay_pipe *pipe, int blt)
+static void mdp4_dsi_cmd_wait4dmap(int cndx);
+static void mdp4_dsi_cmd_wait4ov(int cndx);
+
+static void mdp4_dsi_cmd_do_blt(struct msm_fb_data_type *mfd, int enable)
{
- int locked = 1;
+ unsigned long flags;
+ int cndx = 0;
+ struct vsycn_ctrl *vctrl;
+ struct mdp4_overlay_pipe *pipe;
+ int need_wait;
- if (blt)
- vsync_irq_enable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
- else
- locked = mipi_dsi_ctrl_lock(1);
+ vctrl = &vsync_ctrl_db[cndx];
+ pipe = vctrl->base_pipe;
- if (locked) {
- mdp4_stat.kickoff_ov0++;
- pipe->blt_ov_koff++;
- outpdw(MDP_BASE + 0x0004, 0); /* kickoff overlay engine */
- mb();
+ mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
+
+ if (mfd->ov0_wb_buf->write_addr == 0) {
+ pr_err("%s: no blt_base assigned\n", __func__);
+ return;
}
+
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
+ if (enable && pipe->ov_blt_addr == 0) {
+ vctrl->blt_change++;
+ if (vctrl->dmap_koff != vctrl->dmap_done) {
+ INIT_COMPLETION(vctrl->dmap_comp);
+ need_wait = 1;
+ }
+ } else if (enable == 0 && pipe->ov_blt_addr) {
+ vctrl->blt_change++;
+ if (vctrl->ov_koff != vctrl->dmap_done) {
+ INIT_COMPLETION(vctrl->dmap_comp);
+ need_wait = 1;
+ }
+ }
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+
+ if (need_wait)
+ mdp4_dsi_cmd_wait4dmap(0);
+
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
+ if (enable && pipe->ov_blt_addr == 0) {
+ pipe->ov_blt_addr = mfd->ov0_wb_buf->write_addr;
+ pipe->dma_blt_addr = mfd->ov0_wb_buf->read_addr;
+ pipe->ov_cnt = 0;
+ pipe->dmap_cnt = 0;
+ vctrl->ov_koff = vctrl->dmap_koff;
+ vctrl->ov_done = vctrl->dmap_done;
+ vctrl->blt_free = 0;
+ vctrl->blt_wait = 0;
+ vctrl->blt_end = 0;
+ mdp4_stat.blt_dsi_video++;
+ } else if (enable == 0 && pipe->ov_blt_addr) {
+ pipe->ov_blt_addr = 0;
+ pipe->dma_blt_addr = 0;
+ vctrl->blt_end = 1;
+ vctrl->blt_free = 4; /* 4 commits to free wb buf */
+ }
+
+ pr_debug("%s: changed=%d enable=%d ov_blt_addr=%x\n", __func__,
+ vctrl->blt_change, enable, (int)pipe->ov_blt_addr);
+
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
}
/*
@@ -266,95 +311,137 @@
pr_debug("%s: vndx=%d pipe_ndx=%d expire=%x pid=%d\n", __func__,
undx, pipe->pipe_ndx, vctrl->expire_tick, current->pid);
- *pp = *pipe; /* keep it */
+ *pp = *pipe; /* clone it */
vp->update_cnt++;
- if (vctrl->expire_tick == 0) {
- mipi_dsi_clk_cfg(1);
- mdp_clk_ctrl(1);
- vsync_irq_enable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
- }
- vctrl->expire_tick = VSYNC_EXPIRE_TICK;
mutex_unlock(&vctrl->update_lock);
+ mdp4_stat.overlay_play[pipe->mixer_num]++;
}
+static void mdp4_dsi_cmd_blt_ov_update(struct mdp4_overlay_pipe *pipe);
+
int mdp4_dsi_cmd_pipe_commit(void)
{
-
- int i, undx, cnt;
+ int i, undx;
int mixer = 0;
struct vsycn_ctrl *vctrl;
struct vsync_update *vp;
struct mdp4_overlay_pipe *pipe;
unsigned long flags;
- int diff;
+ int need_dmap_wait = 0;
+ int need_ov_wait = 0;
+ int cnt = 0;
vctrl = &vsync_ctrl_db[0];
+
mutex_lock(&vctrl->update_lock);
undx = vctrl->update_ndx;
vp = &vctrl->vlist[undx];
pipe = vctrl->base_pipe;
mixer = pipe->mixer_num;
- pr_debug("%s: vndx=%d cnt=%d expire=%x pid=%d\n", __func__,
- undx, vp->update_cnt, vctrl->expire_tick, current->pid);
-
- cnt = 0;
if (vp->update_cnt == 0) {
mutex_unlock(&vctrl->update_lock);
return cnt;
}
+
vctrl->update_ndx++;
vctrl->update_ndx &= 0x01;
- vctrl->commit_cnt++;
- vp->update_cnt = 0; /* reset */
+ vp->update_cnt = 0; /* reset */
+ if (vctrl->blt_free) {
+ vctrl->blt_free--;
+ if (vctrl->blt_free == 0)
+ mdp4_free_writeback_buf(vctrl->mfd, mixer);
+ }
mutex_unlock(&vctrl->update_lock);
+
mdp4_backlight_commit_level(vctrl);
/* free previous committed iommu back to pool */
mdp4_overlay_iommu_unmap_freelist(mixer);
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
+ if (pipe->ov_blt_addr) {
+ /* Blt */
+ if (vctrl->blt_wait)
+ need_dmap_wait = 1;
+ else if (vctrl->ov_koff != vctrl->ov_done) {
+ INIT_COMPLETION(vctrl->ov_comp);
+ need_ov_wait = 1;
+ }
+ } else {
+ /* direct out */
+ if (vctrl->dmap_koff != vctrl->dmap_done) {
+ INIT_COMPLETION(vctrl->dmap_comp);
+ pr_debug("%s: wait, ok=%d od=%d dk=%d dd=%d cpu=%d\n",
+ __func__, vctrl->ov_koff, vctrl->ov_done,
+ vctrl->dmap_koff, vctrl->dmap_done, smp_processor_id());
+ need_dmap_wait = 1;
+ }
+ }
+ spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+
+ if (need_dmap_wait) {
+ pr_debug("%s: wait4dmap\n", __func__);
+ mdp4_dsi_cmd_wait4dmap(0);
+ }
+
+ if (need_ov_wait) {
+ pr_debug("%s: wait4ov\n", __func__);
+ mdp4_dsi_cmd_wait4ov(0);
+ }
+
+ if (pipe->ov_blt_addr) {
+ if (vctrl->blt_end) {
+ vctrl->blt_end = 0;
+ pipe->ov_blt_addr = 0;
+ pipe->dma_blt_addr = 0;
+ }
+ }
+
+ if (vctrl->blt_change) {
+ mdp4_overlayproc_cfg(pipe);
+ mdp4_overlay_dmap_xy(pipe);
+ vctrl->blt_change = 0;
+ }
+
pipe = vp->plist;
for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) {
if (pipe->pipe_used) {
cnt++;
mdp4_overlay_vsync_commit(pipe);
/* free previous iommu to freelist
- * which will be freed at next
- * pipe_commit
- */
+ * which will be freed at next
+ * pipe_commit
+ */
mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 0);
pipe->pipe_used = 0; /* clear */
}
}
+
mdp4_mixer_stage_commit(mixer);
-
- pr_debug("%s: intr=%d expire=%d cpu=%d\n", __func__,
- vctrl->rdptr_intr_tot, vctrl->expire_tick, smp_processor_id());
-
- spin_lock_irqsave(&vctrl->spin_lock, flags);
pipe = vctrl->base_pipe;
- if (pipe->blt_changed) {
- /* blt configurtion changed */
- pipe->blt_changed = 0;
- mdp4_overlayproc_cfg(pipe);
- mdp4_overlay_dmap_xy(pipe);
- }
-
+ spin_lock_irqsave(&vctrl->spin_lock, flags);
if (pipe->ov_blt_addr) {
- diff = pipe->blt_ov_koff - pipe->blt_ov_done;
- if (diff < 1) {
- mdp4_blt_overlay0_cfg(pipe);
- vsync_commit_kickoff_ov0(pipe, 1);
- }
+ mdp4_dsi_cmd_blt_ov_update(pipe);
+ pipe->ov_cnt++;
+ vctrl->ov_koff++;
+ vsync_irq_enable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
} else {
- vsync_commit_kickoff_ov0(pipe, 0);
+ vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+ vctrl->dmap_koff++;
}
-
+ pr_debug("%s: kickoff\n", __func__);
+ /* kickoff overlay engine */
+ mdp4_stat.kickoff_ov0++;
+ outpdw(MDP_BASE + 0x0004, 0);
+ mb(); /* make sure kickoff ececuted */
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+ mdp4_stat.overlay_commit[pipe->mixer_num]++;
+
return cnt;
}
@@ -369,23 +456,15 @@
vctrl = &vsync_ctrl_db[cndx];
- if (vctrl->vsync_irq_enabled == enable)
+ if (enable && vctrl->fake_vsync) {
+ vctrl->fake_vsync = 0;
+ schedule_work(&vctrl->vsync_work);
+ }
+
+ if (vctrl->vsync_enabled == enable)
return;
- vctrl->vsync_irq_enabled = enable;
-
- mutex_lock(&vctrl->update_lock);
- if (enable) {
- mipi_dsi_clk_cfg(1);
- mdp_clk_ctrl(1);
- vsync_irq_enable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
- } else {
- mipi_dsi_clk_cfg(0);
- mdp_clk_ctrl(0);
- vsync_irq_disable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
- vctrl->expire_tick = 0;
- }
- mutex_unlock(&vctrl->update_lock);
+ vctrl->vsync_enabled = enable;
}
void mdp4_dsi_cmd_wait4vsync(int cndx, long long *vtime)
@@ -402,8 +481,10 @@
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
- if (atomic_read(&vctrl->suspend) > 0)
+ if (atomic_read(&vctrl->suspend) > 0) {
+ *vtime = -1;
return;
+ }
spin_lock_irqsave(&vctrl->spin_lock, flags);
if (vctrl->wait_vsync_cnt == 0)
@@ -412,10 +493,44 @@
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
wait_for_completion(&vctrl->vsync_comp);
+ mdp4_stat.wait4vsync0++;
*vtime = ktime_to_ns(vctrl->vsync_time);
}
+static void mdp4_dsi_cmd_wait4dmap(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ if (atomic_read(&vctrl->suspend) > 0)
+ return;
+
+ wait_for_completion(&vctrl->dmap_comp);
+}
+
+static void mdp4_dsi_cmd_wait4ov(int cndx)
+{
+ struct vsycn_ctrl *vctrl;
+
+ if (cndx >= MAX_CONTROLLER) {
+ pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+ return;
+ }
+
+ vctrl = &vsync_ctrl_db[cndx];
+
+ if (atomic_read(&vctrl->suspend) > 0)
+ return;
+
+ wait_for_completion(&vctrl->ov_comp);
+}
/*
* primary_rdptr_isr:
@@ -427,10 +542,17 @@
struct vsycn_ctrl *vctrl;
vctrl = &vsync_ctrl_db[cndx];
- pr_debug("%s: cpu=%d\n", __func__, smp_processor_id());
+ pr_debug("%s: ISR, cpu=%d\n", __func__, smp_processor_id());
vctrl->rdptr_intr_tot++;
vctrl->vsync_time = ktime_get();
schedule_work(&vctrl->vsync_work);
+
+ spin_lock(&vctrl->spin_lock);
+ if (vctrl->wait_vsync_cnt) {
+ complete(&vctrl->vsync_comp);
+ vctrl->wait_vsync_cnt = 0;
+ }
+ spin_unlock(&vctrl->spin_lock);
}
void mdp4_dmap_done_dsi_cmd(int cndx)
@@ -439,35 +561,34 @@
struct mdp4_overlay_pipe *pipe;
int diff;
- vsync_irq_disable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
-
vctrl = &vsync_ctrl_db[cndx];
- vctrl->dmap_intr_tot++;
pipe = vctrl->base_pipe;
- if (pipe->ov_blt_addr == 0) {
- mdp4_overlay_dma_commit(cndx);
- return;
- }
-
/* blt enabled */
spin_lock(&vctrl->spin_lock);
- pipe->blt_dmap_done++;
- diff = pipe->blt_ov_done - pipe->blt_dmap_done;
- spin_unlock(&vctrl->spin_lock);
- pr_debug("%s: ov_done=%d dmap_done=%d ov_koff=%d dmap_koff=%d\n",
- __func__, pipe->blt_ov_done, pipe->blt_dmap_done,
- pipe->blt_ov_koff, pipe->blt_dmap_koff);
+ vsync_irq_disable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+ vctrl->dmap_done++;
+ diff = vctrl->ov_done - vctrl->dmap_done;
+ pr_debug("%s: ov_koff=%d ov_done=%d dmap_koff=%d dmap_done=%d cpu=%d\n",
+ __func__, vctrl->ov_koff, vctrl->ov_done, vctrl->dmap_koff,
+ vctrl->dmap_done, smp_processor_id());
+ complete_all(&vctrl->dmap_comp);
if (diff <= 0) {
- if (pipe->blt_end) {
- pipe->blt_end = 0;
- pipe->ov_blt_addr = 0;
- pipe->dma_blt_addr = 0;
- pipe->blt_changed = 1;
- pr_info("%s: BLT-END\n", __func__);
- }
+ if (vctrl->blt_wait)
+ vctrl->blt_wait = 0;
+ spin_unlock(&vctrl->spin_lock);
+ return;
}
- spin_unlock(&dsi_clk_lock);
+
+ /* kick dmap */
+ mdp4_dsi_cmd_blt_dmap_update(pipe);
+ pipe->dmap_cnt++;
+ mdp4_stat.kickoff_dmap++;
+ vctrl->dmap_koff++;
+ vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+ outpdw(MDP_BASE + 0x000c, 0); /* kickoff dmap engine */
+ mb(); /* make sure kickoff executed */
+ spin_unlock(&vctrl->spin_lock);
}
/*
@@ -479,30 +600,61 @@
struct mdp4_overlay_pipe *pipe;
int diff;
- vsync_irq_disable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
-
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
spin_lock(&vctrl->spin_lock);
- pipe->blt_ov_done++;
- diff = pipe->blt_ov_done - pipe->blt_dmap_done;
- spin_unlock(&vctrl->spin_lock);
+ vsync_irq_disable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
+ vctrl->ov_done++;
+ complete_all(&vctrl->ov_comp);
+ diff = vctrl->ov_done - vctrl->dmap_done;
- pr_debug("%s: ov_done=%d dmap_done=%d ov_koff=%d dmap_koff=%d diff=%d\n",
- __func__, pipe->blt_ov_done, pipe->blt_dmap_done,
- pipe->blt_ov_koff, pipe->blt_dmap_koff, diff);
+ pr_debug("%s: ov_koff=%d ov_done=%d dmap_koff=%d dmap_done=%d cpu=%d\n",
+ __func__, vctrl->ov_koff, vctrl->ov_done, vctrl->dmap_koff,
+ vctrl->dmap_done, smp_processor_id());
if (pipe->ov_blt_addr == 0) {
/* blt disabled */
- pr_debug("%s: NON-BLT\n", __func__);
+ spin_unlock(&vctrl->spin_lock);
return;
}
- if (diff == 1) {
- mdp4_blt_dmap_cfg(pipe);
- vsync_commit_kickoff_dmap(pipe);
+ if (diff > 1) {
+ /*
+ * two overlay_done and none dmap_done yet
+ * let dmap_done kickoff dmap
+ * and put pipe_commit to wait
+ */
+ vctrl->blt_wait = 1;
+ pr_debug("%s: blt_wait set\n", __func__);
+ spin_unlock(&vctrl->spin_lock);
+ return;
}
+ mdp4_dsi_cmd_blt_dmap_update(pipe);
+ pipe->dmap_cnt++;
+ mdp4_stat.kickoff_dmap++;
+ vctrl->dmap_koff++;
+ vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+ outpdw(MDP_BASE + 0x000c, 0); /* kickoff dmap engine */
+ mb(); /* make sure kickoff executed */
+ spin_unlock(&vctrl->spin_lock);
+}
+
+static void clk_ctrl_work(struct work_struct *work)
+{
+ struct vsycn_ctrl *vctrl =
+ container_of(work, typeof(*vctrl), clk_work);
+
+ mutex_lock(&vctrl->update_lock);
+ if (vctrl->clk_control) {
+ if (vctrl->clk_enabled) {
+ mdp_clk_ctrl(0);
+ vctrl->clk_enabled = 0;
+ vctrl->fake_vsync = 1;
+ }
+ }
+
+ mutex_unlock(&vctrl->update_lock);
}
static void send_vsync_work(struct work_struct *work)
@@ -539,11 +691,12 @@
vctrl->blight.get = 0;
vctrl->blight.tot = 0;
mutex_init(&vctrl->update_lock);
- init_completion(&vctrl->vsync_comp);
+ init_completion(&vctrl->ov_comp);
init_completion(&vctrl->dmap_comp);
+ init_completion(&vctrl->vsync_comp);
spin_lock_init(&vctrl->spin_lock);
- spin_lock_init(&vctrl->dmap_spin_lock);
INIT_WORK(&vctrl->vsync_work, send_vsync_work);
+ INIT_WORK(&vctrl->clk_work, clk_ctrl_work);
}
void mdp4_primary_rdptr(void)
@@ -701,7 +854,7 @@
pipe->ov_blt_addr = 0;
pipe->dma_blt_addr = 0;
- MDP_OUTP(MDP_BASE + 0x021c, 0x10); /* read pointer */
+ MDP_OUTP(MDP_BASE + 0x021c, 10); /* read pointer */
/*
* configure dsi stream id
@@ -727,8 +880,6 @@
/* MDP cmd block disable */
mdp_clk_ctrl(0);
-
- wmb();
}
/* 3D side by side */
@@ -751,7 +902,6 @@
if (pipe->pipe_used == 0 ||
pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) {
pr_err("%s: NOT baselayer\n", __func__);
- mutex_unlock(&mfd->dma->ov_mutex);
return;
}
@@ -809,78 +959,20 @@
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
-int mdp4_dsi_overlay_blt_start(struct msm_fb_data_type *mfd)
+void mdp4_dsi_cmd_blt_start(struct msm_fb_data_type *mfd)
{
- unsigned long flag;
- int cndx = 0;
- struct vsycn_ctrl *vctrl;
- struct mdp4_overlay_pipe *pipe;
-
- vctrl = &vsync_ctrl_db[cndx];
- pipe = vctrl->base_pipe;
-
- pr_debug("%s: blt_end=%d blt_addr=%x pid=%d\n",
- __func__, pipe->blt_end, (int)pipe->ov_blt_addr, current->pid);
-
- mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
-
- if (mfd->ov0_wb_buf->write_addr == 0) {
- pr_err("%s: no blt_base assigned\n", __func__);
- return -EBUSY;
- }
-
- if (pipe->ov_blt_addr == 0) {
- spin_lock_irqsave(&vctrl->spin_lock, flag);
- pipe->blt_end = 0;
- pipe->blt_cnt = 0;
- pipe->blt_changed = 1;
- pipe->ov_cnt = 0;
- pipe->dmap_cnt = 0;
- pipe->blt_ov_koff = 0;
- pipe->blt_dmap_koff = 0;
- pipe->blt_ov_done = 0;
- pipe->blt_dmap_done = 0;
- pipe->ov_blt_addr = mfd->ov0_wb_buf->write_addr;
- pipe->dma_blt_addr = mfd->ov0_wb_buf->read_addr;
- mdp4_stat.blt_dsi_cmd++;
- spin_unlock_irqrestore(&vctrl->spin_lock, flag);
- return 0;
- }
-
- return -EBUSY;
+ mdp4_dsi_cmd_do_blt(mfd, 1);
}
-int mdp4_dsi_overlay_blt_stop(struct msm_fb_data_type *mfd)
+void mdp4_dsi_cmd_blt_stop(struct msm_fb_data_type *mfd)
{
- unsigned long flag;
- int cndx = 0;
- struct vsycn_ctrl *vctrl;
- struct mdp4_overlay_pipe *pipe;
-
- vctrl = &vsync_ctrl_db[cndx];
- pipe = vctrl->base_pipe;
-
- pr_info("%s: blt_end=%d blt_addr=%x pid=%d\n",
- __func__, pipe->blt_end, (int)pipe->ov_blt_addr, current->pid);
-
- if ((pipe->blt_end == 0) && pipe->ov_blt_addr) {
- spin_lock_irqsave(&vctrl->spin_lock, flag);
- pipe->blt_end = 1; /* mark as end */
- spin_unlock_irqrestore(&vctrl->spin_lock, flag);
- return 0;
- }
-
- return -EBUSY;
+ mdp4_dsi_cmd_do_blt(mfd, 0);
}
-void mdp4_dsi_overlay_blt(struct msm_fb_data_type *mfd,
+void mdp4_dsi_cmd_overlay_blt(struct msm_fb_data_type *mfd,
struct msmfb_overlay_blt *req)
{
- if (req->enable)
- mdp4_dsi_overlay_blt_start(mfd);
- else if (req->enable == 0)
- mdp4_dsi_overlay_blt_stop(mfd);
-
+ mdp4_dsi_cmd_do_blt(mfd, req->enable);
}
int mdp4_dsi_cmd_on(struct platform_device *pdev)
@@ -895,9 +987,11 @@
mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
vctrl = &vsync_ctrl_db[cndx];
+ vctrl->mfd = mfd;
vctrl->dev = mfd->fbi->dev;
mdp_clk_ctrl(1);
+ vsync_irq_enable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
if (vctrl->base_pipe == NULL)
mdp4_overlay_update_dsi_cmd(mfd);
@@ -932,16 +1026,16 @@
atomic_set(&vctrl->suspend, 1);
- /* make sure dsi clk is on so that
- * at panel_next_off() dsi panel can be shut off
- */
- mipi_dsi_ahb_ctrl(1);
- mipi_dsi_clk_enable();
+ mipi_dsi_cmd_backlight_tx(150);
mdp4_mixer_stage_down(pipe);
mdp4_overlay_pipe_free(pipe);
vctrl->base_pipe = NULL;
+ vctrl->fake_vsync = 1;
+
+ vsync_irq_disable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
+
pr_info("%s-:\n", __func__);
/*
@@ -984,12 +1078,14 @@
int cndx = 0;
struct vsycn_ctrl *vctrl;
struct mdp4_overlay_pipe *pipe;
+ long long xx;
vctrl = &vsync_ctrl_db[cndx];
if (!mfd->panel_power_on)
return;
+ vctrl->clk_control = 0;
pipe = vctrl->base_pipe;
if (pipe == NULL) {
pr_err("%s: NO base pipe\n", __func__);
@@ -1001,5 +1097,19 @@
mdp4_overlay_setup_pipe_addr(mfd, pipe);
mdp4_dsi_cmd_pipe_queue(0, pipe);
}
+
+ if (mfd->use_ov0_blt != mfd->ov0_blt_state) {
+
+ if (mfd->use_ov0_blt)
+ mdp4_dsi_cmd_do_blt(mfd, 1);
+ else
+ mdp4_dsi_cmd_do_blt(mfd, 0);
+
+ mfd->ov0_blt_state = mfd->use_ov0_blt;
+ }
+
mdp4_dsi_cmd_pipe_commit();
+ mdp4_dsi_cmd_wait4vsync(0, &xx);
+ vctrl->expire_tick = VSYNC_EXPIRE_TICK;
+ vctrl->clk_control = 1;
}
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 9f1bfda..340faa2 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -997,6 +997,16 @@
mdp4_dsi_video_pipe_queue(0, pipe);
}
+ if (mfd->use_ov0_blt != mfd->ov0_blt_state) {
+
+ if (mfd->use_ov0_blt)
+ mdp4_dsi_video_do_blt(mfd, 1);
+ else
+ mdp4_dsi_video_do_blt(mfd, 0);
+
+ mfd->ov0_blt_state = mfd->use_ov0_blt;
+ }
+
mdp4_dsi_video_pipe_commit();
if (pipe->ov_blt_addr)
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index e02e79c..d0d4f40 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -75,6 +75,7 @@
int blt_change;
int fake_vsync;
struct mutex update_lock;
+ struct completion ov_comp;
struct completion dmae_comp;
struct completion vsync_comp;
spinlock_t spin_lock;
@@ -160,6 +161,7 @@
*pp = *pipe; /* keep it */
vp->update_cnt++;
mutex_unlock(&vctrl->update_lock);
+ mdp4_stat.overlay_play[pipe->mixer_num]++;
}
static void mdp4_dtv_blt_ov_update(struct mdp4_overlay_pipe *pipe);
@@ -198,6 +200,11 @@
if (pipe->pipe_used) {
cnt++;
mdp4_overlay_vsync_commit(pipe);
+ /* free previous iommu to freelist
+ * which will be freed at next
+ * pipe_commit
+ */
+ mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 0);
pipe->pipe_used = 0; /* clear */
}
}
@@ -216,10 +223,11 @@
outpdw(MDP_BASE + 0x0008, 0);
} else if (vctrl->dmae_intr_cnt == 0) {
/* schedule second phase update at dmap */
- vctrl->dmae_intr_cnt++;
+ INIT_COMPLETION(vctrl->dmae_comp);
vsync_irq_enable(INTR_DMA_E_DONE, MDP_DMA_E_TERM);
}
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+ mdp4_stat.overlay_commit[pipe->mixer_num]++;
return cnt;
}
@@ -285,7 +293,6 @@
static void mdp4_dtv_wait4dmae(int cndx)
{
- unsigned long flags;
struct vsycn_ctrl *vctrl;
if (cndx >= MAX_CONTROLLER) {
@@ -298,19 +305,7 @@
if (atomic_read(&vctrl->suspend) > 0)
return;
- spin_lock_irqsave(&vctrl->spin_lock, flags);
- if (vctrl->dmae_wait_cnt == 0) {
- INIT_COMPLETION(vctrl->dmae_comp);
- if (vctrl->dmae_intr_cnt == 0) {
- vctrl->dmae_intr_cnt++;
- vsync_irq_enable(INTR_DMA_E_DONE, MDP_DMA_E_TERM);
- }
- }
- vctrl->dmae_wait_cnt++;
- spin_unlock_irqrestore(&vctrl->spin_lock, flags);
-
wait_for_completion(&vctrl->dmae_comp);
- pr_info("%s: pid=%d after wait\n", __func__, current->pid);
}
static void send_vsync_work(struct work_struct *work)
@@ -346,6 +341,8 @@
vctrl->update_ndx = 0;
mutex_init(&vctrl->update_lock);
init_completion(&vctrl->vsync_comp);
+ init_completion(&vctrl->ov_comp);
+ init_completion(&vctrl->dmae_comp);
atomic_set(&vctrl->suspend, 0);
spin_lock_init(&vctrl->spin_lock);
INIT_WORK(&vctrl->vsync_work, send_vsync_work);
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index cae523f..feba8b8 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -900,6 +900,16 @@
mdp4_lcdc_pipe_queue(0, pipe);
}
+ if (mfd->use_ov0_blt != mfd->ov0_blt_state) {
+
+ if (mfd->use_ov0_blt)
+ mdp4_lcdc_do_blt(mfd, 1);
+ else
+ mdp4_lcdc_do_blt(mfd, 0);
+
+ mfd->ov0_blt_state = mfd->use_ov0_blt;
+ }
+
mdp4_lcdc_pipe_commit();
if (pipe->ov_blt_addr)
diff --git a/drivers/video/msm/mdp_vsync.c b/drivers/video/msm/mdp_vsync.c
index 966b40d..cc350d3 100644
--- a/drivers/video/msm/mdp_vsync.c
+++ b/drivers/video/msm/mdp_vsync.c
@@ -74,14 +74,13 @@
static uint32 vsync_cnt_cfg;
-
-void vsync_clk_enable()
+void vsync_clk_prepare_enable(void)
{
if (mdp_vsync_clk)
clk_prepare_enable(mdp_vsync_clk);
}
-void vsync_clk_disable()
+void vsync_clk_disable_unprepare(void)
{
if (mdp_vsync_clk)
clk_disable_unprepare(mdp_vsync_clk);
diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c
index b4fb930..f08a4e4 100644
--- a/drivers/video/msm/mipi_dsi.c
+++ b/drivers/video/msm/mipi_dsi.c
@@ -554,8 +554,10 @@
if (rc)
goto mipi_dsi_probe_err;
- if ((dsi_pclk_rate < 3300000) || (dsi_pclk_rate > 103300000))
+ if ((dsi_pclk_rate < 3300000) || (dsi_pclk_rate > 223000000)) {
+ pr_err("%s: Pixel clock not supported\n", __func__);
dsi_pclk_rate = 35000000;
+ }
mipi->dsi_pclk_rate = dsi_pclk_rate;
/*
diff --git a/drivers/video/msm/mipi_dsi_host.c b/drivers/video/msm/mipi_dsi_host.c
index 4afffb0..39e2d6d 100644
--- a/drivers/video/msm/mipi_dsi_host.c
+++ b/drivers/video/msm/mipi_dsi_host.c
@@ -1151,15 +1151,11 @@
spin_lock_irqsave(&dsi_mdp_lock, flag);
dsi_mdp_busy = TRUE;
- spin_unlock_irqrestore(&dsi_mdp_lock, flag);
-
led_pwm1[1] = (unsigned char)(level);
tp = &dsi_tx_buf;
cmd = &backlight_cmd;
mipi_dsi_buf_init(&dsi_tx_buf);
-
-
if (tp->dmap) {
dma_unmap_single(&dsi_dev, tp->dmap, tp->len, DMA_TO_DEVICE);
tp->dmap = 0;
@@ -1180,10 +1176,6 @@
wmb();
MIPI_OUTP(MIPI_DSI_BASE + 0x08c, 0x01); /* trigger */
wmb();
-
- spin_lock_irqsave(&dsi_mdp_lock, flag);
- dsi_mdp_busy = FALSE;
- complete(&dsi_mdp_comp);
spin_unlock_irqrestore(&dsi_mdp_lock, flag);
}
@@ -1383,6 +1375,8 @@
int mipi_dsi_cmd_dma_tx(struct dsi_buf *tp)
{
+ unsigned long flags;
+
#ifdef DSI_HOST_DEBUG
int i;
char *bp;
@@ -1396,6 +1390,7 @@
pr_debug("\n");
#endif
+ spin_lock_irqsave(&dsi_mdp_lock, flags);
tp->len += 3;
tp->len &= ~0x03; /* multipled by 4 */
@@ -1410,6 +1405,7 @@
wmb();
MIPI_OUTP(MIPI_DSI_BASE + 0x08c, 0x01); /* trigger */
wmb();
+ spin_unlock_irqrestore(&dsi_mdp_lock, flags);
wait_for_completion(&dsi_dma_comp);
@@ -1549,8 +1545,8 @@
if (isr & DSI_INTR_CMD_DMA_DONE) {
mipi_dsi_mdp_stat_inc(STAT_DSI_CMD);
- complete(&dsi_dma_comp);
spin_lock(&dsi_mdp_lock);
+ complete(&dsi_dma_comp);
dsi_ctrl_lock = FALSE;
mipi_dsi_disable_irq_nosync();
spin_unlock(&dsi_mdp_lock);
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 18ec3f1..2c1f5b7 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -1772,8 +1772,7 @@
if (mfd->msmfb_no_update_notify_timer.function)
del_timer(&mfd->msmfb_no_update_notify_timer);
- mfd->msmfb_no_update_notify_timer.expires =
- jiffies + ((1000 * HZ) / 1000);
+ mfd->msmfb_no_update_notify_timer.expires = jiffies + (2 * HZ);
add_timer(&mfd->msmfb_no_update_notify_timer);
mutex_unlock(&msm_fb_notify_update_sem);
@@ -2961,8 +2960,7 @@
if (mfd->msmfb_no_update_notify_timer.function)
del_timer(&mfd->msmfb_no_update_notify_timer);
- mfd->msmfb_no_update_notify_timer.expires =
- jiffies + ((1000 * HZ) / 1000);
+ mfd->msmfb_no_update_notify_timer.expires = jiffies + (2 * HZ);
add_timer(&mfd->msmfb_no_update_notify_timer);
mutex_unlock(&msm_fb_notify_update_sem);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
index 267e924..fade821 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
@@ -217,6 +217,7 @@
DDL_METADATA_ALIGNSIZE(suffix);
decoder->suffix = suffix;
output_buf_req->sz += suffix;
+ decoder->meta_data_offset = 0;
DDL_MSG_LOW("metadata output buf size : %d", suffix);
}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
index 2d3bee3..033457d 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -1953,11 +1953,7 @@
DDL_TILE_MULTIPLY_FACTOR);
total_memory_size += component_mem_size;
} else {
- if (decoding)
- total_memory_size = frame_sz.scan_lines *
- frame_sz.stride;
- else
- total_memory_size = frame_sz.height * frame_sz.stride;
+ total_memory_size = frame_sz.scan_lines * frame_sz.stride;
c_offset = DDL_ALIGN(total_memory_size,
DDL_LINEAR_MULTIPLY_FACTOR);
total_memory_size = c_offset + DDL_ALIGN(
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
index d45de2d..d83cde8 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
@@ -897,7 +897,7 @@
VIDC_SM_EXTENDED_PAR_HEIGHT_SHFT);
break;
default:
- DDL_MSG_ERROR("Incorrect Aspect Ratio.");
+ DDL_MSG_HIGH("Incorrect Aspect Ratio.");
aspect_ratio_info->par_width = 1;
aspect_ratio_info->par_height = 1;
break;
@@ -955,7 +955,7 @@
VIDC_SM_EXTENDED_PAR_HEIGHT_SHFT);
break;
default:
- DDL_MSG_ERROR("Incorrect Aspect Ratio.");
+ DDL_MSG_HIGH("Incorrect Aspect Ratio.");
aspect_ratio_info->par_width = 1;
aspect_ratio_info->par_height = 1;
break;
diff --git a/drivers/video/msm/vidc/Kconfig b/drivers/video/msm/vidc/Kconfig
index 9ffcb15..7820e53 100644
--- a/drivers/video/msm/vidc/Kconfig
+++ b/drivers/video/msm/vidc/Kconfig
@@ -37,3 +37,7 @@
help
This option enables support for Video decoder.
+config MSM_VIDC_CONTENT_PROTECTION
+ bool "Enable Content Protection"
+ help
+ Enable content protection feature for Video.
diff --git a/include/linux/coresight-stm.h b/include/linux/coresight-stm.h
index 20c4963..56a6cdf 100644
--- a/include/linux/coresight-stm.h
+++ b/include/linux/coresight-stm.h
@@ -14,12 +14,13 @@
#define __MACH_STM_H
enum {
- OST_ENTITY_NONE = 0x0,
- OST_ENTITY_FTRACE_EVENTS = 0x1,
- OST_ENTITY_TRACE_PRINTK = 0x2,
- OST_ENTITY_TRACE_MARKER = 0x4,
- OST_ENTITY_DEV_NODE = 0x8,
- OST_ENTITY_ALL = 0xF,
+ OST_ENTITY_NONE = 0x00,
+ OST_ENTITY_FTRACE_EVENTS = 0x01,
+ OST_ENTITY_TRACE_PRINTK = 0x02,
+ OST_ENTITY_TRACE_MARKER = 0x04,
+ OST_ENTITY_DEV_NODE = 0x08,
+ OST_ENTITY_PRINTK = 0x10,
+ OST_ENTITY_ALL = 0x1F,
};
enum {
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index b6064a4..04fcd88 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -132,6 +132,7 @@
struct coresight_ops_sink {
int (*enable)(struct coresight_device *csdev);
void (*disable)(struct coresight_device *csdev);
+ void (*abort)(struct coresight_device *csdev);
};
struct coresight_ops_link {
@@ -150,42 +151,21 @@
const struct coresight_ops_source *source_ops;
};
-struct qdss_source {
- struct list_head link;
- const char *name;
- uint32_t fport_mask;
-};
-
-struct msm_qdss_platform_data {
- struct qdss_source *src_table;
- size_t size;
- uint8_t afamily;
-};
-
-
#ifdef CONFIG_MSM_QDSS
-extern struct qdss_source *qdss_get(const char *name);
-extern void qdss_put(struct qdss_source *src);
-extern int qdss_enable(struct qdss_source *src);
-extern void qdss_disable(struct qdss_source *src);
-extern void qdss_disable_sink(void);
extern struct coresight_device *
coresight_register(struct coresight_desc *desc);
extern void coresight_unregister(struct coresight_device *csdev);
extern int coresight_enable(struct coresight_device *csdev);
extern void coresight_disable(struct coresight_device *csdev);
+extern void coresight_abort(void);
#else
-static inline struct qdss_source *qdss_get(const char *name) { return NULL; }
-static inline void qdss_put(struct qdss_source *src) {}
-static inline int qdss_enable(struct qdss_source *src) { return -ENOSYS; }
-static inline void qdss_disable(struct qdss_source *src) {}
-static inline void qdss_disable_sink(void) {}
static inline struct coresight_device *
coresight_register(struct coresight_desc *desc) { return NULL; }
static inline void coresight_unregister(struct coresight_device *csdev) {}
static inline int
coresight_enable(struct coresight_device *csdev) { return -ENOSYS; }
static inline void coresight_disable(struct coresight_device *csdev) {}
+static inline void coresight_abort(void) {}
#endif
#endif
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 17be2cb..105c2cb 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -144,6 +144,7 @@
int (*write_dev)(struct wcd9xxx *wcd9xxx, unsigned short reg,
int bytes, void *src, bool interface_reg);
+ u32 num_of_supplies;
struct regulator_bulk_data *supplies;
enum wcd9xxx_pm_state pm_state;
diff --git a/include/linux/mfd/wcd9xxx/pdata.h b/include/linux/mfd/wcd9xxx/pdata.h
index 1b7706b..e831f0b 100644
--- a/include/linux/mfd/wcd9xxx/pdata.h
+++ b/include/linux/mfd/wcd9xxx/pdata.h
@@ -125,7 +125,7 @@
unsigned int hph_ocp_limit:3; /* Headphone OCP current limit */
};
-#define MAX_REGULATOR 6
+#define MAX_REGULATOR 7
/*
* format : TABLA_<POWER_SUPPLY_PIN_NAME>_CUR_MAX
*
diff --git a/include/linux/of_coresight.h b/include/linux/of_coresight.h
new file mode 100644
index 0000000..47a05c9
--- /dev/null
+++ b/include/linux/of_coresight.h
@@ -0,0 +1,27 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_OF_CORESIGHT_H
+#define __LINUX_OF_CORESIGHT_H
+
+#ifdef CONFIG_OF
+extern struct coresight_platform_data *of_get_coresight_platform_data(
+ struct device *dev, struct device_node *node);
+#else
+static inline struct coresight_platform_data *of_get_coresight_platform_data(
+ struct device *dev, struct device_node *node)
+{
+ return NULL;
+}
+#endif
+
+#endif
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 763e977..e731f97 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -363,6 +363,7 @@
#define PHY_PWR_COLLAPSED BIT(0)
#define PHY_RETENTIONED BIT(1)
#define XO_SHUTDOWN BIT(2)
+#define CLOCKS_DOWN BIT(3)
int reset_counter;
unsigned long b_last_se0_sess;
unsigned long tmouts;
diff --git a/include/media/vcap_v4l2.h b/include/media/vcap_v4l2.h
index 390a843..cf99435 100644
--- a/include/media/vcap_v4l2.h
+++ b/include/media/vcap_v4l2.h
@@ -28,6 +28,7 @@
#include <media/v4l2-common.h>
#include <media/vcap_fmt.h>
#include <mach/board.h>
+#include <mach/iommu_domains.h>
#define to_client_data(val) container_of(val, struct vcap_client_data, vfh)
@@ -94,7 +95,7 @@
};
struct nr_buffer {
- void *vaddr;
+ struct ion_handle *nr_handle;
unsigned long paddr;
enum nr_buf_pos nr_pos;
};
@@ -118,6 +119,7 @@
struct vcap_buffer *bufOut;
+ struct ion_handle *motionHandle;
void *bufMotion;
struct nr_buffer bufNR;
struct nr_param nr_param;
diff --git a/include/net/bluetooth/sco.h b/include/net/bluetooth/sco.h
index 160e3f0..6d94c34 100644
--- a/include/net/bluetooth/sco.h
+++ b/include/net/bluetooth/sco.h
@@ -31,7 +31,7 @@
#define SCO_DEFAULT_FLUSH_TO 0xFFFF
#define SCO_CONN_TIMEOUT (HZ * 40)
-#define SCO_DISCONN_TIMEOUT (HZ * 2)
+#define SCO_DISCONN_TIMEOUT (HZ * 20)
#define SCO_CONN_IDLE_TIMEOUT (HZ * 60)
/* SCO socket address */
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index 7697249..5d675a7 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -17,6 +17,7 @@
*/
#include <linux/ftrace_event.h>
+#include <linux/coresight-stm.h>
/*
* DECLARE_EVENT_CLASS can be used to add a generic function
@@ -544,9 +545,12 @@
\
{ assign; } \
\
- if (!filter_current_check_discard(buffer, event_call, entry, event)) \
+ if (!filter_current_check_discard(buffer, event_call, entry, event)) { \
+ stm_log(OST_ENTITY_FTRACE_EVENTS, entry, \
+ sizeof(*entry) + __data_size); \
trace_nowake_buffer_unlock_commit(buffer, \
event, irq_flags, pc); \
+ } \
}
/*
* The ftrace_test_probe is compiled out, it is only here as a build time check
diff --git a/kernel/printk.c b/kernel/printk.c
index 4cf4670..90dfdde 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -41,6 +41,7 @@
#include <linux/cpu.h>
#include <linux/notifier.h>
#include <linux/rculist.h>
+#include <linux/coresight-stm.h>
#include <asm/uaccess.h>
@@ -959,6 +960,8 @@
}
}
+ stm_log(OST_ENTITY_PRINTK, printk_buf, printed_len);
+
/*
* Copy the output into log_buf. If the caller didn't provide
* the appropriate log prefix, we insert them here
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 05970ea..b9d1a73 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -38,6 +38,7 @@
#include <linux/poll.h>
#include <linux/nmi.h>
#include <linux/fs.h>
+#include <linux/coresight-stm.h>
#include "trace.h"
#include "trace_output.h"
@@ -1629,6 +1630,7 @@
memcpy(&entry->buf, trace_buf, len);
entry->buf[len] = '\0';
if (!filter_check_discard(call, entry, buffer, event)) {
+ stm_log(OST_ENTITY_TRACE_PRINTK, event, size);
ring_buffer_unlock_commit(buffer, event);
ftrace_trace_stack(buffer, irq_flags, 6, pc);
}
@@ -3826,6 +3828,7 @@
} else
entry->buf[cnt] = '\0';
+ stm_log(OST_ENTITY_TRACE_MARKER, event, size);
ring_buffer_unlock_commit(buffer, event);
written = cnt;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index f83c108..6e8500b 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2929,8 +2929,16 @@
static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_sniff_subrate *ev = (void *) skb->data;
+ struct hci_conn *conn =
+ hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
BT_DBG("%s status %d", hdev->name, ev->status);
+ if (conn && (ev->max_rx_latency > hdev->sniff_max_interval)) {
+ BT_ERR("value of rx_latency:%d", ev->max_rx_latency);
+ hci_dev_lock(hdev);
+ hci_conn_enter_active_mode(conn, 1);
+ hci_dev_unlock(hdev);
+ }
}
static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 0a89c11..d80c0e3 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -95,12 +95,12 @@
static struct device *hidp_get_device(struct hidp_session *session)
{
- bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
- bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
+ bdaddr_t *dst = &session->bdaddr;
+
struct device *device = NULL;
struct hci_dev *hdev;
- hdev = hci_get_route(dst, src);
+ hdev = hci_get_route(dst, BDADDR_ANY);
if (!hdev)
return NULL;
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index f090a77..9669d4a 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -394,6 +394,15 @@
case BT_CONNECTED:
case BT_CONFIG:
+ if (sco_pi(sk)->conn) {
+ sk->sk_state = BT_DISCONN;
+ sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT);
+ hci_conn_put(sco_pi(sk)->conn->hcon);
+ sco_pi(sk)->conn->hcon = NULL;
+ } else
+ sco_chan_del(sk, ECONNRESET);
+ break;
+
case BT_CONNECT:
case BT_DISCONN:
sco_chan_del(sk, ECONNRESET);
@@ -803,6 +812,9 @@
if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
err = bt_sock_wait_state(sk, BT_CLOSED,
sk->sk_lingertime);
+ else
+ err = bt_sock_wait_state(sk, BT_CLOSED,
+ SCO_DISCONN_TIMEOUT);
}
release_sock(sk);
return err;
@@ -824,6 +836,11 @@
lock_sock(sk);
err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
release_sock(sk);
+ } else {
+ lock_sock(sk);
+ err = bt_sock_wait_state(sk, BT_CLOSED,
+ SCO_DISCONN_TIMEOUT);
+ release_sock(sk);
}
sock_orphan(sk);
@@ -857,7 +874,9 @@
conn->sk = NULL;
sco_pi(sk)->conn = NULL;
sco_conn_unlock(conn);
- hci_conn_put(conn->hcon);
+
+ if (conn->hcon)
+ hci_conn_put(conn->hcon);
}
sk->sk_state = BT_CLOSED;
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 571e71c..4758829 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -35,6 +35,10 @@
#include <linux/gpio.h>
#include "wcd9310.h"
+static int cfilt_adjust_ms = 10;
+module_param(cfilt_adjust_ms, int, 0644);
+MODULE_PARM_DESC(cfilt_adjust_ms, "delay after adjusting cfilt voltage in ms");
+
#define WCD9310_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
@@ -2240,26 +2244,26 @@
}
snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x84);
- if (!tabla->no_mic_headset_override) {
- if (mbhc_state == MBHC_STATE_POTENTIAL) {
- pr_debug("%s recovering MBHC state macine\n", __func__);
- tabla->mbhc_state = MBHC_STATE_POTENTIAL_RECOVERY;
- /* set to max button press threshold */
- snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B2_CTL,
- 0x7F);
- snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL,
- 0xFF);
- snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL,
- (TABLA_IS_1_X(tabla_core->version) ?
- 0x07 : 0x7F));
- snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B3_CTL,
- 0xFF);
- /* set to max */
- snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B6_CTL,
- 0x7F);
- snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B5_CTL,
- 0xFF);
- }
+ if (tabla->no_mic_headset_override) {
+ pr_debug("%s setting button threshold to min", __func__);
+ /* set to min */
+ snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL, 0x80);
+ snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B3_CTL, 0x00);
+ snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B6_CTL, 0x80);
+ snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B5_CTL, 0x00);
+ } else if (unlikely(mbhc_state == MBHC_STATE_POTENTIAL)) {
+ pr_debug("%s recovering MBHC state machine\n", __func__);
+ tabla->mbhc_state = MBHC_STATE_POTENTIAL_RECOVERY;
+ /* set to max button press threshold */
+ snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B2_CTL, 0x7F);
+ snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL, 0xFF);
+ snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL,
+ (TABLA_IS_1_X(tabla_core->version) ?
+ 0x07 : 0x7F));
+ snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B3_CTL, 0xFF);
+ /* set to max */
+ snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B6_CTL, 0x7F);
+ snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B5_CTL, 0xFF);
}
snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x1);
@@ -2479,11 +2483,11 @@
cfilt_k_val = tabla_find_k_value(
tabla->pdata->micbias.ldoh_v,
VDDIO_MICBIAS_MV);
- usleep_range(10000, 10000);
snd_soc_update_bits(codec,
tabla->mbhc_bias_regs.cfilt_val,
0xFC, (cfilt_k_val << 2));
- usleep_range(10000, 10000);
+ usleep_range(cfilt_adjust_ms * 1000,
+ cfilt_adjust_ms * 1000);
snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL,
tabla->mbhc_data.adj_v_ins_hu & 0xFF);
snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B2_CTL,
@@ -2517,7 +2521,8 @@
snd_soc_update_bits(codec,
tabla->mbhc_bias_regs.cfilt_val,
0xFC, (cfilt_k_val << 2));
- usleep_range(10000, 10000);
+ usleep_range(cfilt_adjust_ms * 1000,
+ cfilt_adjust_ms * 1000);
snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL,
tabla->mbhc_data.v_ins_hu & 0xFF);
snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B2_CTL,
@@ -3878,11 +3883,22 @@
}
} else if (dai->id == AIF1_CAP || dai->id == AIF2_CAP ||
dai->id == AIF3_CAP) {
- for (i = 0; i < tx_num; i++) {
- tabla->dai[dai->id - 1].ch_num[i] = tx_slot[i];
- tabla->dai[dai->id - 1].ch_act = 0;
- tabla->dai[dai->id - 1].ch_tot = tx_num;
+ tabla->dai[dai->id - 1].ch_tot = tx_num;
+ /* All channels are already active.
+ * do not reset ch_act flag
+ */
+ if ((tabla->dai[dai->id - 1].ch_tot != 0)
+ && (tabla->dai[dai->id - 1].ch_act ==
+ tabla->dai[dai->id - 1].ch_tot)) {
+ pr_info("%s: ch_act = %d, ch_tot = %d\n", __func__,
+ tabla->dai[dai->id - 1].ch_act,
+ tabla->dai[dai->id - 1].ch_tot);
+ return 0;
}
+
+ tabla->dai[dai->id - 1].ch_act = 0;
+ for (i = 0; i < tx_num; i++)
+ tabla->dai[dai->id - 1].ch_num[i] = tx_slot[i];
}
return 0;
}
@@ -7766,9 +7782,15 @@
lbuf[cnt] = '\0';
buf = (char *)lbuf;
- tabla->no_mic_headset_override = (*strsep(&buf, " ") == '0') ?
- false : true;
- return rc;
+ TABLA_ACQUIRE_LOCK(tabla->codec_resource_lock);
+ tabla->no_mic_headset_override =
+ (*strsep(&buf, " ") == '0') ? false : true;
+ if (tabla->no_mic_headset_override && tabla->mbhc_polling_active) {
+ tabla_codec_pause_hs_polling(tabla->codec);
+ tabla_codec_start_hs_polling(tabla->codec);
+ }
+ TABLA_RELEASE_LOCK(tabla->codec_resource_lock);
+ return cnt;
}
static ssize_t codec_mbhc_debug_read(struct file *file, char __user *buf,
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 6da9166..01820eb 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -6817,18 +6817,21 @@
struct snd_soc_codec *codec = taiko->codec;
struct wcd9xxx_pdata *pdata = taiko->pdata;
int k1, k2, k3, rc = 0;
- u8 leg_mode = pdata->amic_settings.legacy_mode;
- u8 txfe_bypass = pdata->amic_settings.txfe_enable;
- u8 txfe_buff = pdata->amic_settings.txfe_buff;
- u8 flag = pdata->amic_settings.use_pdata;
+ u8 leg_mode, txfe_bypass, txfe_buff, flag;
u8 i = 0, j = 0;
u8 val_txfe = 0, value = 0;
if (!pdata) {
+ pr_err("%s: NULL pdata\n", __func__);
rc = -ENODEV;
goto done;
}
+ leg_mode = pdata->amic_settings.legacy_mode;
+ txfe_bypass = pdata->amic_settings.txfe_enable;
+ txfe_buff = pdata->amic_settings.txfe_buff;
+ flag = pdata->amic_settings.use_pdata;
+
/* Make sure settings are correct */
if ((pdata->micbias.ldoh_v > TAIKO_LDOH_2P85_V) ||
(pdata->micbias.bias1_cfilt_sel > TAIKO_CFILT3_SEL) ||
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index da3d335..26dbb21 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -1782,6 +1782,7 @@
.put = msm_routing_set_srs_trumedia_control,
.private_value = ((unsigned long)&(struct soc_mixer_control)
{.reg = SND_SOC_NOPM,
+ .rreg = SND_SOC_NOPM,
.shift = 0,
.rshift = 0,
.max = 0xFFFFFFFF,
@@ -1801,6 +1802,7 @@
.put = msm_routing_set_srs_trumedia_control_HDMI,
.private_value = ((unsigned long)&(struct soc_mixer_control)
{.reg = SND_SOC_NOPM,
+ .rreg = SND_SOC_NOPM,
.shift = 0,
.rshift = 0,
.max = 0xFFFFFFFF,
@@ -1820,6 +1822,7 @@
.put = msm_routing_set_srs_trumedia_control_I2S,
.private_value = ((unsigned long)&(struct soc_mixer_control)
{.reg = SND_SOC_NOPM,
+ .rreg = SND_SOC_NOPM,
.shift = 0,
.rshift = 0,
.max = 0xFFFFFFFF,
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 3791f24..2a21dfa 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -36,10 +36,16 @@
#define VOC_PATH_VOLTE_PASSIVE 2
#define VOC_PATH_SGLTE_PASSIVE 3
-/* CVP CAL Size: 245760 = 240 * 1024 */
-#define CVP_CAL_SIZE 245760
-/* CVS CAL Size: 49152 = 48 * 1024 */
-#define CVS_CAL_SIZE 49152
+#define CAL_BUFFER_SIZE 4096
+#define NUM_CVP_CAL_BLOCKS 75
+#define NUM_CVS_CAL_BLOCKS 15
+#define CVP_CAL_SIZE (NUM_CVP_CAL_BLOCKS * CAL_BUFFER_SIZE)
+#define CVS_CAL_SIZE (NUM_CVS_CAL_BLOCKS * CAL_BUFFER_SIZE)
+#define VOICE_CAL_BUFFER_SIZE (CVP_CAL_SIZE + CVS_CAL_SIZE)
+/* Total cal needed to support concurrent VOIP & VOLTE sessions */
+/* Due to memory map issue on Q6 separate memory has to be used */
+/* for VOIP & VOLTE */
+#define TOTAL_VOICE_CAL_SIZE (NUM_VOICE_CAL_BUFFERS * VOICE_CAL_BUFFER_SIZE)
static struct common_data common;
@@ -198,6 +204,72 @@
return (session_id == common.voice[VOC_PATH_SGLTE_PASSIVE].session_id);
}
+/* Only for memory allocated in the voice driver */
+/* which includes voip & volte */
+static int voice_get_cal_kernel_addr(int16_t session_id, int cal_type,
+ uint32_t *kvaddr)
+{
+ int i, result = 0;
+ pr_debug("%s\n", __func__);
+
+ if (kvaddr == NULL) {
+ pr_err("%s: NULL pointer sent to function\n", __func__);
+ result = -EINVAL;
+ goto done;
+ } else if (is_voip_session(session_id)) {
+ i = VOIP_CAL;
+ } else if (is_volte_session(session_id)) {
+ i = VOLTE_CAL;
+ } else {
+ result = -EINVAL;
+ goto done;
+ }
+
+ if (common.voice_cal[i].cal_data[cal_type].kvaddr == 0) {
+ pr_err("%s: NULL pointer for session_id %d, type %d, cal_type %d\n",
+ __func__, session_id, i, cal_type);
+ result = -EFAULT;
+ goto done;
+ }
+
+ *kvaddr = common.voice_cal[i].cal_data[cal_type].kvaddr;
+done:
+ return result;
+}
+
+/* Only for memory allocated in the voice driver */
+/* which includes voip & volte */
+static int voice_get_cal_phys_addr(int16_t session_id, int cal_type,
+ uint32_t *paddr)
+{
+ int i, result = 0;
+ pr_debug("%s\n", __func__);
+
+ if (paddr == NULL) {
+ pr_err("%s: NULL pointer sent to function\n", __func__);
+ result = -EINVAL;
+ goto done;
+ } else if (is_voip_session(session_id)) {
+ i = VOIP_CAL;
+ } else if (is_volte_session(session_id)) {
+ i = VOLTE_CAL;
+ } else {
+ result = -EINVAL;
+ goto done;
+ }
+
+ if (common.voice_cal[i].cal_data[cal_type].paddr == 0) {
+ pr_err("%s: No addr for session_id %d, type %d, cal_type %d\n",
+ __func__, session_id, i, cal_type);
+ result = -EFAULT;
+ goto done;
+ }
+
+ *paddr = common.voice_cal[i].cal_data[cal_type].paddr;
+done:
+ return result;
+}
+
static int voice_apr_register(void)
{
pr_debug("%s\n", __func__);
@@ -1237,7 +1309,8 @@
int ret = 0;
void *apr_cvs;
u16 cvs_handle;
- uint32_t cal_paddr;
+ uint32_t cal_paddr = 0;
+ uint32_t cal_buf = 0;
/* get the cvs cal data */
get_all_vocstrm_cal(&cal_block);
@@ -1255,16 +1328,20 @@
return -EINVAL;
}
- if (is_voip_session(v->session_id)) {
- if (common.cvs_cal.buf) {
- cal_paddr = common.cvs_cal.phy;
+ if (is_volte_session(v->session_id) ||
+ is_voip_session(v->session_id)) {
+ ret = voice_get_cal_phys_addr(v->session_id, CVS_CAL,
+ &cal_paddr);
+ if (ret < 0)
+ return ret;
- memcpy(common.cvs_cal.buf,
- (void *) cal_block.cal_kvaddr,
- cal_block.cal_size);
- } else {
- return -EINVAL;
- }
+ ret = voice_get_cal_kernel_addr(v->session_id, CVS_CAL,
+ &cal_buf);
+ if (ret < 0)
+ return ret;
+
+ memcpy((void *)cal_buf, (void *)cal_block.cal_kvaddr,
+ cal_block.cal_size);
} else {
cal_paddr = cal_block.cal_paddr;
}
@@ -1364,7 +1441,7 @@
int ret = 0;
void *apr_cvp;
u16 cvp_handle;
- uint32_t cal_paddr;
+ uint32_t cal_paddr = 0;
/* get all cvp cal data */
get_all_cvp_cal(&cal_block);
@@ -1382,14 +1459,16 @@
return -EINVAL;
}
- if (is_voip_session(v->session_id)) {
- if (common.cvp_cal.buf)
- cal_paddr = common.cvp_cal.phy;
- else
- return -EINVAL;
+ if (is_volte_session(v->session_id) ||
+ is_voip_session(v->session_id)) {
+ ret = voice_get_cal_phys_addr(v->session_id, CVP_CAL,
+ &cal_paddr);
+ if (ret < 0)
+ return ret;
} else {
cal_paddr = cal_block.cal_paddr;
}
+
cvp_handle = voice_get_cvp_handle(v);
/* fill in the header */
@@ -1402,7 +1481,7 @@
cvp_map_mem_cmd.hdr.token = 0;
cvp_map_mem_cmd.hdr.opcode = VSS_ICOMMON_CMD_MAP_MEMORY;
- pr_debug("%s, phy_addr:0x%x, mem_size:%d\n", __func__,
+ pr_debug("%s, phys_addr: 0x%x, mem_size: %d\n", __func__,
cal_paddr, cal_block.cal_size);
cvp_map_mem_cmd.vss_map_mem.phys_addr = cal_paddr;
cvp_map_mem_cmd.vss_map_mem.mem_size = cal_block.cal_size;
@@ -1435,7 +1514,7 @@
int ret = 0;
void *apr_cvp;
u16 cvp_handle;
- uint32_t cal_paddr;
+ uint32_t cal_paddr = 0;
get_all_cvp_cal(&cal_block);
if (cal_block.cal_size == 0)
@@ -1452,10 +1531,15 @@
return -EINVAL;
}
- if (is_voip_session(v->session_id))
- cal_paddr = common.cvp_cal.phy;
- else
+ if (is_volte_session(v->session_id) ||
+ is_voip_session(v->session_id)) {
+ ret = voice_get_cal_phys_addr(v->session_id, CVP_CAL,
+ &cal_paddr);
+ if (ret < 0)
+ return ret;
+ } else {
cal_paddr = cal_block.cal_paddr;
+ }
cvp_handle = voice_get_cvp_handle(v);
@@ -1497,7 +1581,7 @@
int ret = 0;
void *apr_cvs;
u16 cvs_handle;
- uint32_t cal_paddr;
+ uint32_t cal_paddr = 0;
/* get all cvs cal data */
get_all_vocstrm_cal(&cal_block);
@@ -1515,11 +1599,12 @@
return -EINVAL;
}
- if (is_voip_session(v->session_id)) {
- if (common.cvs_cal.buf)
- cal_paddr = common.cvs_cal.phy;
- else
- return -EINVAL;
+ if (is_volte_session(v->session_id) ||
+ is_voip_session(v->session_id)) {
+ ret = voice_get_cal_phys_addr(v->session_id, CVS_CAL,
+ &cal_paddr);
+ if (ret < 0)
+ return ret;
} else {
cal_paddr = cal_block.cal_paddr;
}
@@ -1569,7 +1654,7 @@
int ret = 0;
void *apr_cvs;
u16 cvs_handle;
- uint32_t cal_paddr;
+ uint32_t cal_paddr = 0;
get_all_vocstrm_cal(&cal_block);
if (cal_block.cal_size == 0)
@@ -1586,10 +1671,15 @@
return -EINVAL;
}
- if (is_voip_session(v->session_id))
- cal_paddr = common.cvs_cal.phy;
- else
+ if (is_volte_session(v->session_id) ||
+ is_voip_session(v->session_id)) {
+ ret = voice_get_cal_phys_addr(v->session_id, CVS_CAL,
+ &cal_paddr);
+ if (ret < 0)
+ return ret;
+ } else {
cal_paddr = cal_block.cal_paddr;
+ }
cvs_handle = voice_get_cvs_handle(v);
@@ -1631,7 +1721,8 @@
int ret = 0;
void *apr_cvp;
u16 cvp_handle;
- uint32_t cal_paddr;
+ uint32_t cal_paddr = 0;
+ uint32_t cal_buf = 0;
/* get the cvp cal data */
get_all_vocproc_cal(&cal_block);
@@ -1649,16 +1740,20 @@
return -EINVAL;
}
- if (is_voip_session(v->session_id)) {
- if (common.cvp_cal.buf) {
- cal_paddr = common.cvp_cal.phy;
+ if (is_volte_session(v->session_id) ||
+ is_voip_session(v->session_id)) {
+ ret = voice_get_cal_phys_addr(v->session_id, CVP_CAL,
+ &cal_paddr);
+ if (ret < 0)
+ return ret;
- memcpy(common.cvp_cal.buf,
- (void *)cal_block.cal_kvaddr,
- cal_block.cal_size);
- } else {
- return -EINVAL;
- }
+ ret = voice_get_cal_kernel_addr(v->session_id, CVP_CAL,
+ &cal_buf);
+ if (ret < 0)
+ return ret;
+
+ memcpy((void *)cal_buf, (void *)cal_block.cal_kvaddr,
+ cal_block.cal_size);
} else {
cal_paddr = cal_block.cal_paddr;
}
@@ -1759,7 +1854,8 @@
int ret = 0;
void *apr_cvp;
u16 cvp_handle;
- uint32_t cal_paddr;
+ uint32_t cal_paddr = 0;
+ uint32_t cal_buf = 0;
/* get the cvp vol cal data */
get_all_vocvol_cal(&vol_block);
@@ -1779,16 +1875,21 @@
return -EINVAL;
}
- if (is_voip_session(v->session_id)) {
- if (common.cvp_cal.buf) {
- cal_paddr = common.cvp_cal.phy + voc_block.cal_size;
+ if (is_volte_session(v->session_id) ||
+ is_voip_session(v->session_id)) {
+ ret = voice_get_cal_phys_addr(v->session_id, CVP_CAL,
+ &cal_paddr);
+ if (ret < 0)
+ return ret;
- memcpy(common.cvp_cal.buf + voc_block.cal_size,
- (void *) vol_block.cal_kvaddr,
- vol_block.cal_size);
- } else {
- return -EINVAL;
- }
+ cal_paddr += voc_block.cal_size;
+ ret = voice_get_cal_kernel_addr(v->session_id, CVP_CAL,
+ &cal_buf);
+ if (ret < 0)
+ return ret;
+
+ memcpy((void *)(cal_buf + voc_block.cal_size),
+ (void *)vol_block.cal_kvaddr, vol_block.cal_size);
} else {
cal_paddr = vol_block.cal_paddr;
}
@@ -3943,76 +4044,83 @@
}
+static void voice_allocate_shared_memory(void)
+{
+ int i, j, result;
+ int offset = 0;
+ int mem_len;
+ unsigned long paddr;
+ void *kvptr;
+ pr_debug("%s\n", __func__);
+
+ common.ion_client = msm_ion_client_create(UINT_MAX, "q6voice_client");
+ if (IS_ERR_OR_NULL((void *)common.ion_client)) {
+ pr_err("%s: ION create client failed\n", __func__);
+ goto err;
+ }
+
+ common.ion_handle = ion_alloc(common.ion_client,
+ TOTAL_VOICE_CAL_SIZE,
+ SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+ if (IS_ERR_OR_NULL((void *) common.ion_handle)) {
+ pr_err("%s: ION memory allocation failed\n",
+ __func__);
+ goto err_ion_client;
+ }
+
+ result = ion_phys(common.ion_client, common.ion_handle,
+ &paddr, (size_t *)&mem_len);
+ if (result) {
+ pr_err("%s: ION Get Physical failed, rc = %d\n",
+ __func__, result);
+ goto err_ion_handle;
+ }
+
+ kvptr = ion_map_kernel(common.ion_client,
+ common.ion_handle, 0);
+ if (IS_ERR_OR_NULL(kvptr)) {
+ pr_err("%s: ION memory mapping failed\n", __func__);
+ goto err_ion_handle;
+ }
+
+ /* Make all phys & buf point to the correct address */
+ for (i = 0; i < NUM_VOICE_CAL_BUFFERS; i++) {
+ for (j = 0; j < NUM_VOICE_CAL_TYPES; j++) {
+ common.voice_cal[i].cal_data[j].paddr =
+ (uint32_t)(paddr + offset);
+ common.voice_cal[i].cal_data[j].kvaddr =
+ (uint32_t)((uint8_t *)kvptr + offset);
+ if (j == CVP_CAL)
+ offset += CVP_CAL_SIZE;
+ else
+ offset += CVS_CAL_SIZE;
+
+ pr_debug("%s: kernel addr = 0x%x, phys addr = 0x%x\n",
+ __func__,
+ common.voice_cal[i].cal_data[j].kvaddr,
+ common.voice_cal[i].cal_data[j].paddr);
+ }
+ }
+
+ return;
+
+err_ion_handle:
+ ion_free(common.ion_client, common.ion_handle);
+err_ion_client:
+ ion_client_destroy(common.ion_client);
+err:
+ return;
+}
+
static int __init voice_init(void)
{
int rc = 0, i = 0;
- int len;
memset(&common, 0, sizeof(struct common_data));
- /* Allocate memory for VoIP calibration */
- common.client = msm_ion_client_create(UINT_MAX, "voip_client");
- if (IS_ERR_OR_NULL((void *)common.client)) {
- pr_err("%s: ION create client for Voip failed\n", __func__);
- goto cont;
- }
- common.cvp_cal.handle = ion_alloc(common.client, CVP_CAL_SIZE, SZ_4K,
- ION_HEAP(ION_AUDIO_HEAP_ID));
- if (IS_ERR_OR_NULL((void *) common.cvp_cal.handle)) {
- pr_err("%s: ION memory allocation for CVP failed\n",
- __func__);
- ion_client_destroy(common.client);
- goto cont;
- }
+ /* Allocate shared memory */
+ voice_allocate_shared_memory();
- rc = ion_phys(common.client, common.cvp_cal.handle,
- (ion_phys_addr_t *)&common.cvp_cal.phy, (size_t *)&len);
- if (rc) {
- pr_err("%s: ION Get Physical for cvp failed, rc = %d\n",
- __func__, rc);
- ion_free(common.client, common.cvp_cal.handle);
- ion_client_destroy(common.client);
- goto cont;
- }
-
- common.cvp_cal.buf = ion_map_kernel(common.client,
- common.cvp_cal.handle, 0);
- if (IS_ERR_OR_NULL((void *) common.cvp_cal.buf)) {
- pr_err("%s: ION memory mapping for cvp failed\n", __func__);
- common.cvp_cal.buf = NULL;
- ion_free(common.client, common.cvp_cal.handle);
- ion_client_destroy(common.client);
- goto cont;
- }
- memset((void *)common.cvp_cal.buf, 0, CVP_CAL_SIZE);
-
- common.cvs_cal.handle = ion_alloc(common.client, CVS_CAL_SIZE, SZ_4K,
- ION_HEAP(ION_AUDIO_HEAP_ID));
- if (IS_ERR_OR_NULL((void *) common.cvs_cal.handle)) {
- pr_err("%s: ION memory allocation for CVS failed\n",
- __func__);
- goto cont;
- }
-
- rc = ion_phys(common.client, common.cvs_cal.handle,
- (ion_phys_addr_t *)&common.cvs_cal.phy, (size_t *)&len);
- if (rc) {
- pr_err("%s: ION Get Physical for cvs failed, rc = %d\n",
- __func__, rc);
- ion_free(common.client, common.cvs_cal.handle);
- goto cont;
- }
-
- common.cvs_cal.buf = ion_map_kernel(common.client,
- common.cvs_cal.handle, 0);
- if (IS_ERR_OR_NULL((void *) common.cvs_cal.buf)) {
- pr_err("%s: ION memory mapping for cvs failed\n", __func__);
- common.cvs_cal.buf = NULL;
- ion_free(common.client, common.cvs_cal.handle);
- goto cont;
- }
- memset((void *)common.cvs_cal.buf, 0, CVS_CAL_SIZE);
-cont:
/* set default value */
common.default_mute_val = 0; /* default is un-mute */
common.default_vol_val = 0;
diff --git a/sound/soc/msm/qdsp6/q6voice.h b/sound/soc/msm/qdsp6/q6voice.h
index 468aba8..1cb2878 100644
--- a/sound/soc/msm/qdsp6/q6voice.h
+++ b/sound/soc/msm/qdsp6/q6voice.h
@@ -22,6 +22,20 @@
#define VOC_REC_DOWNLINK 0x01
#define VOC_REC_BOTH 0x02
+/* Needed for VOIP & VOLTE support */
+/* Due to Q6 memory map issue */
+enum {
+ VOIP_CAL,
+ VOLTE_CAL,
+ NUM_VOICE_CAL_BUFFERS
+};
+
+enum {
+ CVP_CAL,
+ CVS_CAL,
+ NUM_VOICE_CAL_TYPES
+};
+
struct voice_header {
uint32_t id;
uint32_t data_len;
@@ -913,9 +927,14 @@
};
struct cal_mem {
- struct ion_handle *handle;
- uint32_t phy;
- void *buf;
+ /* Physical Address */
+ uint32_t paddr;
+ /* Kernel Virtual Address */
+ uint32_t kvaddr;
+};
+
+struct cal_data {
+ struct cal_mem cal_data[NUM_VOICE_CAL_TYPES];
};
#define MAX_VOC_SESSIONS 4
@@ -934,9 +953,9 @@
/* APR to CVP in the Q6 */
void *apr_q6_cvp;
- struct ion_client *client;
- struct cal_mem cvp_cal;
- struct cal_mem cvs_cal;
+ struct ion_client *ion_client;
+ struct ion_handle *ion_handle;
+ struct cal_data voice_cal[NUM_VOICE_CAL_BUFFERS];
struct mutex common_lock;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index be2e0c5..2d2b333 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -700,7 +700,7 @@
if (perf_pmu__config(pmu, &attr, head_config))
return -EINVAL;
- return add_event(list, idx, &attr, (char *) "pmu");
+ return add_event(list, idx, &attr, pmu->name);
}
void parse_events_update_lists(struct list_head *list_event,
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 28e5548..4b3a3c9 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -64,7 +64,7 @@
num_dec [0-9]+
num_hex 0x[a-fA-F0-9]+
num_raw_hex [a-fA-F0-9]+
-name [a-zA-Z_*?][a-zA-Z0-9_*?]*
+name [a-zA-Z_*?][a-zA-Z\-0-9_*?]*
modifier_event [ukhpGH]{1,8}
modifier_bp [rwx]