提交 6ae840e7 编写于 作者: L Linus Torvalds

Merge tag 'char-misc-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc

Pull char/misc driver updates from Greg KH:
 "Here's the big char/misc driver update for 3.19-rc1

  Lots of little things all over the place in different drivers, and a
  new subsystem, "coresight" has been added.  Full details are in the
  shortlog"

* tag 'char-misc-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (73 commits)
  parport: parport_pc, do not remove parent devices early
  spmi: Remove shutdown/suspend/resume kernel-doc
  carma-fpga-program: drop videobuf dependency
  carma-fpga: drop videobuf dependency
  carma-fpga-program.c: fix compile errors
  i8k: Fix temperature bug handling in i8k_get_temp()
  cxl: Name interrupts in /proc/interrupt
  CXL: Return error to PSL if IRQ demultiplexing fails & print clearer warning
  coresight-replicator: remove .owner field for driver
  coresight: fixed comments in coresight.h
  coresight: fix typo in comment in coresight-priv.h
  coresight: bindings for coresight drivers
  coresight: Adding ABI documentation
  w1: support auto-load of w1_bq27000 module.
  w1: avoid potential u16 overflow
  cn: verify msg->len before making callback
  mei: export fw status registers through sysfs
  mei: read and print all six FW status registers
  mei: txe: add cherrytrail device id
  mei: kill cached host and me csr values
  ...
What: /sys/bus/coresight/devices/<memory_map>.etb/enable_sink
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Add/remove a sink from a trace path. There can be multiple
source for a single sink.
ex: echo 1 > /sys/bus/coresight/devices/20010000.etb/enable_sink
What: /sys/bus/coresight/devices/<memory_map>.etb/status
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (R) List various control and status registers. The specific
layout and content is driver specific.
What: /sys/bus/coresight/devices/<memory_map>.etb/trigger_cntr
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Disables write access to the Trace RAM by stopping the
formatter after a defined number of words have been stored
following the trigger event. The number of 32-bit words written
into the Trace RAM following the trigger event is equal to the
value stored in this register+1 (from ARM ETB-TRM).
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/enable_source
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Enable/disable tracing on this specific trace entiry.
Enabling a source implies the source has been configured
properly and a sink has been identidifed for it. The path
of coresight components linking the source to the sink is
configured and managed automatically by the coresight framework.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/status
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (R) List various control and status registers. The specific
layout and content is driver specific.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/addr_idx
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: Select which address comparator or pair (of comparators) to
work with.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/addr_acctype
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Used in conjunction with @addr_idx. Specifies
characteristics about the address comparator being configure,
for example the access type, the kind of instruction to trace,
processor contect ID to trigger on, etc. Individual fields in
the access type register may vary on the version of the trace
entity.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/addr_range
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Used in conjunction with @addr_idx. Specifies the range of
addresses to trigger on. Inclusion or exclusion is specificed
in the corresponding access type register.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/addr_single
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Used in conjunction with @addr_idx. Specifies the single
address to trigger on, highly influenced by the configuration
options of the corresponding access type register.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/addr_start
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Used in conjunction with @addr_idx. Specifies the single
address to start tracing on, highly influenced by the
configuration options of the corresponding access type register.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/addr_stop
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Used in conjunction with @addr_idx. Specifies the single
address to stop tracing on, highly influenced by the
configuration options of the corresponding access type register.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/cntr_idx
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Specifies the counter to work on.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/cntr_event
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Used in conjunction with cntr_idx, give access to the
counter event register.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/cntr_val
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Used in conjunction with cntr_idx, give access to the
counter value register.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/cntr_rld_val
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Used in conjunction with cntr_idx, give access to the
counter reload value register.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/cntr_rld_event
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Used in conjunction with cntr_idx, give access to the
counter reload event register.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/ctxid_idx
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Specifies the index of the context ID register to be
selected.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/ctxid_mask
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Mask to apply to all the context ID comparator.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/ctxid_val
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Used with the ctxid_idx, specify with context ID to trigger
on.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/enable_event
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Defines which event triggers a trace.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/etmsr
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Gives access to the ETM status register, which holds
programming information and status on certains events.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/fifofull_level
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Number of byte left in the fifo before considering it full.
Depending on the tracer's version, can also hold threshold for
data suppression.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/mode
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Interface with the driver's 'mode' field, controlling
various aspect of the trace entity such as time stamping,
context ID size and cycle accurate tracing. Driver specific
and bound to change depending on the driver.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/nr_addr_cmp
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (R) Provides the number of address comparators pairs accessible
on a trace unit, as specified by bit 3:0 of register ETMCCR.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/nr_cntr
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (R) Provides the number of counters accessible on a trace unit,
as specified by bit 15:13 of register ETMCCR.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/nr_ctxid_cmp
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (R) Provides the number of context ID comparator available on a
trace unit, as specified by bit 25:24 of register ETMCCR.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/reset
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (W) Cancels all configuration on a trace unit and set it back
to its boot configuration.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/seq_12_event
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Defines the event that causes the sequencer to transition
from state 1 to state 2.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/seq_13_event
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Defines the event that causes the sequencer to transition
from state 1 to state 3.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/seq_21_event
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Defines the event that causes the sequencer to transition
from state 2 to state 1.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/seq_23_event
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Defines the event that causes the sequencer to transition
from state 2 to state 3.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/seq_31_event
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Defines the event that causes the sequencer to transition
from state 3 to state 1.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/seq_32_event
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Defines the event that causes the sequencer to transition
from state 3 to state 2.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/curr_seq_state
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (R) Holds the current state of the sequencer.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/sync_freq
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Holds the trace synchronization frequency value - must be
programmed with the various implementation behavior in mind.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/timestamp_event
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Defines an event that requests the insertion of a timestamp
into the trace stream.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/traceid
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Holds the trace ID that will appear in the trace stream
coming from this trace entity.
What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/trigger_event
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Define the event that controls the trigger.
What: /sys/bus/coresight/devices/<memory_map>.funnel/funnel_ctrl
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Enables the slave ports and defines the hold time of the
slave ports.
What: /sys/bus/coresight/devices/<memory_map>.funnel/priority
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Defines input port priority order.
What: /sys/bus/coresight/devices/<memory_map>.tmc/trigger_cntr
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Disables write access to the Trace RAM by stopping the
formatter after a defined number of words have been stored
following the trigger event. Additional interface for this
driver are expected to be added as it matures.
......@@ -540,7 +540,7 @@ appears in sysfs.
</para></listitem>
<listitem><para>
<varname>unsigned long size</varname>: Fill in the size of the
<varname>resource_size_t size</varname>: Fill in the size of the
memory block that <varname>addr</varname> points to. If <varname>size</varname>
is zero, the mapping is considered unused. Note that you
<emphasis>must</emphasis> initialize <varname>size</varname> with zero for
......
* CoreSight Components:
CoreSight components are compliant with the ARM CoreSight architecture
specification and can be connected in various topologies to suit 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 for all components *except* non-configurable replicators:
* compatible: These have to be supplemented with "arm,primecell" as
drivers are using the AMBA bus interface. Possible values include:
- "arm,coresight-etb10", "arm,primecell";
- "arm,coresight-tpiu", "arm,primecell";
- "arm,coresight-tmc", "arm,primecell";
- "arm,coresight-funnel", "arm,primecell";
- "arm,coresight-etm3x", "arm,primecell";
* reg: physical base address and length of the register
set(s) of the component.
* clocks: the clock associated to this component.
* clock-names: the name of the clock as referenced by the code.
Since we are using the AMBA framework, the name should be
"apb_pclk".
* port or ports: The representation of the component's port
layout using the generic DT graph presentation found in
"bindings/graph.txt".
* 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
AMBA markee):
- "arm,coresight-replicator"
* id: a unique number that will identify this replicator.
* port or ports: same as above.
* Optional properties for ETM/PTMs:
* arm,cp14: must be present if the system accesses ETM/PTM management
registers via co-processor 14.
* cpu: the cpu phandle this ETM/PTM is affined to. When omitted the
source is considered to belong to CPU0.
* Optional property for TMC:
* arm,buffer-size: size of contiguous buffer space for TMC ETR
(embedded trace router)
Example:
1. Sinks
etb@20010000 {
compatible = "arm,coresight-etb10", "arm,primecell";
reg = <0 0x20010000 0 0x1000>;
coresight-default-sink;
clocks = <&oscclk6a>;
clock-names = "apb_pclk";
port {
etb_in_port: endpoint@0 {
slave-mode;
remote-endpoint = <&replicator_out_port0>;
};
};
};
tpiu@20030000 {
compatible = "arm,coresight-tpiu", "arm,primecell";
reg = <0 0x20030000 0 0x1000>;
clocks = <&oscclk6a>;
clock-names = "apb_pclk";
port {
tpiu_in_port: endpoint@0 {
slave-mode;
remote-endpoint = <&replicator_out_port1>;
};
};
};
2. Links
replicator {
/* non-configurable replicators don't show up on the
* AMBA bus. As such no need to add "arm,primecell".
*/
compatible = "arm,coresight-replicator";
/* this will show up in debugfs as "0.replicator" */
id = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
/* replicator output ports */
port@0 {
reg = <0>;
replicator_out_port0: endpoint {
remote-endpoint = <&etb_in_port>;
};
};
port@1 {
reg = <1>;
replicator_out_port1: endpoint {
remote-endpoint = <&tpiu_in_port>;
};
};
/* replicator input port */
port@2 {
reg = <0>;
replicator_in_port0: endpoint {
slave-mode;
remote-endpoint = <&funnel_out_port0>;
};
};
};
};
funnel@20040000 {
compatible = "arm,coresight-funnel", "arm,primecell";
reg = <0 0x20040000 0 0x1000>;
clocks = <&oscclk6a>;
clock-names = "apb_pclk";
ports {
#address-cells = <1>;
#size-cells = <0>;
/* funnel output port */
port@0 {
reg = <0>;
funnel_out_port0: endpoint {
remote-endpoint =
<&replicator_in_port0>;
};
};
/* funnel input ports */
port@1 {
reg = <0>;
funnel_in_port0: endpoint {
slave-mode;
remote-endpoint = <&ptm0_out_port>;
};
};
port@2 {
reg = <1>;
funnel_in_port1: endpoint {
slave-mode;
remote-endpoint = <&ptm1_out_port>;
};
};
port@3 {
reg = <2>;
funnel_in_port2: endpoint {
slave-mode;
remote-endpoint = <&etm0_out_port>;
};
};
};
};
3. Sources
ptm@2201c000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0x2201c000 0 0x1000>;
cpu = <&cpu0>;
clocks = <&oscclk6a>;
clock-names = "apb_pclk";
port {
ptm0_out_port: endpoint {
remote-endpoint = <&funnel_in_port0>;
};
};
};
ptm@2201d000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0x2201d000 0 0x1000>;
cpu = <&cpu1>;
clocks = <&oscclk6a>;
clock-names = "apb_pclk";
port {
ptm1_out_port: endpoint {
remote-endpoint = <&funnel_in_port1>;
};
};
};
Coresight - HW Assisted Tracing on ARM
======================================
Author: Mathieu Poirier <mathieu.poirier@linaro.org>
Date: September 11th, 2014
Introduction
------------
Coresight is an umbrella of technologies allowing for the debugging of ARM
based SoC. It includes solutions for JTAG and HW assisted tracing. This
document is concerned with the latter.
HW assisted tracing is becoming increasingly useful when dealing with systems
that have many SoCs and other components like GPU and DMA engines. ARM has
developed a HW assisted tracing solution by means of different components, each
being added to a design at systhesis time to cater to specific tracing needs.
Compoments are generally categorised as source, link and sinks and are
(usually) discovered using the AMBA bus.
"Sources" generate a compressed stream representing the processor instruction
path based on tracing scenarios as configured by users. From there the stream
flows through the coresight system (via ATB bus) using links that are connecting
the emanating source to a sink(s). Sinks serve as endpoints to the coresight
implementation, either storing the compressed stream in a memory buffer or
creating an interface to the outside world where data can be transferred to a
host without fear of filling up the onboard coresight memory buffer.
At typical coresight system would look like this:
*****************************************************************
**************************** AMBA AXI ****************************===||
***************************************************************** ||
^ ^ | ||
| | * **
0000000 ::::: 0000000 ::::: ::::: @@@@@@@ ||||||||||||
0 CPU 0<-->: C : 0 CPU 0<-->: C : : C : @ STM @ || System ||
|->0000000 : T : |->0000000 : T : : T :<--->@@@@@ || Memory ||
| #######<-->: I : | #######<-->: I : : I : @@@<-| ||||||||||||
| # ETM # ::::: | # PTM # ::::: ::::: @ |
| ##### ^ ^ | ##### ^ ! ^ ! . | |||||||||
| |->### | ! | |->### | ! | ! . | || DAP ||
| | # | ! | | # | ! | ! . | |||||||||
| | . | ! | | . | ! | ! . | | |
| | . | ! | | . | ! | ! . | | *
| | . | ! | | . | ! | ! . | | SWD/
| | . | ! | | . | ! | ! . | | JTAG
*****************************************************************<-|
*************************** AMBA Debug ABP ************************
*****************************************************************
| . ! . ! ! . |
| . * . * * . |
*****************************************************************
******************** Cross Trigger Matrix (CTM) *******************
*****************************************************************
| . ^ . . |
| * ! * * |
*****************************************************************
****************** AMBA Advanced Trace Bus (ATB) ******************
*****************************************************************
| ! =============== |
| * ===== F =====<---------|
| ::::::::: ==== U ====
|-->:: CTI ::<!! === N ===
| ::::::::: ! == N ==
| ^ * == E ==
| ! &&&&&&&&& IIIIIII == L ==
|------>&& ETB &&<......II I =======
| ! &&&&&&&&& II I .
| ! I I .
| ! I REP I<..........
| ! I I
| !!>&&&&&&&&& II I *Source: ARM ltd.
|------>& TPIU &<......II I DAP = Debug Access Port
&&&&&&&&& IIIIIII ETM = Embedded Trace Macrocell
; PTM = Program Trace Macrocell
; CTI = Cross Trigger Interface
* ETB = Embedded Trace Buffer
To trace port TPIU= Trace Port Interface Unit
SWD = Serial Wire Debug
While on target configuration of the components is done via the ABP bus,
all trace data are carried out-of-band on the ATB bus. The CTM provides
a way to aggregate and distribute signals between CoreSight components.
The coresight framework provides a central point to represent, configure and
manage coresight devices on a platform. This first implementation centers on
the basic tracing functionality, enabling components such ETM/PTM, funnel,
replicator, TMC, TPIU and ETB. Future work will enable more
intricate IP blocks such as STM and CTI.
Acronyms and Classification
---------------------------
Acronyms:
PTM: Program Trace Macrocell
ETM: Embedded Trace Macrocell
STM: System trace Macrocell
ETB: Embedded Trace Buffer
ITM: Instrumentation Trace Macrocell
TPIU: Trace Port Interface Unit
TMC-ETR: Trace Memory Controller, configured as Embedded Trace Router
TMC-ETF: Trace Memory Controller, configured as Embedded Trace FIFO
CTI: Cross Trigger Interface
Classification:
Source:
ETMv3.x ETMv4, PTMv1.0, PTMv1.1, STM, STM500, ITM
Link:
Funnel, replicator (intelligent or not), TMC-ETR
Sinks:
ETBv1.0, ETB1.1, TPIU, TMC-ETF
Misc:
CTI
Device Tree Bindings
----------------------
See Documentation/devicetree/bindings/arm/coresight.txt for details.
As of this writing drivers for ITM, STMs and CTIs are not provided but are
expected to be added as the solution matures.
Framework and implementation
----------------------------
The coresight framework provides a central point to represent, configure and
manage coresight devices on a platform. Any coresight compliant device can
register with the framework for as long as they use the right APIs:
struct coresight_device *coresight_register(struct coresight_desc *desc);
void coresight_unregister(struct coresight_device *csdev);
The registering function is taking a "struct coresight_device *csdev" and
register the device with the core framework. The unregister function takes
a reference to a "strut coresight_device", obtained at registration time.
If everything goes well during the registration process the new devices will
show up under /sys/bus/coresight/devices, as showns here for a TC2 platform:
root:~# ls /sys/bus/coresight/devices/
replicator 20030000.tpiu 2201c000.ptm 2203c000.etm 2203e000.etm
20010000.etb 20040000.funnel 2201d000.ptm 2203d000.etm
root:~#
The functions take a "struct coresight_device", which looks like this:
struct coresight_desc {
enum coresight_dev_type type;
struct coresight_dev_subtype subtype;
const struct coresight_ops *ops;
struct coresight_platform_data *pdata;
struct device *dev;
const struct attribute_group **groups;
};
The "coresight_dev_type" identifies what the device is, i.e, source link or
sink while the "coresight_dev_subtype" will characterise that type further.
The "struct coresight_ops" is mandatory and will tell the framework how to
perform base operations related to the components, each component having
a different set of requirement. For that "struct coresight_ops_sink",
"struct coresight_ops_link" and "struct coresight_ops_source" have been
provided.
The next field, "struct coresight_platform_data *pdata" is acquired by calling
"of_get_coresight_platform_data()", as part of the driver's _probe routine and
"struct device *dev" gets the device reference embedded in the "amba_device":
static int etm_probe(struct amba_device *adev, const struct amba_id *id)
{
...
...
drvdata->dev = &adev->dev;
...
}
Specific class of device (source, link, or sink) have generic operations
that can be performed on them (see "struct coresight_ops"). The
"**groups" is a list of sysfs entries pertaining to operations
specific to that component only. "Implementation defined" customisations are
expected to be accessed and controlled using those entries.
Last but not least, "struct module *owner" is expected to be set to reflect
the information carried in "THIS_MODULE".
How to use
----------
Before trace collection can start, a coresight sink needs to be identify.
There is no limit on the amount of sinks (nor sources) that can be enabled at
any given moment. As a generic operation, all device pertaining to the sink
class will have an "active" entry in sysfs:
root:/sys/bus/coresight/devices# ls
replicator 20030000.tpiu 2201c000.ptm 2203c000.etm 2203e000.etm
20010000.etb 20040000.funnel 2201d000.ptm 2203d000.etm
root:/sys/bus/coresight/devices# ls 20010000.etb
enable_sink status trigger_cntr
root:/sys/bus/coresight/devices# echo 1 > 20010000.etb/enable_sink
root:/sys/bus/coresight/devices# cat 20010000.etb/enable_sink
1
root:/sys/bus/coresight/devices#
At boot time the current etm3x driver will configure the first address
comparator with "_stext" and "_etext", essentially tracing any instruction
that falls within that range. As such "enabling" a source will immediately
trigger a trace capture:
root:/sys/bus/coresight/devices# echo 1 > 2201c000.ptm/enable_source
root:/sys/bus/coresight/devices# cat 2201c000.ptm/enable_source
1
root:/sys/bus/coresight/devices# cat 20010000.etb/status
Depth: 0x2000
Status: 0x1
RAM read ptr: 0x0
RAM wrt ptr: 0x19d3 <----- The write pointer is moving
Trigger cnt: 0x0
Control: 0x1
Flush status: 0x0
Flush ctrl: 0x2001
root:/sys/bus/coresight/devices#
Trace collection is stopped the same way:
root:/sys/bus/coresight/devices# echo 0 > 2201c000.ptm/enable_source
root:/sys/bus/coresight/devices#
The content of the ETB buffer can be harvested directly from /dev:
root:/sys/bus/coresight/devices# dd if=/dev/20010000.etb \
of=~/cstrace.bin
64+0 records in
64+0 records out
32768 bytes (33 kB) copied, 0.00125258 s, 26.2 MB/s
root:/sys/bus/coresight/devices#
The file cstrace.bin can be decompressed using "ptm2human", DS-5 or Trace32.
Following is a DS-5 output of an experimental loop that increments a variable up
to a certain value. The example is simple and yet provides a glimpse of the
wealth of possibilities that coresight provides.
Info Tracing enabled
Instruction 106378866 0x8026B53C E52DE004 false PUSH {lr}
Instruction 0 0x8026B540 E24DD00C false SUB sp,sp,#0xc
Instruction 0 0x8026B544 E3A03000 false MOV r3,#0
Instruction 0 0x8026B548 E58D3004 false STR r3,[sp,#4]
Instruction 0 0x8026B54C E59D3004 false LDR r3,[sp,#4]
Instruction 0 0x8026B550 E3530004 false CMP r3,#4
Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1
Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4]
Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c
Timestamp Timestamp: 17106715833
Instruction 319 0x8026B54C E59D3004 false LDR r3,[sp,#4]
Instruction 0 0x8026B550 E3530004 false CMP r3,#4
Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1
Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4]
Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c
Instruction 9 0x8026B54C E59D3004 false LDR r3,[sp,#4]
Instruction 0 0x8026B550 E3530004 false CMP r3,#4
Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1
Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4]
Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c
Instruction 7 0x8026B54C E59D3004 false LDR r3,[sp,#4]
Instruction 0 0x8026B550 E3530004 false CMP r3,#4
Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1
Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4]
Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c
Instruction 7 0x8026B54C E59D3004 false LDR r3,[sp,#4]
Instruction 0 0x8026B550 E3530004 false CMP r3,#4
Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1
Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4]
Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c
Instruction 10 0x8026B54C E59D3004 false LDR r3,[sp,#4]
Instruction 0 0x8026B550 E3530004 false CMP r3,#4
Instruction 0 0x8026B554 E2833001 false ADD r3,r3,#1
Instruction 0 0x8026B558 E58D3004 false STR r3,[sp,#4]
Instruction 0 0x8026B55C DAFFFFFA true BLE {pc}-0x10 ; 0x8026b54c
Instruction 6 0x8026B560 EE1D3F30 false MRC p15,#0x0,r3,c13,c0,#1
Instruction 0 0x8026B564 E1A0100D false MOV r1,sp
Instruction 0 0x8026B568 E3C12D7F false BIC r2,r1,#0x1fc0
Instruction 0 0x8026B56C E3C2203F false BIC r2,r2,#0x3f
Instruction 0 0x8026B570 E59D1004 false LDR r1,[sp,#4]
Instruction 0 0x8026B574 E59F0010 false LDR r0,[pc,#16] ; [0x8026B58C] = 0x80550368
Instruction 0 0x8026B578 E592200C false LDR r2,[r2,#0xc]
Instruction 0 0x8026B57C E59221D0 false LDR r2,[r2,#0x1d0]
Instruction 0 0x8026B580 EB07A4CF true BL {pc}+0x1e9344 ; 0x804548c4
Info Tracing enabled
Instruction 13570831 0x8026B584 E28DD00C false ADD sp,sp,#0xc
Instruction 0 0x8026B588 E8BD8000 true LDM sp!,{pc}
Timestamp Timestamp: 17107041535
......@@ -920,6 +920,15 @@ M: Hubert Feurstein <hubert.feurstein@contec.at>
S: Maintained
F: arch/arm/mach-ep93xx/micro9.c
ARM/CORESIGHT FRAMEWORK AND DRIVERS
M: Mathieu Poirier <mathieu.poirier@linaro.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: drivers/coresight/*
F: Documentation/trace/coresight.txt
F: Documentation/devicetree/bindings/arm/coresight.txt
F: Documentation/ABI/testing/sysfs-bus-coresight-devices-*
ARM/CORGI MACHINE SUPPORT
M: Richard Purdie <rpurdie@rpsys.net>
S: Maintained
......
......@@ -1452,14 +1452,6 @@ config EARLY_PRINTK
kernel low-level debugging functions. Add earlyprintk to your
kernel parameters to enable this console.
config OC_ETM
bool "On-chip ETM and ETB"
depends on ARM_AMBA
help
Enables the on-chip embedded trace macrocell and embedded trace
buffer driver that will allow you to collect traces of the
kernel code.
config ARM_KPROBES_TEST
tristate "Kprobes test module"
depends on KPROBES && MODULES
......@@ -1486,4 +1478,59 @@ config DEBUG_SET_MODULE_RONX
against certain classes of kernel exploits.
If in doubt, say "N".
menuconfig CORESIGHT
bool "CoreSight Tracing Support"
select ARM_AMBA
help
This framework provides a kernel interface for the CoreSight debug
and trace drivers to register themselves with. It's intended to build
a topological view of the CoreSight components based on a DT
specification and configure the right serie of components when a
trace source gets enabled.
if CORESIGHT
config CORESIGHT_LINKS_AND_SINKS
bool "CoreSight Link and Sink drivers"
help
This enables support for CoreSight link and sink drivers that are
responsible for transporting and collecting the trace data
respectively. Link and sinks are dynamically aggregated with a trace
entity at run time to form a complete trace path.
config CORESIGHT_LINK_AND_SINK_TMC
bool "Coresight generic TMC driver"
depends on CORESIGHT_LINKS_AND_SINKS
help
This enables support for the Trace Memory Controller driver. Depending
on its configuration the device can act as a link (embedded trace router
- ETR) or sink (embedded trace FIFO). The driver complies with the
generic implementation of the component without special enhancement or
added features.
config CORESIGHT_SINK_TPIU
bool "Coresight generic TPIU driver"
depends on CORESIGHT_LINKS_AND_SINKS
help
This enables support for the Trace Port Interface Unit driver, responsible
for bridging the gap between the on-chip coresight components and a trace
port collection engine, typically connected to an external host for use
case capturing more traces than the on-board coresight memory can handle.
config CORESIGHT_SINK_ETBV10
bool "Coresight ETBv1.0 driver"
depends on CORESIGHT_LINKS_AND_SINKS
help
This enables support for the Embedded Trace Buffer version 1.0 driver
that complies with the generic implementation of the component without
special enhancement or added features.
config CORESIGHT_SOURCE_ETM3X
bool "CoreSight Embedded Trace Macrocell 3.x driver"
select CORESIGHT_LINKS_AND_SINKS
help
This driver provides support for processor ETM3.x and PTM1.x modules,
which allows tracing the instructions that a processor is executing
This is primarily useful for instruction level tracing. Depending
the ETM version data tracing may also be available.
endif
endmenu
......@@ -190,6 +190,12 @@
clock-frequency = <168000000>;
};
clk_375m: clk_375m {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <375000000>;
};
soc {
/* It's a 32-bit SoC. */
#address-cells = <1>;
......@@ -264,4 +270,715 @@
};
};
etb@0,e3c42000 {
compatible = "arm,coresight-etb10", "arm,primecell";
reg = <0 0xe3c42000 0 0x1000>;
coresight-default-sink;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
port {
etb0_in_port: endpoint@0 {
slave-mode;
remote-endpoint = <&replicator0_out_port0>;
};
};
};
etb@0,e3c82000 {
compatible = "arm,coresight-etb10", "arm,primecell";
reg = <0 0xe3c82000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
port {
etb1_in_port: endpoint@0 {
slave-mode;
remote-endpoint = <&replicator1_out_port0>;
};
};
};
etb@0,e3cc2000 {
compatible = "arm,coresight-etb10", "arm,primecell";
reg = <0 0xe3cc2000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
port {
etb2_in_port: endpoint@0 {
slave-mode;
remote-endpoint = <&replicator2_out_port0>;
};
};
};
etb@0,e3d02000 {
compatible = "arm,coresight-etb10", "arm,primecell";
reg = <0 0xe3d02000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
port {
etb3_in_port: endpoint@0 {
slave-mode;
remote-endpoint = <&replicator3_out_port0>;
};
};
};
tpiu@0,e3c05000 {
compatible = "arm,coresight-tpiu", "arm,primecell";
reg = <0 0xe3c05000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
port {
tpiu_in_port: endpoint@0 {
slave-mode;
remote-endpoint = <&funnel4_out_port0>;
};
};
};
replicator0 {
/* non-configurable replicators don't show up on the
* AMBA bus. As such no need to add "arm,primecell".
*/
compatible = "arm,coresight-replicator";
ports {
#address-cells = <1>;
#size-cells = <0>;
/* replicator output ports */
port@0 {
reg = <0>;
replicator0_out_port0: endpoint {
remote-endpoint = <&etb0_in_port>;
};
};
port@1 {
reg = <1>;
replicator0_out_port1: endpoint {
remote-endpoint = <&funnel4_in_port0>;
};
};
/* replicator input port */
port@2 {
reg = <0>;
replicator0_in_port0: endpoint {
slave-mode;
remote-endpoint = <&funnel0_out_port0>;
};
};
};
};
replicator1 {
/* non-configurable replicators don't show up on the
* AMBA bus. As such no need to add "arm,primecell".
*/
compatible = "arm,coresight-replicator";
ports {
#address-cells = <1>;
#size-cells = <0>;
/* replicator output ports */
port@0 {
reg = <0>;
replicator1_out_port0: endpoint {
remote-endpoint = <&etb1_in_port>;
};
};
port@1 {
reg = <1>;
replicator1_out_port1: endpoint {
remote-endpoint = <&funnel4_in_port1>;
};
};
/* replicator input port */
port@2 {
reg = <0>;
replicator1_in_port0: endpoint {
slave-mode;
remote-endpoint = <&funnel1_out_port0>;
};
};
};
};
replicator2 {
/* non-configurable replicators don't show up on the
* AMBA bus. As such no need to add "arm,primecell".
*/
compatible = "arm,coresight-replicator";
ports {
#address-cells = <1>;
#size-cells = <0>;
/* replicator output ports */
port@0 {
reg = <0>;
replicator2_out_port0: endpoint {
remote-endpoint = <&etb2_in_port>;
};
};
port@1 {
reg = <1>;
replicator2_out_port1: endpoint {
remote-endpoint = <&funnel4_in_port2>;
};
};
/* replicator input port */
port@2 {
reg = <0>;
replicator2_in_port0: endpoint {
slave-mode;
remote-endpoint = <&funnel2_out_port0>;
};
};
};
};
replicator3 {
/* non-configurable replicators don't show up on the
* AMBA bus. As such no need to add "arm,primecell".
*/
compatible = "arm,coresight-replicator";
ports {
#address-cells = <1>;
#size-cells = <0>;
/* replicator output ports */
port@0 {
reg = <0>;
replicator3_out_port0: endpoint {
remote-endpoint = <&etb3_in_port>;
};
};
port@1 {
reg = <1>;
replicator3_out_port1: endpoint {
remote-endpoint = <&funnel4_in_port3>;
};
};
/* replicator input port */
port@2 {
reg = <0>;
replicator3_in_port0: endpoint {
slave-mode;
remote-endpoint = <&funnel3_out_port0>;
};
};
};
};
funnel@0,e3c41000 {
compatible = "arm,coresight-funnel", "arm,primecell";
reg = <0 0xe3c41000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
ports {
#address-cells = <1>;
#size-cells = <0>;
/* funnel output port */
port@0 {
reg = <0>;
funnel0_out_port0: endpoint {
remote-endpoint =
<&replicator0_in_port0>;
};
};
/* funnel input ports */
port@1 {
reg = <0>;
funnel0_in_port0: endpoint {
slave-mode;
remote-endpoint = <&ptm0_out_port>;
};
};
port@2 {
reg = <1>;
funnel0_in_port1: endpoint {
slave-mode;
remote-endpoint = <&ptm1_out_port>;
};
};
port@3 {
reg = <2>;
funnel0_in_port2: endpoint {
slave-mode;
remote-endpoint = <&ptm2_out_port>;
};
};
port@4 {
reg = <3>;
funnel0_in_port3: endpoint {
slave-mode;
remote-endpoint = <&ptm3_out_port>;
};
};
};
};
funnel@0,e3c81000 {
compatible = "arm,coresight-funnel", "arm,primecell";
reg = <0 0xe3c81000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
ports {
#address-cells = <1>;
#size-cells = <0>;
/* funnel output port */
port@0 {
reg = <0>;
funnel1_out_port0: endpoint {
remote-endpoint =
<&replicator1_in_port0>;
};
};
/* funnel input ports */
port@1 {
reg = <0>;
funnel1_in_port0: endpoint {
slave-mode;
remote-endpoint = <&ptm4_out_port>;
};
};
port@2 {
reg = <1>;
funnel1_in_port1: endpoint {
slave-mode;
remote-endpoint = <&ptm5_out_port>;
};
};
port@3 {
reg = <2>;
funnel1_in_port2: endpoint {
slave-mode;
remote-endpoint = <&ptm6_out_port>;
};
};
port@4 {
reg = <3>;
funnel1_in_port3: endpoint {
slave-mode;
remote-endpoint = <&ptm7_out_port>;
};
};
};
};
funnel@0,e3cc1000 {
compatible = "arm,coresight-funnel", "arm,primecell";
reg = <0 0xe3cc1000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
ports {
#address-cells = <1>;
#size-cells = <0>;
/* funnel output port */
port@0 {
reg = <0>;
funnel2_out_port0: endpoint {
remote-endpoint =
<&replicator2_in_port0>;
};
};
/* funnel input ports */
port@1 {
reg = <0>;
funnel2_in_port0: endpoint {
slave-mode;
remote-endpoint = <&ptm8_out_port>;
};
};
port@2 {
reg = <1>;
funnel2_in_port1: endpoint {
slave-mode;
remote-endpoint = <&ptm9_out_port>;
};
};
port@3 {
reg = <2>;
funnel2_in_port2: endpoint {
slave-mode;
remote-endpoint = <&ptm10_out_port>;
};
};
port@4 {
reg = <3>;
funnel2_in_port3: endpoint {
slave-mode;
remote-endpoint = <&ptm11_out_port>;
};
};
};
};
funnel@0,e3d01000 {
compatible = "arm,coresight-funnel", "arm,primecell";
reg = <0 0xe3d01000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
ports {
#address-cells = <1>;
#size-cells = <0>;
/* funnel output port */
port@0 {
reg = <0>;
funnel3_out_port0: endpoint {
remote-endpoint =
<&replicator3_in_port0>;
};
};
/* funnel input ports */
port@1 {
reg = <0>;
funnel3_in_port0: endpoint {
slave-mode;
remote-endpoint = <&ptm12_out_port>;
};
};
port@2 {
reg = <1>;
funnel3_in_port1: endpoint {
slave-mode;
remote-endpoint = <&ptm13_out_port>;
};
};
port@3 {
reg = <2>;
funnel3_in_port2: endpoint {
slave-mode;
remote-endpoint = <&ptm14_out_port>;
};
};
port@4 {
reg = <3>;
funnel3_in_port3: endpoint {
slave-mode;
remote-endpoint = <&ptm15_out_port>;
};
};
};
};
funnel@0,e3c04000 {
compatible = "arm,coresight-funnel", "arm,primecell";
reg = <0 0xe3c04000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
ports {
#address-cells = <1>;
#size-cells = <0>;
/* funnel output port */
port@0 {
reg = <0>;
funnel4_out_port0: endpoint {
remote-endpoint = <&tpiu_in_port>;
};
};
/* funnel input ports */
port@1 {
reg = <0>;
funnel4_in_port0: endpoint {
slave-mode;
remote-endpoint =
<&replicator0_out_port1>;
};
};
port@2 {
reg = <1>;
funnel4_in_port1: endpoint {
slave-mode;
remote-endpoint =
<&replicator1_out_port1>;
};
};
port@3 {
reg = <2>;
funnel4_in_port2: endpoint {
slave-mode;
remote-endpoint =
<&replicator2_out_port1>;
};
};
port@4 {
reg = <3>;
funnel4_in_port3: endpoint {
slave-mode;
remote-endpoint =
<&replicator3_out_port1>;
};
};
};
};
ptm@0,e3c7c000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0xe3c7c000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
cpu = <&CPU0>;
port {
ptm0_out_port: endpoint {
remote-endpoint = <&funnel0_in_port0>;
};
};
};
ptm@0,e3c7d000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0xe3c7d000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
cpu = <&CPU1>;
port {
ptm1_out_port: endpoint {
remote-endpoint = <&funnel0_in_port1>;
};
};
};
ptm@0,e3c7e000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0xe3c7e000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
cpu = <&CPU2>;
port {
ptm2_out_port: endpoint {
remote-endpoint = <&funnel0_in_port2>;
};
};
};
ptm@0,e3c7f000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0xe3c7f000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
cpu = <&CPU3>;
port {
ptm3_out_port: endpoint {
remote-endpoint = <&funnel0_in_port3>;
};
};
};
ptm@0,e3cbc000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0xe3cbc000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
cpu = <&CPU4>;
port {
ptm4_out_port: endpoint {
remote-endpoint = <&funnel1_in_port0>;
};
};
};
ptm@0,e3cbd000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0xe3cbd000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
cpu = <&CPU5>;
port {
ptm5_out_port: endpoint {
remote-endpoint = <&funnel1_in_port1>;
};
};
};
ptm@0,e3cbe000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0xe3cbe000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
cpu = <&CPU6>;
port {
ptm6_out_port: endpoint {
remote-endpoint = <&funnel1_in_port2>;
};
};
};
ptm@0,e3cbf000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0xe3cbf000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
cpu = <&CPU7>;
port {
ptm7_out_port: endpoint {
remote-endpoint = <&funnel1_in_port3>;
};
};
};
ptm@0,e3cfc000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0xe3cfc000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
cpu = <&CPU8>;
port {
ptm8_out_port: endpoint {
remote-endpoint = <&funnel2_in_port0>;
};
};
};
ptm@0,e3cfd000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0xe3cfd000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
cpu = <&CPU9>;
port {
ptm9_out_port: endpoint {
remote-endpoint = <&funnel2_in_port1>;
};
};
};
ptm@0,e3cfe000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0xe3cfe000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
cpu = <&CPU10>;
port {
ptm10_out_port: endpoint {
remote-endpoint = <&funnel2_in_port2>;
};
};
};
ptm@0,e3cff000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0xe3cff000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
cpu = <&CPU11>;
port {
ptm11_out_port: endpoint {
remote-endpoint = <&funnel2_in_port3>;
};
};
};
ptm@0,e3d3c000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0xe3d3c000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
cpu = <&CPU12>;
port {
ptm12_out_port: endpoint {
remote-endpoint = <&funnel3_in_port0>;
};
};
};
ptm@0,e3d3d000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0xe3d3d000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
cpu = <&CPU13>;
port {
ptm13_out_port: endpoint {
remote-endpoint = <&funnel3_in_port1>;
};
};
};
ptm@0,e3d3e000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0xe3d3e000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
cpu = <&CPU14>;
port {
ptm14_out_port: endpoint {
remote-endpoint = <&funnel3_in_port2>;
};
};
};
ptm@0,e3d3f000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0xe3d3f000 0 0x1000>;
clocks = <&clk_375m>;
clock-names = "apb_pclk";
cpu = <&CPU15>;
port {
ptm15_out_port: endpoint {
remote-endpoint = <&funnel3_in_port3>;
};
};
};
};
......@@ -145,6 +145,34 @@
};
};
};
etb@5401b000 {
compatible = "arm,coresight-etb10", "arm,primecell";
reg = <0x5401b000 0x1000>;
coresight-default-sink;
clocks = <&emu_src_ck>;
clock-names = "apb_pclk";
port {
etb_in: endpoint {
slave-mode;
remote-endpoint = <&etm_out>;
};
};
};
etm@54010000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0x54010000 0x1000>;
clocks = <&emu_src_ck>;
clock-names = "apb_pclk";
port {
etm_out: endpoint {
remote-endpoint = <&etb_in>;
};
};
};
};
&omap3_pmx_wkup {
......
......@@ -140,6 +140,34 @@
};
};
};
etb@540000000 {
compatible = "arm,coresight-etb10", "arm,primecell";
reg = <0x5401b000 0x1000>;
coresight-default-sink;
clocks = <&emu_src_ck>;
clock-names = "apb_pclk";
port {
etb_in: endpoint {
slave-mode;
remote-endpoint = <&etm_out>;
};
};
};
etm@54010000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0x54010000 0x1000>;
clocks = <&emu_src_ck>;
clock-names = "apb_pclk";
port {
etm_out: endpoint {
remote-endpoint = <&etb_in>;
};
};
};
};
&omap3_pmx_wkup {
......
......@@ -358,6 +358,205 @@
};
};
etb@0,20010000 {
compatible = "arm,coresight-etb10", "arm,primecell";
reg = <0 0x20010000 0 0x1000>;
coresight-default-sink;
clocks = <&oscclk6a>;
clock-names = "apb_pclk";
port {
etb_in_port: endpoint@0 {
slave-mode;
remote-endpoint = <&replicator_out_port0>;
};
};
};
tpiu@0,20030000 {
compatible = "arm,coresight-tpiu", "arm,primecell";
reg = <0 0x20030000 0 0x1000>;
clocks = <&oscclk6a>;
clock-names = "apb_pclk";
port {
tpiu_in_port: endpoint@0 {
slave-mode;
remote-endpoint = <&replicator_out_port1>;
};
};
};
replicator {
/* non-configurable replicators don't show up on the
* AMBA bus. As such no need to add "arm,primecell".
*/
compatible = "arm,coresight-replicator";
ports {
#address-cells = <1>;
#size-cells = <0>;
/* replicator output ports */
port@0 {
reg = <0>;
replicator_out_port0: endpoint {
remote-endpoint = <&etb_in_port>;
};
};
port@1 {
reg = <1>;
replicator_out_port1: endpoint {
remote-endpoint = <&tpiu_in_port>;
};
};
/* replicator input port */
port@2 {
reg = <0>;
replicator_in_port0: endpoint {
slave-mode;
remote-endpoint = <&funnel_out_port0>;
};
};
};
};
funnel@0,20040000 {
compatible = "arm,coresight-funnel", "arm,primecell";
reg = <0 0x20040000 0 0x1000>;
clocks = <&oscclk6a>;
clock-names = "apb_pclk";
ports {
#address-cells = <1>;
#size-cells = <0>;
/* funnel output port */
port@0 {
reg = <0>;
funnel_out_port0: endpoint {
remote-endpoint =
<&replicator_in_port0>;
};
};
/* funnel input ports */
port@1 {
reg = <0>;
funnel_in_port0: endpoint {
slave-mode;
remote-endpoint = <&ptm0_out_port>;
};
};
port@2 {
reg = <1>;
funnel_in_port1: endpoint {
slave-mode;
remote-endpoint = <&ptm1_out_port>;
};
};
port@3 {
reg = <2>;
funnel_in_port2: endpoint {
slave-mode;
remote-endpoint = <&etm0_out_port>;
};
};
/* Input port #3 is for ITM, not supported here */
port@4 {
reg = <4>;
funnel_in_port4: endpoint {
slave-mode;
remote-endpoint = <&etm1_out_port>;
};
};
port@5 {
reg = <5>;
funnel_in_port5: endpoint {
slave-mode;
remote-endpoint = <&etm2_out_port>;
};
};
};
};
ptm@0,2201c000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0x2201c000 0 0x1000>;
cpu = <&cpu0>;
clocks = <&oscclk6a>;
clock-names = "apb_pclk";
port {
ptm0_out_port: endpoint {
remote-endpoint = <&funnel_in_port0>;
};
};
};
ptm@0,2201d000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0x2201d000 0 0x1000>;
cpu = <&cpu1>;
clocks = <&oscclk6a>;
clock-names = "apb_pclk";
port {
ptm1_out_port: endpoint {
remote-endpoint = <&funnel_in_port1>;
};
};
};
etm@0,2203c000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0x2203c000 0 0x1000>;
cpu = <&cpu2>;
clocks = <&oscclk6a>;
clock-names = "apb_pclk";
port {
etm0_out_port: endpoint {
remote-endpoint = <&funnel_in_port2>;
};
};
};
etm@0,2203d000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0x2203d000 0 0x1000>;
cpu = <&cpu3>;
clocks = <&oscclk6a>;
clock-names = "apb_pclk";
port {
etm1_out_port: endpoint {
remote-endpoint = <&funnel_in_port4>;
};
};
};
etm@0,2203e000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0 0x2203e000 0 0x1000>;
cpu = <&cpu4>;
clocks = <&oscclk6a>;
clock-names = "apb_pclk";
port {
etm2_out_port: endpoint {
remote-endpoint = <&funnel_in_port5>;
};
};
};
smb {
compatible = "simple-bus";
......
/*
* linux/arch/arm/include/asm/hardware/coresight.h
*
* CoreSight components' registers
*
* Copyright (C) 2009 Nokia Corporation.
* Alexander Shishkin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ASM_HARDWARE_CORESIGHT_H
#define __ASM_HARDWARE_CORESIGHT_H
#define TRACER_ACCESSED_BIT 0
#define TRACER_RUNNING_BIT 1
#define TRACER_CYCLE_ACC_BIT 2
#define TRACER_ACCESSED BIT(TRACER_ACCESSED_BIT)
#define TRACER_RUNNING BIT(TRACER_RUNNING_BIT)
#define TRACER_CYCLE_ACC BIT(TRACER_CYCLE_ACC_BIT)
#define TRACER_TIMEOUT 10000
#define etm_writel(t, v, x) \
(writel_relaxed((v), (t)->etm_regs + (x)))
#define etm_readl(t, x) (readl_relaxed((t)->etm_regs + (x)))
/* CoreSight Management Registers */
#define CSMR_LOCKACCESS 0xfb0
#define CSMR_LOCKSTATUS 0xfb4
#define CSMR_AUTHSTATUS 0xfb8
#define CSMR_DEVID 0xfc8
#define CSMR_DEVTYPE 0xfcc
/* CoreSight Component Registers */
#define CSCR_CLASS 0xff4
#define CS_LAR_KEY 0xc5acce55
/* ETM control register, "ETM Architecture", 3.3.1 */
#define ETMR_CTRL 0
#define ETMCTRL_POWERDOWN 1
#define ETMCTRL_PROGRAM (1 << 10)
#define ETMCTRL_PORTSEL (1 << 11)
#define ETMCTRL_DO_CONTEXTID (3 << 14)
#define ETMCTRL_PORTMASK1 (7 << 4)
#define ETMCTRL_PORTMASK2 (1 << 21)
#define ETMCTRL_PORTMASK (ETMCTRL_PORTMASK1 | ETMCTRL_PORTMASK2)
#define ETMCTRL_PORTSIZE(x) ((((x) & 7) << 4) | (!!((x) & 8)) << 21)
#define ETMCTRL_DO_CPRT (1 << 1)
#define ETMCTRL_DATAMASK (3 << 2)
#define ETMCTRL_DATA_DO_DATA (1 << 2)
#define ETMCTRL_DATA_DO_ADDR (1 << 3)
#define ETMCTRL_DATA_DO_BOTH (ETMCTRL_DATA_DO_DATA | ETMCTRL_DATA_DO_ADDR)
#define ETMCTRL_BRANCH_OUTPUT (1 << 8)
#define ETMCTRL_CYCLEACCURATE (1 << 12)
/* ETM configuration code register */
#define ETMR_CONFCODE (0x04)
/* ETM trace start/stop resource control register */
#define ETMR_TRACESSCTRL (0x18)
/* ETM trigger event register */
#define ETMR_TRIGEVT (0x08)
/* address access type register bits, "ETM architecture",
* table 3-27 */
/* - access type */
#define ETMAAT_IFETCH 0
#define ETMAAT_IEXEC 1
#define ETMAAT_IEXECPASS 2
#define ETMAAT_IEXECFAIL 3
#define ETMAAT_DLOADSTORE 4
#define ETMAAT_DLOAD 5
#define ETMAAT_DSTORE 6
/* - comparison access size */
#define ETMAAT_JAVA (0 << 3)
#define ETMAAT_THUMB (1 << 3)
#define ETMAAT_ARM (3 << 3)
/* - data value comparison control */
#define ETMAAT_NOVALCMP (0 << 5)
#define ETMAAT_VALMATCH (1 << 5)
#define ETMAAT_VALNOMATCH (3 << 5)
/* - exact match */
#define ETMAAT_EXACTMATCH (1 << 7)
/* - context id comparator control */
#define ETMAAT_IGNCONTEXTID (0 << 8)
#define ETMAAT_VALUE1 (1 << 8)
#define ETMAAT_VALUE2 (2 << 8)
#define ETMAAT_VALUE3 (3 << 8)
/* - security level control */
#define ETMAAT_IGNSECURITY (0 << 10)
#define ETMAAT_NSONLY (1 << 10)
#define ETMAAT_SONLY (2 << 10)
#define ETMR_COMP_VAL(x) (0x40 + (x) * 4)
#define ETMR_COMP_ACC_TYPE(x) (0x80 + (x) * 4)
/* ETM status register, "ETM Architecture", 3.3.2 */
#define ETMR_STATUS (0x10)
#define ETMST_OVERFLOW BIT(0)
#define ETMST_PROGBIT BIT(1)
#define ETMST_STARTSTOP BIT(2)
#define ETMST_TRIGGER BIT(3)
#define etm_progbit(t) (etm_readl((t), ETMR_STATUS) & ETMST_PROGBIT)
#define etm_started(t) (etm_readl((t), ETMR_STATUS) & ETMST_STARTSTOP)
#define etm_triggered(t) (etm_readl((t), ETMR_STATUS) & ETMST_TRIGGER)
#define ETMR_TRACEENCTRL2 0x1c
#define ETMR_TRACEENCTRL 0x24
#define ETMTE_INCLEXCL BIT(24)
#define ETMR_TRACEENEVT 0x20
#define ETMCTRL_OPTS (ETMCTRL_DO_CPRT | \
ETMCTRL_DATA_DO_ADDR | \
ETMCTRL_BRANCH_OUTPUT | \
ETMCTRL_DO_CONTEXTID)
/* ETM management registers, "ETM Architecture", 3.5.24 */
#define ETMMR_OSLAR 0x300
#define ETMMR_OSLSR 0x304
#define ETMMR_OSSRR 0x308
#define ETMMR_PDSR 0x314
/* ETB registers, "CoreSight Components TRM", 9.3 */
#define ETBR_DEPTH 0x04
#define ETBR_STATUS 0x0c
#define ETBR_READMEM 0x10
#define ETBR_READADDR 0x14
#define ETBR_WRITEADDR 0x18
#define ETBR_TRIGGERCOUNT 0x1c
#define ETBR_CTRL 0x20
#define ETBR_FORMATTERCTRL 0x304
#define ETBFF_ENFTC 1
#define ETBFF_ENFCONT BIT(1)
#define ETBFF_FONFLIN BIT(4)
#define ETBFF_MANUAL_FLUSH BIT(6)
#define ETBFF_TRIGIN BIT(8)
#define ETBFF_TRIGEVT BIT(9)
#define ETBFF_TRIGFL BIT(10)
#define etb_writel(t, v, x) \
(writel_relaxed((v), (t)->etb_regs + (x)))
#define etb_readl(t, x) (readl_relaxed((t)->etb_regs + (x)))
#define etm_lock(t) do { etm_writel((t), 0, CSMR_LOCKACCESS); } while (0)
#define etm_unlock(t) \
do { etm_writel((t), CS_LAR_KEY, CSMR_LOCKACCESS); } while (0)
#define etb_lock(t) do { etb_writel((t), 0, CSMR_LOCKACCESS); } while (0)
#define etb_unlock(t) \
do { etb_writel((t), CS_LAR_KEY, CSMR_LOCKACCESS); } while (0)
#endif /* __ASM_HARDWARE_CORESIGHT_H */
此差异已折叠。
......@@ -30,7 +30,6 @@ else
obj-y += entry-armv.o
endif
obj-$(CONFIG_OC_ETM) += etm.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_ISA_DMA_API) += dma.o
obj-$(CONFIG_FIQ) += fiq.o fiqasm.o
......
/*
* linux/arch/arm/kernel/etm.c
*
* Driver for ARM's Embedded Trace Macrocell and Embedded Trace Buffer.
*
* Copyright (C) 2009 Nokia Corporation.
* Alexander Shishkin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/io.h>
#include <linux/sysrq.h>
#include <linux/device.h>
#include <linux/clk.h>
#include <linux/amba/bus.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/vmalloc.h>
#include <linux/mutex.h>
#include <linux/module.h>
#include <asm/hardware/coresight.h>
#include <asm/sections.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alexander Shishkin");
/*
* ETM tracer state
*/
struct tracectx {
unsigned int etb_bufsz;
void __iomem *etb_regs;
void __iomem *etm_regs;
unsigned long flags;
int ncmppairs;
int etm_portsz;
struct device *dev;
struct clk *emu_clk;
struct mutex mutex;
};
static struct tracectx tracer;
static inline bool trace_isrunning(struct tracectx *t)
{
return !!(t->flags & TRACER_RUNNING);
}
static int etm_setup_address_range(struct tracectx *t, int n,
unsigned long start, unsigned long end, int exclude, int data)
{
u32 flags = ETMAAT_ARM | ETMAAT_IGNCONTEXTID | ETMAAT_NSONLY | \
ETMAAT_NOVALCMP;
if (n < 1 || n > t->ncmppairs)
return -EINVAL;
/* comparators and ranges are numbered starting with 1 as opposed
* to bits in a word */
n--;
if (data)
flags |= ETMAAT_DLOADSTORE;
else
flags |= ETMAAT_IEXEC;
/* first comparator for the range */
etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2));
etm_writel(t, start, ETMR_COMP_VAL(n * 2));
/* second comparator is right next to it */
etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2 + 1));
etm_writel(t, end, ETMR_COMP_VAL(n * 2 + 1));
flags = exclude ? ETMTE_INCLEXCL : 0;
etm_writel(t, flags | (1 << n), ETMR_TRACEENCTRL);
return 0;
}
static int trace_start(struct tracectx *t)
{
u32 v;
unsigned long timeout = TRACER_TIMEOUT;
etb_unlock(t);
etb_writel(t, 0, ETBR_FORMATTERCTRL);
etb_writel(t, 1, ETBR_CTRL);
etb_lock(t);
/* configure etm */
v = ETMCTRL_OPTS | ETMCTRL_PROGRAM | ETMCTRL_PORTSIZE(t->etm_portsz);
if (t->flags & TRACER_CYCLE_ACC)
v |= ETMCTRL_CYCLEACCURATE;
etm_unlock(t);
etm_writel(t, v, ETMR_CTRL);
while (!(etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout)
;
if (!timeout) {
dev_dbg(t->dev, "Waiting for progbit to assert timed out\n");
etm_lock(t);
return -EFAULT;
}
etm_setup_address_range(t, 1, (unsigned long)_stext,
(unsigned long)_etext, 0, 0);
etm_writel(t, 0, ETMR_TRACEENCTRL2);
etm_writel(t, 0, ETMR_TRACESSCTRL);
etm_writel(t, 0x6f, ETMR_TRACEENEVT);
v &= ~ETMCTRL_PROGRAM;
v |= ETMCTRL_PORTSEL;
etm_writel(t, v, ETMR_CTRL);
timeout = TRACER_TIMEOUT;
while (etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM && --timeout)
;
if (!timeout) {
dev_dbg(t->dev, "Waiting for progbit to deassert timed out\n");
etm_lock(t);
return -EFAULT;
}
etm_lock(t);
t->flags |= TRACER_RUNNING;
return 0;
}
static int trace_stop(struct tracectx *t)
{
unsigned long timeout = TRACER_TIMEOUT;
etm_unlock(t);
etm_writel(t, 0x440, ETMR_CTRL);
while (!(etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout)
;
if (!timeout) {
dev_dbg(t->dev, "Waiting for progbit to assert timed out\n");
etm_lock(t);
return -EFAULT;
}
etm_lock(t);
etb_unlock(t);
etb_writel(t, ETBFF_MANUAL_FLUSH, ETBR_FORMATTERCTRL);
timeout = TRACER_TIMEOUT;
while (etb_readl(t, ETBR_FORMATTERCTRL) &
ETBFF_MANUAL_FLUSH && --timeout)
;
if (!timeout) {
dev_dbg(t->dev, "Waiting for formatter flush to commence "
"timed out\n");
etb_lock(t);
return -EFAULT;
}
etb_writel(t, 0, ETBR_CTRL);
etb_lock(t);
t->flags &= ~TRACER_RUNNING;
return 0;
}
static int etb_getdatalen(struct tracectx *t)
{
u32 v;
int rp, wp;
v = etb_readl(t, ETBR_STATUS);
if (v & 1)
return t->etb_bufsz;
rp = etb_readl(t, ETBR_READADDR);
wp = etb_readl(t, ETBR_WRITEADDR);
if (rp > wp) {
etb_writel(t, 0, ETBR_READADDR);
etb_writel(t, 0, ETBR_WRITEADDR);
return 0;
}
return wp - rp;
}
/* sysrq+v will always stop the running trace and leave it at that */
static void etm_dump(void)
{
struct tracectx *t = &tracer;
u32 first = 0;
int length;
if (!t->etb_regs) {
pr_info("No tracing hardware found\n");
return;
}
if (trace_isrunning(t))
trace_stop(t);
etb_unlock(t);
length = etb_getdatalen(t);
if (length == t->etb_bufsz)
first = etb_readl(t, ETBR_WRITEADDR);
etb_writel(t, first, ETBR_READADDR);
pr_info("Trace buffer contents length: %d\n", length);
pr_info("--- ETB buffer begin ---\n");
for (; length; length--)
printk("%08x", cpu_to_be32(etb_readl(t, ETBR_READMEM)));
pr_info("\n--- ETB buffer end ---\n");
/* deassert the overflow bit */
etb_writel(t, 1, ETBR_CTRL);
etb_writel(t, 0, ETBR_CTRL);
etb_writel(t, 0, ETBR_TRIGGERCOUNT);
etb_writel(t, 0, ETBR_READADDR);
etb_writel(t, 0, ETBR_WRITEADDR);
etb_lock(t);
}
static void sysrq_etm_dump(int key)
{
dev_dbg(tracer.dev, "Dumping ETB buffer\n");
etm_dump();
}
static struct sysrq_key_op sysrq_etm_op = {
.handler = sysrq_etm_dump,
.help_msg = "etm-buffer-dump(v)",
.action_msg = "etm",
};
static int etb_open(struct inode *inode, struct file *file)
{
if (!tracer.etb_regs)
return -ENODEV;
file->private_data = &tracer;
return nonseekable_open(inode, file);
}
static ssize_t etb_read(struct file *file, char __user *data,
size_t len, loff_t *ppos)
{
int total, i;
long length;
struct tracectx *t = file->private_data;
u32 first = 0;
u32 *buf;
mutex_lock(&t->mutex);
if (trace_isrunning(t)) {
length = 0;
goto out;
}
etb_unlock(t);
total = etb_getdatalen(t);
if (total == t->etb_bufsz)
first = etb_readl(t, ETBR_WRITEADDR);
etb_writel(t, first, ETBR_READADDR);
length = min(total * 4, (int)len);
buf = vmalloc(length);
dev_dbg(t->dev, "ETB buffer length: %d\n", total);
dev_dbg(t->dev, "ETB status reg: %x\n", etb_readl(t, ETBR_STATUS));
for (i = 0; i < length / 4; i++)
buf[i] = etb_readl(t, ETBR_READMEM);
/* the only way to deassert overflow bit in ETB status is this */
etb_writel(t, 1, ETBR_CTRL);
etb_writel(t, 0, ETBR_CTRL);
etb_writel(t, 0, ETBR_WRITEADDR);
etb_writel(t, 0, ETBR_READADDR);
etb_writel(t, 0, ETBR_TRIGGERCOUNT);
etb_lock(t);
length -= copy_to_user(data, buf, length);
vfree(buf);
out:
mutex_unlock(&t->mutex);
return length;
}
static int etb_release(struct inode *inode, struct file *file)
{
/* there's nothing to do here, actually */
return 0;
}
static const struct file_operations etb_fops = {
.owner = THIS_MODULE,
.read = etb_read,
.open = etb_open,
.release = etb_release,
.llseek = no_llseek,
};
static struct miscdevice etb_miscdev = {
.name = "tracebuf",
.minor = 0,
.fops = &etb_fops,
};
static int etb_probe(struct amba_device *dev, const struct amba_id *id)
{
struct tracectx *t = &tracer;
int ret = 0;
ret = amba_request_regions(dev, NULL);
if (ret)
goto out;
t->etb_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res));
if (!t->etb_regs) {
ret = -ENOMEM;
goto out_release;
}
amba_set_drvdata(dev, t);
etb_miscdev.parent = &dev->dev;
ret = misc_register(&etb_miscdev);
if (ret)
goto out_unmap;
t->emu_clk = clk_get(&dev->dev, "emu_src_ck");
if (IS_ERR(t->emu_clk)) {
dev_dbg(&dev->dev, "Failed to obtain emu_src_ck.\n");
return -EFAULT;
}
clk_enable(t->emu_clk);
etb_unlock(t);
t->etb_bufsz = etb_readl(t, ETBR_DEPTH);
dev_dbg(&dev->dev, "Size: %x\n", t->etb_bufsz);
/* make sure trace capture is disabled */
etb_writel(t, 0, ETBR_CTRL);
etb_writel(t, 0x1000, ETBR_FORMATTERCTRL);
etb_lock(t);
dev_dbg(&dev->dev, "ETB AMBA driver initialized.\n");
out:
return ret;
out_unmap:
iounmap(t->etb_regs);
out_release:
amba_release_regions(dev);
return ret;
}
static int etb_remove(struct amba_device *dev)
{
struct tracectx *t = amba_get_drvdata(dev);
iounmap(t->etb_regs);
t->etb_regs = NULL;
clk_disable(t->emu_clk);
clk_put(t->emu_clk);
amba_release_regions(dev);
return 0;
}
static struct amba_id etb_ids[] = {
{
.id = 0x0003b907,
.mask = 0x0007ffff,
},
{ 0, 0 },
};
static struct amba_driver etb_driver = {
.drv = {
.name = "etb",
.owner = THIS_MODULE,
},
.probe = etb_probe,
.remove = etb_remove,
.id_table = etb_ids,
};
/* use a sysfs file "trace_running" to start/stop tracing */
static ssize_t trace_running_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
{
return sprintf(buf, "%x\n", trace_isrunning(&tracer));
}
static ssize_t trace_running_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t n)
{
unsigned int value;
int ret;
if (sscanf(buf, "%u", &value) != 1)
return -EINVAL;
mutex_lock(&tracer.mutex);
ret = value ? trace_start(&tracer) : trace_stop(&tracer);
mutex_unlock(&tracer.mutex);
return ret ? : n;
}
static struct kobj_attribute trace_running_attr =
__ATTR(trace_running, 0644, trace_running_show, trace_running_store);
static ssize_t trace_info_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
{
u32 etb_wa, etb_ra, etb_st, etb_fc, etm_ctrl, etm_st;
int datalen;
etb_unlock(&tracer);
datalen = etb_getdatalen(&tracer);
etb_wa = etb_readl(&tracer, ETBR_WRITEADDR);
etb_ra = etb_readl(&tracer, ETBR_READADDR);
etb_st = etb_readl(&tracer, ETBR_STATUS);
etb_fc = etb_readl(&tracer, ETBR_FORMATTERCTRL);
etb_lock(&tracer);
etm_unlock(&tracer);
etm_ctrl = etm_readl(&tracer, ETMR_CTRL);
etm_st = etm_readl(&tracer, ETMR_STATUS);
etm_lock(&tracer);
return sprintf(buf, "Trace buffer len: %d\nComparator pairs: %d\n"
"ETBR_WRITEADDR:\t%08x\n"
"ETBR_READADDR:\t%08x\n"
"ETBR_STATUS:\t%08x\n"
"ETBR_FORMATTERCTRL:\t%08x\n"
"ETMR_CTRL:\t%08x\n"
"ETMR_STATUS:\t%08x\n",
datalen,
tracer.ncmppairs,
etb_wa,
etb_ra,
etb_st,
etb_fc,
etm_ctrl,
etm_st
);
}
static struct kobj_attribute trace_info_attr =
__ATTR(trace_info, 0444, trace_info_show, NULL);
static ssize_t trace_mode_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
{
return sprintf(buf, "%d %d\n",
!!(tracer.flags & TRACER_CYCLE_ACC),
tracer.etm_portsz);
}
static ssize_t trace_mode_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t n)
{
unsigned int cycacc, portsz;
if (sscanf(buf, "%u %u", &cycacc, &portsz) != 2)
return -EINVAL;
mutex_lock(&tracer.mutex);
if (cycacc)
tracer.flags |= TRACER_CYCLE_ACC;
else
tracer.flags &= ~TRACER_CYCLE_ACC;
tracer.etm_portsz = portsz & 0x0f;
mutex_unlock(&tracer.mutex);
return n;
}
static struct kobj_attribute trace_mode_attr =
__ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store);
static int etm_probe(struct amba_device *dev, const struct amba_id *id)
{
struct tracectx *t = &tracer;
int ret = 0;
if (t->etm_regs) {
dev_dbg(&dev->dev, "ETM already initialized\n");
ret = -EBUSY;
goto out;
}
ret = amba_request_regions(dev, NULL);
if (ret)
goto out;
t->etm_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res));
if (!t->etm_regs) {
ret = -ENOMEM;
goto out_release;
}
amba_set_drvdata(dev, t);
mutex_init(&t->mutex);
t->dev = &dev->dev;
t->flags = TRACER_CYCLE_ACC;
t->etm_portsz = 1;
etm_unlock(t);
(void)etm_readl(t, ETMMR_PDSR);
/* dummy first read */
(void)etm_readl(&tracer, ETMMR_OSSRR);
t->ncmppairs = etm_readl(t, ETMR_CONFCODE) & 0xf;
etm_writel(t, 0x440, ETMR_CTRL);
etm_lock(t);
ret = sysfs_create_file(&dev->dev.kobj,
&trace_running_attr.attr);
if (ret)
goto out_unmap;
/* failing to create any of these two is not fatal */
ret = sysfs_create_file(&dev->dev.kobj, &trace_info_attr.attr);
if (ret)
dev_dbg(&dev->dev, "Failed to create trace_info in sysfs\n");
ret = sysfs_create_file(&dev->dev.kobj, &trace_mode_attr.attr);
if (ret)
dev_dbg(&dev->dev, "Failed to create trace_mode in sysfs\n");
dev_dbg(t->dev, "ETM AMBA driver initialized.\n");
out:
return ret;
out_unmap:
iounmap(t->etm_regs);
out_release:
amba_release_regions(dev);
return ret;
}
static int etm_remove(struct amba_device *dev)
{
struct tracectx *t = amba_get_drvdata(dev);
iounmap(t->etm_regs);
t->etm_regs = NULL;
amba_release_regions(dev);
sysfs_remove_file(&dev->dev.kobj, &trace_running_attr.attr);
sysfs_remove_file(&dev->dev.kobj, &trace_info_attr.attr);
sysfs_remove_file(&dev->dev.kobj, &trace_mode_attr.attr);
return 0;
}
static struct amba_id etm_ids[] = {
{
.id = 0x0003b921,
.mask = 0x0007ffff,
},
{ 0, 0 },
};
static struct amba_driver etm_driver = {
.drv = {
.name = "etm",
.owner = THIS_MODULE,
},
.probe = etm_probe,
.remove = etm_remove,
.id_table = etm_ids,
};
static int __init etm_init(void)
{
int retval;
retval = amba_driver_register(&etb_driver);
if (retval) {
pr_err("Failed to register etb\n");
return retval;
}
retval = amba_driver_register(&etm_driver);
if (retval) {
amba_driver_unregister(&etb_driver);
pr_err("Failed to probe etm\n");
return retval;
}
/* not being able to install this handler is not fatal */
(void)register_sysrq_key('v', &sysrq_etm_op);
return 0;
}
device_initcall(etm_init);
......@@ -29,6 +29,7 @@
#include <linux/hw_breakpoint.h>
#include <linux/smp.h>
#include <linux/cpu_pm.h>
#include <linux/coresight.h>
#include <asm/cacheflush.h>
#include <asm/cputype.h>
......@@ -36,7 +37,6 @@
#include <asm/hw_breakpoint.h>
#include <asm/kdebug.h>
#include <asm/traps.h>
#include <asm/hardware/coresight.h>
/* Breakpoint currently in use for each BRP. */
static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]);
......@@ -976,7 +976,7 @@ static void reset_ctrl_regs(void *unused)
* Unconditionally clear the OS lock by writing a value
* other than CS_LAR_KEY to the access register.
*/
ARM_DBG_WRITE(c1, c0, 4, ~CS_LAR_KEY);
ARM_DBG_WRITE(c1, c0, 4, ~CORESIGHT_UNLOCK);
isb();
/*
......
......@@ -278,14 +278,6 @@ config MACH_SBC3530
default y
select OMAP_PACKAGE_CUS
config OMAP3_EMU
bool "OMAP3 debugging peripherals"
depends on ARCH_OMAP3
select ARM_AMBA
select OC_ETM
help
Say Y here to enable debugging hardware of omap3
config OMAP3_SDRC_AC_TIMING
bool "Enable SDRC AC timing register changes"
depends on ARCH_OMAP3
......
......@@ -228,7 +228,6 @@ obj-$(CONFIG_SOC_OMAP5) += omap_hwmod_54xx_data.o
obj-$(CONFIG_SOC_DRA7XX) += omap_hwmod_7xx_data.o
# EMU peripherals
obj-$(CONFIG_OMAP3_EMU) += emu.o
obj-$(CONFIG_HW_PERF_EVENTS) += pmu.o
iommu-$(CONFIG_OMAP_IOMMU) := omap-iommu.o
......
/*
* emu.c
*
* ETM and ETB CoreSight components' resources as found in OMAP3xxx.
*
* Copyright (C) 2009 Nokia Corporation.
* Alexander Shishkin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/amba/bus.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/err.h>
#include "soc.h"
#include "iomap.h"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alexander Shishkin");
/* Cortex CoreSight components within omap3xxx EMU */
#define ETM_BASE (L4_EMU_34XX_PHYS + 0x10000)
#define DBG_BASE (L4_EMU_34XX_PHYS + 0x11000)
#define ETB_BASE (L4_EMU_34XX_PHYS + 0x1b000)
#define DAPCTL (L4_EMU_34XX_PHYS + 0x1d000)
static AMBA_APB_DEVICE(omap3_etb, "etb", 0x000bb907, ETB_BASE, { }, NULL);
static AMBA_APB_DEVICE(omap3_etm, "etm", 0x102bb921, ETM_BASE, { }, NULL);
static int __init emu_init(void)
{
if (!cpu_is_omap34xx())
return -ENODEV;
amba_device_register(&omap3_etb_device, &iomem_resource);
amba_device_register(&omap3_etm_device, &iomem_resource);
return 0;
}
omap_subsys_initcall(emu_init);
......@@ -161,3 +161,4 @@ obj-$(CONFIG_POWERCAP) += powercap/
obj-$(CONFIG_MCB) += mcb/
obj-$(CONFIG_RAS) += ras/
obj-$(CONFIG_THUNDERBOLT) += thunderbolt/
obj-$(CONFIG_CORESIGHT) += coresight/
......@@ -343,7 +343,7 @@ int amba_device_add(struct amba_device *dev, struct resource *parent)
amba_put_disable_pclk(dev);
if (cid == AMBA_CID)
if (cid == AMBA_CID || cid == CORESIGHT_CID)
dev->periphid = pid;
if (!dev->periphid)
......
......@@ -168,8 +168,8 @@ static int __init hangcheck_init(void)
printk("Hangcheck: starting hangcheck timer %s (tick is %d seconds, margin is %d seconds).\n",
VERSION_STR, hangcheck_tick, hangcheck_margin);
hangcheck_tsc_margin =
(unsigned long long)(hangcheck_margin + hangcheck_tick);
hangcheck_tsc_margin *= (unsigned long long)TIMER_FREQ;
(unsigned long long)hangcheck_margin + hangcheck_tick;
hangcheck_tsc_margin *= TIMER_FREQ;
hangcheck_tsc = ktime_get_ns();
mod_timer(&hangcheck_ticktock, jiffies + (hangcheck_tick*HZ));
......
......@@ -298,7 +298,7 @@ static int i8k_get_temp(int sensor)
int temp;
#ifdef I8K_TEMPERATURE_BUG
static int prev[4];
static int prev[4] = { I8K_MAX_TEMP+1, I8K_MAX_TEMP+1, I8K_MAX_TEMP+1, I8K_MAX_TEMP+1 };
#endif
regs.ebx = sensor & 0xff;
rc = i8k_smm(&regs);
......@@ -317,10 +317,12 @@ static int i8k_get_temp(int sensor)
*/
if (temp > I8K_MAX_TEMP) {
temp = prev[sensor];
prev[sensor] = I8K_MAX_TEMP;
prev[sensor] = I8K_MAX_TEMP+1;
} else {
prev[sensor] = temp;
}
if (temp > I8K_MAX_TEMP)
return -ERANGE;
#endif
return temp;
......@@ -499,6 +501,8 @@ static ssize_t i8k_hwmon_show_temp(struct device *dev,
int temp;
temp = i8k_get_temp(index);
if (temp == -ERANGE)
return -EINVAL;
if (temp < 0)
return temp;
return sprintf(buf, "%d\n", temp * 1000);
......@@ -610,17 +614,17 @@ static int __init i8k_init_hwmon(void)
/* CPU temperature attributes, if temperature reading is OK */
err = i8k_get_temp(0);
if (err >= 0)
if (err >= 0 || err == -ERANGE)
i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP1;
/* check for additional temperature sensors */
err = i8k_get_temp(1);
if (err >= 0)
if (err >= 0 || err == -ERANGE)
i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP2;
err = i8k_get_temp(2);
if (err >= 0)
if (err >= 0 || err == -ERANGE)
i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP3;
err = i8k_get_temp(3);
if (err >= 0)
if (err >= 0 || err == -ERANGE)
i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4;
/* Left fan attributes, if left fan is present */
......@@ -710,6 +714,14 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = {
},
.driver_data = (void *)&i8k_config_data[DELL_LATITUDE_D520],
},
{
.ident = "Dell Latitude E6440",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6440"),
},
.driver_data = (void *)&i8k_config_data[DELL_LATITUDE_E6540],
},
{
.ident = "Dell Latitude E6540",
.matches = {
......@@ -788,6 +800,8 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = {
{ }
};
MODULE_DEVICE_TABLE(dmi, i8k_dmi_table);
/*
* Probe for the presence of a supported laptop.
*/
......
......@@ -141,12 +141,18 @@ EXPORT_SYMBOL_GPL(cn_netlink_send);
*/
static int cn_call_callback(struct sk_buff *skb)
{
struct nlmsghdr *nlh;
struct cn_callback_entry *i, *cbq = NULL;
struct cn_dev *dev = &cdev;
struct cn_msg *msg = nlmsg_data(nlmsg_hdr(skb));
struct netlink_skb_parms *nsp = &NETLINK_CB(skb);
int err = -ENODEV;
/* verify msg->len is within skb */
nlh = nlmsg_hdr(skb);
if (nlh->nlmsg_len < NLMSG_HDRLEN + sizeof(struct cn_msg) + msg->len)
return -EINVAL;
spin_lock_bh(&dev->cbdev->queue_lock);
list_for_each_entry(i, &dev->cbdev->queue_list, callback_entry) {
if (cn_cb_equal(&i->id.id, &msg->id)) {
......
#
# Makefile for CoreSight drivers.
#
obj-$(CONFIG_CORESIGHT) += coresight.o
obj-$(CONFIG_OF) += of_coresight.o
obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o
obj-$(CONFIG_CORESIGHT_SINK_TPIU) += coresight-tpiu.o
obj-$(CONFIG_CORESIGHT_SINK_ETBV10) += coresight-etb10.o
obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-funnel.o \
coresight-replicator.o
obj-$(CONFIG_CORESIGHT_SOURCE_ETM3X) += coresight-etm3x.o coresight-etm-cp14.o
/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/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/spinlock.h>
#include <linux/clk.h>
#include <linux/seq_file.h>
#include <linux/coresight.h>
#include <linux/amba/bus.h>
#include "coresight-priv.h"
#define ETB_RAM_DEPTH_REG 0x004
#define ETB_STATUS_REG 0x00c
#define ETB_RAM_READ_DATA_REG 0x010
#define ETB_RAM_READ_POINTER 0x014
#define ETB_RAM_WRITE_POINTER 0x018
#define ETB_TRG 0x01c
#define ETB_CTL_REG 0x020
#define ETB_RWD_REG 0x024
#define ETB_FFSR 0x300
#define ETB_FFCR 0x304
#define ETB_ITMISCOP0 0xee0
#define ETB_ITTRFLINACK 0xee4
#define ETB_ITTRFLIN 0xee8
#define ETB_ITATBDATA0 0xeeC
#define ETB_ITATBCTR2 0xef0
#define ETB_ITATBCTR1 0xef4
#define ETB_ITATBCTR0 0xef8
/* register description */
/* STS - 0x00C */
#define ETB_STATUS_RAM_FULL BIT(0)
/* CTL - 0x020 */
#define ETB_CTL_CAPT_EN BIT(0)
/* FFCR - 0x304 */
#define ETB_FFCR_EN_FTC BIT(0)
#define ETB_FFCR_FON_MAN BIT(6)
#define ETB_FFCR_STOP_FI BIT(12)
#define ETB_FFCR_STOP_TRIGGER BIT(13)
#define ETB_FFCR_BIT 6
#define ETB_FFSR_BIT 1
#define ETB_FRAME_SIZE_WORDS 4
/**
* struct etb_drvdata - specifics associated to an ETB component
* @base: memory mapped base address for this component.
* @dev: the device entity associated to this component.
* @csdev: component vitals needed by the framework.
* @miscdev: specifics to handle "/dev/xyz.etb" entry.
* @clk: the clock this component is associated to.
* @spinlock: only one at a time pls.
* @in_use: synchronise user space access to etb buffer.
* @buf: area of memory where ETB buffer content gets sent.
* @buffer_depth: size of @buf.
* @enable: this ETB is being used.
* @trigger_cntr: amount of words to store after a trigger.
*/
struct etb_drvdata {
void __iomem *base;
struct device *dev;
struct coresight_device *csdev;
struct miscdevice miscdev;
struct clk *clk;
spinlock_t spinlock;
atomic_t in_use;
u8 *buf;
u32 buffer_depth;
bool enable;
u32 trigger_cntr;
};
static unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
{
int ret;
u32 depth = 0;
ret = clk_prepare_enable(drvdata->clk);
if (ret)
return ret;
/* RO registers don't need locking */
depth = readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG);
clk_disable_unprepare(drvdata->clk);
return depth;
}
static void etb_enable_hw(struct etb_drvdata *drvdata)
{
int i;
u32 depth;
CS_UNLOCK(drvdata->base);
depth = drvdata->buffer_depth;
/* reset write RAM pointer address */
writel_relaxed(0x0, drvdata->base + ETB_RAM_WRITE_POINTER);
/* clear entire RAM buffer */
for (i = 0; i < depth; i++)
writel_relaxed(0x0, drvdata->base + ETB_RWD_REG);
/* reset write RAM pointer address */
writel_relaxed(0x0, drvdata->base + ETB_RAM_WRITE_POINTER);
/* reset read RAM pointer address */
writel_relaxed(0x0, drvdata->base + ETB_RAM_READ_POINTER);
writel_relaxed(drvdata->trigger_cntr, drvdata->base + ETB_TRG);
writel_relaxed(ETB_FFCR_EN_FTC | ETB_FFCR_STOP_TRIGGER,
drvdata->base + ETB_FFCR);
/* ETB trace capture enable */
writel_relaxed(ETB_CTL_CAPT_EN, drvdata->base + ETB_CTL_REG);
CS_LOCK(drvdata->base);
}
static int etb_enable(struct coresight_device *csdev)
{
struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
int ret;
unsigned long flags;
ret = clk_prepare_enable(drvdata->clk);
if (ret)
return ret;
spin_lock_irqsave(&drvdata->spinlock, flags);
etb_enable_hw(drvdata);
drvdata->enable = true;
spin_unlock_irqrestore(&drvdata->spinlock, flags);
dev_info(drvdata->dev, "ETB enabled\n");
return 0;
}
static void etb_disable_hw(struct etb_drvdata *drvdata)
{
u32 ffcr;
CS_UNLOCK(drvdata->base);
ffcr = readl_relaxed(drvdata->base + ETB_FFCR);
/* stop formatter when a stop has completed */
ffcr |= ETB_FFCR_STOP_FI;
writel_relaxed(ffcr, drvdata->base + ETB_FFCR);
/* manually generate a flush of the system */
ffcr |= ETB_FFCR_FON_MAN;
writel_relaxed(ffcr, drvdata->base + ETB_FFCR);
if (coresight_timeout(drvdata->base, ETB_FFCR, ETB_FFCR_BIT, 0)) {
dev_err(drvdata->dev,
"timeout observed when probing at offset %#x\n",
ETB_FFCR);
}
/* disable trace capture */
writel_relaxed(0x0, drvdata->base + ETB_CTL_REG);
if (coresight_timeout(drvdata->base, ETB_FFSR, ETB_FFSR_BIT, 1)) {
dev_err(drvdata->dev,
"timeout observed when probing at offset %#x\n",
ETB_FFCR);
}
CS_LOCK(drvdata->base);
}
static void etb_dump_hw(struct etb_drvdata *drvdata)
{
int i;
u8 *buf_ptr;
u32 read_data, depth;
u32 read_ptr, write_ptr;
u32 frame_off, frame_endoff;
CS_UNLOCK(drvdata->base);
read_ptr = readl_relaxed(drvdata->base + ETB_RAM_READ_POINTER);
write_ptr = readl_relaxed(drvdata->base + ETB_RAM_WRITE_POINTER);
frame_off = write_ptr % ETB_FRAME_SIZE_WORDS;
frame_endoff = ETB_FRAME_SIZE_WORDS - frame_off;
if (frame_off) {
dev_err(drvdata->dev,
"write_ptr: %lu not aligned to formatter frame size\n",
(unsigned long)write_ptr);
dev_err(drvdata->dev, "frameoff: %lu, frame_endoff: %lu\n",
(unsigned long)frame_off, (unsigned long)frame_endoff);
write_ptr += frame_endoff;
}
if ((readl_relaxed(drvdata->base + ETB_STATUS_REG)
& ETB_STATUS_RAM_FULL) == 0)
writel_relaxed(0x0, drvdata->base + ETB_RAM_READ_POINTER);
else
writel_relaxed(write_ptr, drvdata->base + ETB_RAM_READ_POINTER);
depth = drvdata->buffer_depth;
buf_ptr = drvdata->buf;
for (i = 0; i < depth; i++) {
read_data = readl_relaxed(drvdata->base +
ETB_RAM_READ_DATA_REG);
*buf_ptr++ = read_data >> 0;
*buf_ptr++ = read_data >> 8;
*buf_ptr++ = read_data >> 16;
*buf_ptr++ = read_data >> 24;
}
if (frame_off) {
buf_ptr -= (frame_endoff * 4);
for (i = 0; i < frame_endoff; i++) {
*buf_ptr++ = 0x0;
*buf_ptr++ = 0x0;
*buf_ptr++ = 0x0;
*buf_ptr++ = 0x0;
}
}
writel_relaxed(read_ptr, drvdata->base + ETB_RAM_READ_POINTER);
CS_LOCK(drvdata->base);
}
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_hw(drvdata);
etb_dump_hw(drvdata);
drvdata->enable = false;
spin_unlock_irqrestore(&drvdata->spinlock, flags);
clk_disable_unprepare(drvdata->clk);
dev_info(drvdata->dev, "ETB disabled\n");
}
static const struct coresight_ops_sink etb_sink_ops = {
.enable = etb_enable,
.disable = etb_disable,
};
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->enable) {
etb_disable_hw(drvdata);
etb_dump_hw(drvdata);
etb_enable_hw(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;
dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
return 0;
}
static ssize_t etb_read(struct file *file, char __user *data,
size_t len, loff_t *ppos)
{
u32 depth;
struct etb_drvdata *drvdata = container_of(file->private_data,
struct etb_drvdata, miscdev);
etb_dump(drvdata);
depth = drvdata->buffer_depth;
if (*ppos + len > depth * 4)
len = depth * 4 - *ppos;
if (copy_to_user(data, drvdata->buf + *ppos, 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) (depth * 4 - *ppos));
return len;
}
static int etb_release(struct inode *inode, struct file *file)
{
struct etb_drvdata *drvdata = container_of(file->private_data,
struct etb_drvdata, miscdev);
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,
.llseek = no_llseek,
};
static ssize_t status_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
unsigned long flags;
u32 etb_rdr, etb_sr, etb_rrp, etb_rwp;
u32 etb_trg, etb_cr, etb_ffsr, etb_ffcr;
struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
ret = clk_prepare_enable(drvdata->clk);
if (ret)
goto out;
spin_lock_irqsave(&drvdata->spinlock, flags);
CS_UNLOCK(drvdata->base);
etb_rdr = readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG);
etb_sr = readl_relaxed(drvdata->base + ETB_STATUS_REG);
etb_rrp = readl_relaxed(drvdata->base + ETB_RAM_READ_POINTER);
etb_rwp = readl_relaxed(drvdata->base + ETB_RAM_WRITE_POINTER);
etb_trg = readl_relaxed(drvdata->base + ETB_TRG);
etb_cr = readl_relaxed(drvdata->base + ETB_CTL_REG);
etb_ffsr = readl_relaxed(drvdata->base + ETB_FFSR);
etb_ffcr = readl_relaxed(drvdata->base + ETB_FFCR);
CS_LOCK(drvdata->base);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
clk_disable_unprepare(drvdata->clk);
return sprintf(buf,
"Depth:\t\t0x%x\n"
"Status:\t\t0x%x\n"
"RAM read ptr:\t0x%x\n"
"RAM wrt ptr:\t0x%x\n"
"Trigger cnt:\t0x%x\n"
"Control:\t0x%x\n"
"Flush status:\t0x%x\n"
"Flush ctrl:\t0x%x\n",
etb_rdr, etb_sr, etb_rrp, etb_rwp,
etb_trg, etb_cr, etb_ffsr, etb_ffcr);
out:
return -EINVAL;
}
static DEVICE_ATTR_RO(status);
static ssize_t trigger_cntr_show(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 sprintf(buf, "%#lx\n", val);
}
static ssize_t trigger_cntr_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
int ret;
unsigned long val;
struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
ret = kstrtoul(buf, 16, &val);
if (ret)
return ret;
drvdata->trigger_cntr = val;
return size;
}
static DEVICE_ATTR_RW(trigger_cntr);
static struct attribute *coresight_etb_attrs[] = {
&dev_attr_trigger_cntr.attr,
&dev_attr_status.attr,
NULL,
};
ATTRIBUTE_GROUPS(coresight_etb);
static int etb_probe(struct amba_device *adev, const struct amba_id *id)
{
int ret;
void __iomem *base;
struct device *dev = &adev->dev;
struct coresight_platform_data *pdata = NULL;
struct etb_drvdata *drvdata;
struct resource *res = &adev->res;
struct coresight_desc *desc;
struct device_node *np = adev->dev.of_node;
if (np) {
pdata = of_get_coresight_platform_data(dev, np);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
adev->dev.platform_data = pdata;
}
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
drvdata->dev = &adev->dev;
dev_set_drvdata(dev, drvdata);
/* validity for the resource is already checked by the AMBA core */
base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
drvdata->base = base;
spin_lock_init(&drvdata->spinlock);
drvdata->clk = adev->pclk;
ret = clk_prepare_enable(drvdata->clk);
if (ret)
return ret;
drvdata->buffer_depth = etb_get_buffer_depth(drvdata);
clk_disable_unprepare(drvdata->clk);
if (drvdata->buffer_depth < 0)
return -EINVAL;
drvdata->buf = devm_kzalloc(dev,
drvdata->buffer_depth * 4, 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 = pdata;
desc->dev = dev;
desc->groups = coresight_etb_groups;
drvdata->csdev = coresight_register(desc);
if (IS_ERR(drvdata->csdev))
return PTR_ERR(drvdata->csdev);
drvdata->miscdev.name = pdata->name;
drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
drvdata->miscdev.fops = &etb_fops;
ret = misc_register(&drvdata->miscdev);
if (ret)
goto err_misc_register;
dev_info(dev, "ETB initialized\n");
return 0;
err_misc_register:
coresight_unregister(drvdata->csdev);
return ret;
}
static int etb_remove(struct amba_device *adev)
{
struct etb_drvdata *drvdata = amba_get_drvdata(adev);
misc_deregister(&drvdata->miscdev);
coresight_unregister(drvdata->csdev);
return 0;
}
static struct amba_id etb_ids[] = {
{
.id = 0x0003b907,
.mask = 0x0003ffff,
},
{ 0, 0},
};
static struct amba_driver etb_driver = {
.drv = {
.name = "coresight-etb10",
.owner = THIS_MODULE,
},
.probe = etb_probe,
.remove = etb_remove,
.id_table = etb_ids,
};
static int __init etb_init(void)
{
return amba_driver_register(&etb_driver);
}
module_init(etb_init);
static void __exit etb_exit(void)
{
amba_driver_unregister(&etb_driver);
}
module_exit(etb_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("CoreSight Embedded Trace Buffer driver");
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/bug.h>
#include <asm/hardware/cp14.h>
#include "coresight-etm.h"
int etm_readl_cp14(u32 reg, unsigned int *val)
{
switch (reg) {
case ETMCR:
*val = etm_read(ETMCR);
return 0;
case ETMCCR:
*val = etm_read(ETMCCR);
return 0;
case ETMTRIGGER:
*val = etm_read(ETMTRIGGER);
return 0;
case ETMSR:
*val = etm_read(ETMSR);
return 0;
case ETMSCR:
*val = etm_read(ETMSCR);
return 0;
case ETMTSSCR:
*val = etm_read(ETMTSSCR);
return 0;
case ETMTEEVR:
*val = etm_read(ETMTEEVR);
return 0;
case ETMTECR1:
*val = etm_read(ETMTECR1);
return 0;
case ETMFFLR:
*val = etm_read(ETMFFLR);
return 0;
case ETMACVRn(0):
*val = etm_read(ETMACVR0);
return 0;
case ETMACVRn(1):
*val = etm_read(ETMACVR1);
return 0;
case ETMACVRn(2):
*val = etm_read(ETMACVR2);
return 0;
case ETMACVRn(3):
*val = etm_read(ETMACVR3);
return 0;
case ETMACVRn(4):
*val = etm_read(ETMACVR4);
return 0;
case ETMACVRn(5):
*val = etm_read(ETMACVR5);
return 0;
case ETMACVRn(6):
*val = etm_read(ETMACVR6);
return 0;
case ETMACVRn(7):
*val = etm_read(ETMACVR7);
return 0;
case ETMACVRn(8):
*val = etm_read(ETMACVR8);
return 0;
case ETMACVRn(9):
*val = etm_read(ETMACVR9);
return 0;
case ETMACVRn(10):
*val = etm_read(ETMACVR10);
return 0;
case ETMACVRn(11):
*val = etm_read(ETMACVR11);
return 0;
case ETMACVRn(12):
*val = etm_read(ETMACVR12);
return 0;
case ETMACVRn(13):
*val = etm_read(ETMACVR13);
return 0;
case ETMACVRn(14):
*val = etm_read(ETMACVR14);
return 0;
case ETMACVRn(15):
*val = etm_read(ETMACVR15);
return 0;
case ETMACTRn(0):
*val = etm_read(ETMACTR0);
return 0;
case ETMACTRn(1):
*val = etm_read(ETMACTR1);
return 0;
case ETMACTRn(2):
*val = etm_read(ETMACTR2);
return 0;
case ETMACTRn(3):
*val = etm_read(ETMACTR3);
return 0;
case ETMACTRn(4):
*val = etm_read(ETMACTR4);
return 0;
case ETMACTRn(5):
*val = etm_read(ETMACTR5);
return 0;
case ETMACTRn(6):
*val = etm_read(ETMACTR6);
return 0;
case ETMACTRn(7):
*val = etm_read(ETMACTR7);
return 0;
case ETMACTRn(8):
*val = etm_read(ETMACTR8);
return 0;
case ETMACTRn(9):
*val = etm_read(ETMACTR9);
return 0;
case ETMACTRn(10):
*val = etm_read(ETMACTR10);
return 0;
case ETMACTRn(11):
*val = etm_read(ETMACTR11);
return 0;
case ETMACTRn(12):
*val = etm_read(ETMACTR12);
return 0;
case ETMACTRn(13):
*val = etm_read(ETMACTR13);
return 0;
case ETMACTRn(14):
*val = etm_read(ETMACTR14);
return 0;
case ETMACTRn(15):
*val = etm_read(ETMACTR15);
return 0;
case ETMCNTRLDVRn(0):
*val = etm_read(ETMCNTRLDVR0);
return 0;
case ETMCNTRLDVRn(1):
*val = etm_read(ETMCNTRLDVR1);
return 0;
case ETMCNTRLDVRn(2):
*val = etm_read(ETMCNTRLDVR2);
return 0;
case ETMCNTRLDVRn(3):
*val = etm_read(ETMCNTRLDVR3);
return 0;
case ETMCNTENRn(0):
*val = etm_read(ETMCNTENR0);
return 0;
case ETMCNTENRn(1):
*val = etm_read(ETMCNTENR1);
return 0;
case ETMCNTENRn(2):
*val = etm_read(ETMCNTENR2);
return 0;
case ETMCNTENRn(3):
*val = etm_read(ETMCNTENR3);
return 0;
case ETMCNTRLDEVRn(0):
*val = etm_read(ETMCNTRLDEVR0);
return 0;
case ETMCNTRLDEVRn(1):
*val = etm_read(ETMCNTRLDEVR1);
return 0;
case ETMCNTRLDEVRn(2):
*val = etm_read(ETMCNTRLDEVR2);
return 0;
case ETMCNTRLDEVRn(3):
*val = etm_read(ETMCNTRLDEVR3);
return 0;
case ETMCNTVRn(0):
*val = etm_read(ETMCNTVR0);
return 0;
case ETMCNTVRn(1):
*val = etm_read(ETMCNTVR1);
return 0;
case ETMCNTVRn(2):
*val = etm_read(ETMCNTVR2);
return 0;
case ETMCNTVRn(3):
*val = etm_read(ETMCNTVR3);
return 0;
case ETMSQ12EVR:
*val = etm_read(ETMSQ12EVR);
return 0;
case ETMSQ21EVR:
*val = etm_read(ETMSQ21EVR);
return 0;
case ETMSQ23EVR:
*val = etm_read(ETMSQ23EVR);
return 0;
case ETMSQ31EVR:
*val = etm_read(ETMSQ31EVR);
return 0;
case ETMSQ32EVR:
*val = etm_read(ETMSQ32EVR);
return 0;
case ETMSQ13EVR:
*val = etm_read(ETMSQ13EVR);
return 0;
case ETMSQR:
*val = etm_read(ETMSQR);
return 0;
case ETMEXTOUTEVRn(0):
*val = etm_read(ETMEXTOUTEVR0);
return 0;
case ETMEXTOUTEVRn(1):
*val = etm_read(ETMEXTOUTEVR1);
return 0;
case ETMEXTOUTEVRn(2):
*val = etm_read(ETMEXTOUTEVR2);
return 0;
case ETMEXTOUTEVRn(3):
*val = etm_read(ETMEXTOUTEVR3);
return 0;
case ETMCIDCVRn(0):
*val = etm_read(ETMCIDCVR0);
return 0;
case ETMCIDCVRn(1):
*val = etm_read(ETMCIDCVR1);
return 0;
case ETMCIDCVRn(2):
*val = etm_read(ETMCIDCVR2);
return 0;
case ETMCIDCMR:
*val = etm_read(ETMCIDCMR);
return 0;
case ETMIMPSPEC0:
*val = etm_read(ETMIMPSPEC0);
return 0;
case ETMIMPSPEC1:
*val = etm_read(ETMIMPSPEC1);
return 0;
case ETMIMPSPEC2:
*val = etm_read(ETMIMPSPEC2);
return 0;
case ETMIMPSPEC3:
*val = etm_read(ETMIMPSPEC3);
return 0;
case ETMIMPSPEC4:
*val = etm_read(ETMIMPSPEC4);
return 0;
case ETMIMPSPEC5:
*val = etm_read(ETMIMPSPEC5);
return 0;
case ETMIMPSPEC6:
*val = etm_read(ETMIMPSPEC6);
return 0;
case ETMIMPSPEC7:
*val = etm_read(ETMIMPSPEC7);
return 0;
case ETMSYNCFR:
*val = etm_read(ETMSYNCFR);
return 0;
case ETMIDR:
*val = etm_read(ETMIDR);
return 0;
case ETMCCER:
*val = etm_read(ETMCCER);
return 0;
case ETMEXTINSELR:
*val = etm_read(ETMEXTINSELR);
return 0;
case ETMTESSEICR:
*val = etm_read(ETMTESSEICR);
return 0;
case ETMEIBCR:
*val = etm_read(ETMEIBCR);
return 0;
case ETMTSEVR:
*val = etm_read(ETMTSEVR);
return 0;
case ETMAUXCR:
*val = etm_read(ETMAUXCR);
return 0;
case ETMTRACEIDR:
*val = etm_read(ETMTRACEIDR);
return 0;
case ETMVMIDCVR:
*val = etm_read(ETMVMIDCVR);
return 0;
case ETMOSLSR:
*val = etm_read(ETMOSLSR);
return 0;
case ETMOSSRR:
*val = etm_read(ETMOSSRR);
return 0;
case ETMPDCR:
*val = etm_read(ETMPDCR);
return 0;
case ETMPDSR:
*val = etm_read(ETMPDSR);
return 0;
default:
*val = 0;
return -EINVAL;
}
}
int etm_writel_cp14(u32 reg, u32 val)
{
switch (reg) {
case ETMCR:
etm_write(val, ETMCR);
break;
case ETMTRIGGER:
etm_write(val, ETMTRIGGER);
break;
case ETMSR:
etm_write(val, ETMSR);
break;
case ETMTSSCR:
etm_write(val, ETMTSSCR);
break;
case ETMTEEVR:
etm_write(val, ETMTEEVR);
break;
case ETMTECR1:
etm_write(val, ETMTECR1);
break;
case ETMFFLR:
etm_write(val, ETMFFLR);
break;
case ETMACVRn(0):
etm_write(val, ETMACVR0);
break;
case ETMACVRn(1):
etm_write(val, ETMACVR1);
break;
case ETMACVRn(2):
etm_write(val, ETMACVR2);
break;
case ETMACVRn(3):
etm_write(val, ETMACVR3);
break;
case ETMACVRn(4):
etm_write(val, ETMACVR4);
break;
case ETMACVRn(5):
etm_write(val, ETMACVR5);
break;
case ETMACVRn(6):
etm_write(val, ETMACVR6);
break;
case ETMACVRn(7):
etm_write(val, ETMACVR7);
break;
case ETMACVRn(8):
etm_write(val, ETMACVR8);
break;
case ETMACVRn(9):
etm_write(val, ETMACVR9);
break;
case ETMACVRn(10):
etm_write(val, ETMACVR10);
break;
case ETMACVRn(11):
etm_write(val, ETMACVR11);
break;
case ETMACVRn(12):
etm_write(val, ETMACVR12);
break;
case ETMACVRn(13):
etm_write(val, ETMACVR13);
break;
case ETMACVRn(14):
etm_write(val, ETMACVR14);
break;
case ETMACVRn(15):
etm_write(val, ETMACVR15);
break;
case ETMACTRn(0):
etm_write(val, ETMACTR0);
break;
case ETMACTRn(1):
etm_write(val, ETMACTR1);
break;
case ETMACTRn(2):
etm_write(val, ETMACTR2);
break;
case ETMACTRn(3):
etm_write(val, ETMACTR3);
break;
case ETMACTRn(4):
etm_write(val, ETMACTR4);
break;
case ETMACTRn(5):
etm_write(val, ETMACTR5);
break;
case ETMACTRn(6):
etm_write(val, ETMACTR6);
break;
case ETMACTRn(7):
etm_write(val, ETMACTR7);
break;
case ETMACTRn(8):
etm_write(val, ETMACTR8);
break;
case ETMACTRn(9):
etm_write(val, ETMACTR9);
break;
case ETMACTRn(10):
etm_write(val, ETMACTR10);
break;
case ETMACTRn(11):
etm_write(val, ETMACTR11);
break;
case ETMACTRn(12):
etm_write(val, ETMACTR12);
break;
case ETMACTRn(13):
etm_write(val, ETMACTR13);
break;
case ETMACTRn(14):
etm_write(val, ETMACTR14);
break;
case ETMACTRn(15):
etm_write(val, ETMACTR15);
break;
case ETMCNTRLDVRn(0):
etm_write(val, ETMCNTRLDVR0);
break;
case ETMCNTRLDVRn(1):
etm_write(val, ETMCNTRLDVR1);
break;
case ETMCNTRLDVRn(2):
etm_write(val, ETMCNTRLDVR2);
break;
case ETMCNTRLDVRn(3):
etm_write(val, ETMCNTRLDVR3);
break;
case ETMCNTENRn(0):
etm_write(val, ETMCNTENR0);
break;
case ETMCNTENRn(1):
etm_write(val, ETMCNTENR1);
break;
case ETMCNTENRn(2):
etm_write(val, ETMCNTENR2);
break;
case ETMCNTENRn(3):
etm_write(val, ETMCNTENR3);
break;
case ETMCNTRLDEVRn(0):
etm_write(val, ETMCNTRLDEVR0);
break;
case ETMCNTRLDEVRn(1):
etm_write(val, ETMCNTRLDEVR1);
break;
case ETMCNTRLDEVRn(2):
etm_write(val, ETMCNTRLDEVR2);
break;
case ETMCNTRLDEVRn(3):
etm_write(val, ETMCNTRLDEVR3);
break;
case ETMCNTVRn(0):
etm_write(val, ETMCNTVR0);
break;
case ETMCNTVRn(1):
etm_write(val, ETMCNTVR1);
break;
case ETMCNTVRn(2):
etm_write(val, ETMCNTVR2);
break;
case ETMCNTVRn(3):
etm_write(val, ETMCNTVR3);
break;
case ETMSQ12EVR:
etm_write(val, ETMSQ12EVR);
break;
case ETMSQ21EVR:
etm_write(val, ETMSQ21EVR);
break;
case ETMSQ23EVR:
etm_write(val, ETMSQ23EVR);
break;
case ETMSQ31EVR:
etm_write(val, ETMSQ31EVR);
break;
case ETMSQ32EVR:
etm_write(val, ETMSQ32EVR);
break;
case ETMSQ13EVR:
etm_write(val, ETMSQ13EVR);
break;
case ETMSQR:
etm_write(val, ETMSQR);
break;
case ETMEXTOUTEVRn(0):
etm_write(val, ETMEXTOUTEVR0);
break;
case ETMEXTOUTEVRn(1):
etm_write(val, ETMEXTOUTEVR1);
break;
case ETMEXTOUTEVRn(2):
etm_write(val, ETMEXTOUTEVR2);
break;
case ETMEXTOUTEVRn(3):
etm_write(val, ETMEXTOUTEVR3);
break;
case ETMCIDCVRn(0):
etm_write(val, ETMCIDCVR0);
break;
case ETMCIDCVRn(1):
etm_write(val, ETMCIDCVR1);
break;
case ETMCIDCVRn(2):
etm_write(val, ETMCIDCVR2);
break;
case ETMCIDCMR:
etm_write(val, ETMCIDCMR);
break;
case ETMIMPSPEC0:
etm_write(val, ETMIMPSPEC0);
break;
case ETMIMPSPEC1:
etm_write(val, ETMIMPSPEC1);
break;
case ETMIMPSPEC2:
etm_write(val, ETMIMPSPEC2);
break;
case ETMIMPSPEC3:
etm_write(val, ETMIMPSPEC3);
break;
case ETMIMPSPEC4:
etm_write(val, ETMIMPSPEC4);
break;
case ETMIMPSPEC5:
etm_write(val, ETMIMPSPEC5);
break;
case ETMIMPSPEC6:
etm_write(val, ETMIMPSPEC6);
break;
case ETMIMPSPEC7:
etm_write(val, ETMIMPSPEC7);
break;
case ETMSYNCFR:
etm_write(val, ETMSYNCFR);
break;
case ETMEXTINSELR:
etm_write(val, ETMEXTINSELR);
break;
case ETMTESSEICR:
etm_write(val, ETMTESSEICR);
break;
case ETMEIBCR:
etm_write(val, ETMEIBCR);
break;
case ETMTSEVR:
etm_write(val, ETMTSEVR);
break;
case ETMAUXCR:
etm_write(val, ETMAUXCR);
break;
case ETMTRACEIDR:
etm_write(val, ETMTRACEIDR);
break;
case ETMVMIDCVR:
etm_write(val, ETMVMIDCVR);
break;
case ETMOSLAR:
etm_write(val, ETMOSLAR);
break;
case ETMOSSRR:
etm_write(val, ETMOSSRR);
break;
case ETMPDCR:
etm_write(val, ETMPDCR);
break;
case ETMPDSR:
etm_write(val, ETMPDSR);
break;
default:
return -EINVAL;
}
return 0;
}
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _CORESIGHT_CORESIGHT_ETM_H
#define _CORESIGHT_CORESIGHT_ETM_H
#include <linux/spinlock.h>
#include "coresight-priv.h"
/*
* Device registers:
* 0x000 - 0x2FC: Trace registers
* 0x300 - 0x314: Management registers
* 0x318 - 0xEFC: Trace registers
*
* Coresight registers
* 0xF00 - 0xF9C: Management registers
* 0xFA0 - 0xFA4: Management registers in PFTv1.0
* Trace registers in PFTv1.1
* 0xFA8 - 0xFFC: Management registers
*/
/* Trace registers (0x000-0x2FC) */
#define ETMCR 0x000
#define ETMCCR 0x004
#define ETMTRIGGER 0x008
#define ETMSR 0x010
#define ETMSCR 0x014
#define ETMTSSCR 0x018
#define ETMTECR2 0x01c
#define ETMTEEVR 0x020
#define ETMTECR1 0x024
#define ETMFFLR 0x02c
#define ETMACVRn(n) (0x040 + (n * 4))
#define ETMACTRn(n) (0x080 + (n * 4))
#define ETMCNTRLDVRn(n) (0x140 + (n * 4))
#define ETMCNTENRn(n) (0x150 + (n * 4))
#define ETMCNTRLDEVRn(n) (0x160 + (n * 4))
#define ETMCNTVRn(n) (0x170 + (n * 4))
#define ETMSQ12EVR 0x180
#define ETMSQ21EVR 0x184
#define ETMSQ23EVR 0x188
#define ETMSQ31EVR 0x18c
#define ETMSQ32EVR 0x190
#define ETMSQ13EVR 0x194
#define ETMSQR 0x19c
#define ETMEXTOUTEVRn(n) (0x1a0 + (n * 4))
#define ETMCIDCVRn(n) (0x1b0 + (n * 4))
#define ETMCIDCMR 0x1bc
#define ETMIMPSPEC0 0x1c0
#define ETMIMPSPEC1 0x1c4
#define ETMIMPSPEC2 0x1c8
#define ETMIMPSPEC3 0x1cc
#define ETMIMPSPEC4 0x1d0
#define ETMIMPSPEC5 0x1d4
#define ETMIMPSPEC6 0x1d8
#define ETMIMPSPEC7 0x1dc
#define ETMSYNCFR 0x1e0
#define ETMIDR 0x1e4
#define ETMCCER 0x1e8
#define ETMEXTINSELR 0x1ec
#define ETMTESSEICR 0x1f0
#define ETMEIBCR 0x1f4
#define ETMTSEVR 0x1f8
#define ETMAUXCR 0x1fc
#define ETMTRACEIDR 0x200
#define ETMVMIDCVR 0x240
/* Management registers (0x300-0x314) */
#define ETMOSLAR 0x300
#define ETMOSLSR 0x304
#define ETMOSSRR 0x308
#define ETMPDCR 0x310
#define ETMPDSR 0x314
#define ETM_MAX_ADDR_CMP 16
#define ETM_MAX_CNTR 4
#define ETM_MAX_CTXID_CMP 3
/* Register definition */
/* ETMCR - 0x00 */
#define ETMCR_PWD_DWN BIT(0)
#define ETMCR_STALL_MODE BIT(7)
#define ETMCR_ETM_PRG BIT(10)
#define ETMCR_ETM_EN BIT(11)
#define ETMCR_CYC_ACC BIT(12)
#define ETMCR_CTXID_SIZE (BIT(14)|BIT(15))
#define ETMCR_TIMESTAMP_EN BIT(28)
/* ETMCCR - 0x04 */
#define ETMCCR_FIFOFULL BIT(23)
/* ETMPDCR - 0x310 */
#define ETMPDCR_PWD_UP BIT(3)
/* ETMTECR1 - 0x024 */
#define ETMTECR1_ADDR_COMP_1 BIT(0)
#define ETMTECR1_INC_EXC BIT(24)
#define ETMTECR1_START_STOP BIT(25)
/* ETMCCER - 0x1E8 */
#define ETMCCER_TIMESTAMP BIT(22)
#define ETM_MODE_EXCLUDE BIT(0)
#define ETM_MODE_CYCACC BIT(1)
#define ETM_MODE_STALL BIT(2)
#define ETM_MODE_TIMESTAMP BIT(3)
#define ETM_MODE_CTXID BIT(4)
#define ETM_MODE_ALL 0x1f
#define ETM_SQR_MASK 0x3
#define ETM_TRACEID_MASK 0x3f
#define ETM_EVENT_MASK 0x1ffff
#define ETM_SYNC_MASK 0xfff
#define ETM_ALL_MASK 0xffffffff
#define ETMSR_PROG_BIT 1
#define ETM_SEQ_STATE_MAX_VAL (0x2)
#define PORT_SIZE_MASK (GENMASK(21, 21) | GENMASK(6, 4))
#define ETM_HARD_WIRE_RES_A /* Hard wired, always true */ \
((0x0f << 0) | \
/* Resource index A */ \
(0x06 << 4))
#define ETM_ADD_COMP_0 /* Single addr comparator 1 */ \
((0x00 << 7) | \
/* Resource index B */ \
(0x00 << 11))
#define ETM_EVENT_NOT_A BIT(14) /* NOT(A) */
#define ETM_DEFAULT_EVENT_VAL (ETM_HARD_WIRE_RES_A | \
ETM_ADD_COMP_0 | \
ETM_EVENT_NOT_A)
/**
* struct etm_drvdata - specifics associated to an ETM component
* @base: memory mapped base address for this component.
* @dev: the device entity associated to this component.
* @csdev: component vitals needed by the framework.
* @clk: the clock this component is associated to.
* @spinlock: only one at a time pls.
* @cpu: the cpu this component is affined to.
* @port_size: port size as reported by ETMCR bit 4-6 and 21.
* @arch: ETM/PTM version number.
* @use_cpu14: true if management registers need to be accessed via CP14.
* @enable: is this ETM/PTM currently tracing.
* @sticky_enable: true if ETM base configuration has been done.
* @boot_enable:true if we should start tracing at boot time.
* @os_unlock: true if access to management registers is allowed.
* @nr_addr_cmp:Number of pairs of address comparators as found in ETMCCR.
* @nr_cntr: Number of counters as found in ETMCCR bit 13-15.
* @nr_ext_inp: Number of external input as found in ETMCCR bit 17-19.
* @nr_ext_out: Number of external output as found in ETMCCR bit 20-22.
* @nr_ctxid_cmp: Number of contextID comparators as found in ETMCCR bit 24-25.
* @etmccr: value of register ETMCCR.
* @etmccer: value of register ETMCCER.
* @traceid: value of the current ID for this component.
* @mode: controls various modes supported by this ETM/PTM.
* @ctrl: used in conjunction with @mode.
* @trigger_event: setting for register ETMTRIGGER.
* @startstop_ctrl: setting for register ETMTSSCR.
* @enable_event: setting for register ETMTEEVR.
* @enable_ctrl1: setting for register ETMTECR1.
* @fifofull_level: setting for register ETMFFLR.
* @addr_idx: index for the address comparator selection.
* @addr_val: value for address comparator register.
* @addr_acctype: access type for address comparator register.
* @addr_type: current status of the comparator register.
* @cntr_idx: index for the counter register selection.
* @cntr_rld_val: reload value of a counter register.
* @cntr_event: control for counter enable register.
* @cntr_rld_event: value for counter reload event register.
* @cntr_val: counter value register.
* @seq_12_event: event causing the transition from 1 to 2.
* @seq_21_event: event causing the transition from 2 to 1.
* @seq_23_event: event causing the transition from 2 to 3.
* @seq_31_event: event causing the transition from 3 to 1.
* @seq_32_event: event causing the transition from 3 to 2.
* @seq_13_event: event causing the transition from 1 to 3.
* @seq_curr_state: current value of the sequencer register.
* @ctxid_idx: index for the context ID registers.
* @ctxid_val: value for the context ID to trigger on.
* @ctxid_mask: mask applicable to all the context IDs.
* @sync_freq: Synchronisation frequency.
* @timestamp_event: Defines an event that requests the insertion
of a timestamp into the trace stream.
*/
struct etm_drvdata {
void __iomem *base;
struct device *dev;
struct coresight_device *csdev;
struct clk *clk;
spinlock_t spinlock;
int cpu;
int port_size;
u8 arch;
bool use_cp14;
bool enable;
bool sticky_enable;
bool boot_enable;
bool os_unlock;
u8 nr_addr_cmp;
u8 nr_cntr;
u8 nr_ext_inp;
u8 nr_ext_out;
u8 nr_ctxid_cmp;
u32 etmccr;
u32 etmccer;
u32 traceid;
u32 mode;
u32 ctrl;
u32 trigger_event;
u32 startstop_ctrl;
u32 enable_event;
u32 enable_ctrl1;
u32 fifofull_level;
u8 addr_idx;
u32 addr_val[ETM_MAX_ADDR_CMP];
u32 addr_acctype[ETM_MAX_ADDR_CMP];
u32 addr_type[ETM_MAX_ADDR_CMP];
u8 cntr_idx;
u32 cntr_rld_val[ETM_MAX_CNTR];
u32 cntr_event[ETM_MAX_CNTR];
u32 cntr_rld_event[ETM_MAX_CNTR];
u32 cntr_val[ETM_MAX_CNTR];
u32 seq_12_event;
u32 seq_21_event;
u32 seq_23_event;
u32 seq_31_event;
u32 seq_32_event;
u32 seq_13_event;
u32 seq_curr_state;
u8 ctxid_idx;
u32 ctxid_val[ETM_MAX_CTXID_CMP];
u32 ctxid_mask;
u32 sync_freq;
u32 timestamp_event;
};
enum etm_addr_type {
ETM_ADDR_TYPE_NONE,
ETM_ADDR_TYPE_SINGLE,
ETM_ADDR_TYPE_RANGE,
ETM_ADDR_TYPE_START,
ETM_ADDR_TYPE_STOP,
};
#endif
此差异已折叠。
此差异已折叠。
/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _CORESIGHT_PRIV_H
#define _CORESIGHT_PRIV_H
#include <linux/bitops.h>
#include <linux/io.h>
#include <linux/coresight.h>
/*
* Coresight management registers (0xf00-0xfcc)
* 0xfa0 - 0xfa4: Management registers in PFTv1.0
* Trace registers in PFTv1.1
*/
#define CORESIGHT_ITCTRL 0xf00
#define CORESIGHT_CLAIMSET 0xfa0
#define CORESIGHT_CLAIMCLR 0xfa4
#define CORESIGHT_LAR 0xfb0
#define CORESIGHT_LSR 0xfb4
#define CORESIGHT_AUTHSTATUS 0xfb8
#define CORESIGHT_DEVID 0xfc8
#define CORESIGHT_DEVTYPE 0xfcc
#define TIMEOUT_US 100
#define BMVAL(val, lsb, msb) ((val & GENMASK(msb, lsb)) >> lsb)
static inline void CS_LOCK(void __iomem *addr)
{
do {
/* Wait for things to settle */
mb();
writel_relaxed(0x0, addr + CORESIGHT_LAR);
} while (0);
}
static inline void CS_UNLOCK(void __iomem *addr)
{
do {
writel_relaxed(CORESIGHT_UNLOCK, addr + CORESIGHT_LAR);
/* Make sure everyone has seen this */
mb();
} while (0);
}
#ifdef CONFIG_CORESIGHT_SOURCE_ETM3X
extern int etm_readl_cp14(u32 off, unsigned int *val);
extern int etm_writel_cp14(u32 off, u32 val);
#else
static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; }
static inline int etm_writel_cp14(u32 val, u32 off) { return 0; }
#endif
#endif
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -29,6 +29,7 @@
#include <linux/fs.h>
#include <linux/err.h>
#include <linux/extcon.h>
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/of.h>
......@@ -997,13 +998,16 @@ struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
return ERR_PTR(-ENODEV);
}
edev = extcon_get_extcon_dev(node->name);
if (!edev) {
dev_err(dev, "unable to get extcon device : %s\n", node->name);
return ERR_PTR(-ENODEV);
mutex_lock(&extcon_dev_list_lock);
list_for_each_entry(edev, &extcon_dev_list, entry) {
if (edev->dev.parent && edev->dev.parent->of_node == node) {
mutex_unlock(&extcon_dev_list_lock);
return edev;
}
}
mutex_unlock(&extcon_dev_list_lock);
return edev;
return ERR_PTR(-EPROBE_DEFER);
}
#else
struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
......
/*
* extcon-max14577.c - MAX14577/77836 extcon driver to support MUIC
*
* Copyright (C) 2013,2014 Samsung Electrnoics
* Copyright (C) 2013,2014 Samsung Electronics
* Chanwoo Choi <cw00.choi@samsung.com>
* Krzysztof Kozlowski <k.kozlowski@samsung.com>
*
......
......@@ -232,7 +232,7 @@ static const char *max77693_extcon_cable[] = {
[EXTCON_CABLE_JIG_USB_ON] = "JIG-USB-ON",
[EXTCON_CABLE_JIG_USB_OFF] = "JIG-USB-OFF",
[EXTCON_CABLE_JIG_UART_OFF] = "JIG-UART-OFF",
[EXTCON_CABLE_JIG_UART_ON] = "Dock-Car",
[EXTCON_CABLE_JIG_UART_ON] = "JIG-UART-ON",
[EXTCON_CABLE_DOCK_SMART] = "Dock-Smart",
[EXTCON_CABLE_DOCK_DESK] = "Dock-Desk",
[EXTCON_CABLE_DOCK_AUDIO] = "Dock-Audio",
......@@ -532,9 +532,6 @@ static int max77693_muic_dock_handler(struct max77693_muic_info *info,
extcon_set_cable_state(info->edev, "Dock-Smart", attached);
extcon_set_cable_state(info->edev, "MHL", attached);
goto out;
case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON: /* Dock-Car */
strcpy(dock_name, "Dock-Car");
break;
case MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE: /* Dock-Desk */
strcpy(dock_name, "Dock-Desk");
break;
......@@ -669,6 +666,11 @@ static int max77693_muic_jig_handler(struct max77693_muic_info *info,
strcpy(cable_name, "JIG-UART-OFF");
path = CONTROL1_SW_UART;
break;
case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON: /* ADC_JIG_UART_ON */
/* PATH:AP_UART */
strcpy(cable_name, "JIG-UART-ON");
path = CONTROL1_SW_UART;
break;
default:
dev_err(info->dev, "failed to detect %s jig cable\n",
attached ? "attached" : "detached");
......@@ -708,13 +710,13 @@ static int max77693_muic_adc_handler(struct max77693_muic_info *info)
case MAX77693_MUIC_ADC_FACTORY_MODE_USB_OFF:
case MAX77693_MUIC_ADC_FACTORY_MODE_USB_ON:
case MAX77693_MUIC_ADC_FACTORY_MODE_UART_OFF:
case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON:
/* JIG */
ret = max77693_muic_jig_handler(info, cable_type, attached);
if (ret < 0)
return ret;
break;
case MAX77693_MUIC_ADC_RESERVED_ACC_3: /* Dock-Smart */
case MAX77693_MUIC_ADC_FACTORY_MODE_UART_ON: /* Dock-Car */
case MAX77693_MUIC_ADC_AUDIO_MODE_REMOTE: /* Dock-Desk */
case MAX77693_MUIC_ADC_AV_CABLE_NOLOAD: /* Dock-Audio */
/*
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
obj-$(CONFIG_ARCH_TEGRA) += tegra/
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -37,6 +37,7 @@
static const struct pci_device_id mei_txe_pci_tbl[] = {
{PCI_VDEVICE(INTEL, 0x0F18)}, /* Baytrail */
{PCI_VDEVICE(INTEL, 0x2298)}, /* Cherrytrail */
{0, }
};
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册