Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ebc72c4f authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "coresight-etm4x: use trace ids starting 0x1 for ETMs devices"

parents fa1c3c80 e1cbe03f
Loading
Loading
Loading
Loading
+127 −1
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ its hardware characteristcs.
		- "arm,coresight-funnel", "arm,primecell";
		- "arm,coresight-etm3x", "arm,primecell";
		- "qcom,coresight-replicator1x", "arm,primecell";
		- "arm,coresight-stm", "arm,primecell";

	* reg: physical base address and length of the register
	  set(s) of the component.
@@ -35,12 +36,20 @@ its hardware characteristcs.
* Required properties for devices that don't show up on the AMBA bus, such as
  non-configurable replicators:

	* compatible: Currently supported value is (note the absence of the
	* compatible: Currently supported values are (note the absence of the
	  AMBA markee):
		- "arm,coresight-replicator"
		- "qcom,coresight-csr"
		- "arm,coresight-cti"
		- "qcom,coresight-tpda"
		- "qcom,coresight-tpdm"

	* port or ports: same as above.

* Optional properties for all components:
	* coresight-name: unique descriptive name of the component.
	* reg-names: names corresponding to each reg property value.

* Optional properties for ETM/PTMs:

	* arm,cp14: must be present if the system accesses ETM/PTM management
@@ -54,6 +63,35 @@ its hardware characteristcs.
	* arm,buffer-size: size of contiguous buffer space for TMC ETR
	 (embedded trace router)

* Required property for TPDAs:

	* qcom,tpda-atid: must be present. Specifies the ATID for TPDA.

* Optional properties for TPDAs:

	* qcom,bc-elem-size: specifies the BC element size supported by each
	  monitor connected to the aggregator on each port. Should be specified
          in pairs (port, bc element size).

	* qcom,tc-elem-size: specifies the TC element size supported by each
	  monitor connected to the aggregator on each port. Should be specified
	  in pairs (port, tc element size).

	* qcom,dsb-elem-size: specifies the DSB element size supported by each
	  monitor connected to the aggregator on each port. Should be specified
	  in pairs (port, dsb element size).

	* qcom,cmb-elem-size: specifies the CMB element size supported by each
	  monitor connected to the aggregator on each port. Should be specified
	  in pairs (port, cmb element size).

* Optional properties for TPDM:

	* qcom,clk-enable: specifies whether additional clock bit needs to be
	  set for M4M TPDM.

	* qcom,msr-fix-req: boolean, indicating if MSRs need to be programmed
	  after enabling the subunit.

Example:

@@ -170,6 +208,42 @@ Example:
		};
	};

	tpda_mss: tpda@7043000 {
		compatible = "qcom,coresight-tpda";
		reg = <0x7043000 0x1000>;
		reg-names = "tpda-base";

		coresight-name = "coresight-tpda-mss";

		qcom,tpda-atid = <67>;
		qcom,dsb-elem-size = <0 32>;
		qcom,cmb-elem-size = <0 32>;

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";

		ports {
			#address-cells = <1>;
			#size-cells = <0>;
			port@0 {
				reg = <0>;
				tpda_mss_out_funnel_in1: endpoint {
					remote-endpoint =
						<&funnel_in1_in_tpda_mss>;
				};
			};
			port@1 {
				reg = <0>;
				tpda_mss_in_tpdm_mss: endpoint {
					slave-mode;
					remote-endpoint =
						<&tpdm_mss_out_tpda_mss>;
				};
			};
		};
	};

3. Sources
	ptm@2201c000 {
		compatible = "arm,coresight-etm3x", "arm,primecell";
@@ -198,3 +272,55 @@ Example:
			};
		};
	};

	stm: stm@6002000 {
		compatible = "arm,coresight-stm", "arm,primecell";
		arm,primecell-periphid = <0x0003b962>;

		reg = <0x6002000 0x1000>,
		      <0x16280000 0x180000>;
		reg-names = "stm-base", "stm-data-base";

		coresight-name = "coresight-stm";

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "apb_pclk", "core_a_clk";

		port{
			stm_out_funnel_in0: endpoint {
				remote-endpoint = <&funnel_in0_in_stm>;
			};
		};
	};

	tpdm_mss: tpdm@7042000 {
		compatible = "qcom,coresight-tpdm";
		reg = <0x7042000 0x1000>;
		reg-names = "tpdm-base";

		coresight-name = "coresight-tpdm-mss";

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";

		port{
			tpdm_mss_out_tpda_mss: endpoint {
				remote-endpoint = <&tpda_mss_in_tpdm_mss>;
			};
		};
	};

4. CTIs
	cti0: cti@6010000 {
		compatible = "arm,coresight-cti";
		reg = <0x6010000 0x1000>;
		reg-names = "cti-base";

		coresight-name = "coresight-cti0";

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";
	};
+553 −0
Original line number Diff line number Diff line
@@ -165,6 +165,22 @@
				};
			};
			port@1 {
				reg = <3>;
				funnel_in0_in_funnel_spss: endpoint {
					slave-mode;
					remote-endpoint =
						<&funnel_spss_out_funnel_in0>;
				};
			};
			port@2 {
				reg = <6>;
				funnel_in0_in_funnel_qatb: endpoint {
					slave-mode;
					remote-endpoint =
						<&funnel_qatb_out_funnel_in0>;
				};
			};
			port@3 {
				reg = <7>;
				funnel_in0_in_stm: endpoint {
					slave-mode;
@@ -199,6 +215,22 @@
				};
			};
			port@1 {
				reg = <2>;
				funnel_in1_in_tpda_nav: endpoint {
					slave-mode;
					remote-endpoint =
					    <&tpda_nav_out_funnel_in1>;
				};
			};
			port@2 {
				reg = <3>;
				funnel_in1_in_tpda_mss: endpoint {
					slave-mode;
					remote-endpoint =
					    <&tpda_mss_out_funnel_in1>;
				};
			};
			port@3 {
				reg = <6>;
				funnel_in1_in_funnel_apss_merg: endpoint {
					slave-mode;
@@ -241,6 +273,22 @@
					    <&funnel_apss_out_funnel_apss_merg>;
				};
			};
			port@2 {
				reg = <1>;
				funnel_apss_merg_in_tpda_olc: endpoint {
					slave-mode;
					remote-endpoint =
					    <&tpda_olc_out_funnel_apss_merg>;
				};
			};
			port@3 {
				reg = <3>;
				funnel_apss_merg_in_tpda_apss: endpoint {
					slave-mode;
					remote-endpoint =
					    <&tpda_apss_out_funnel_apss_merg>;
				};
			};
		};
	};

@@ -811,4 +859,509 @@
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";
	};

	funnel_qatb: funnel@6005000 {
		compatible = "arm,primecell";
		arm,primecell-periphid = <0x0003b908>;

		reg = <0x6005000 0x1000>;
		reg-names = "funnel-base";

		coresight-name = "coresight-funnel-qatb";

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "apb_pclk", "core_a_clk";

		ports {
			#address-cells = <1>;
			#size-cells = <0>;

			port@0 {
				reg = <0>;
				funnel_qatb_out_funnel_in0: endpoint {
					remote-endpoint =
					    <&funnel_in0_in_funnel_qatb>;
				};
			};
			port@1 {
				reg = <0>;
				funnel_qatb_in_tpda: endpoint {
					slave-mode;
					remote-endpoint =
						<&tpda_out_funnel_qatb>;
				};
			};
		};
	};

	tpda: tpda@6004000 {
		compatible = "qcom,coresight-tpda";
		reg = <0x6004000 0x1000>;
		reg-names = "tpda-base";

		coresight-name = "coresight-tpda";

		qcom,tpda-atid = <65>;
		qcom,bc-elem-size = <7 32>,
				    <9 32>;
		qcom,tc-elem-size = <3 32>,
				    <6 32>,
				    <9 32>;
		qcom,dsb-elem-size = <7 32>,
				     <9 32>;
		qcom,cmb-elem-size = <3 32>,
				     <4 32>,
				     <5 32>,
				     <9 64>;

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";

		ports {
			#address-cells = <1>;
			#size-cells = <0>;
			port@0 {
				reg = <0>;
				tpda_out_funnel_qatb: endpoint {
					remote-endpoint =
						<&funnel_qatb_in_tpda>;
				};
			};
			port@1 {
				reg = <3>;
				tpda_in_tpdm_vsense: endpoint {
					slave-mode;
					remote-endpoint =
						<&tpdm_vsense_out_tpda>;
				};
			};
			port@2 {
				reg = <4>;
				tpda_in_tpdm_dcc: endpoint {
					slave-mode;
					remote-endpoint =
						<&tpdm_dcc_out_tpda>;
				};
			};
			port@3 {
				reg = <5>;
				tpda_in_tpdm_prng: endpoint {
					slave-mode;
					remote-endpoint =
						<&tpdm_prng_out_tpda>;
				};
			};
			port@4 {
				reg = <7>;
				tpda_in_tpdm_qm: endpoint {
					slave-mode;
					remote-endpoint =
						<&tpdm_qm_out_tpda>;
				};
			};
			port@5 {
				reg = <9>;
				tpda_in_tpdm_pimem: endpoint {
					slave-mode;
					remote-endpoint =
						<&tpdm_pimem_out_tpda>;
				};
			};
		};
	};

	tpdm_vsense: tpdm@7038000 {
		compatible = "qcom,coresight-tpdm";
		reg = <0x7038000 0x1000>;
		reg-names = "tpdm-base";

		coresight-name = "coresight-tpdm-vsense";

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";

		port{
			tpdm_vsense_out_tpda: endpoint {
				remote-endpoint = <&tpda_in_tpdm_vsense>;
			};
		};
	};

	tpdm_dcc: tpdm@7054000 {
		compatible = "qcom,coresight-tpdm";
		reg = <0x7054000 0x1000>;
		reg-names = "tpdm-base";

		coresight-name = "coresight-tpdm-dcc";

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";

		port{
			tpdm_dcc_out_tpda: endpoint {
				remote-endpoint = <&tpda_in_tpdm_dcc>;
			};
		};
	};

	tpdm_prng: tpdm@704c000 {
		compatible = "qcom,coresight-tpdm";
		reg = <0x704c000 0x1000>;
		reg-names = "tpdm-base";

		coresight-name = "coresight-tpdm-prng";

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";

		port{
			tpdm_prng_out_tpda: endpoint {
				remote-endpoint = <&tpda_in_tpdm_prng>;
			};
		};
	};

	tpdm_qm: tpdm@71d0000 {
		compatible = "qcom,coresight-tpdm";
		reg = <0x71d0000 0x1000>;
		reg-names = "tpdm-base";

		coresight-name = "coresight-tpdm-qm";

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";

		port{
			tpdm_qm_out_tpda: endpoint {
				remote-endpoint = <&tpda_in_tpdm_qm>;
			};
		};

	};

	tpdm_pimem: tpdm@7050000 {
		compatible = "qcom,coresight-tpdm";
		reg = <0x7050000 0x1000>;
		reg-names = "tpdm-base";

		coresight-name = "coresight-tpdm-pimem";

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";

		port{
			tpdm_pimem_out_tpda: endpoint {
				remote-endpoint = <&tpda_in_tpdm_pimem>;
			};
		};

	};

	tpda_apss: tpda@7bc2000 {
		compatible = "qcom,coresight-tpda";
		reg = <0x7bc2000 0x1000>;
		reg-names = "tpda-base";

		coresight-name = "coresight-tpda-apss";

		qcom,tpda-atid = <66>;
		qcom,dsb-elem-size = <0 32>;

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";

		ports {
			#address-cells = <1>;
			#size-cells = <0>;
			port@0 {
				reg = <0>;
				tpda_apss_out_funnel_apss_merg: endpoint {
					remote-endpoint =
					       <&funnel_apss_merg_in_tpda_apss>;
				};
			};
			port@1 {
				reg = <0>;
				tpda_apss_in_tpdm_apss: endpoint {
					slave-mode;
					remote-endpoint =
						<&tpdm_apss_out_tpda_apss>;
				};
			};
		};
	};

	tpdm_apss: tpdm@7bc0000 {
		compatible = "qcom,coresight-tpdm";
		reg = <0x7bc0000 0x1000>;
		reg-names = "tpdm-base";

		coresight-name = "coresight-tpdm-apss";

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";

		port{
			tpdm_apss_out_tpda_apss: endpoint {
				remote-endpoint = <&tpda_apss_in_tpdm_apss>;
			};
		};
	};

	tpda_mss: tpda@7043000 {
		compatible = "qcom,coresight-tpda";
		reg = <0x7043000 0x1000>;
		reg-names = "tpda-base";

		coresight-name = "coresight-tpda-mss";

		qcom,tpda-atid = <67>;
		qcom,dsb-elem-size = <0 32>;
		qcom,cmb-elem-size = <0 32>;

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";

		ports {
			#address-cells = <1>;
			#size-cells = <0>;
			port@0 {
				reg = <0>;
				tpda_mss_out_funnel_in1: endpoint {
					remote-endpoint =
						<&funnel_in1_in_tpda_mss>;
				};
			};
			port@1 {
				reg = <0>;
				tpda_mss_in_tpdm_mss: endpoint {
					slave-mode;
					remote-endpoint =
						<&tpdm_mss_out_tpda_mss>;
				};
			};
		};
	};

	tpdm_mss: tpdm@7042000 {
		compatible = "qcom,coresight-tpdm";
		reg = <0x7042000 0x1000>;
		reg-names = "tpdm-base";

		coresight-name = "coresight-tpdm-mss";

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";

		port{
			tpdm_mss_out_tpda_mss: endpoint {
				remote-endpoint = <&tpda_mss_in_tpdm_mss>;
			};
		};
	};

	tpda_nav: tpda@7191000 {
		compatible = "qcom,coresight-tpda";
		reg = <0x7191000 0x1000>;
		reg-names = "tpda-base";

		coresight-name = "coresight-tpda-nav";

		qcom,tpda-atid = <68>;
		qcom,cmb-elem-size = <0 32>;

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";

		ports {
			#address-cells = <1>;
			#size-cells = <0>;
			port@0 {
				reg = <0>;
				tpda_nav_out_funnel_in1: endpoint {
					remote-endpoint =
						<&funnel_in1_in_tpda_nav>;
				};
			};
			port@1 {
				reg = <0>;
				tpda_nav_in_tpdm_nav: endpoint {
					slave-mode;
					remote-endpoint =
						<&tpdm_nav_out_tpda_nav>;
				};
			};
		};
	};

	tpdm_nav: tpdm@7190000 {
		compatible = "qcom,coresight-tpdm";
		reg = <0x7190000 0x1000>;
		reg-names = "tpdm-base";

		coresight-name = "coresight-tpdm-nav";

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";

		port{
			tpdm_nav_out_tpda_nav: endpoint {
				remote-endpoint = <&tpda_nav_in_tpdm_nav>;
			};
		};
	};

	tpda_olc: tpda@7b92000 {
		compatible = "qcom,coresight-tpda";
		reg = <0x7b92000 0x1000>;
		reg-names = "tpda-base";

		coresight-name = "coresight-tpda-olc";

		qcom,tpda-atid = <69>;
		qcom,cmb-elem-size = <0 64>;

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";

		ports {
			#address-cells = <1>;
			#size-cells = <0>;
			port@0 {
				reg = <0>;
				tpda_olc_out_funnel_apss_merg: endpoint {
					remote-endpoint =
						<&funnel_apss_merg_in_tpda_olc>;
				};
			};
			port@1 {
				reg = <0>;
				tpda_olc_in_tpdm_olc: endpoint {
					slave-mode;
					remote-endpoint =
						<&tpdm_olc_out_tpda_olc>;
				};
			};
		};
	};

	tpdm_olc: tpdm@7b90000 {
		compatible = "qcom,coresight-tpdm";
		reg = <0x7b90000 0x1000>;
		reg-names = "tpdm-base";

		coresight-name = "coresight-tpdm-olc";

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";

		port{
			tpdm_olc_out_tpda_olc: endpoint {
				remote-endpoint = <&tpda_olc_in_tpdm_olc>;
			};
		};
	};

	funnel_spss: funnel@7083000 {
		compatible = "arm,primecell";
		arm,primecell-periphid = <0x0003b908>;

		reg = <0x7083000 0x1000>;
		reg-names = "funnel-base";

		coresight-name = "coresight-funnel-spss";

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "apb_pclk", "core_a_clk";

		ports {
			#address-cells = <1>;
			#size-cells = <0>;

			port@0 {
				reg = <0>;
				funnel_spss_out_funnel_in0: endpoint {
					remote-endpoint =
					    <&funnel_in0_in_funnel_spss>;
				};
			};
			port@1 {
				reg = <0>;
				funnel_spss_in_tpda_spss: endpoint {
					slave-mode;
					remote-endpoint =
						<&tpda_spss_out_funnel_spss>;
				};
			};
		};
	};

	tpda_spss: tpda@7082000 {
		compatible = "qcom,coresight-tpda";
		reg = <0x7082000 0x1000>;
		reg-names = "tpda-base";

		coresight-name = "coresight-tpda-spss";

		qcom,tpda-atid = <70>;
		qcom,dsb-elem-size = <0 32>;

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";

		ports {
			#address-cells = <1>;
			#size-cells = <0>;
			port@0 {
				reg = <0>;
				tpda_spss_out_funnel_spss: endpoint {
					remote-endpoint =
						<&funnel_spss_in_tpda_spss>;
				};
			};
			port@1 {
				reg = <0>;
				tpda_spss_in_tpdm_spss: endpoint {
					slave-mode;
					remote-endpoint =
						<&tpdm_spss_out_tpda_spss>;
				};
			};
		};
	};

	tpdm_spss: tpdm@7080000 {
		compatible = "qcom,coresight-tpdm";
		reg = <0x7080000 0x1000>;
		reg-names = "tpdm-base";

		coresight-name = "coresight-tpdm-spss";

		clocks = <&clock_gcc clk_qdss_clk>,
			 <&clock_gcc clk_qdss_a_clk>;
		clock-names = "core_clk", "core_a_clk";

		port{
			tpdm_spss_out_tpda_spss: endpoint {
				remote-endpoint = <&tpda_spss_in_tpdm_spss>;
			};
		};
	};
};
+27 −0
Original line number Diff line number Diff line
@@ -103,4 +103,31 @@ config CORESIGHT_CTI
	  hardware component to another. It can also be used to pass
	  software generated events.

config CORESIGHT_TPDA
	bool "CoreSight Trace, Profiling & Diagnostics Aggregator driver"
	help
	  This driver provides support for configuring aggregator. This is
	  primarily useful for pulling the data sets from one or more
	  attached monitors and pushing the resultant data out. Multiple
	  monitors are connected on different input ports of TPDA.

config CORESIGHT_TPDM
	bool "CoreSight Trace, Profiling & Diagnostics Monitor driver"
	help
	  This driver provides support for configuring monitor. Monitors are
	  primarily responsible for data set collection and support the
	  ability to collect any permutation of data set types. Monitors are
	  also responsible for interaction with system cross triggering.

config CORESIGHT_TPDM_DEFAULT_ENABLE
	bool "Turn on TPDM tracing by default"
	depends on CORESIGHT_TPDM
	help
	  Turns on CoreSight TPDM tracing for different data set types by
	  default. Otherwise, tracing is disabled by default but can be
	  enabled via sysfs.

	  If unsure, say 'N' here to avoid potential power and performance
	  penalty.

endif
+2 −0
Original line number Diff line number Diff line
@@ -14,3 +14,5 @@ obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o
obj-$(CONFIG_CORESIGHT_QCOM_REPLICATOR) += coresight-replicator-qcom.o
obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o
obj-$(CONFIG_CORESIGHT_CTI) += coresight-cti.o
obj-$(CONFIG_CORESIGHT_TPDA) += coresight-tpda.o
obj-$(CONFIG_CORESIGHT_TPDM) += coresight-tpdm.o
+130 −44
Original line number Diff line number Diff line
/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014, 2016 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -24,7 +24,6 @@
#include <linux/smp.h>
#include <linux/sysfs.h>
#include <linux/stat.h>
#include <linux/clk.h>
#include <linux/cpu.h>
#include <linux/coresight.h>
#include <linux/pm_wakeup.h>
@@ -42,14 +41,17 @@ module_param_named(boot_enable, boot_enable, int, S_IRUGO);
/* The number of ETMv4 currently registered */
static int etm4_count;
static struct etmv4_drvdata *etmdrvdata[NR_CPUS];
static struct notifier_block etm4_cpu_notifier;

static void etm4_os_unlock(void *info)
{
	struct etmv4_drvdata *drvdata = (struct etmv4_drvdata *)info;

	CS_UNLOCK(drvdata->base);
	/* Writing any value to ETMOSLAR unlocks the trace registers */
	writel_relaxed(0x0, drvdata->base + TRCOSLAR);
	isb();
	CS_LOCK(drvdata->base);
}

static bool etm4_arch_supported(u8 arch)
@@ -93,8 +95,6 @@ static void etm4_enable_hw(void *info)

	CS_UNLOCK(drvdata->base);

	etm4_os_unlock(drvdata);

	/* Disable the trace unit before programming trace registers */
	writel_relaxed(0, drvdata->base + TRCPRGCTLR);

@@ -2543,27 +2543,84 @@ static void etm4_init_default_data(struct etmv4_drvdata *drvdata)
	drvdata->vmid_mask1 = 0x0;

	/*
	 * A trace ID value of 0 is invalid, so let's start at some
	 * random value that fits in 7 bits.  ETMv3.x has 0x10 so let's
	 * start at 0x20.
	 * Start trace id from 0x1.
	 */
	drvdata->trcid = 0x20 + drvdata->cpu;
	drvdata->trcid = 0x1 + drvdata->cpu;
}

static int etm4_late_init(struct etmv4_drvdata *drvdata)
{
	int ret;
	struct coresight_desc *desc;
	struct device *dev = drvdata->dev;

	if (etm4_arch_supported(drvdata->arch) == false)
		return -EINVAL;

	etm4_init_default_data(drvdata);

	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_PROC;
	desc->ops = &etm4_cs_ops;
	desc->pdata = dev->platform_data;
	desc->dev = dev;
	desc->groups = coresight_etmv4_groups;
	drvdata->csdev = coresight_register(desc);
	if (IS_ERR(drvdata->csdev)) {
		ret = PTR_ERR(drvdata->csdev);
		goto err_coresight_register;
	}

	dev_info(dev, "ETM 4.0 initialized\n");

	if (boot_enable) {
		coresight_enable(drvdata->csdev);
		drvdata->boot_enable = true;
	}

	drvdata->init = true;

	return 0;

err_coresight_register:
	devm_kfree(dev, desc);
	return ret;
}

static int etm4_cpu_callback(struct notifier_block *nfb, unsigned long action,
			    void *hcpu)
{
	unsigned int cpu = (unsigned long)hcpu;
	static bool clk_disable[NR_CPUS];
	int ret;

	if (!etmdrvdata[cpu])
		goto out;

	switch (action & (~CPU_TASKS_FROZEN)) {
	case CPU_UP_PREPARE:
		if (!etmdrvdata[cpu]->os_unlock) {
			ret = pm_runtime_get_sync(etmdrvdata[cpu]->dev);
			if (ret) {
				dev_err(etmdrvdata[cpu]->dev,
					"ETM clk enable during hotplug failed for cpu: %d, ret: %d\n",
					cpu, ret);
				goto err_clk_init;
			}
			clk_disable[cpu] = true;
		}
		break;

	case CPU_STARTING:
		spin_lock(&etmdrvdata[cpu]->spinlock);
		if (!etmdrvdata[cpu]->os_unlock) {
			etm4_os_unlock(etmdrvdata[cpu]);
			etmdrvdata[cpu]->os_unlock = true;
			etm4_init_arch_data(etmdrvdata[cpu]);
		}

		if (etmdrvdata[cpu]->enable)
@@ -2572,11 +2629,36 @@ static int etm4_cpu_callback(struct notifier_block *nfb, unsigned long action,
		break;

	case CPU_ONLINE:
		mutex_lock(&etmdrvdata[cpu]->mutex);
		if (!etmdrvdata[cpu]->init) {
			ret = etm4_late_init(etmdrvdata[cpu]);
			if (ret) {
				dev_err(etmdrvdata[cpu]->dev,
					"ETM init failed. Cpu: %d, ret: %d\n",
					cpu, ret);
				mutex_unlock(&etmdrvdata[cpu]->mutex);
				goto err_init;
			}
		}
		mutex_unlock(&etmdrvdata[cpu]->mutex);

		if (clk_disable[cpu]) {
			pm_runtime_put(etmdrvdata[cpu]->dev);
			clk_disable[cpu] = false;
		}

		if (etmdrvdata[cpu]->boot_enable &&
			!etmdrvdata[cpu]->sticky_enable)
			coresight_enable(etmdrvdata[cpu]->csdev);
		break;

	case CPU_UP_CANCELED:
		if (clk_disable[cpu]) {
			pm_runtime_put(etmdrvdata[cpu]->dev);
			clk_disable[cpu] = false;
		}
		break;

	case CPU_DYING:
		spin_lock(&etmdrvdata[cpu]->spinlock);
		if (etmdrvdata[cpu]->enable)
@@ -2586,6 +2668,23 @@ static int etm4_cpu_callback(struct notifier_block *nfb, unsigned long action,
	}
out:
	return NOTIFY_OK;

err_init:
	if (--etm4_count == 0)
		unregister_hotcpu_notifier(&etm4_cpu_notifier);

	if (clk_disable[cpu]) {
		pm_runtime_put(etmdrvdata[cpu]->dev);
		clk_disable[cpu] = false;
	}

	devm_iounmap(etmdrvdata[cpu]->dev, etmdrvdata[cpu]->base);
	dev_set_drvdata(etmdrvdata[cpu]->dev, NULL);
	devm_kfree(etmdrvdata[cpu]->dev, etmdrvdata[cpu]);
	etmdrvdata[cpu] = NULL;

err_clk_init:
	return notifier_from_errno(ret);
}

static struct notifier_block etm4_cpu_notifier = {
@@ -2600,13 +2699,8 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
	struct coresight_platform_data *pdata = NULL;
	struct etmv4_drvdata *drvdata;
	struct resource *res = &adev->res;
	struct coresight_desc *desc;
	struct device_node *np = adev->dev.of_node;

	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
	if (!desc)
		return -ENOMEM;

	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
	if (!drvdata)
		return -ENOMEM;
@@ -2629,56 +2723,48 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
	drvdata->base = base;

	spin_lock_init(&drvdata->spinlock);
	mutex_init(&drvdata->mutex);

	drvdata->cpu = pdata ? pdata->cpu : 0;

	get_online_cpus();
	etmdrvdata[drvdata->cpu] = drvdata;

	if (!smp_call_function_single(drvdata->cpu, etm4_os_unlock, drvdata, 1))
	if (!smp_call_function_single(drvdata->cpu, etm4_os_unlock,
				      drvdata, 1)) {
		drvdata->os_unlock = true;

	if (smp_call_function_single(drvdata->cpu,
				etm4_init_arch_data,  drvdata, 1))
		ret = smp_call_function_single(drvdata->cpu,
					       etm4_init_arch_data, drvdata, 1);
		if (ret) {
			dev_err(dev, "ETM arch init failed\n");
			put_online_cpus();
			pm_runtime_put(&adev->dev);
			return ret;
		}
	}

	etmdrvdata[drvdata->cpu] = drvdata;

	if (!etm4_count++)
		register_hotcpu_notifier(&etm4_cpu_notifier);

	put_online_cpus();

	if (etm4_arch_supported(drvdata->arch) == false) {
		ret = -EINVAL;
		goto err_arch_supported;
	}
	etm4_init_default_data(drvdata);

	pm_runtime_put(&adev->dev);

	desc->type = CORESIGHT_DEV_TYPE_SOURCE;
	desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
	desc->ops = &etm4_cs_ops;
	desc->pdata = pdata;
	desc->dev = dev;
	desc->groups = coresight_etmv4_groups;
	drvdata->csdev = coresight_register(desc);
	if (IS_ERR(drvdata->csdev)) {
		ret = PTR_ERR(drvdata->csdev);
		goto err_coresight_register;
	mutex_lock(&drvdata->mutex);
	if (drvdata->os_unlock && !drvdata->init) {
		ret = etm4_late_init(drvdata);
		if (ret) {
			mutex_unlock(&drvdata->mutex);
			goto err_late_init;
		}

	dev_info(dev, "%s initialized\n", (char *)id->data);

	if (boot_enable) {
		coresight_enable(drvdata->csdev);
		drvdata->boot_enable = true;
	}
	mutex_unlock(&drvdata->mutex);

	return 0;

err_arch_supported:
	pm_runtime_put(&adev->dev);
err_coresight_register:
err_late_init:
	if (--etm4_count == 0)
		unregister_hotcpu_notifier(&etm4_cpu_notifier);
	return ret;
Loading