Char/Misc driver patches for 3.19-rc1
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. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iEYEABECAAYFAlSODosACgkQMUfUDdst+ykSNwCfcqx1Z3rQzbLwSrR2sa1fV3Zb yEAAniJoLZ4ZkoQK4/1ozsFc31q+gXNm =/epr -----END PGP SIGNATURE----- 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 ...
This commit is contained in:
commit
6ae840e7cc
24
Documentation/ABI/testing/sysfs-bus-coresight-devices-etb10
Normal file
24
Documentation/ABI/testing/sysfs-bus-coresight-devices-etb10
Normal file
@ -0,0 +1,24 @@
|
||||
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).
|
253
Documentation/ABI/testing/sysfs-bus-coresight-devices-etm3x
Normal file
253
Documentation/ABI/testing/sysfs-bus-coresight-devices-etm3x
Normal file
@ -0,0 +1,253 @@
|
||||
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.
|
12
Documentation/ABI/testing/sysfs-bus-coresight-devices-funnel
Normal file
12
Documentation/ABI/testing/sysfs-bus-coresight-devices-funnel
Normal file
@ -0,0 +1,12 @@
|
||||
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.
|
@ -0,0 +1,8 @@
|
||||
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
|
||||
|
204
Documentation/devicetree/bindings/arm/coresight.txt
Normal file
204
Documentation/devicetree/bindings/arm/coresight.txt
Normal file
@ -0,0 +1,204 @@
|
||||
* 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>;
|
||||
};
|
||||
};
|
||||
};
|
299
Documentation/trace/coresight.txt
Normal file
299
Documentation/trace/coresight.txt
Normal file
@ -0,0 +1,299 @@
|
||||
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";
|
||||
|
||||
|
@ -1,157 +0,0 @@
|
||||
/*
|
||||
* 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 */
|
||||
|
542
arch/arm/include/asm/hardware/cp14.h
Normal file
542
arch/arm/include/asm/hardware/cp14.h
Normal file
@ -0,0 +1,542 @@
|
||||
/* 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 __ASM_HARDWARE_CP14_H
|
||||
#define __ASM_HARDWARE_CP14_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Accessors for CP14 registers */
|
||||
#define dbg_read(reg) RCP14_##reg()
|
||||
#define dbg_write(val, reg) WCP14_##reg(val)
|
||||
#define etm_read(reg) RCP14_##reg()
|
||||
#define etm_write(val, reg) WCP14_##reg(val)
|
||||
|
||||
/* MRC14 and MCR14 */
|
||||
#define MRC14(op1, crn, crm, op2) \
|
||||
({ \
|
||||
u32 val; \
|
||||
asm volatile("mrc p14, "#op1", %0, "#crn", "#crm", "#op2 : "=r" (val)); \
|
||||
val; \
|
||||
})
|
||||
|
||||
#define MCR14(val, op1, crn, crm, op2) \
|
||||
({ \
|
||||
asm volatile("mcr p14, "#op1", %0, "#crn", "#crm", "#op2 : : "r" (val));\
|
||||
})
|
||||
|
||||
/*
|
||||
* Debug Registers
|
||||
*
|
||||
* Available only in DBGv7
|
||||
* DBGECR, DBGDSCCR, DBGDSMCR, DBGDRCR
|
||||
*
|
||||
* Available only in DBGv7.1
|
||||
* DBGBXVRm, DBGOSDLR, DBGDEVID2, DBGDEVID1
|
||||
*
|
||||
* Read only
|
||||
* DBGDIDR, DBGDSCRint, DBGDTRRXint, DBGDRAR, DBGOSLSR, DBGOSSRR, DBGPRSR,
|
||||
* DBGPRSR, DBGDSAR, DBGAUTHSTATUS, DBGDEVID2, DBGDEVID1, DBGDEVID
|
||||
*
|
||||
* Write only
|
||||
* DBGDTRTXint, DBGOSLAR
|
||||
*/
|
||||
#define RCP14_DBGDIDR() MRC14(0, c0, c0, 0)
|
||||
#define RCP14_DBGDSCRint() MRC14(0, c0, c1, 0)
|
||||
#define RCP14_DBGDTRRXint() MRC14(0, c0, c5, 0)
|
||||
#define RCP14_DBGWFAR() MRC14(0, c0, c6, 0)
|
||||
#define RCP14_DBGVCR() MRC14(0, c0, c7, 0)
|
||||
#define RCP14_DBGECR() MRC14(0, c0, c9, 0)
|
||||
#define RCP14_DBGDSCCR() MRC14(0, c0, c10, 0)
|
||||
#define RCP14_DBGDSMCR() MRC14(0, c0, c11, 0)
|
||||
#define RCP14_DBGDTRRXext() MRC14(0, c0, c0, 2)
|
||||
#define RCP14_DBGDSCRext() MRC14(0, c0, c2, 2)
|
||||
#define RCP14_DBGDTRTXext() MRC14(0, c0, c3, 2)
|
||||
#define RCP14_DBGDRCR() MRC14(0, c0, c4, 2)
|
||||
#define RCP14_DBGBVR0() MRC14(0, c0, c0, 4)
|
||||
#define RCP14_DBGBVR1() MRC14(0, c0, c1, 4)
|
||||
#define RCP14_DBGBVR2() MRC14(0, c0, c2, 4)
|
||||
#define RCP14_DBGBVR3() MRC14(0, c0, c3, 4)
|
||||
#define RCP14_DBGBVR4() MRC14(0, c0, c4, 4)
|
||||
#define RCP14_DBGBVR5() MRC14(0, c0, c5, 4)
|
||||
#define RCP14_DBGBVR6() MRC14(0, c0, c6, 4)
|
||||
#define RCP14_DBGBVR7() MRC14(0, c0, c7, 4)
|
||||
#define RCP14_DBGBVR8() MRC14(0, c0, c8, 4)
|
||||
#define RCP14_DBGBVR9() MRC14(0, c0, c9, 4)
|
||||
#define RCP14_DBGBVR10() MRC14(0, c0, c10, 4)
|
||||
#define RCP14_DBGBVR11() MRC14(0, c0, c11, 4)
|
||||
#define RCP14_DBGBVR12() MRC14(0, c0, c12, 4)
|
||||
#define RCP14_DBGBVR13() MRC14(0, c0, c13, 4)
|
||||
#define RCP14_DBGBVR14() MRC14(0, c0, c14, 4)
|
||||
#define RCP14_DBGBVR15() MRC14(0, c0, c15, 4)
|
||||
#define RCP14_DBGBCR0() MRC14(0, c0, c0, 5)
|
||||
#define RCP14_DBGBCR1() MRC14(0, c0, c1, 5)
|
||||
#define RCP14_DBGBCR2() MRC14(0, c0, c2, 5)
|
||||
#define RCP14_DBGBCR3() MRC14(0, c0, c3, 5)
|
||||
#define RCP14_DBGBCR4() MRC14(0, c0, c4, 5)
|
||||
#define RCP14_DBGBCR5() MRC14(0, c0, c5, 5)
|
||||
#define RCP14_DBGBCR6() MRC14(0, c0, c6, 5)
|
||||
#define RCP14_DBGBCR7() MRC14(0, c0, c7, 5)
|
||||
#define RCP14_DBGBCR8() MRC14(0, c0, c8, 5)
|
||||
#define RCP14_DBGBCR9() MRC14(0, c0, c9, 5)
|
||||
#define RCP14_DBGBCR10() MRC14(0, c0, c10, 5)
|
||||
#define RCP14_DBGBCR11() MRC14(0, c0, c11, 5)
|
||||
#define RCP14_DBGBCR12() MRC14(0, c0, c12, 5)
|
||||
#define RCP14_DBGBCR13() MRC14(0, c0, c13, 5)
|
||||
#define RCP14_DBGBCR14() MRC14(0, c0, c14, 5)
|
||||
#define RCP14_DBGBCR15() MRC14(0, c0, c15, 5)
|
||||
#define RCP14_DBGWVR0() MRC14(0, c0, c0, 6)
|
||||
#define RCP14_DBGWVR1() MRC14(0, c0, c1, 6)
|
||||
#define RCP14_DBGWVR2() MRC14(0, c0, c2, 6)
|
||||
#define RCP14_DBGWVR3() MRC14(0, c0, c3, 6)
|
||||
#define RCP14_DBGWVR4() MRC14(0, c0, c4, 6)
|
||||
#define RCP14_DBGWVR5() MRC14(0, c0, c5, 6)
|
||||
#define RCP14_DBGWVR6() MRC14(0, c0, c6, 6)
|
||||
#define RCP14_DBGWVR7() MRC14(0, c0, c7, 6)
|
||||
#define RCP14_DBGWVR8() MRC14(0, c0, c8, 6)
|
||||
#define RCP14_DBGWVR9() MRC14(0, c0, c9, 6)
|
||||
#define RCP14_DBGWVR10() MRC14(0, c0, c10, 6)
|
||||
#define RCP14_DBGWVR11() MRC14(0, c0, c11, 6)
|
||||
#define RCP14_DBGWVR12() MRC14(0, c0, c12, 6)
|
||||
#define RCP14_DBGWVR13() MRC14(0, c0, c13, 6)
|
||||
#define RCP14_DBGWVR14() MRC14(0, c0, c14, 6)
|
||||
#define RCP14_DBGWVR15() MRC14(0, c0, c15, 6)
|
||||
#define RCP14_DBGWCR0() MRC14(0, c0, c0, 7)
|
||||
#define RCP14_DBGWCR1() MRC14(0, c0, c1, 7)
|
||||
#define RCP14_DBGWCR2() MRC14(0, c0, c2, 7)
|
||||
#define RCP14_DBGWCR3() MRC14(0, c0, c3, 7)
|
||||
#define RCP14_DBGWCR4() MRC14(0, c0, c4, 7)
|
||||
#define RCP14_DBGWCR5() MRC14(0, c0, c5, 7)
|
||||
#define RCP14_DBGWCR6() MRC14(0, c0, c6, 7)
|
||||
#define RCP14_DBGWCR7() MRC14(0, c0, c7, 7)
|
||||
#define RCP14_DBGWCR8() MRC14(0, c0, c8, 7)
|
||||
#define RCP14_DBGWCR9() MRC14(0, c0, c9, 7)
|
||||
#define RCP14_DBGWCR10() MRC14(0, c0, c10, 7)
|
||||
#define RCP14_DBGWCR11() MRC14(0, c0, c11, 7)
|
||||
#define RCP14_DBGWCR12() MRC14(0, c0, c12, 7)
|
||||
#define RCP14_DBGWCR13() MRC14(0, c0, c13, 7)
|
||||
#define RCP14_DBGWCR14() MRC14(0, c0, c14, 7)
|
||||
#define RCP14_DBGWCR15() MRC14(0, c0, c15, 7)
|
||||
#define RCP14_DBGDRAR() MRC14(0, c1, c0, 0)
|
||||
#define RCP14_DBGBXVR0() MRC14(0, c1, c0, 1)
|
||||
#define RCP14_DBGBXVR1() MRC14(0, c1, c1, 1)
|
||||
#define RCP14_DBGBXVR2() MRC14(0, c1, c2, 1)
|
||||
#define RCP14_DBGBXVR3() MRC14(0, c1, c3, 1)
|
||||
#define RCP14_DBGBXVR4() MRC14(0, c1, c4, 1)
|
||||
#define RCP14_DBGBXVR5() MRC14(0, c1, c5, 1)
|
||||
#define RCP14_DBGBXVR6() MRC14(0, c1, c6, 1)
|
||||
#define RCP14_DBGBXVR7() MRC14(0, c1, c7, 1)
|
||||
#define RCP14_DBGBXVR8() MRC14(0, c1, c8, 1)
|
||||
#define RCP14_DBGBXVR9() MRC14(0, c1, c9, 1)
|
||||
#define RCP14_DBGBXVR10() MRC14(0, c1, c10, 1)
|
||||
#define RCP14_DBGBXVR11() MRC14(0, c1, c11, 1)
|
||||
#define RCP14_DBGBXVR12() MRC14(0, c1, c12, 1)
|
||||
#define RCP14_DBGBXVR13() MRC14(0, c1, c13, 1)
|
||||
#define RCP14_DBGBXVR14() MRC14(0, c1, c14, 1)
|
||||
#define RCP14_DBGBXVR15() MRC14(0, c1, c15, 1)
|
||||
#define RCP14_DBGOSLSR() MRC14(0, c1, c1, 4)
|
||||
#define RCP14_DBGOSSRR() MRC14(0, c1, c2, 4)
|
||||
#define RCP14_DBGOSDLR() MRC14(0, c1, c3, 4)
|
||||
#define RCP14_DBGPRCR() MRC14(0, c1, c4, 4)
|
||||
#define RCP14_DBGPRSR() MRC14(0, c1, c5, 4)
|
||||
#define RCP14_DBGDSAR() MRC14(0, c2, c0, 0)
|
||||
#define RCP14_DBGITCTRL() MRC14(0, c7, c0, 4)
|
||||
#define RCP14_DBGCLAIMSET() MRC14(0, c7, c8, 6)
|
||||
#define RCP14_DBGCLAIMCLR() MRC14(0, c7, c9, 6)
|
||||
#define RCP14_DBGAUTHSTATUS() MRC14(0, c7, c14, 6)
|
||||
#define RCP14_DBGDEVID2() MRC14(0, c7, c0, 7)
|
||||
#define RCP14_DBGDEVID1() MRC14(0, c7, c1, 7)
|
||||
#define RCP14_DBGDEVID() MRC14(0, c7, c2, 7)
|
||||
|
||||
#define WCP14_DBGDTRTXint(val) MCR14(val, 0, c0, c5, 0)
|
||||
#define WCP14_DBGWFAR(val) MCR14(val, 0, c0, c6, 0)
|
||||
#define WCP14_DBGVCR(val) MCR14(val, 0, c0, c7, 0)
|
||||
#define WCP14_DBGECR(val) MCR14(val, 0, c0, c9, 0)
|
||||
#define WCP14_DBGDSCCR(val) MCR14(val, 0, c0, c10, 0)
|
||||
#define WCP14_DBGDSMCR(val) MCR14(val, 0, c0, c11, 0)
|
||||
#define WCP14_DBGDTRRXext(val) MCR14(val, 0, c0, c0, 2)
|
||||
#define WCP14_DBGDSCRext(val) MCR14(val, 0, c0, c2, 2)
|
||||
#define WCP14_DBGDTRTXext(val) MCR14(val, 0, c0, c3, 2)
|
||||
#define WCP14_DBGDRCR(val) MCR14(val, 0, c0, c4, 2)
|
||||
#define WCP14_DBGBVR0(val) MCR14(val, 0, c0, c0, 4)
|
||||
#define WCP14_DBGBVR1(val) MCR14(val, 0, c0, c1, 4)
|
||||
#define WCP14_DBGBVR2(val) MCR14(val, 0, c0, c2, 4)
|
||||
#define WCP14_DBGBVR3(val) MCR14(val, 0, c0, c3, 4)
|
||||
#define WCP14_DBGBVR4(val) MCR14(val, 0, c0, c4, 4)
|
||||
#define WCP14_DBGBVR5(val) MCR14(val, 0, c0, c5, 4)
|
||||
#define WCP14_DBGBVR6(val) MCR14(val, 0, c0, c6, 4)
|
||||
#define WCP14_DBGBVR7(val) MCR14(val, 0, c0, c7, 4)
|
||||
#define WCP14_DBGBVR8(val) MCR14(val, 0, c0, c8, 4)
|
||||
#define WCP14_DBGBVR9(val) MCR14(val, 0, c0, c9, 4)
|
||||
#define WCP14_DBGBVR10(val) MCR14(val, 0, c0, c10, 4)
|
||||
#define WCP14_DBGBVR11(val) MCR14(val, 0, c0, c11, 4)
|
||||
#define WCP14_DBGBVR12(val) MCR14(val, 0, c0, c12, 4)
|
||||
#define WCP14_DBGBVR13(val) MCR14(val, 0, c0, c13, 4)
|
||||
#define WCP14_DBGBVR14(val) MCR14(val, 0, c0, c14, 4)
|
||||
#define WCP14_DBGBVR15(val) MCR14(val, 0, c0, c15, 4)
|
||||
#define WCP14_DBGBCR0(val) MCR14(val, 0, c0, c0, 5)
|
||||
#define WCP14_DBGBCR1(val) MCR14(val, 0, c0, c1, 5)
|
||||
#define WCP14_DBGBCR2(val) MCR14(val, 0, c0, c2, 5)
|
||||
#define WCP14_DBGBCR3(val) MCR14(val, 0, c0, c3, 5)
|
||||
#define WCP14_DBGBCR4(val) MCR14(val, 0, c0, c4, 5)
|
||||
#define WCP14_DBGBCR5(val) MCR14(val, 0, c0, c5, 5)
|
||||
#define WCP14_DBGBCR6(val) MCR14(val, 0, c0, c6, 5)
|
||||
#define WCP14_DBGBCR7(val) MCR14(val, 0, c0, c7, 5)
|
||||
#define WCP14_DBGBCR8(val) MCR14(val, 0, c0, c8, 5)
|
||||
#define WCP14_DBGBCR9(val) MCR14(val, 0, c0, c9, 5)
|
||||
#define WCP14_DBGBCR10(val) MCR14(val, 0, c0, c10, 5)
|
||||
#define WCP14_DBGBCR11(val) MCR14(val, 0, c0, c11, 5)
|
||||
#define WCP14_DBGBCR12(val) MCR14(val, 0, c0, c12, 5)
|
||||
#define WCP14_DBGBCR13(val) MCR14(val, 0, c0, c13, 5)
|
||||
#define WCP14_DBGBCR14(val) MCR14(val, 0, c0, c14, 5)
|
||||
#define WCP14_DBGBCR15(val) MCR14(val, 0, c0, c15, 5)
|
||||
#define WCP14_DBGWVR0(val) MCR14(val, 0, c0, c0, 6)
|
||||
#define WCP14_DBGWVR1(val) MCR14(val, 0, c0, c1, 6)
|
||||
#define WCP14_DBGWVR2(val) MCR14(val, 0, c0, c2, 6)
|
||||
#define WCP14_DBGWVR3(val) MCR14(val, 0, c0, c3, 6)
|
||||
#define WCP14_DBGWVR4(val) MCR14(val, 0, c0, c4, 6)
|
||||
#define WCP14_DBGWVR5(val) MCR14(val, 0, c0, c5, 6)
|
||||
#define WCP14_DBGWVR6(val) MCR14(val, 0, c0, c6, 6)
|
||||
#define WCP14_DBGWVR7(val) MCR14(val, 0, c0, c7, 6)
|
||||
#define WCP14_DBGWVR8(val) MCR14(val, 0, c0, c8, 6)
|
||||
#define WCP14_DBGWVR9(val) MCR14(val, 0, c0, c9, 6)
|
||||
#define WCP14_DBGWVR10(val) MCR14(val, 0, c0, c10, 6)
|
||||
#define WCP14_DBGWVR11(val) MCR14(val, 0, c0, c11, 6)
|
||||
#define WCP14_DBGWVR12(val) MCR14(val, 0, c0, c12, 6)
|
||||
#define WCP14_DBGWVR13(val) MCR14(val, 0, c0, c13, 6)
|
||||
#define WCP14_DBGWVR14(val) MCR14(val, 0, c0, c14, 6)
|
||||
#define WCP14_DBGWVR15(val) MCR14(val, 0, c0, c15, 6)
|
||||
#define WCP14_DBGWCR0(val) MCR14(val, 0, c0, c0, 7)
|
||||
#define WCP14_DBGWCR1(val) MCR14(val, 0, c0, c1, 7)
|
||||
#define WCP14_DBGWCR2(val) MCR14(val, 0, c0, c2, 7)
|
||||
#define WCP14_DBGWCR3(val) MCR14(val, 0, c0, c3, 7)
|
||||
#define WCP14_DBGWCR4(val) MCR14(val, 0, c0, c4, 7)
|
||||
#define WCP14_DBGWCR5(val) MCR14(val, 0, c0, c5, 7)
|
||||
#define WCP14_DBGWCR6(val) MCR14(val, 0, c0, c6, 7)
|
||||
#define WCP14_DBGWCR7(val) MCR14(val, 0, c0, c7, 7)
|
||||
#define WCP14_DBGWCR8(val) MCR14(val, 0, c0, c8, 7)
|
||||
#define WCP14_DBGWCR9(val) MCR14(val, 0, c0, c9, 7)
|
||||
#define WCP14_DBGWCR10(val) MCR14(val, 0, c0, c10, 7)
|
||||
#define WCP14_DBGWCR11(val) MCR14(val, 0, c0, c11, 7)
|
||||
#define WCP14_DBGWCR12(val) MCR14(val, 0, c0, c12, 7)
|
||||
#define WCP14_DBGWCR13(val) MCR14(val, 0, c0, c13, 7)
|
||||
#define WCP14_DBGWCR14(val) MCR14(val, 0, c0, c14, 7)
|
||||
#define WCP14_DBGWCR15(val) MCR14(val, 0, c0, c15, 7)
|
||||
#define WCP14_DBGBXVR0(val) MCR14(val, 0, c1, c0, 1)
|
||||
#define WCP14_DBGBXVR1(val) MCR14(val, 0, c1, c1, 1)
|
||||
#define WCP14_DBGBXVR2(val) MCR14(val, 0, c1, c2, 1)
|
||||
#define WCP14_DBGBXVR3(val) MCR14(val, 0, c1, c3, 1)
|
||||
#define WCP14_DBGBXVR4(val) MCR14(val, 0, c1, c4, 1)
|
||||
#define WCP14_DBGBXVR5(val) MCR14(val, 0, c1, c5, 1)
|
||||
#define WCP14_DBGBXVR6(val) MCR14(val, 0, c1, c6, 1)
|
||||
#define WCP14_DBGBXVR7(val) MCR14(val, 0, c1, c7, 1)
|
||||
#define WCP14_DBGBXVR8(val) MCR14(val, 0, c1, c8, 1)
|
||||
#define WCP14_DBGBXVR9(val) MCR14(val, 0, c1, c9, 1)
|
||||
#define WCP14_DBGBXVR10(val) MCR14(val, 0, c1, c10, 1)
|
||||
#define WCP14_DBGBXVR11(val) MCR14(val, 0, c1, c11, 1)
|
||||
#define WCP14_DBGBXVR12(val) MCR14(val, 0, c1, c12, 1)
|
||||
#define WCP14_DBGBXVR13(val) MCR14(val, 0, c1, c13, 1)
|
||||
#define WCP14_DBGBXVR14(val) MCR14(val, 0, c1, c14, 1)
|
||||
#define WCP14_DBGBXVR15(val) MCR14(val, 0, c1, c15, 1)
|
||||
#define WCP14_DBGOSLAR(val) MCR14(val, 0, c1, c0, 4)
|
||||
#define WCP14_DBGOSSRR(val) MCR14(val, 0, c1, c2, 4)
|
||||
#define WCP14_DBGOSDLR(val) MCR14(val, 0, c1, c3, 4)
|
||||
#define WCP14_DBGPRCR(val) MCR14(val, 0, c1, c4, 4)
|
||||
#define WCP14_DBGITCTRL(val) MCR14(val, 0, c7, c0, 4)
|
||||
#define WCP14_DBGCLAIMSET(val) MCR14(val, 0, c7, c8, 6)
|
||||
#define WCP14_DBGCLAIMCLR(val) MCR14(val, 0, c7, c9, 6)
|
||||
|
||||
/*
|
||||
* ETM Registers
|
||||
*
|
||||
* Available only in ETMv3.3, 3.4, 3.5
|
||||
* ETMASICCR, ETMTECR2, ETMFFRR, ETMVDEVR, ETMVDCR1, ETMVDCR2, ETMVDCR3,
|
||||
* ETMDCVRn, ETMDCMRn
|
||||
*
|
||||
* Available only in ETMv3.5 as read only
|
||||
* ETMIDR2
|
||||
*
|
||||
* Available only in ETMv3.5, PFTv1.0, 1.1
|
||||
* ETMTSEVR, ETMVMIDCVR, ETMPDCR
|
||||
*
|
||||
* Read only
|
||||
* ETMCCR, ETMSCR, ETMIDR, ETMCCER, ETMOSLSR
|
||||
* ETMLSR, ETMAUTHSTATUS, ETMDEVID, ETMDEVTYPE, ETMPIDR4, ETMPIDR5, ETMPIDR6,
|
||||
* ETMPIDR7, ETMPIDR0, ETMPIDR1, ETMPIDR2, ETMPIDR2, ETMPIDR3, ETMCIDR0,
|
||||
* ETMCIDR1, ETMCIDR2, ETMCIDR3
|
||||
*
|
||||
* Write only
|
||||
* ETMOSLAR, ETMLAR
|
||||
* Note: ETMCCER[11] controls WO nature of certain regs. Refer ETM arch spec.
|
||||
*/
|
||||
#define RCP14_ETMCR() MRC14(1, c0, c0, 0)
|
||||
#define RCP14_ETMCCR() MRC14(1, c0, c1, 0)
|
||||
#define RCP14_ETMTRIGGER() MRC14(1, c0, c2, 0)
|
||||
#define RCP14_ETMASICCR() MRC14(1, c0, c3, 0)
|
||||
#define RCP14_ETMSR() MRC14(1, c0, c4, 0)
|
||||
#define RCP14_ETMSCR() MRC14(1, c0, c5, 0)
|
||||
#define RCP14_ETMTSSCR() MRC14(1, c0, c6, 0)
|
||||
#define RCP14_ETMTECR2() MRC14(1, c0, c7, 0)
|
||||
#define RCP14_ETMTEEVR() MRC14(1, c0, c8, 0)
|
||||
#define RCP14_ETMTECR1() MRC14(1, c0, c9, 0)
|
||||
#define RCP14_ETMFFRR() MRC14(1, c0, c10, 0)
|
||||
#define RCP14_ETMFFLR() MRC14(1, c0, c11, 0)
|
||||
#define RCP14_ETMVDEVR() MRC14(1, c0, c12, 0)
|
||||
#define RCP14_ETMVDCR1() MRC14(1, c0, c13, 0)
|
||||
#define RCP14_ETMVDCR2() MRC14(1, c0, c14, 0)
|
||||
#define RCP14_ETMVDCR3() MRC14(1, c0, c15, 0)
|
||||
#define RCP14_ETMACVR0() MRC14(1, c0, c0, 1)
|
||||
#define RCP14_ETMACVR1() MRC14(1, c0, c1, 1)
|
||||
#define RCP14_ETMACVR2() MRC14(1, c0, c2, 1)
|
||||
#define RCP14_ETMACVR3() MRC14(1, c0, c3, 1)
|
||||
#define RCP14_ETMACVR4() MRC14(1, c0, c4, 1)
|
||||
#define RCP14_ETMACVR5() MRC14(1, c0, c5, 1)
|
||||
#define RCP14_ETMACVR6() MRC14(1, c0, c6, 1)
|
||||
#define RCP14_ETMACVR7() MRC14(1, c0, c7, 1)
|
||||
#define RCP14_ETMACVR8() MRC14(1, c0, c8, 1)
|
||||
#define RCP14_ETMACVR9() MRC14(1, c0, c9, 1)
|
||||
#define RCP14_ETMACVR10() MRC14(1, c0, c10, 1)
|
||||
#define RCP14_ETMACVR11() MRC14(1, c0, c11, 1)
|
||||
#define RCP14_ETMACVR12() MRC14(1, c0, c12, 1)
|
||||
#define RCP14_ETMACVR13() MRC14(1, c0, c13, 1)
|
||||
#define RCP14_ETMACVR14() MRC14(1, c0, c14, 1)
|
||||
#define RCP14_ETMACVR15() MRC14(1, c0, c15, 1)
|
||||
#define RCP14_ETMACTR0() MRC14(1, c0, c0, 2)
|
||||
#define RCP14_ETMACTR1() MRC14(1, c0, c1, 2)
|
||||
#define RCP14_ETMACTR2() MRC14(1, c0, c2, 2)
|
||||
#define RCP14_ETMACTR3() MRC14(1, c0, c3, 2)
|
||||
#define RCP14_ETMACTR4() MRC14(1, c0, c4, 2)
|
||||
#define RCP14_ETMACTR5() MRC14(1, c0, c5, 2)
|
||||
#define RCP14_ETMACTR6() MRC14(1, c0, c6, 2)
|
||||
#define RCP14_ETMACTR7() MRC14(1, c0, c7, 2)
|
||||
#define RCP14_ETMACTR8() MRC14(1, c0, c8, 2)
|
||||
#define RCP14_ETMACTR9() MRC14(1, c0, c9, 2)
|
||||
#define RCP14_ETMACTR10() MRC14(1, c0, c10, 2)
|
||||
#define RCP14_ETMACTR11() MRC14(1, c0, c11, 2)
|
||||
#define RCP14_ETMACTR12() MRC14(1, c0, c12, 2)
|
||||
#define RCP14_ETMACTR13() MRC14(1, c0, c13, 2)
|
||||
#define RCP14_ETMACTR14() MRC14(1, c0, c14, 2)
|
||||
#define RCP14_ETMACTR15() MRC14(1, c0, c15, 2)
|
||||
#define RCP14_ETMDCVR0() MRC14(1, c0, c0, 3)
|
||||
#define RCP14_ETMDCVR2() MRC14(1, c0, c2, 3)
|
||||
#define RCP14_ETMDCVR4() MRC14(1, c0, c4, 3)
|
||||
#define RCP14_ETMDCVR6() MRC14(1, c0, c6, 3)
|
||||
#define RCP14_ETMDCVR8() MRC14(1, c0, c8, 3)
|
||||
#define RCP14_ETMDCVR10() MRC14(1, c0, c10, 3)
|
||||
#define RCP14_ETMDCVR12() MRC14(1, c0, c12, 3)
|
||||
#define RCP14_ETMDCVR14() MRC14(1, c0, c14, 3)
|
||||
#define RCP14_ETMDCMR0() MRC14(1, c0, c0, 4)
|
||||
#define RCP14_ETMDCMR2() MRC14(1, c0, c2, 4)
|
||||
#define RCP14_ETMDCMR4() MRC14(1, c0, c4, 4)
|
||||
#define RCP14_ETMDCMR6() MRC14(1, c0, c6, 4)
|
||||
#define RCP14_ETMDCMR8() MRC14(1, c0, c8, 4)
|
||||
#define RCP14_ETMDCMR10() MRC14(1, c0, c10, 4)
|
||||
#define RCP14_ETMDCMR12() MRC14(1, c0, c12, 4)
|
||||
#define RCP14_ETMDCMR14() MRC14(1, c0, c14, 4)
|
||||
#define RCP14_ETMCNTRLDVR0() MRC14(1, c0, c0, 5)
|
||||
#define RCP14_ETMCNTRLDVR1() MRC14(1, c0, c1, 5)
|
||||
#define RCP14_ETMCNTRLDVR2() MRC14(1, c0, c2, 5)
|
||||
#define RCP14_ETMCNTRLDVR3() MRC14(1, c0, c3, 5)
|
||||
#define RCP14_ETMCNTENR0() MRC14(1, c0, c4, 5)
|
||||
#define RCP14_ETMCNTENR1() MRC14(1, c0, c5, 5)
|
||||
#define RCP14_ETMCNTENR2() MRC14(1, c0, c6, 5)
|
||||
#define RCP14_ETMCNTENR3() MRC14(1, c0, c7, 5)
|
||||
#define RCP14_ETMCNTRLDEVR0() MRC14(1, c0, c8, 5)
|
||||
#define RCP14_ETMCNTRLDEVR1() MRC14(1, c0, c9, 5)
|
||||
#define RCP14_ETMCNTRLDEVR2() MRC14(1, c0, c10, 5)
|
||||
#define RCP14_ETMCNTRLDEVR3() MRC14(1, c0, c11, 5)
|
||||
#define RCP14_ETMCNTVR0() MRC14(1, c0, c12, 5)
|
||||
#define RCP14_ETMCNTVR1() MRC14(1, c0, c13, 5)
|
||||
#define RCP14_ETMCNTVR2() MRC14(1, c0, c14, 5)
|
||||
#define RCP14_ETMCNTVR3() MRC14(1, c0, c15, 5)
|
||||
#define RCP14_ETMSQ12EVR() MRC14(1, c0, c0, 6)
|
||||
#define RCP14_ETMSQ21EVR() MRC14(1, c0, c1, 6)
|
||||
#define RCP14_ETMSQ23EVR() MRC14(1, c0, c2, 6)
|
||||
#define RCP14_ETMSQ31EVR() MRC14(1, c0, c3, 6)
|
||||
#define RCP14_ETMSQ32EVR() MRC14(1, c0, c4, 6)
|
||||
#define RCP14_ETMSQ13EVR() MRC14(1, c0, c5, 6)
|
||||
#define RCP14_ETMSQR() MRC14(1, c0, c7, 6)
|
||||
#define RCP14_ETMEXTOUTEVR0() MRC14(1, c0, c8, 6)
|
||||
#define RCP14_ETMEXTOUTEVR1() MRC14(1, c0, c9, 6)
|
||||
#define RCP14_ETMEXTOUTEVR2() MRC14(1, c0, c10, 6)
|
||||
#define RCP14_ETMEXTOUTEVR3() MRC14(1, c0, c11, 6)
|
||||
#define RCP14_ETMCIDCVR0() MRC14(1, c0, c12, 6)
|
||||
#define RCP14_ETMCIDCVR1() MRC14(1, c0, c13, 6)
|
||||
#define RCP14_ETMCIDCVR2() MRC14(1, c0, c14, 6)
|
||||
#define RCP14_ETMCIDCMR() MRC14(1, c0, c15, 6)
|
||||
#define RCP14_ETMIMPSPEC0() MRC14(1, c0, c0, 7)
|
||||
#define RCP14_ETMIMPSPEC1() MRC14(1, c0, c1, 7)
|
||||
#define RCP14_ETMIMPSPEC2() MRC14(1, c0, c2, 7)
|
||||
#define RCP14_ETMIMPSPEC3() MRC14(1, c0, c3, 7)
|
||||
#define RCP14_ETMIMPSPEC4() MRC14(1, c0, c4, 7)
|
||||
#define RCP14_ETMIMPSPEC5() MRC14(1, c0, c5, 7)
|
||||
#define RCP14_ETMIMPSPEC6() MRC14(1, c0, c6, 7)
|
||||
#define RCP14_ETMIMPSPEC7() MRC14(1, c0, c7, 7)
|
||||
#define RCP14_ETMSYNCFR() MRC14(1, c0, c8, 7)
|
||||
#define RCP14_ETMIDR() MRC14(1, c0, c9, 7)
|
||||
#define RCP14_ETMCCER() MRC14(1, c0, c10, 7)
|
||||
#define RCP14_ETMEXTINSELR() MRC14(1, c0, c11, 7)
|
||||
#define RCP14_ETMTESSEICR() MRC14(1, c0, c12, 7)
|
||||
#define RCP14_ETMEIBCR() MRC14(1, c0, c13, 7)
|
||||
#define RCP14_ETMTSEVR() MRC14(1, c0, c14, 7)
|
||||
#define RCP14_ETMAUXCR() MRC14(1, c0, c15, 7)
|
||||
#define RCP14_ETMTRACEIDR() MRC14(1, c1, c0, 0)
|
||||
#define RCP14_ETMIDR2() MRC14(1, c1, c2, 0)
|
||||
#define RCP14_ETMVMIDCVR() MRC14(1, c1, c0, 1)
|
||||
#define RCP14_ETMOSLSR() MRC14(1, c1, c1, 4)
|
||||
/* Not available in PFTv1.1 */
|
||||
#define RCP14_ETMOSSRR() MRC14(1, c1, c2, 4)
|
||||
#define RCP14_ETMPDCR() MRC14(1, c1, c4, 4)
|
||||
#define RCP14_ETMPDSR() MRC14(1, c1, c5, 4)
|
||||
#define RCP14_ETMITCTRL() MRC14(1, c7, c0, 4)
|
||||
#define RCP14_ETMCLAIMSET() MRC14(1, c7, c8, 6)
|
||||
#define RCP14_ETMCLAIMCLR() MRC14(1, c7, c9, 6)
|
||||
#define RCP14_ETMLSR() MRC14(1, c7, c13, 6)
|
||||
#define RCP14_ETMAUTHSTATUS() MRC14(1, c7, c14, 6)
|
||||
#define RCP14_ETMDEVID() MRC14(1, c7, c2, 7)
|
||||
#define RCP14_ETMDEVTYPE() MRC14(1, c7, c3, 7)
|
||||
#define RCP14_ETMPIDR4() MRC14(1, c7, c4, 7)
|
||||
#define RCP14_ETMPIDR5() MRC14(1, c7, c5, 7)
|
||||
#define RCP14_ETMPIDR6() MRC14(1, c7, c6, 7)
|
||||
#define RCP14_ETMPIDR7() MRC14(1, c7, c7, 7)
|
||||
#define RCP14_ETMPIDR0() MRC14(1, c7, c8, 7)
|
||||
#define RCP14_ETMPIDR1() MRC14(1, c7, c9, 7)
|
||||
#define RCP14_ETMPIDR2() MRC14(1, c7, c10, 7)
|
||||
#define RCP14_ETMPIDR3() MRC14(1, c7, c11, 7)
|
||||
#define RCP14_ETMCIDR0() MRC14(1, c7, c12, 7)
|
||||
#define RCP14_ETMCIDR1() MRC14(1, c7, c13, 7)
|
||||
#define RCP14_ETMCIDR2() MRC14(1, c7, c14, 7)
|
||||
#define RCP14_ETMCIDR3() MRC14(1, c7, c15, 7)
|
||||
|
||||
#define WCP14_ETMCR(val) MCR14(val, 1, c0, c0, 0)
|
||||
#define WCP14_ETMTRIGGER(val) MCR14(val, 1, c0, c2, 0)
|
||||
#define WCP14_ETMASICCR(val) MCR14(val, 1, c0, c3, 0)
|
||||
#define WCP14_ETMSR(val) MCR14(val, 1, c0, c4, 0)
|
||||
#define WCP14_ETMTSSCR(val) MCR14(val, 1, c0, c6, 0)
|
||||
#define WCP14_ETMTECR2(val) MCR14(val, 1, c0, c7, 0)
|
||||
#define WCP14_ETMTEEVR(val) MCR14(val, 1, c0, c8, 0)
|
||||
#define WCP14_ETMTECR1(val) MCR14(val, 1, c0, c9, 0)
|
||||
#define WCP14_ETMFFRR(val) MCR14(val, 1, c0, c10, 0)
|
||||
#define WCP14_ETMFFLR(val) MCR14(val, 1, c0, c11, 0)
|
||||
#define WCP14_ETMVDEVR(val) MCR14(val, 1, c0, c12, 0)
|
||||
#define WCP14_ETMVDCR1(val) MCR14(val, 1, c0, c13, 0)
|
||||
#define WCP14_ETMVDCR2(val) MCR14(val, 1, c0, c14, 0)
|
||||
#define WCP14_ETMVDCR3(val) MCR14(val, 1, c0, c15, 0)
|
||||
#define WCP14_ETMACVR0(val) MCR14(val, 1, c0, c0, 1)
|
||||
#define WCP14_ETMACVR1(val) MCR14(val, 1, c0, c1, 1)
|
||||
#define WCP14_ETMACVR2(val) MCR14(val, 1, c0, c2, 1)
|
||||
#define WCP14_ETMACVR3(val) MCR14(val, 1, c0, c3, 1)
|
||||
#define WCP14_ETMACVR4(val) MCR14(val, 1, c0, c4, 1)
|
||||
#define WCP14_ETMACVR5(val) MCR14(val, 1, c0, c5, 1)
|
||||
#define WCP14_ETMACVR6(val) MCR14(val, 1, c0, c6, 1)
|
||||
#define WCP14_ETMACVR7(val) MCR14(val, 1, c0, c7, 1)
|
||||
#define WCP14_ETMACVR8(val) MCR14(val, 1, c0, c8, 1)
|
||||
#define WCP14_ETMACVR9(val) MCR14(val, 1, c0, c9, 1)
|
||||
#define WCP14_ETMACVR10(val) MCR14(val, 1, c0, c10, 1)
|
||||
#define WCP14_ETMACVR11(val) MCR14(val, 1, c0, c11, 1)
|
||||
#define WCP14_ETMACVR12(val) MCR14(val, 1, c0, c12, 1)
|
||||
#define WCP14_ETMACVR13(val) MCR14(val, 1, c0, c13, 1)
|
||||
#define WCP14_ETMACVR14(val) MCR14(val, 1, c0, c14, 1)
|
||||
#define WCP14_ETMACVR15(val) MCR14(val, 1, c0, c15, 1)
|
||||
#define WCP14_ETMACTR0(val) MCR14(val, 1, c0, c0, 2)
|
||||
#define WCP14_ETMACTR1(val) MCR14(val, 1, c0, c1, 2)
|
||||
#define WCP14_ETMACTR2(val) MCR14(val, 1, c0, c2, 2)
|
||||
#define WCP14_ETMACTR3(val) MCR14(val, 1, c0, c3, 2)
|
||||
#define WCP14_ETMACTR4(val) MCR14(val, 1, c0, c4, 2)
|
||||
#define WCP14_ETMACTR5(val) MCR14(val, 1, c0, c5, 2)
|
||||
#define WCP14_ETMACTR6(val) MCR14(val, 1, c0, c6, 2)
|
||||
#define WCP14_ETMACTR7(val) MCR14(val, 1, c0, c7, 2)
|
||||
#define WCP14_ETMACTR8(val) MCR14(val, 1, c0, c8, 2)
|
||||
#define WCP14_ETMACTR9(val) MCR14(val, 1, c0, c9, 2)
|
||||
#define WCP14_ETMACTR10(val) MCR14(val, 1, c0, c10, 2)
|
||||
#define WCP14_ETMACTR11(val) MCR14(val, 1, c0, c11, 2)
|
||||
#define WCP14_ETMACTR12(val) MCR14(val, 1, c0, c12, 2)
|
||||
#define WCP14_ETMACTR13(val) MCR14(val, 1, c0, c13, 2)
|
||||
#define WCP14_ETMACTR14(val) MCR14(val, 1, c0, c14, 2)
|
||||
#define WCP14_ETMACTR15(val) MCR14(val, 1, c0, c15, 2)
|
||||
#define WCP14_ETMDCVR0(val) MCR14(val, 1, c0, c0, 3)
|
||||
#define WCP14_ETMDCVR2(val) MCR14(val, 1, c0, c2, 3)
|
||||
#define WCP14_ETMDCVR4(val) MCR14(val, 1, c0, c4, 3)
|
||||
#define WCP14_ETMDCVR6(val) MCR14(val, 1, c0, c6, 3)
|
||||
#define WCP14_ETMDCVR8(val) MCR14(val, 1, c0, c8, 3)
|
||||
#define WCP14_ETMDCVR10(val) MCR14(val, 1, c0, c10, 3)
|
||||
#define WCP14_ETMDCVR12(val) MCR14(val, 1, c0, c12, 3)
|
||||
#define WCP14_ETMDCVR14(val) MCR14(val, 1, c0, c14, 3)
|
||||
#define WCP14_ETMDCMR0(val) MCR14(val, 1, c0, c0, 4)
|
||||
#define WCP14_ETMDCMR2(val) MCR14(val, 1, c0, c2, 4)
|
||||
#define WCP14_ETMDCMR4(val) MCR14(val, 1, c0, c4, 4)
|
||||
#define WCP14_ETMDCMR6(val) MCR14(val, 1, c0, c6, 4)
|
||||
#define WCP14_ETMDCMR8(val) MCR14(val, 1, c0, c8, 4)
|
||||
#define WCP14_ETMDCMR10(val) MCR14(val, 1, c0, c10, 4)
|
||||
#define WCP14_ETMDCMR12(val) MCR14(val, 1, c0, c12, 4)
|
||||
#define WCP14_ETMDCMR14(val) MCR14(val, 1, c0, c14, 4)
|
||||
#define WCP14_ETMCNTRLDVR0(val) MCR14(val, 1, c0, c0, 5)
|
||||
#define WCP14_ETMCNTRLDVR1(val) MCR14(val, 1, c0, c1, 5)
|
||||
#define WCP14_ETMCNTRLDVR2(val) MCR14(val, 1, c0, c2, 5)
|
||||
#define WCP14_ETMCNTRLDVR3(val) MCR14(val, 1, c0, c3, 5)
|
||||
#define WCP14_ETMCNTENR0(val) MCR14(val, 1, c0, c4, 5)
|
||||
#define WCP14_ETMCNTENR1(val) MCR14(val, 1, c0, c5, 5)
|
||||
#define WCP14_ETMCNTENR2(val) MCR14(val, 1, c0, c6, 5)
|
||||
#define WCP14_ETMCNTENR3(val) MCR14(val, 1, c0, c7, 5)
|
||||
#define WCP14_ETMCNTRLDEVR0(val) MCR14(val, 1, c0, c8, 5)
|
||||
#define WCP14_ETMCNTRLDEVR1(val) MCR14(val, 1, c0, c9, 5)
|
||||
#define WCP14_ETMCNTRLDEVR2(val) MCR14(val, 1, c0, c10, 5)
|
||||
#define WCP14_ETMCNTRLDEVR3(val) MCR14(val, 1, c0, c11, 5)
|
||||
#define WCP14_ETMCNTVR0(val) MCR14(val, 1, c0, c12, 5)
|
||||
#define WCP14_ETMCNTVR1(val) MCR14(val, 1, c0, c13, 5)
|
||||
#define WCP14_ETMCNTVR2(val) MCR14(val, 1, c0, c14, 5)
|
||||
#define WCP14_ETMCNTVR3(val) MCR14(val, 1, c0, c15, 5)
|
||||
#define WCP14_ETMSQ12EVR(val) MCR14(val, 1, c0, c0, 6)
|
||||
#define WCP14_ETMSQ21EVR(val) MCR14(val, 1, c0, c1, 6)
|
||||
#define WCP14_ETMSQ23EVR(val) MCR14(val, 1, c0, c2, 6)
|
||||
#define WCP14_ETMSQ31EVR(val) MCR14(val, 1, c0, c3, 6)
|
||||
#define WCP14_ETMSQ32EVR(val) MCR14(val, 1, c0, c4, 6)
|
||||
#define WCP14_ETMSQ13EVR(val) MCR14(val, 1, c0, c5, 6)
|
||||
#define WCP14_ETMSQR(val) MCR14(val, 1, c0, c7, 6)
|
||||
#define WCP14_ETMEXTOUTEVR0(val) MCR14(val, 1, c0, c8, 6)
|
||||
#define WCP14_ETMEXTOUTEVR1(val) MCR14(val, 1, c0, c9, 6)
|
||||
#define WCP14_ETMEXTOUTEVR2(val) MCR14(val, 1, c0, c10, 6)
|
||||
#define WCP14_ETMEXTOUTEVR3(val) MCR14(val, 1, c0, c11, 6)
|
||||
#define WCP14_ETMCIDCVR0(val) MCR14(val, 1, c0, c12, 6)
|
||||
#define WCP14_ETMCIDCVR1(val) MCR14(val, 1, c0, c13, 6)
|
||||
#define WCP14_ETMCIDCVR2(val) MCR14(val, 1, c0, c14, 6)
|
||||
#define WCP14_ETMCIDCMR(val) MCR14(val, 1, c0, c15, 6)
|
||||
#define WCP14_ETMIMPSPEC0(val) MCR14(val, 1, c0, c0, 7)
|
||||
#define WCP14_ETMIMPSPEC1(val) MCR14(val, 1, c0, c1, 7)
|
||||
#define WCP14_ETMIMPSPEC2(val) MCR14(val, 1, c0, c2, 7)
|
||||
#define WCP14_ETMIMPSPEC3(val) MCR14(val, 1, c0, c3, 7)
|
||||
#define WCP14_ETMIMPSPEC4(val) MCR14(val, 1, c0, c4, 7)
|
||||
#define WCP14_ETMIMPSPEC5(val) MCR14(val, 1, c0, c5, 7)
|
||||
#define WCP14_ETMIMPSPEC6(val) MCR14(val, 1, c0, c6, 7)
|
||||
#define WCP14_ETMIMPSPEC7(val) MCR14(val, 1, c0, c7, 7)
|
||||
/* Can be read only in ETMv3.4, ETMv3.5 */
|
||||
#define WCP14_ETMSYNCFR(val) MCR14(val, 1, c0, c8, 7)
|
||||
#define WCP14_ETMEXTINSELR(val) MCR14(val, 1, c0, c11, 7)
|
||||
#define WCP14_ETMTESSEICR(val) MCR14(val, 1, c0, c12, 7)
|
||||
#define WCP14_ETMEIBCR(val) MCR14(val, 1, c0, c13, 7)
|
||||
#define WCP14_ETMTSEVR(val) MCR14(val, 1, c0, c14, 7)
|
||||
#define WCP14_ETMAUXCR(val) MCR14(val, 1, c0, c15, 7)
|
||||
#define WCP14_ETMTRACEIDR(val) MCR14(val, 1, c1, c0, 0)
|
||||
#define WCP14_ETMIDR2(val) MCR14(val, 1, c1, c2, 0)
|
||||
#define WCP14_ETMVMIDCVR(val) MCR14(val, 1, c1, c0, 1)
|
||||
#define WCP14_ETMOSLAR(val) MCR14(val, 1, c1, c0, 4)
|
||||
/* Not available in PFTv1.1 */
|
||||
#define WCP14_ETMOSSRR(val) MCR14(val, 1, c1, c2, 4)
|
||||
#define WCP14_ETMPDCR(val) MCR14(val, 1, c1, c4, 4)
|
||||
#define WCP14_ETMPDSR(val) MCR14(val, 1, c1, c5, 4)
|
||||
#define WCP14_ETMITCTRL(val) MCR14(val, 1, c7, c0, 4)
|
||||
#define WCP14_ETMCLAIMSET(val) MCR14(val, 1, c7, c8, 6)
|
||||
#define WCP14_ETMCLAIMCLR(val) MCR14(val, 1, c7, c9, 6)
|
||||
/* Writes to this from CP14 interface are ignored */
|
||||
#define WCP14_ETMLAR(val) MCR14(val, 1, c7, c12, 6)
|
||||
|
||||
#endif
|
@ -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
|
||||
|
@ -1,654 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* 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(®s);
|
||||
@ -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)) {
|
||||
|
11
drivers/coresight/Makefile
Normal file
11
drivers/coresight/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
#
|
||||
# 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
|
537
drivers/coresight/coresight-etb10.c
Normal file
537
drivers/coresight/coresight-etb10.c
Normal file
@ -0,0 +1,537 @@
|
||||
/* 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");
|
591
drivers/coresight/coresight-etm-cp14.c
Normal file
591
drivers/coresight/coresight-etm-cp14.c
Normal file
@ -0,0 +1,591 @@
|
||||
/* 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;
|
||||
}
|
251
drivers/coresight/coresight-etm.h
Normal file
251
drivers/coresight/coresight-etm.h
Normal file
@ -0,0 +1,251 @@
|
||||
/* 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
|
1928
drivers/coresight/coresight-etm3x.c
Normal file
1928
drivers/coresight/coresight-etm3x.c
Normal file
File diff suppressed because it is too large
Load Diff
268
drivers/coresight/coresight-funnel.c
Normal file
268
drivers/coresight/coresight-funnel.c
Normal file
@ -0,0 +1,268 @@
|
||||
/* 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/err.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/coresight.h>
|
||||
#include <linux/amba/bus.h>
|
||||
|
||||
#include "coresight-priv.h"
|
||||
|
||||
#define FUNNEL_FUNCTL 0x000
|
||||
#define FUNNEL_PRICTL 0x004
|
||||
|
||||
#define FUNNEL_HOLDTIME_MASK 0xf00
|
||||
#define FUNNEL_HOLDTIME_SHFT 0x8
|
||||
#define FUNNEL_HOLDTIME (0x7 << FUNNEL_HOLDTIME_SHFT)
|
||||
|
||||
/**
|
||||
* struct funnel_drvdata - specifics associated to a funnel 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.
|
||||
* @priority: port selection order.
|
||||
*/
|
||||
struct funnel_drvdata {
|
||||
void __iomem *base;
|
||||
struct device *dev;
|
||||
struct coresight_device *csdev;
|
||||
struct clk *clk;
|
||||
unsigned long priority;
|
||||
};
|
||||
|
||||
static void funnel_enable_hw(struct funnel_drvdata *drvdata, int port)
|
||||
{
|
||||
u32 functl;
|
||||
|
||||
CS_UNLOCK(drvdata->base);
|
||||
|
||||
functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL);
|
||||
functl &= ~FUNNEL_HOLDTIME_MASK;
|
||||
functl |= FUNNEL_HOLDTIME;
|
||||
functl |= (1 << port);
|
||||
writel_relaxed(functl, drvdata->base + FUNNEL_FUNCTL);
|
||||
writel_relaxed(drvdata->priority, drvdata->base + FUNNEL_PRICTL);
|
||||
|
||||
CS_LOCK(drvdata->base);
|
||||
}
|
||||
|
||||
static int funnel_enable(struct coresight_device *csdev, int inport,
|
||||
int outport)
|
||||
{
|
||||
struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(drvdata->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
funnel_enable_hw(drvdata, inport);
|
||||
|
||||
dev_info(drvdata->dev, "FUNNEL inport %d enabled\n", inport);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void funnel_disable_hw(struct funnel_drvdata *drvdata, int inport)
|
||||
{
|
||||
u32 functl;
|
||||
|
||||
CS_UNLOCK(drvdata->base);
|
||||
|
||||
functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL);
|
||||
functl &= ~(1 << inport);
|
||||
writel_relaxed(functl, drvdata->base + FUNNEL_FUNCTL);
|
||||
|
||||
CS_LOCK(drvdata->base);
|
||||
}
|
||||
|
||||
static void funnel_disable(struct coresight_device *csdev, int inport,
|
||||
int outport)
|
||||
{
|
||||
struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
|
||||
funnel_disable_hw(drvdata, inport);
|
||||
|
||||
clk_disable_unprepare(drvdata->clk);
|
||||
|
||||
dev_info(drvdata->dev, "FUNNEL inport %d disabled\n", inport);
|
||||
}
|
||||
|
||||
static const struct coresight_ops_link funnel_link_ops = {
|
||||
.enable = funnel_enable,
|
||||
.disable = funnel_disable,
|
||||
};
|
||||
|
||||
static const struct coresight_ops funnel_cs_ops = {
|
||||
.link_ops = &funnel_link_ops,
|
||||
};
|
||||
|
||||
static ssize_t priority_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
unsigned long val = drvdata->priority;
|
||||
|
||||
return sprintf(buf, "%#lx\n", val);
|
||||
}
|
||||
|
||||
static ssize_t priority_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int ret;
|
||||
unsigned long val;
|
||||
struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
|
||||
ret = kstrtoul(buf, 16, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drvdata->priority = val;
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR_RW(priority);
|
||||
|
||||
static u32 get_funnel_ctrl_hw(struct funnel_drvdata *drvdata)
|
||||
{
|
||||
u32 functl;
|
||||
|
||||
CS_UNLOCK(drvdata->base);
|
||||
functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL);
|
||||
CS_LOCK(drvdata->base);
|
||||
|
||||
return functl;
|
||||
}
|
||||
|
||||
static ssize_t funnel_ctrl_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int ret;
|
||||
u32 val;
|
||||
struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
|
||||
ret = clk_prepare_enable(drvdata->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val = get_funnel_ctrl_hw(drvdata);
|
||||
clk_disable_unprepare(drvdata->clk);
|
||||
|
||||
return sprintf(buf, "%#x\n", val);
|
||||
}
|
||||
static DEVICE_ATTR_RO(funnel_ctrl);
|
||||
|
||||
static struct attribute *coresight_funnel_attrs[] = {
|
||||
&dev_attr_funnel_ctrl.attr,
|
||||
&dev_attr_priority.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(coresight_funnel);
|
||||
|
||||
static int funnel_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
{
|
||||
void __iomem *base;
|
||||
struct device *dev = &adev->dev;
|
||||
struct coresight_platform_data *pdata = NULL;
|
||||
struct funnel_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;
|
||||
|
||||
drvdata->clk = adev->pclk;
|
||||
|
||||
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
|
||||
if (!desc)
|
||||
return -ENOMEM;
|
||||
|
||||
desc->type = CORESIGHT_DEV_TYPE_LINK;
|
||||
desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG;
|
||||
desc->ops = &funnel_cs_ops;
|
||||
desc->pdata = pdata;
|
||||
desc->dev = dev;
|
||||
desc->groups = coresight_funnel_groups;
|
||||
drvdata->csdev = coresight_register(desc);
|
||||
if (IS_ERR(drvdata->csdev))
|
||||
return PTR_ERR(drvdata->csdev);
|
||||
|
||||
dev_info(dev, "FUNNEL initialized\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int funnel_remove(struct amba_device *adev)
|
||||
{
|
||||
struct funnel_drvdata *drvdata = amba_get_drvdata(adev);
|
||||
|
||||
coresight_unregister(drvdata->csdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct amba_id funnel_ids[] = {
|
||||
{
|
||||
.id = 0x0003b908,
|
||||
.mask = 0x0003ffff,
|
||||
},
|
||||
{ 0, 0},
|
||||
};
|
||||
|
||||
static struct amba_driver funnel_driver = {
|
||||
.drv = {
|
||||
.name = "coresight-funnel",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = funnel_probe,
|
||||
.remove = funnel_remove,
|
||||
.id_table = funnel_ids,
|
||||
};
|
||||
|
||||
static int __init funnel_init(void)
|
||||
{
|
||||
return amba_driver_register(&funnel_driver);
|
||||
}
|
||||
module_init(funnel_init);
|
||||
|
||||
static void __exit funnel_exit(void)
|
||||
{
|
||||
amba_driver_unregister(&funnel_driver);
|
||||
}
|
||||
module_exit(funnel_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("CoreSight Funnel driver");
|
63
drivers/coresight/coresight-priv.h
Normal file
63
drivers/coresight/coresight-priv.h
Normal file
@ -0,0 +1,63 @@
|
||||
/* 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
|
137
drivers/coresight/coresight-replicator.c
Normal file
137
drivers/coresight/coresight-replicator.c
Normal file
@ -0,0 +1,137 @@
|
||||
/* 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/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/coresight.h>
|
||||
|
||||
#include "coresight-priv.h"
|
||||
|
||||
/**
|
||||
* struct replicator_drvdata - specifics associated to a replicator component
|
||||
* @dev: the device entity associated with this component
|
||||
* @csdev: component vitals needed by the framework
|
||||
*/
|
||||
struct replicator_drvdata {
|
||||
struct device *dev;
|
||||
struct coresight_device *csdev;
|
||||
};
|
||||
|
||||
static int replicator_enable(struct coresight_device *csdev, int inport,
|
||||
int outport)
|
||||
{
|
||||
struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
|
||||
dev_info(drvdata->dev, "REPLICATOR enabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void replicator_disable(struct coresight_device *csdev, int inport,
|
||||
int outport)
|
||||
{
|
||||
struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
|
||||
dev_info(drvdata->dev, "REPLICATOR disabled\n");
|
||||
}
|
||||
|
||||
static const struct coresight_ops_link replicator_link_ops = {
|
||||
.enable = replicator_enable,
|
||||
.disable = replicator_disable,
|
||||
};
|
||||
|
||||
static const struct coresight_ops replicator_cs_ops = {
|
||||
.link_ops = &replicator_link_ops,
|
||||
};
|
||||
|
||||
static int replicator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct coresight_platform_data *pdata = NULL;
|
||||
struct replicator_drvdata *drvdata;
|
||||
struct coresight_desc *desc;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
|
||||
if (np) {
|
||||
pdata = of_get_coresight_platform_data(dev, np);
|
||||
if (IS_ERR(pdata))
|
||||
return PTR_ERR(pdata);
|
||||
pdev->dev.platform_data = pdata;
|
||||
}
|
||||
|
||||
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
|
||||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
|
||||
drvdata->dev = &pdev->dev;
|
||||
platform_set_drvdata(pdev, drvdata);
|
||||
|
||||
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
|
||||
if (!desc)
|
||||
return -ENOMEM;
|
||||
|
||||
desc->type = CORESIGHT_DEV_TYPE_LINK;
|
||||
desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT;
|
||||
desc->ops = &replicator_cs_ops;
|
||||
desc->pdata = pdev->dev.platform_data;
|
||||
desc->dev = &pdev->dev;
|
||||
drvdata->csdev = coresight_register(desc);
|
||||
if (IS_ERR(drvdata->csdev))
|
||||
return PTR_ERR(drvdata->csdev);
|
||||
|
||||
dev_info(dev, "REPLICATOR initialized\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int replicator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct replicator_drvdata *drvdata = platform_get_drvdata(pdev);
|
||||
|
||||
coresight_unregister(drvdata->csdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id replicator_match[] = {
|
||||
{.compatible = "arm,coresight-replicator"},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver replicator_driver = {
|
||||
.probe = replicator_probe,
|
||||
.remove = replicator_remove,
|
||||
.driver = {
|
||||
.name = "coresight-replicator",
|
||||
.of_match_table = replicator_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init replicator_init(void)
|
||||
{
|
||||
return platform_driver_register(&replicator_driver);
|
||||
}
|
||||
module_init(replicator_init);
|
||||
|
||||
static void __exit replicator_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&replicator_driver);
|
||||
}
|
||||
module_exit(replicator_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("CoreSight Replicator driver");
|
776
drivers/coresight/coresight-tmc.c
Normal file
776
drivers/coresight/coresight-tmc.c
Normal file
@ -0,0 +1,776 @@
|
||||
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/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/dma-mapping.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/coresight.h>
|
||||
#include <linux/amba/bus.h>
|
||||
|
||||
#include "coresight-priv.h"
|
||||
|
||||
#define TMC_RSZ 0x004
|
||||
#define TMC_STS 0x00c
|
||||
#define TMC_RRD 0x010
|
||||
#define TMC_RRP 0x014
|
||||
#define TMC_RWP 0x018
|
||||
#define TMC_TRG 0x01c
|
||||
#define TMC_CTL 0x020
|
||||
#define TMC_RWD 0x024
|
||||
#define TMC_MODE 0x028
|
||||
#define TMC_LBUFLEVEL 0x02c
|
||||
#define TMC_CBUFLEVEL 0x030
|
||||
#define TMC_BUFWM 0x034
|
||||
#define TMC_RRPHI 0x038
|
||||
#define TMC_RWPHI 0x03c
|
||||
#define TMC_AXICTL 0x110
|
||||
#define TMC_DBALO 0x118
|
||||
#define TMC_DBAHI 0x11c
|
||||
#define TMC_FFSR 0x300
|
||||
#define TMC_FFCR 0x304
|
||||
#define TMC_PSCR 0x308
|
||||
#define TMC_ITMISCOP0 0xee0
|
||||
#define TMC_ITTRFLIN 0xee8
|
||||
#define TMC_ITATBDATA0 0xeec
|
||||
#define TMC_ITATBCTR2 0xef0
|
||||
#define TMC_ITATBCTR1 0xef4
|
||||
#define TMC_ITATBCTR0 0xef8
|
||||
|
||||
/* register description */
|
||||
/* TMC_CTL - 0x020 */
|
||||
#define TMC_CTL_CAPT_EN BIT(0)
|
||||
/* TMC_STS - 0x00C */
|
||||
#define TMC_STS_TRIGGERED BIT(1)
|
||||
/* TMC_AXICTL - 0x110 */
|
||||
#define TMC_AXICTL_PROT_CTL_B0 BIT(0)
|
||||
#define TMC_AXICTL_PROT_CTL_B1 BIT(1)
|
||||
#define TMC_AXICTL_SCT_GAT_MODE BIT(7)
|
||||
#define TMC_AXICTL_WR_BURST_LEN 0xF00
|
||||
/* TMC_FFCR - 0x304 */
|
||||
#define TMC_FFCR_EN_FMT BIT(0)
|
||||
#define TMC_FFCR_EN_TI BIT(1)
|
||||
#define TMC_FFCR_FON_FLIN BIT(4)
|
||||
#define TMC_FFCR_FON_TRIG_EVT BIT(5)
|
||||
#define TMC_FFCR_FLUSHMAN BIT(6)
|
||||
#define TMC_FFCR_TRIGON_TRIGIN BIT(8)
|
||||
#define TMC_FFCR_STOP_ON_FLUSH BIT(12)
|
||||
|
||||
#define TMC_STS_TRIGGERED_BIT 2
|
||||
#define TMC_FFCR_FLUSHMAN_BIT 6
|
||||
|
||||
enum tmc_config_type {
|
||||
TMC_CONFIG_TYPE_ETB,
|
||||
TMC_CONFIG_TYPE_ETR,
|
||||
TMC_CONFIG_TYPE_ETF,
|
||||
};
|
||||
|
||||
enum tmc_mode {
|
||||
TMC_MODE_CIRCULAR_BUFFER,
|
||||
TMC_MODE_SOFTWARE_FIFO,
|
||||
TMC_MODE_HARDWARE_FIFO,
|
||||
};
|
||||
|
||||
enum tmc_mem_intf_width {
|
||||
TMC_MEM_INTF_WIDTH_32BITS = 0x2,
|
||||
TMC_MEM_INTF_WIDTH_64BITS = 0x3,
|
||||
TMC_MEM_INTF_WIDTH_128BITS = 0x4,
|
||||
TMC_MEM_INTF_WIDTH_256BITS = 0x5,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tmc_drvdata - specifics associated to an TMC 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.tmc" entry.
|
||||
* @clk: the clock this component is associated to.
|
||||
* @spinlock: only one at a time pls.
|
||||
* @read_count: manages preparation of buffer for reading.
|
||||
* @buf: area of memory where trace data get sent.
|
||||
* @paddr: DMA start location in RAM.
|
||||
* @vaddr: virtual representation of @paddr.
|
||||
* @size: @buf size.
|
||||
* @enable: this TMC is being used.
|
||||
* @config_type: TMC variant, must be of type @tmc_config_type.
|
||||
* @trigger_cntr: amount of words to store after a trigger.
|
||||
*/
|
||||
struct tmc_drvdata {
|
||||
void __iomem *base;
|
||||
struct device *dev;
|
||||
struct coresight_device *csdev;
|
||||
struct miscdevice miscdev;
|
||||
struct clk *clk;
|
||||
spinlock_t spinlock;
|
||||
int read_count;
|
||||
bool reading;
|
||||
char *buf;
|
||||
dma_addr_t paddr;
|
||||
void __iomem *vaddr;
|
||||
u32 size;
|
||||
bool enable;
|
||||
enum tmc_config_type config_type;
|
||||
u32 trigger_cntr;
|
||||
};
|
||||
|
||||
static void tmc_wait_for_ready(struct tmc_drvdata *drvdata)
|
||||
{
|
||||
/* Ensure formatter, unformatter and hardware fifo are empty */
|
||||
if (coresight_timeout(drvdata->base,
|
||||
TMC_STS, TMC_STS_TRIGGERED_BIT, 1)) {
|
||||
dev_err(drvdata->dev,
|
||||
"timeout observed when probing at offset %#x\n",
|
||||
TMC_STS);
|
||||
}
|
||||
}
|
||||
|
||||
static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
|
||||
{
|
||||
u32 ffcr;
|
||||
|
||||
ffcr = readl_relaxed(drvdata->base + TMC_FFCR);
|
||||
ffcr |= TMC_FFCR_STOP_ON_FLUSH;
|
||||
writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
|
||||
ffcr |= TMC_FFCR_FLUSHMAN;
|
||||
writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
|
||||
/* Ensure flush completes */
|
||||
if (coresight_timeout(drvdata->base,
|
||||
TMC_FFCR, TMC_FFCR_FLUSHMAN_BIT, 0)) {
|
||||
dev_err(drvdata->dev,
|
||||
"timeout observed when probing at offset %#x\n",
|
||||
TMC_FFCR);
|
||||
}
|
||||
|
||||
tmc_wait_for_ready(drvdata);
|
||||
}
|
||||
|
||||
static void tmc_enable_hw(struct tmc_drvdata *drvdata)
|
||||
{
|
||||
writel_relaxed(TMC_CTL_CAPT_EN, drvdata->base + TMC_CTL);
|
||||
}
|
||||
|
||||
static void tmc_disable_hw(struct tmc_drvdata *drvdata)
|
||||
{
|
||||
writel_relaxed(0x0, drvdata->base + TMC_CTL);
|
||||
}
|
||||
|
||||
static void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
|
||||
{
|
||||
/* Zero out the memory to help with debug */
|
||||
memset(drvdata->buf, 0, drvdata->size);
|
||||
|
||||
CS_UNLOCK(drvdata->base);
|
||||
|
||||
writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
|
||||
writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
|
||||
TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
|
||||
TMC_FFCR_TRIGON_TRIGIN,
|
||||
drvdata->base + TMC_FFCR);
|
||||
|
||||
writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
|
||||
tmc_enable_hw(drvdata);
|
||||
|
||||
CS_LOCK(drvdata->base);
|
||||
}
|
||||
|
||||
static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
|
||||
{
|
||||
u32 axictl;
|
||||
|
||||
/* Zero out the memory to help with debug */
|
||||
memset(drvdata->vaddr, 0, drvdata->size);
|
||||
|
||||
CS_UNLOCK(drvdata->base);
|
||||
|
||||
writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ);
|
||||
writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
|
||||
|
||||
axictl = readl_relaxed(drvdata->base + TMC_AXICTL);
|
||||
axictl |= TMC_AXICTL_WR_BURST_LEN;
|
||||
writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
|
||||
axictl &= ~TMC_AXICTL_SCT_GAT_MODE;
|
||||
writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
|
||||
axictl = (axictl &
|
||||
~(TMC_AXICTL_PROT_CTL_B0 | TMC_AXICTL_PROT_CTL_B1)) |
|
||||
TMC_AXICTL_PROT_CTL_B1;
|
||||
writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
|
||||
|
||||
writel_relaxed(drvdata->paddr, drvdata->base + TMC_DBALO);
|
||||
writel_relaxed(0x0, drvdata->base + TMC_DBAHI);
|
||||
writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
|
||||
TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
|
||||
TMC_FFCR_TRIGON_TRIGIN,
|
||||
drvdata->base + TMC_FFCR);
|
||||
writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
|
||||
tmc_enable_hw(drvdata);
|
||||
|
||||
CS_LOCK(drvdata->base);
|
||||
}
|
||||
|
||||
static void tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
|
||||
{
|
||||
CS_UNLOCK(drvdata->base);
|
||||
|
||||
writel_relaxed(TMC_MODE_HARDWARE_FIFO, drvdata->base + TMC_MODE);
|
||||
writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI,
|
||||
drvdata->base + TMC_FFCR);
|
||||
writel_relaxed(0x0, drvdata->base + TMC_BUFWM);
|
||||
tmc_enable_hw(drvdata);
|
||||
|
||||
CS_LOCK(drvdata->base);
|
||||
}
|
||||
|
||||
static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
|
||||
{
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
ret = clk_prepare_enable(drvdata->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||
if (drvdata->reading) {
|
||||
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||
clk_disable_unprepare(drvdata->clk);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
|
||||
tmc_etb_enable_hw(drvdata);
|
||||
} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
|
||||
tmc_etr_enable_hw(drvdata);
|
||||
} else {
|
||||
if (mode == TMC_MODE_CIRCULAR_BUFFER)
|
||||
tmc_etb_enable_hw(drvdata);
|
||||
else
|
||||
tmc_etf_enable_hw(drvdata);
|
||||
}
|
||||
drvdata->enable = true;
|
||||
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||
|
||||
dev_info(drvdata->dev, "TMC enabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tmc_enable_sink(struct coresight_device *csdev)
|
||||
{
|
||||
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
|
||||
return tmc_enable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
|
||||
}
|
||||
|
||||
static int tmc_enable_link(struct coresight_device *csdev, int inport,
|
||||
int outport)
|
||||
{
|
||||
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
|
||||
return tmc_enable(drvdata, TMC_MODE_HARDWARE_FIFO);
|
||||
}
|
||||
|
||||
static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
|
||||
{
|
||||
enum tmc_mem_intf_width memwidth;
|
||||
u8 memwords;
|
||||
char *bufp;
|
||||
u32 read_data;
|
||||
int i;
|
||||
|
||||
memwidth = BMVAL(readl_relaxed(drvdata->base + CORESIGHT_DEVID), 8, 10);
|
||||
if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
|
||||
memwords = 1;
|
||||
else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
|
||||
memwords = 2;
|
||||
else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
|
||||
memwords = 4;
|
||||
else
|
||||
memwords = 8;
|
||||
|
||||
bufp = drvdata->buf;
|
||||
while (1) {
|
||||
for (i = 0; i < memwords; i++) {
|
||||
read_data = readl_relaxed(drvdata->base + TMC_RRD);
|
||||
if (read_data == 0xFFFFFFFF)
|
||||
return;
|
||||
memcpy(bufp, &read_data, 4);
|
||||
bufp += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
|
||||
{
|
||||
CS_UNLOCK(drvdata->base);
|
||||
|
||||
tmc_flush_and_stop(drvdata);
|
||||
tmc_etb_dump_hw(drvdata);
|
||||
tmc_disable_hw(drvdata);
|
||||
|
||||
CS_LOCK(drvdata->base);
|
||||
}
|
||||
|
||||
static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
|
||||
{
|
||||
u32 rwp, val;
|
||||
|
||||
rwp = readl_relaxed(drvdata->base + TMC_RWP);
|
||||
val = readl_relaxed(drvdata->base + TMC_STS);
|
||||
|
||||
/* How much memory do we still have */
|
||||
if (val & BIT(0))
|
||||
drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
|
||||
else
|
||||
drvdata->buf = drvdata->vaddr;
|
||||
}
|
||||
|
||||
static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
|
||||
{
|
||||
CS_UNLOCK(drvdata->base);
|
||||
|
||||
tmc_flush_and_stop(drvdata);
|
||||
tmc_etr_dump_hw(drvdata);
|
||||
tmc_disable_hw(drvdata);
|
||||
|
||||
CS_LOCK(drvdata->base);
|
||||
}
|
||||
|
||||
static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
|
||||
{
|
||||
CS_UNLOCK(drvdata->base);
|
||||
|
||||
tmc_flush_and_stop(drvdata);
|
||||
tmc_disable_hw(drvdata);
|
||||
|
||||
CS_LOCK(drvdata->base);
|
||||
}
|
||||
|
||||
static void tmc_disable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||
if (drvdata->reading)
|
||||
goto out;
|
||||
|
||||
if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
|
||||
tmc_etb_disable_hw(drvdata);
|
||||
} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
|
||||
tmc_etr_disable_hw(drvdata);
|
||||
} else {
|
||||
if (mode == TMC_MODE_CIRCULAR_BUFFER)
|
||||
tmc_etb_disable_hw(drvdata);
|
||||
else
|
||||
tmc_etf_disable_hw(drvdata);
|
||||
}
|
||||
out:
|
||||
drvdata->enable = false;
|
||||
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||
|
||||
clk_disable_unprepare(drvdata->clk);
|
||||
|
||||
dev_info(drvdata->dev, "TMC disabled\n");
|
||||
}
|
||||
|
||||
static void tmc_disable_sink(struct coresight_device *csdev)
|
||||
{
|
||||
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
|
||||
tmc_disable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
|
||||
}
|
||||
|
||||
static void tmc_disable_link(struct coresight_device *csdev, int inport,
|
||||
int outport)
|
||||
{
|
||||
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
|
||||
tmc_disable(drvdata, TMC_MODE_HARDWARE_FIFO);
|
||||
}
|
||||
|
||||
static const struct coresight_ops_sink tmc_sink_ops = {
|
||||
.enable = tmc_enable_sink,
|
||||
.disable = tmc_disable_sink,
|
||||
};
|
||||
|
||||
static const struct coresight_ops_link tmc_link_ops = {
|
||||
.enable = tmc_enable_link,
|
||||
.disable = tmc_disable_link,
|
||||
};
|
||||
|
||||
static const struct coresight_ops tmc_etb_cs_ops = {
|
||||
.sink_ops = &tmc_sink_ops,
|
||||
};
|
||||
|
||||
static const struct coresight_ops tmc_etr_cs_ops = {
|
||||
.sink_ops = &tmc_sink_ops,
|
||||
};
|
||||
|
||||
static const struct coresight_ops tmc_etf_cs_ops = {
|
||||
.sink_ops = &tmc_sink_ops,
|
||||
.link_ops = &tmc_link_ops,
|
||||
};
|
||||
|
||||
static int tmc_read_prepare(struct tmc_drvdata *drvdata)
|
||||
{
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
enum tmc_mode mode;
|
||||
|
||||
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||
if (!drvdata->enable)
|
||||
goto out;
|
||||
|
||||
if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
|
||||
tmc_etb_disable_hw(drvdata);
|
||||
} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
|
||||
tmc_etr_disable_hw(drvdata);
|
||||
} else {
|
||||
mode = readl_relaxed(drvdata->base + TMC_MODE);
|
||||
if (mode == TMC_MODE_CIRCULAR_BUFFER) {
|
||||
tmc_etb_disable_hw(drvdata);
|
||||
} else {
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
out:
|
||||
drvdata->reading = true;
|
||||
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||
|
||||
dev_info(drvdata->dev, "TMC read start\n");
|
||||
return 0;
|
||||
err:
|
||||
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void tmc_read_unprepare(struct tmc_drvdata *drvdata)
|
||||
{
|
||||
unsigned long flags;
|
||||
enum tmc_mode mode;
|
||||
|
||||
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||
if (!drvdata->enable)
|
||||
goto out;
|
||||
|
||||
if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
|
||||
tmc_etb_enable_hw(drvdata);
|
||||
} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
|
||||
tmc_etr_enable_hw(drvdata);
|
||||
} else {
|
||||
mode = readl_relaxed(drvdata->base + TMC_MODE);
|
||||
if (mode == TMC_MODE_CIRCULAR_BUFFER)
|
||||
tmc_etb_enable_hw(drvdata);
|
||||
}
|
||||
out:
|
||||
drvdata->reading = false;
|
||||
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||
|
||||
dev_info(drvdata->dev, "TMC read end\n");
|
||||
}
|
||||
|
||||
static int tmc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct tmc_drvdata *drvdata = container_of(file->private_data,
|
||||
struct tmc_drvdata, miscdev);
|
||||
int ret = 0;
|
||||
|
||||
if (drvdata->read_count++)
|
||||
goto out;
|
||||
|
||||
ret = tmc_read_prepare(drvdata);
|
||||
if (ret)
|
||||
return ret;
|
||||
out:
|
||||
nonseekable_open(inode, file);
|
||||
|
||||
dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct tmc_drvdata *drvdata = container_of(file->private_data,
|
||||
struct tmc_drvdata, miscdev);
|
||||
char *bufp = drvdata->buf + *ppos;
|
||||
|
||||
if (*ppos + len > drvdata->size)
|
||||
len = drvdata->size - *ppos;
|
||||
|
||||
if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
|
||||
if (bufp == (char *)(drvdata->vaddr + drvdata->size))
|
||||
bufp = drvdata->vaddr;
|
||||
else if (bufp > (char *)(drvdata->vaddr + drvdata->size))
|
||||
bufp -= drvdata->size;
|
||||
if ((bufp + len) > (char *)(drvdata->vaddr + drvdata->size))
|
||||
len = (char *)(drvdata->vaddr + drvdata->size) - bufp;
|
||||
}
|
||||
|
||||
if (copy_to_user(data, bufp, len)) {
|
||||
dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
*ppos += len;
|
||||
|
||||
dev_dbg(drvdata->dev, "%s: %d bytes copied, %d bytes left\n",
|
||||
__func__, len, (int) (drvdata->size - *ppos));
|
||||
return len;
|
||||
}
|
||||
|
||||
static int tmc_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct tmc_drvdata *drvdata = container_of(file->private_data,
|
||||
struct tmc_drvdata, miscdev);
|
||||
|
||||
if (--drvdata->read_count) {
|
||||
if (drvdata->read_count < 0) {
|
||||
dev_err(drvdata->dev, "mismatched close\n");
|
||||
drvdata->read_count = 0;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmc_read_unprepare(drvdata);
|
||||
out:
|
||||
dev_dbg(drvdata->dev, "%s: released\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations tmc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = tmc_open,
|
||||
.read = tmc_read,
|
||||
.release = tmc_release,
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static ssize_t trigger_cntr_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
|
||||
unsigned long val = drvdata->trigger_cntr;
|
||||
|
||||
return 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 tmc_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,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(coresight_etb);
|
||||
|
||||
static struct attribute *coresight_etr_attrs[] = {
|
||||
&dev_attr_trigger_cntr.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(coresight_etr);
|
||||
|
||||
static struct attribute *coresight_etf_attrs[] = {
|
||||
&dev_attr_trigger_cntr.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(coresight_etf);
|
||||
|
||||
static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 devid;
|
||||
void __iomem *base;
|
||||
struct device *dev = &adev->dev;
|
||||
struct coresight_platform_data *pdata = NULL;
|
||||
struct tmc_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;
|
||||
|
||||
devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
|
||||
drvdata->config_type = BMVAL(devid, 6, 7);
|
||||
|
||||
if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
|
||||
if (np)
|
||||
ret = of_property_read_u32(np,
|
||||
"arm,buffer-size",
|
||||
&drvdata->size);
|
||||
if (ret)
|
||||
drvdata->size = SZ_1M;
|
||||
} else {
|
||||
drvdata->size = readl_relaxed(drvdata->base + TMC_RSZ) * 4;
|
||||
}
|
||||
|
||||
clk_disable_unprepare(drvdata->clk);
|
||||
|
||||
if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
|
||||
drvdata->vaddr = dma_alloc_coherent(dev, drvdata->size,
|
||||
&drvdata->paddr, GFP_KERNEL);
|
||||
if (!drvdata->vaddr)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(drvdata->vaddr, 0, drvdata->size);
|
||||
drvdata->buf = drvdata->vaddr;
|
||||
} else {
|
||||
drvdata->buf = devm_kzalloc(dev, drvdata->size, GFP_KERNEL);
|
||||
if (!drvdata->buf)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
|
||||
if (!desc) {
|
||||
ret = -ENOMEM;
|
||||
goto err_devm_kzalloc;
|
||||
}
|
||||
|
||||
desc->pdata = pdata;
|
||||
desc->dev = dev;
|
||||
desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
|
||||
|
||||
if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
|
||||
desc->type = CORESIGHT_DEV_TYPE_SINK;
|
||||
desc->ops = &tmc_etb_cs_ops;
|
||||
desc->groups = coresight_etb_groups;
|
||||
} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
|
||||
desc->type = CORESIGHT_DEV_TYPE_SINK;
|
||||
desc->ops = &tmc_etr_cs_ops;
|
||||
desc->groups = coresight_etr_groups;
|
||||
} else {
|
||||
desc->type = CORESIGHT_DEV_TYPE_LINKSINK;
|
||||
desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO;
|
||||
desc->ops = &tmc_etf_cs_ops;
|
||||
desc->groups = coresight_etf_groups;
|
||||
}
|
||||
|
||||
drvdata->csdev = coresight_register(desc);
|
||||
if (IS_ERR(drvdata->csdev)) {
|
||||
ret = PTR_ERR(drvdata->csdev);
|
||||
goto err_devm_kzalloc;
|
||||
}
|
||||
|
||||
drvdata->miscdev.name = pdata->name;
|
||||
drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
|
||||
drvdata->miscdev.fops = &tmc_fops;
|
||||
ret = misc_register(&drvdata->miscdev);
|
||||
if (ret)
|
||||
goto err_misc_register;
|
||||
|
||||
dev_info(dev, "TMC initialized\n");
|
||||
return 0;
|
||||
|
||||
err_misc_register:
|
||||
coresight_unregister(drvdata->csdev);
|
||||
err_devm_kzalloc:
|
||||
if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
|
||||
dma_free_coherent(dev, drvdata->size,
|
||||
&drvdata->paddr, GFP_KERNEL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tmc_remove(struct amba_device *adev)
|
||||
{
|
||||
struct tmc_drvdata *drvdata = amba_get_drvdata(adev);
|
||||
|
||||
misc_deregister(&drvdata->miscdev);
|
||||
coresight_unregister(drvdata->csdev);
|
||||
if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
|
||||
dma_free_coherent(drvdata->dev, drvdata->size,
|
||||
&drvdata->paddr, GFP_KERNEL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct amba_id tmc_ids[] = {
|
||||
{
|
||||
.id = 0x0003b961,
|
||||
.mask = 0x0003ffff,
|
||||
},
|
||||
{ 0, 0},
|
||||
};
|
||||
|
||||
static struct amba_driver tmc_driver = {
|
||||
.drv = {
|
||||
.name = "coresight-tmc",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = tmc_probe,
|
||||
.remove = tmc_remove,
|
||||
.id_table = tmc_ids,
|
||||
};
|
||||
|
||||
static int __init tmc_init(void)
|
||||
{
|
||||
return amba_driver_register(&tmc_driver);
|
||||
}
|
||||
module_init(tmc_init);
|
||||
|
||||
static void __exit tmc_exit(void)
|
||||
{
|
||||
amba_driver_unregister(&tmc_driver);
|
||||
}
|
||||
module_exit(tmc_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("CoreSight Trace Memory Controller driver");
|
217
drivers/coresight/coresight-tpiu.c
Normal file
217
drivers/coresight/coresight-tpiu.c
Normal file
@ -0,0 +1,217 @@
|
||||
/* 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/device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/coresight.h>
|
||||
#include <linux/amba/bus.h>
|
||||
|
||||
#include "coresight-priv.h"
|
||||
|
||||
#define TPIU_SUPP_PORTSZ 0x000
|
||||
#define TPIU_CURR_PORTSZ 0x004
|
||||
#define TPIU_SUPP_TRIGMODES 0x100
|
||||
#define TPIU_TRIG_CNTRVAL 0x104
|
||||
#define TPIU_TRIG_MULT 0x108
|
||||
#define TPIU_SUPP_TESTPATM 0x200
|
||||
#define TPIU_CURR_TESTPATM 0x204
|
||||
#define TPIU_TEST_PATREPCNTR 0x208
|
||||
#define TPIU_FFSR 0x300
|
||||
#define TPIU_FFCR 0x304
|
||||
#define TPIU_FSYNC_CNTR 0x308
|
||||
#define TPIU_EXTCTL_INPORT 0x400
|
||||
#define TPIU_EXTCTL_OUTPORT 0x404
|
||||
#define TPIU_ITTRFLINACK 0xee4
|
||||
#define TPIU_ITTRFLIN 0xee8
|
||||
#define TPIU_ITATBDATA0 0xeec
|
||||
#define TPIU_ITATBCTR2 0xef0
|
||||
#define TPIU_ITATBCTR1 0xef4
|
||||
#define TPIU_ITATBCTR0 0xef8
|
||||
|
||||
/** register definition **/
|
||||
/* FFCR - 0x304 */
|
||||
#define FFCR_FON_MAN BIT(6)
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
struct tpiu_drvdata {
|
||||
void __iomem *base;
|
||||
struct device *dev;
|
||||
struct coresight_device *csdev;
|
||||
struct clk *clk;
|
||||
};
|
||||
|
||||
static void tpiu_enable_hw(struct tpiu_drvdata *drvdata)
|
||||
{
|
||||
CS_UNLOCK(drvdata->base);
|
||||
|
||||
/* TODO: fill this up */
|
||||
|
||||
CS_LOCK(drvdata->base);
|
||||
}
|
||||
|
||||
static int tpiu_enable(struct coresight_device *csdev)
|
||||
{
|
||||
struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(drvdata->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
tpiu_enable_hw(drvdata);
|
||||
|
||||
dev_info(drvdata->dev, "TPIU enabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tpiu_disable_hw(struct tpiu_drvdata *drvdata)
|
||||
{
|
||||
CS_UNLOCK(drvdata->base);
|
||||
|
||||
/* Clear formatter controle reg. */
|
||||
writel_relaxed(0x0, drvdata->base + TPIU_FFCR);
|
||||
/* Generate manual flush */
|
||||
writel_relaxed(FFCR_FON_MAN, drvdata->base + TPIU_FFCR);
|
||||
|
||||
CS_LOCK(drvdata->base);
|
||||
}
|
||||
|
||||
static void tpiu_disable(struct coresight_device *csdev)
|
||||
{
|
||||
struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
|
||||
tpiu_disable_hw(drvdata);
|
||||
|
||||
clk_disable_unprepare(drvdata->clk);
|
||||
|
||||
dev_info(drvdata->dev, "TPIU disabled\n");
|
||||
}
|
||||
|
||||
static const struct coresight_ops_sink tpiu_sink_ops = {
|
||||
.enable = tpiu_enable,
|
||||
.disable = tpiu_disable,
|
||||
};
|
||||
|
||||
static const struct coresight_ops tpiu_cs_ops = {
|
||||
.sink_ops = &tpiu_sink_ops,
|
||||
};
|
||||
|
||||
static int tpiu_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 tpiu_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;
|
||||
|
||||
drvdata->clk = adev->pclk;
|
||||
ret = clk_prepare_enable(drvdata->clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Disable tpiu to support older devices */
|
||||
tpiu_disable_hw(drvdata);
|
||||
|
||||
clk_disable_unprepare(drvdata->clk);
|
||||
|
||||
desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
|
||||
if (!desc)
|
||||
return -ENOMEM;
|
||||
|
||||
desc->type = CORESIGHT_DEV_TYPE_SINK;
|
||||
desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_PORT;
|
||||
desc->ops = &tpiu_cs_ops;
|
||||
desc->pdata = pdata;
|
||||
desc->dev = dev;
|
||||
drvdata->csdev = coresight_register(desc);
|
||||
if (IS_ERR(drvdata->csdev))
|
||||
return PTR_ERR(drvdata->csdev);
|
||||
|
||||
dev_info(dev, "TPIU initialized\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tpiu_remove(struct amba_device *adev)
|
||||
{
|
||||
struct tpiu_drvdata *drvdata = amba_get_drvdata(adev);
|
||||
|
||||
coresight_unregister(drvdata->csdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct amba_id tpiu_ids[] = {
|
||||
{
|
||||
.id = 0x0003b912,
|
||||
.mask = 0x0003ffff,
|
||||
},
|
||||
{ 0, 0},
|
||||
};
|
||||
|
||||
static struct amba_driver tpiu_driver = {
|
||||
.drv = {
|
||||
.name = "coresight-tpiu",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = tpiu_probe,
|
||||
.remove = tpiu_remove,
|
||||
.id_table = tpiu_ids,
|
||||
};
|
||||
|
||||
static int __init tpiu_init(void)
|
||||
{
|
||||
return amba_driver_register(&tpiu_driver);
|
||||
}
|
||||
module_init(tpiu_init);
|
||||
|
||||
static void __exit tpiu_exit(void)
|
||||
{
|
||||
amba_driver_unregister(&tpiu_driver);
|
||||
}
|
||||
module_exit(tpiu_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("CoreSight Trace Port Interface Unit driver");
|
717
drivers/coresight/coresight.c
Normal file
717
drivers/coresight/coresight.c
Normal file
@ -0,0 +1,717 @@
|
||||
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/coresight.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "coresight-priv.h"
|
||||
|
||||
static DEFINE_MUTEX(coresight_mutex);
|
||||
|
||||
static int coresight_id_match(struct device *dev, void *data)
|
||||
{
|
||||
int trace_id, i_trace_id;
|
||||
struct coresight_device *csdev, *i_csdev;
|
||||
|
||||
csdev = data;
|
||||
i_csdev = to_coresight_device(dev);
|
||||
|
||||
/*
|
||||
* No need to care about oneself and components that are not
|
||||
* sources or not enabled
|
||||
*/
|
||||
if (i_csdev == csdev || !i_csdev->enable ||
|
||||
i_csdev->type != CORESIGHT_DEV_TYPE_SOURCE)
|
||||
return 0;
|
||||
|
||||
/* Get the source ID for both compoment */
|
||||
trace_id = source_ops(csdev)->trace_id(csdev);
|
||||
i_trace_id = source_ops(i_csdev)->trace_id(i_csdev);
|
||||
|
||||
/* All you need is one */
|
||||
if (trace_id == i_trace_id)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int coresight_source_is_unique(struct coresight_device *csdev)
|
||||
{
|
||||
int trace_id = source_ops(csdev)->trace_id(csdev);
|
||||
|
||||
/* this shouldn't happen */
|
||||
if (trace_id < 0)
|
||||
return 0;
|
||||
|
||||
return !bus_for_each_dev(&coresight_bustype, NULL,
|
||||
csdev, coresight_id_match);
|
||||
}
|
||||
|
||||
static int coresight_find_link_inport(struct coresight_device *csdev)
|
||||
{
|
||||
int i;
|
||||
struct coresight_device *parent;
|
||||
struct coresight_connection *conn;
|
||||
|
||||
parent = container_of(csdev->path_link.next,
|
||||
struct coresight_device, path_link);
|
||||
|
||||
for (i = 0; i < parent->nr_outport; i++) {
|
||||
conn = &parent->conns[i];
|
||||
if (conn->child_dev == csdev)
|
||||
return conn->child_port;
|
||||
}
|
||||
|
||||
dev_err(&csdev->dev, "couldn't find inport, parent: %s, child: %s\n",
|
||||
dev_name(&parent->dev), dev_name(&csdev->dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int coresight_find_link_outport(struct coresight_device *csdev)
|
||||
{
|
||||
int i;
|
||||
struct coresight_device *child;
|
||||
struct coresight_connection *conn;
|
||||
|
||||
child = container_of(csdev->path_link.prev,
|
||||
struct coresight_device, path_link);
|
||||
|
||||
for (i = 0; i < csdev->nr_outport; i++) {
|
||||
conn = &csdev->conns[i];
|
||||
if (conn->child_dev == child)
|
||||
return conn->outport;
|
||||
}
|
||||
|
||||
dev_err(&csdev->dev, "couldn't find outport, parent: %s, child: %s\n",
|
||||
dev_name(&csdev->dev), dev_name(&child->dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int coresight_enable_sink(struct coresight_device *csdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!csdev->enable) {
|
||||
if (sink_ops(csdev)->enable) {
|
||||
ret = sink_ops(csdev)->enable(csdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
csdev->enable = true;
|
||||
}
|
||||
|
||||
atomic_inc(csdev->refcnt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void coresight_disable_sink(struct coresight_device *csdev)
|
||||
{
|
||||
if (atomic_dec_return(csdev->refcnt) == 0) {
|
||||
if (sink_ops(csdev)->disable) {
|
||||
sink_ops(csdev)->disable(csdev);
|
||||
csdev->enable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int coresight_enable_link(struct coresight_device *csdev)
|
||||
{
|
||||
int ret;
|
||||
int link_subtype;
|
||||
int refport, inport, outport;
|
||||
|
||||
inport = coresight_find_link_inport(csdev);
|
||||
outport = coresight_find_link_outport(csdev);
|
||||
link_subtype = csdev->subtype.link_subtype;
|
||||
|
||||
if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG)
|
||||
refport = inport;
|
||||
else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT)
|
||||
refport = outport;
|
||||
else
|
||||
refport = 0;
|
||||
|
||||
if (atomic_inc_return(&csdev->refcnt[refport]) == 1) {
|
||||
if (link_ops(csdev)->enable) {
|
||||
ret = link_ops(csdev)->enable(csdev, inport, outport);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
csdev->enable = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void coresight_disable_link(struct coresight_device *csdev)
|
||||
{
|
||||
int i, nr_conns;
|
||||
int link_subtype;
|
||||
int refport, inport, outport;
|
||||
|
||||
inport = coresight_find_link_inport(csdev);
|
||||
outport = coresight_find_link_outport(csdev);
|
||||
link_subtype = csdev->subtype.link_subtype;
|
||||
|
||||
if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) {
|
||||
refport = inport;
|
||||
nr_conns = csdev->nr_inport;
|
||||
} else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) {
|
||||
refport = outport;
|
||||
nr_conns = csdev->nr_outport;
|
||||
} else {
|
||||
refport = 0;
|
||||
nr_conns = 1;
|
||||
}
|
||||
|
||||
if (atomic_dec_return(&csdev->refcnt[refport]) == 0) {
|
||||
if (link_ops(csdev)->disable)
|
||||
link_ops(csdev)->disable(csdev, inport, outport);
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_conns; i++)
|
||||
if (atomic_read(&csdev->refcnt[i]) != 0)
|
||||
return;
|
||||
|
||||
csdev->enable = false;
|
||||
}
|
||||
|
||||
static int coresight_enable_source(struct coresight_device *csdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!coresight_source_is_unique(csdev)) {
|
||||
dev_warn(&csdev->dev, "traceID %d not unique\n",
|
||||
source_ops(csdev)->trace_id(csdev));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!csdev->enable) {
|
||||
if (source_ops(csdev)->enable) {
|
||||
ret = source_ops(csdev)->enable(csdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
csdev->enable = true;
|
||||
}
|
||||
|
||||
atomic_inc(csdev->refcnt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void coresight_disable_source(struct coresight_device *csdev)
|
||||
{
|
||||
if (atomic_dec_return(csdev->refcnt) == 0) {
|
||||
if (source_ops(csdev)->disable) {
|
||||
source_ops(csdev)->disable(csdev);
|
||||
csdev->enable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int coresight_enable_path(struct list_head *path)
|
||||
{
|
||||
int ret = 0;
|
||||
struct coresight_device *cd;
|
||||
|
||||
list_for_each_entry(cd, path, path_link) {
|
||||
if (cd == list_first_entry(path, struct coresight_device,
|
||||
path_link)) {
|
||||
ret = coresight_enable_sink(cd);
|
||||
} else if (list_is_last(&cd->path_link, path)) {
|
||||
/*
|
||||
* Don't enable the source just yet - this needs to
|
||||
* happen at the very end when all links and sink
|
||||
* along the path have been configured properly.
|
||||
*/
|
||||
;
|
||||
} else {
|
||||
ret = coresight_enable_link(cd);
|
||||
}
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
list_for_each_entry_continue_reverse(cd, path, path_link) {
|
||||
if (cd == list_first_entry(path, struct coresight_device,
|
||||
path_link)) {
|
||||
coresight_disable_sink(cd);
|
||||
} else if (list_is_last(&cd->path_link, path)) {
|
||||
;
|
||||
} else {
|
||||
coresight_disable_link(cd);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int coresight_disable_path(struct list_head *path)
|
||||
{
|
||||
struct coresight_device *cd;
|
||||
|
||||
list_for_each_entry_reverse(cd, path, path_link) {
|
||||
if (cd == list_first_entry(path, struct coresight_device,
|
||||
path_link)) {
|
||||
coresight_disable_sink(cd);
|
||||
} else if (list_is_last(&cd->path_link, path)) {
|
||||
/*
|
||||
* The source has already been stopped, no need
|
||||
* to do it again here.
|
||||
*/
|
||||
;
|
||||
} else {
|
||||
coresight_disable_link(cd);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int coresight_build_paths(struct coresight_device *csdev,
|
||||
struct list_head *path,
|
||||
bool enable)
|
||||
{
|
||||
int i, ret = -EINVAL;
|
||||
struct coresight_connection *conn;
|
||||
|
||||
list_add(&csdev->path_link, path);
|
||||
|
||||
if (csdev->type == CORESIGHT_DEV_TYPE_SINK && csdev->activated) {
|
||||
if (enable)
|
||||
ret = coresight_enable_path(path);
|
||||
else
|
||||
ret = coresight_disable_path(path);
|
||||
} else {
|
||||
for (i = 0; i < csdev->nr_outport; i++) {
|
||||
conn = &csdev->conns[i];
|
||||
if (coresight_build_paths(conn->child_dev,
|
||||
path, enable) == 0)
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (list_first_entry(path, struct coresight_device, path_link) != csdev)
|
||||
dev_err(&csdev->dev, "wrong device in %s\n", __func__);
|
||||
|
||||
list_del(&csdev->path_link);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int coresight_enable(struct coresight_device *csdev)
|
||||
{
|
||||
int ret = 0;
|
||||
LIST_HEAD(path);
|
||||
|
||||
mutex_lock(&coresight_mutex);
|
||||
if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) {
|
||||
ret = -EINVAL;
|
||||
dev_err(&csdev->dev, "wrong device type in %s\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (csdev->enable)
|
||||
goto out;
|
||||
|
||||
if (coresight_build_paths(csdev, &path, true)) {
|
||||
dev_err(&csdev->dev, "building path(s) failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (coresight_enable_source(csdev))
|
||||
dev_err(&csdev->dev, "source enable failed\n");
|
||||
out:
|
||||
mutex_unlock(&coresight_mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_enable);
|
||||
|
||||
void coresight_disable(struct coresight_device *csdev)
|
||||
{
|
||||
LIST_HEAD(path);
|
||||
|
||||
mutex_lock(&coresight_mutex);
|
||||
if (csdev->type != CORESIGHT_DEV_TYPE_SOURCE) {
|
||||
dev_err(&csdev->dev, "wrong device type in %s\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
if (!csdev->enable)
|
||||
goto out;
|
||||
|
||||
coresight_disable_source(csdev);
|
||||
if (coresight_build_paths(csdev, &path, false))
|
||||
dev_err(&csdev->dev, "releasing path(s) failed\n");
|
||||
|
||||
out:
|
||||
mutex_unlock(&coresight_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_disable);
|
||||
|
||||
static ssize_t enable_sink_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct coresight_device *csdev = to_coresight_device(dev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n", (unsigned)csdev->activated);
|
||||
}
|
||||
|
||||
static ssize_t enable_sink_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int ret;
|
||||
unsigned long val;
|
||||
struct coresight_device *csdev = to_coresight_device(dev);
|
||||
|
||||
ret = kstrtoul(buf, 10, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val)
|
||||
csdev->activated = true;
|
||||
else
|
||||
csdev->activated = false;
|
||||
|
||||
return size;
|
||||
|
||||
}
|
||||
static DEVICE_ATTR_RW(enable_sink);
|
||||
|
||||
static ssize_t enable_source_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct coresight_device *csdev = to_coresight_device(dev);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n", (unsigned)csdev->enable);
|
||||
}
|
||||
|
||||
static ssize_t enable_source_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long val;
|
||||
struct coresight_device *csdev = to_coresight_device(dev);
|
||||
|
||||
ret = kstrtoul(buf, 10, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val) {
|
||||
ret = coresight_enable(csdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
coresight_disable(csdev);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
static DEVICE_ATTR_RW(enable_source);
|
||||
|
||||
static struct attribute *coresight_sink_attrs[] = {
|
||||
&dev_attr_enable_sink.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(coresight_sink);
|
||||
|
||||
static struct attribute *coresight_source_attrs[] = {
|
||||
&dev_attr_enable_source.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(coresight_source);
|
||||
|
||||
static struct device_type coresight_dev_type[] = {
|
||||
{
|
||||
.name = "none",
|
||||
},
|
||||
{
|
||||
.name = "sink",
|
||||
.groups = coresight_sink_groups,
|
||||
},
|
||||
{
|
||||
.name = "link",
|
||||
},
|
||||
{
|
||||
.name = "linksink",
|
||||
.groups = coresight_sink_groups,
|
||||
},
|
||||
{
|
||||
.name = "source",
|
||||
.groups = coresight_source_groups,
|
||||
},
|
||||
};
|
||||
|
||||
static void coresight_device_release(struct device *dev)
|
||||
{
|
||||
struct coresight_device *csdev = to_coresight_device(dev);
|
||||
|
||||
kfree(csdev);
|
||||
}
|
||||
|
||||
static int coresight_orphan_match(struct device *dev, void *data)
|
||||
{
|
||||
int i;
|
||||
bool still_orphan = false;
|
||||
struct coresight_device *csdev, *i_csdev;
|
||||
struct coresight_connection *conn;
|
||||
|
||||
csdev = data;
|
||||
i_csdev = to_coresight_device(dev);
|
||||
|
||||
/* No need to check oneself */
|
||||
if (csdev == i_csdev)
|
||||
return 0;
|
||||
|
||||
/* Move on to another component if no connection is orphan */
|
||||
if (!i_csdev->orphan)
|
||||
return 0;
|
||||
/*
|
||||
* Circle throuch all the connection of that component. If we find
|
||||
* an orphan connection whose name matches @csdev, link it.
|
||||
*/
|
||||
for (i = 0; i < i_csdev->nr_outport; i++) {
|
||||
conn = &i_csdev->conns[i];
|
||||
|
||||
/* We have found at least one orphan connection */
|
||||
if (conn->child_dev == NULL) {
|
||||
/* Does it match this newly added device? */
|
||||
if (!strcmp(dev_name(&csdev->dev), conn->child_name))
|
||||
conn->child_dev = csdev;
|
||||
} else {
|
||||
/* Too bad, this component still has an orphan */
|
||||
still_orphan = true;
|
||||
}
|
||||
}
|
||||
|
||||
i_csdev->orphan = still_orphan;
|
||||
|
||||
/*
|
||||
* Returning '0' ensures that all known component on the
|
||||
* bus will be checked.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void coresight_fixup_orphan_conns(struct coresight_device *csdev)
|
||||
{
|
||||
/*
|
||||
* No need to check for a return value as orphan connection(s)
|
||||
* are hooked-up with each newly added component.
|
||||
*/
|
||||
bus_for_each_dev(&coresight_bustype, NULL,
|
||||
csdev, coresight_orphan_match);
|
||||
}
|
||||
|
||||
|
||||
static int coresight_name_match(struct device *dev, void *data)
|
||||
{
|
||||
char *to_match;
|
||||
struct coresight_device *i_csdev;
|
||||
|
||||
to_match = data;
|
||||
i_csdev = to_coresight_device(dev);
|
||||
|
||||
if (!strcmp(to_match, dev_name(&i_csdev->dev)))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void coresight_fixup_device_conns(struct coresight_device *csdev)
|
||||
{
|
||||
int i;
|
||||
struct device *dev = NULL;
|
||||
struct coresight_connection *conn;
|
||||
|
||||
for (i = 0; i < csdev->nr_outport; i++) {
|
||||
conn = &csdev->conns[i];
|
||||
dev = bus_find_device(&coresight_bustype, NULL,
|
||||
(void *)conn->child_name,
|
||||
coresight_name_match);
|
||||
|
||||
if (dev) {
|
||||
conn->child_dev = to_coresight_device(dev);
|
||||
} else {
|
||||
csdev->orphan = true;
|
||||
conn->child_dev = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* coresight_timeout - loop until a bit has changed to a specific state.
|
||||
* @addr: base address of the area of interest.
|
||||
* @offset: address of a register, starting from @addr.
|
||||
* @position: the position of the bit of interest.
|
||||
* @value: the value the bit should have.
|
||||
*
|
||||
* Return: 0 as soon as the bit has taken the desired state or -EAGAIN if
|
||||
* TIMEOUT_US has elapsed, which ever happens first.
|
||||
*/
|
||||
|
||||
int coresight_timeout(void __iomem *addr, u32 offset, int position, int value)
|
||||
{
|
||||
int i;
|
||||
u32 val;
|
||||
|
||||
for (i = TIMEOUT_US; i > 0; i--) {
|
||||
val = __raw_readl(addr + offset);
|
||||
/* waiting on the bit to go from 0 to 1 */
|
||||
if (value) {
|
||||
if (val & BIT(position))
|
||||
return 0;
|
||||
/* waiting on the bit to go from 1 to 0 */
|
||||
} else {
|
||||
if (!(val & BIT(position)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delay is arbitrary - the specification doesn't say how long
|
||||
* we are expected to wait. Extra check required to make sure
|
||||
* we don't wait needlessly on the last iteration.
|
||||
*/
|
||||
if (i - 1)
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
struct bus_type coresight_bustype = {
|
||||
.name = "coresight",
|
||||
};
|
||||
|
||||
static int __init coresight_init(void)
|
||||
{
|
||||
return bus_register(&coresight_bustype);
|
||||
}
|
||||
postcore_initcall(coresight_init);
|
||||
|
||||
struct coresight_device *coresight_register(struct coresight_desc *desc)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
int link_subtype;
|
||||
int nr_refcnts = 1;
|
||||
atomic_t *refcnts = NULL;
|
||||
struct coresight_device *csdev;
|
||||
struct coresight_connection *conns;
|
||||
|
||||
csdev = kzalloc(sizeof(*csdev), GFP_KERNEL);
|
||||
if (!csdev) {
|
||||
ret = -ENOMEM;
|
||||
goto err_kzalloc_csdev;
|
||||
}
|
||||
|
||||
if (desc->type == CORESIGHT_DEV_TYPE_LINK ||
|
||||
desc->type == CORESIGHT_DEV_TYPE_LINKSINK) {
|
||||
link_subtype = desc->subtype.link_subtype;
|
||||
|
||||
if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG)
|
||||
nr_refcnts = desc->pdata->nr_inport;
|
||||
else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT)
|
||||
nr_refcnts = desc->pdata->nr_outport;
|
||||
}
|
||||
|
||||
refcnts = kcalloc(nr_refcnts, sizeof(*refcnts), GFP_KERNEL);
|
||||
if (!refcnts) {
|
||||
ret = -ENOMEM;
|
||||
goto err_kzalloc_refcnts;
|
||||
}
|
||||
|
||||
csdev->refcnt = refcnts;
|
||||
|
||||
csdev->nr_inport = desc->pdata->nr_inport;
|
||||
csdev->nr_outport = desc->pdata->nr_outport;
|
||||
conns = kcalloc(csdev->nr_outport, sizeof(*conns), GFP_KERNEL);
|
||||
if (!conns) {
|
||||
ret = -ENOMEM;
|
||||
goto err_kzalloc_conns;
|
||||
}
|
||||
|
||||
for (i = 0; i < csdev->nr_outport; i++) {
|
||||
conns[i].outport = desc->pdata->outports[i];
|
||||
conns[i].child_name = desc->pdata->child_names[i];
|
||||
conns[i].child_port = desc->pdata->child_ports[i];
|
||||
}
|
||||
|
||||
csdev->conns = conns;
|
||||
|
||||
csdev->type = desc->type;
|
||||
csdev->subtype = desc->subtype;
|
||||
csdev->ops = desc->ops;
|
||||
csdev->orphan = false;
|
||||
|
||||
csdev->dev.type = &coresight_dev_type[desc->type];
|
||||
csdev->dev.groups = desc->groups;
|
||||
csdev->dev.parent = desc->dev;
|
||||
csdev->dev.release = coresight_device_release;
|
||||
csdev->dev.bus = &coresight_bustype;
|
||||
dev_set_name(&csdev->dev, "%s", desc->pdata->name);
|
||||
|
||||
ret = device_register(&csdev->dev);
|
||||
if (ret)
|
||||
goto err_device_register;
|
||||
|
||||
mutex_lock(&coresight_mutex);
|
||||
|
||||
coresight_fixup_device_conns(csdev);
|
||||
coresight_fixup_orphan_conns(csdev);
|
||||
|
||||
mutex_unlock(&coresight_mutex);
|
||||
|
||||
return csdev;
|
||||
|
||||
err_device_register:
|
||||
kfree(conns);
|
||||
err_kzalloc_conns:
|
||||
kfree(refcnts);
|
||||
err_kzalloc_refcnts:
|
||||
kfree(csdev);
|
||||
err_kzalloc_csdev:
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_register);
|
||||
|
||||
void coresight_unregister(struct coresight_device *csdev)
|
||||
{
|
||||
mutex_lock(&coresight_mutex);
|
||||
|
||||
kfree(csdev->conns);
|
||||
device_unregister(&csdev->dev);
|
||||
|
||||
mutex_unlock(&coresight_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_unregister);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
204
drivers/coresight/of_coresight.c
Normal file
204
drivers/coresight/of_coresight.c
Normal file
@ -0,0 +1,204 @@
|
||||
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/coresight.h>
|
||||
#include <asm/smp_plat.h>
|
||||
|
||||
|
||||
static int of_dev_node_match(struct device *dev, void *data)
|
||||
{
|
||||
return dev->of_node == data;
|
||||
}
|
||||
|
||||
static struct device *
|
||||
of_coresight_get_endpoint_device(struct device_node *endpoint)
|
||||
{
|
||||
struct device *dev = NULL;
|
||||
|
||||
/*
|
||||
* If we have a non-configuable replicator, it will be found on the
|
||||
* platform bus.
|
||||
*/
|
||||
dev = bus_find_device(&platform_bus_type, NULL,
|
||||
endpoint, of_dev_node_match);
|
||||
if (dev)
|
||||
return dev;
|
||||
|
||||
/*
|
||||
* We have a configurable component - circle through the AMBA bus
|
||||
* looking for the device that matches the endpoint node.
|
||||
*/
|
||||
return bus_find_device(&amba_bustype, NULL,
|
||||
endpoint, of_dev_node_match);
|
||||
}
|
||||
|
||||
static struct device_node *of_get_coresight_endpoint(
|
||||
const struct device_node *parent, struct device_node *prev)
|
||||
{
|
||||
struct device_node *node = of_graph_get_next_endpoint(parent, prev);
|
||||
|
||||
of_node_put(prev);
|
||||
return node;
|
||||
}
|
||||
|
||||
static void of_coresight_get_ports(struct device_node *node,
|
||||
int *nr_inport, int *nr_outport)
|
||||
{
|
||||
struct device_node *ep = NULL;
|
||||
int in = 0, out = 0;
|
||||
|
||||
do {
|
||||
ep = of_get_coresight_endpoint(node, ep);
|
||||
if (!ep)
|
||||
break;
|
||||
|
||||
if (of_property_read_bool(ep, "slave-mode"))
|
||||
in++;
|
||||
else
|
||||
out++;
|
||||
|
||||
} while (ep);
|
||||
|
||||
*nr_inport = in;
|
||||
*nr_outport = out;
|
||||
}
|
||||
|
||||
static int of_coresight_alloc_memory(struct device *dev,
|
||||
struct coresight_platform_data *pdata)
|
||||
{
|
||||
/* List of output port on this component */
|
||||
pdata->outports = devm_kzalloc(dev, pdata->nr_outport *
|
||||
sizeof(*pdata->outports),
|
||||
GFP_KERNEL);
|
||||
if (!pdata->outports)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Children connected to this component via @outport */
|
||||
pdata->child_names = devm_kzalloc(dev, pdata->nr_outport *
|
||||
sizeof(*pdata->child_names),
|
||||
GFP_KERNEL);
|
||||
if (!pdata->child_names)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Port number on the child this component is connected to */
|
||||
pdata->child_ports = devm_kzalloc(dev, pdata->nr_outport *
|
||||
sizeof(*pdata->child_ports),
|
||||
GFP_KERNEL);
|
||||
if (!pdata->child_ports)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct coresight_platform_data *of_get_coresight_platform_data(
|
||||
struct device *dev, struct device_node *node)
|
||||
{
|
||||
int i = 0, ret = 0;
|
||||
struct coresight_platform_data *pdata;
|
||||
struct of_endpoint endpoint, rendpoint;
|
||||
struct device *rdev;
|
||||
struct device_node *cpu;
|
||||
struct device_node *ep = NULL;
|
||||
struct device_node *rparent = NULL;
|
||||
struct device_node *rport = NULL;
|
||||
|
||||
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/* Use device name as debugfs handle */
|
||||
pdata->name = dev_name(dev);
|
||||
|
||||
/* Get the number of input and output port for this component */
|
||||
of_coresight_get_ports(node, &pdata->nr_inport, &pdata->nr_outport);
|
||||
|
||||
if (pdata->nr_outport) {
|
||||
ret = of_coresight_alloc_memory(dev, pdata);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
/* Iterate through each port to discover topology */
|
||||
do {
|
||||
/* Get a handle on a port */
|
||||
ep = of_get_coresight_endpoint(node, ep);
|
||||
if (!ep)
|
||||
break;
|
||||
|
||||
/*
|
||||
* No need to deal with input ports, processing for as
|
||||
* processing for output ports will deal with them.
|
||||
*/
|
||||
if (of_find_property(ep, "slave-mode", NULL))
|
||||
continue;
|
||||
|
||||
/* Get a handle on the local endpoint */
|
||||
ret = of_graph_parse_endpoint(ep, &endpoint);
|
||||
|
||||
if (ret)
|
||||
continue;
|
||||
|
||||
/* The local out port number */
|
||||
pdata->outports[i] = endpoint.id;
|
||||
|
||||
/*
|
||||
* Get a handle on the remote port and parent
|
||||
* attached to it.
|
||||
*/
|
||||
rparent = of_graph_get_remote_port_parent(ep);
|
||||
rport = of_graph_get_remote_port(ep);
|
||||
|
||||
if (!rparent || !rport)
|
||||
continue;
|
||||
|
||||
if (of_graph_parse_endpoint(rport, &rendpoint))
|
||||
continue;
|
||||
|
||||
rdev = of_coresight_get_endpoint_device(rparent);
|
||||
if (!dev)
|
||||
continue;
|
||||
|
||||
pdata->child_names[i] = dev_name(rdev);
|
||||
pdata->child_ports[i] = rendpoint.id;
|
||||
|
||||
i++;
|
||||
} while (ep);
|
||||
}
|
||||
|
||||
/* Affinity defaults to CPU0 */
|
||||
pdata->cpu = 0;
|
||||
cpu = of_parse_phandle(node, "cpu", 0);
|
||||
if (cpu) {
|
||||
const u32 *mpidr;
|
||||
int len, index;
|
||||
|
||||
mpidr = of_get_property(cpu, "reg", &len);
|
||||
if (mpidr && len == 4) {
|
||||
index = get_logical_index(be32_to_cpup(mpidr));
|
||||
if (index != -EINVAL)
|
||||
pdata->cpu = index;
|
||||
}
|
||||
}
|
||||
|
||||
return pdata;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_get_coresight_platform_data);
|
@ -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)
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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 */
|
||||
/*
|
||||
|
@ -216,9 +216,16 @@ static void vmbus_process_rescind_offer(struct work_struct *work)
|
||||
unsigned long flags;
|
||||
struct vmbus_channel *primary_channel;
|
||||
struct vmbus_channel_relid_released msg;
|
||||
struct device *dev;
|
||||
|
||||
if (channel->device_obj) {
|
||||
dev = get_device(&channel->device_obj->device);
|
||||
if (dev) {
|
||||
vmbus_device_unregister(channel->device_obj);
|
||||
put_device(dev);
|
||||
}
|
||||
}
|
||||
|
||||
if (channel->device_obj)
|
||||
vmbus_device_unregister(channel->device_obj);
|
||||
memset(&msg, 0, sizeof(struct vmbus_channel_relid_released));
|
||||
msg.child_relid = channel->offermsg.child_relid;
|
||||
msg.header.msgtype = CHANNELMSG_RELID_RELEASED;
|
||||
|
@ -1087,10 +1087,12 @@ static void balloon_up(struct work_struct *dummy)
|
||||
struct dm_balloon_response *bl_resp;
|
||||
int alloc_unit;
|
||||
int ret;
|
||||
bool alloc_error = false;
|
||||
bool alloc_error;
|
||||
bool done = false;
|
||||
int i;
|
||||
|
||||
/* The host balloons pages in 2M granularity. */
|
||||
WARN_ON_ONCE(num_pages % PAGES_IN_2M != 0);
|
||||
|
||||
/*
|
||||
* We will attempt 2M allocations. However, if we fail to
|
||||
@ -1107,16 +1109,18 @@ static void balloon_up(struct work_struct *dummy)
|
||||
|
||||
|
||||
num_pages -= num_ballooned;
|
||||
alloc_error = false;
|
||||
num_ballooned = alloc_balloon_pages(&dm_device, num_pages,
|
||||
bl_resp, alloc_unit,
|
||||
&alloc_error);
|
||||
|
||||
if ((alloc_error) && (alloc_unit != 1)) {
|
||||
if (alloc_unit != 1 && num_ballooned == 0) {
|
||||
alloc_unit = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((alloc_error) || (num_ballooned == num_pages)) {
|
||||
if ((alloc_unit == 1 && alloc_error) ||
|
||||
(num_ballooned == num_pages)) {
|
||||
bl_resp->more_pages = 0;
|
||||
done = true;
|
||||
dm_device.state = DM_INITIALIZED;
|
||||
|
@ -350,6 +350,7 @@ kvp_send_key(struct work_struct *dummy)
|
||||
__u8 pool = kvp_transaction.kvp_msg->kvp_hdr.pool;
|
||||
__u32 val32;
|
||||
__u64 val64;
|
||||
int rc;
|
||||
|
||||
msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC);
|
||||
if (!msg)
|
||||
@ -446,7 +447,13 @@ kvp_send_key(struct work_struct *dummy)
|
||||
}
|
||||
|
||||
msg->len = sizeof(struct hv_kvp_msg);
|
||||
cn_netlink_send(msg, 0, 0, GFP_ATOMIC);
|
||||
rc = cn_netlink_send(msg, 0, 0, GFP_ATOMIC);
|
||||
if (rc) {
|
||||
pr_debug("KVP: failed to communicate to the daemon: %d\n", rc);
|
||||
if (cancel_delayed_work_sync(&kvp_work))
|
||||
kvp_respond_to_host(message, HV_E_FAIL);
|
||||
}
|
||||
|
||||
kfree(msg);
|
||||
|
||||
return;
|
||||
|
@ -28,7 +28,7 @@
|
||||
#define VSS_MINOR 0
|
||||
#define VSS_VERSION (VSS_MAJOR << 16 | VSS_MINOR)
|
||||
|
||||
|
||||
#define VSS_USERSPACE_TIMEOUT (msecs_to_jiffies(10 * 1000))
|
||||
|
||||
/*
|
||||
* Global state maintained for transaction that is being processed.
|
||||
@ -55,12 +55,24 @@ static const char vss_name[] = "vss_kernel_module";
|
||||
static __u8 *recv_buffer;
|
||||
|
||||
static void vss_send_op(struct work_struct *dummy);
|
||||
static void vss_timeout_func(struct work_struct *dummy);
|
||||
|
||||
static DECLARE_DELAYED_WORK(vss_timeout_work, vss_timeout_func);
|
||||
static DECLARE_WORK(vss_send_op_work, vss_send_op);
|
||||
|
||||
/*
|
||||
* Callback when data is received from user mode.
|
||||
*/
|
||||
|
||||
static void vss_timeout_func(struct work_struct *dummy)
|
||||
{
|
||||
/*
|
||||
* Timeout waiting for userspace component to reply happened.
|
||||
*/
|
||||
pr_warn("VSS: timeout waiting for daemon to reply\n");
|
||||
vss_respond_to_host(HV_E_FAIL);
|
||||
}
|
||||
|
||||
static void
|
||||
vss_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
|
||||
{
|
||||
@ -76,13 +88,15 @@ vss_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
|
||||
return;
|
||||
|
||||
}
|
||||
vss_respond_to_host(vss_msg->error);
|
||||
if (cancel_delayed_work_sync(&vss_timeout_work))
|
||||
vss_respond_to_host(vss_msg->error);
|
||||
}
|
||||
|
||||
|
||||
static void vss_send_op(struct work_struct *dummy)
|
||||
{
|
||||
int op = vss_transaction.msg->vss_hdr.operation;
|
||||
int rc;
|
||||
struct cn_msg *msg;
|
||||
struct hv_vss_msg *vss_msg;
|
||||
|
||||
@ -98,7 +112,12 @@ static void vss_send_op(struct work_struct *dummy)
|
||||
vss_msg->vss_hdr.operation = op;
|
||||
msg->len = sizeof(struct hv_vss_msg);
|
||||
|
||||
cn_netlink_send(msg, 0, 0, GFP_ATOMIC);
|
||||
rc = cn_netlink_send(msg, 0, 0, GFP_ATOMIC);
|
||||
if (rc) {
|
||||
pr_warn("VSS: failed to communicate to the daemon: %d\n", rc);
|
||||
if (cancel_delayed_work_sync(&vss_timeout_work))
|
||||
vss_respond_to_host(HV_E_FAIL);
|
||||
}
|
||||
kfree(msg);
|
||||
|
||||
return;
|
||||
@ -223,6 +242,8 @@ void hv_vss_onchannelcallback(void *context)
|
||||
case VSS_OP_FREEZE:
|
||||
case VSS_OP_THAW:
|
||||
schedule_work(&vss_send_op_work);
|
||||
schedule_delayed_work(&vss_timeout_work,
|
||||
VSS_USERSPACE_TIMEOUT);
|
||||
return;
|
||||
|
||||
case VSS_OP_HOT_BACKUP:
|
||||
@ -277,5 +298,6 @@ hv_vss_init(struct hv_util_service *srv)
|
||||
void hv_vss_deinit(void)
|
||||
{
|
||||
cn_del_callback(&vss_id);
|
||||
cancel_delayed_work_sync(&vss_timeout_work);
|
||||
cancel_work_sync(&vss_send_op_work);
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ struct ssc_device *ssc_request(unsigned int ssc_num)
|
||||
ssc->user++;
|
||||
spin_unlock(&user_lock);
|
||||
|
||||
clk_prepare_enable(ssc->clk);
|
||||
clk_prepare(ssc->clk);
|
||||
|
||||
return ssc;
|
||||
}
|
||||
@ -77,7 +77,7 @@ void ssc_free(struct ssc_device *ssc)
|
||||
spin_unlock(&user_lock);
|
||||
|
||||
if (disable_clk)
|
||||
clk_disable_unprepare(ssc->clk);
|
||||
clk_unprepare(ssc->clk);
|
||||
}
|
||||
EXPORT_SYMBOL(ssc_free);
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
config CARMA_FPGA
|
||||
tristate "CARMA DATA-FPGA Access Driver"
|
||||
depends on FSL_SOC && PPC_83xx && MEDIA_SUPPORT && HAS_DMA && FSL_DMA
|
||||
select VIDEOBUF_DMA_SG
|
||||
depends on FSL_SOC && PPC_83xx && HAS_DMA && FSL_DMA
|
||||
default n
|
||||
help
|
||||
Say Y here to include support for communicating with the data
|
||||
@ -9,8 +8,7 @@ config CARMA_FPGA
|
||||
|
||||
config CARMA_FPGA_PROGRAM
|
||||
tristate "CARMA DATA-FPGA Programmer"
|
||||
depends on FSL_SOC && PPC_83xx && MEDIA_SUPPORT && HAS_DMA && FSL_DMA
|
||||
select VIDEOBUF_DMA_SG
|
||||
depends on FSL_SOC && PPC_83xx && HAS_DMA && FSL_DMA
|
||||
default n
|
||||
help
|
||||
Say Y here to include support for programming the data processing
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/fsldma.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
@ -30,8 +31,6 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <media/videobuf-dma-sg.h>
|
||||
|
||||
/* MPC8349EMDS specific get_immrbase() */
|
||||
#include <sysdev/fsl_soc.h>
|
||||
|
||||
@ -67,14 +66,79 @@ struct fpga_dev {
|
||||
/* FPGA Bitfile */
|
||||
struct mutex lock;
|
||||
|
||||
struct videobuf_dmabuf vb;
|
||||
bool vb_allocated;
|
||||
void *vaddr;
|
||||
struct scatterlist *sglist;
|
||||
int sglen;
|
||||
int nr_pages;
|
||||
bool buf_allocated;
|
||||
|
||||
/* max size and written bytes */
|
||||
size_t fw_size;
|
||||
size_t bytes;
|
||||
};
|
||||
|
||||
static int fpga_dma_init(struct fpga_dev *priv, int nr_pages)
|
||||
{
|
||||
struct page *pg;
|
||||
int i;
|
||||
|
||||
priv->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT);
|
||||
if (NULL == priv->vaddr) {
|
||||
pr_debug("vmalloc_32(%d pages) failed\n", nr_pages);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pr_debug("vmalloc is at addr 0x%08lx, size=%d\n",
|
||||
(unsigned long)priv->vaddr,
|
||||
nr_pages << PAGE_SHIFT);
|
||||
|
||||
memset(priv->vaddr, 0, nr_pages << PAGE_SHIFT);
|
||||
priv->nr_pages = nr_pages;
|
||||
|
||||
priv->sglist = vzalloc(priv->nr_pages * sizeof(*priv->sglist));
|
||||
if (NULL == priv->sglist)
|
||||
goto vzalloc_err;
|
||||
|
||||
sg_init_table(priv->sglist, priv->nr_pages);
|
||||
for (i = 0; i < priv->nr_pages; i++) {
|
||||
pg = vmalloc_to_page(priv->vaddr + i * PAGE_SIZE);
|
||||
if (NULL == pg)
|
||||
goto vmalloc_to_page_err;
|
||||
sg_set_page(&priv->sglist[i], pg, PAGE_SIZE, 0);
|
||||
}
|
||||
return 0;
|
||||
|
||||
vmalloc_to_page_err:
|
||||
vfree(priv->sglist);
|
||||
priv->sglist = NULL;
|
||||
vzalloc_err:
|
||||
vfree(priv->vaddr);
|
||||
priv->vaddr = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int fpga_dma_map(struct fpga_dev *priv)
|
||||
{
|
||||
priv->sglen = dma_map_sg(priv->dev, priv->sglist,
|
||||
priv->nr_pages, DMA_TO_DEVICE);
|
||||
|
||||
if (0 == priv->sglen) {
|
||||
pr_warn("%s: dma_map_sg failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fpga_dma_unmap(struct fpga_dev *priv)
|
||||
{
|
||||
if (!priv->sglen)
|
||||
return 0;
|
||||
|
||||
dma_unmap_sg(priv->dev, priv->sglist, priv->sglen, DMA_TO_DEVICE);
|
||||
priv->sglen = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* FPGA Bitfile Helpers
|
||||
*/
|
||||
@ -87,8 +151,9 @@ struct fpga_dev {
|
||||
*/
|
||||
static void fpga_drop_firmware_data(struct fpga_dev *priv)
|
||||
{
|
||||
videobuf_dma_free(&priv->vb);
|
||||
priv->vb_allocated = false;
|
||||
vfree(priv->sglist);
|
||||
vfree(priv->vaddr);
|
||||
priv->buf_allocated = false;
|
||||
priv->bytes = 0;
|
||||
}
|
||||
|
||||
@ -427,7 +492,7 @@ static noinline int fpga_program_cpu(struct fpga_dev *priv)
|
||||
dev_dbg(priv->dev, "enabled the controller\n");
|
||||
|
||||
/* Write each chunk of the FPGA bitfile to FPGA programmer */
|
||||
ret = fpga_program_block(priv, priv->vb.vaddr, priv->bytes);
|
||||
ret = fpga_program_block(priv, priv->vaddr, priv->bytes);
|
||||
if (ret)
|
||||
goto out_disable_controller;
|
||||
|
||||
@ -463,7 +528,6 @@ out_disable_controller:
|
||||
*/
|
||||
static noinline int fpga_program_dma(struct fpga_dev *priv)
|
||||
{
|
||||
struct videobuf_dmabuf *vb = &priv->vb;
|
||||
struct dma_chan *chan = priv->chan;
|
||||
struct dma_async_tx_descriptor *tx;
|
||||
size_t num_pages, len, avail = 0;
|
||||
@ -505,7 +569,7 @@ static noinline int fpga_program_dma(struct fpga_dev *priv)
|
||||
}
|
||||
|
||||
/* Map the buffer for DMA */
|
||||
ret = videobuf_dma_map(priv->dev, &priv->vb);
|
||||
ret = fpga_dma_map(priv);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "Unable to map buffer for DMA\n");
|
||||
goto out_free_table;
|
||||
@ -525,7 +589,7 @@ static noinline int fpga_program_dma(struct fpga_dev *priv)
|
||||
goto out_dma_unmap;
|
||||
}
|
||||
|
||||
ret = fsl_dma_external_start(chan, 1)
|
||||
ret = fsl_dma_external_start(chan, 1);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "DMA external control setup failed\n");
|
||||
goto out_dma_unmap;
|
||||
@ -534,7 +598,7 @@ static noinline int fpga_program_dma(struct fpga_dev *priv)
|
||||
/* setup and submit the DMA transaction */
|
||||
|
||||
tx = dmaengine_prep_dma_sg(chan, table.sgl, num_pages,
|
||||
vb->sglist, vb->sglen, 0);
|
||||
priv->sglist, priv->sglen, 0);
|
||||
if (!tx) {
|
||||
dev_err(priv->dev, "Unable to prep DMA transaction\n");
|
||||
ret = -ENOMEM;
|
||||
@ -572,7 +636,7 @@ static noinline int fpga_program_dma(struct fpga_dev *priv)
|
||||
out_disable_controller:
|
||||
fpga_programmer_disable(priv);
|
||||
out_dma_unmap:
|
||||
videobuf_dma_unmap(priv->dev, vb);
|
||||
fpga_dma_unmap(priv);
|
||||
out_free_table:
|
||||
sg_free_table(&table);
|
||||
out_return:
|
||||
@ -702,12 +766,12 @@ static int fpga_open(struct inode *inode, struct file *filp)
|
||||
priv->bytes = 0;
|
||||
|
||||
/* Check if we have already allocated a buffer */
|
||||
if (priv->vb_allocated)
|
||||
if (priv->buf_allocated)
|
||||
return 0;
|
||||
|
||||
/* Allocate a buffer to hold enough data for the bitfile */
|
||||
nr_pages = DIV_ROUND_UP(priv->fw_size, PAGE_SIZE);
|
||||
ret = videobuf_dma_init_kernel(&priv->vb, DMA_TO_DEVICE, nr_pages);
|
||||
ret = fpga_dma_init(priv, nr_pages);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "unable to allocate data buffer\n");
|
||||
mutex_unlock(&priv->lock);
|
||||
@ -715,7 +779,7 @@ static int fpga_open(struct inode *inode, struct file *filp)
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->vb_allocated = true;
|
||||
priv->buf_allocated = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -738,7 +802,7 @@ static ssize_t fpga_write(struct file *filp, const char __user *buf,
|
||||
return -ENOSPC;
|
||||
|
||||
count = min_t(size_t, priv->fw_size - priv->bytes, count);
|
||||
if (copy_from_user(priv->vb.vaddr + priv->bytes, buf, count))
|
||||
if (copy_from_user(priv->vaddr + priv->bytes, buf, count))
|
||||
return -EFAULT;
|
||||
|
||||
priv->bytes += count;
|
||||
@ -749,20 +813,19 @@ static ssize_t fpga_read(struct file *filp, char __user *buf, size_t count,
|
||||
loff_t *f_pos)
|
||||
{
|
||||
struct fpga_dev *priv = filp->private_data;
|
||||
return simple_read_from_buffer(buf, count, ppos,
|
||||
priv->vb.vaddr, priv->bytes);
|
||||
return simple_read_from_buffer(buf, count, f_pos,
|
||||
priv->vaddr, priv->bytes);
|
||||
}
|
||||
|
||||
static loff_t fpga_llseek(struct file *filp, loff_t offset, int origin)
|
||||
{
|
||||
struct fpga_dev *priv = filp->private_data;
|
||||
loff_t newpos;
|
||||
|
||||
/* only read-only opens are allowed to seek */
|
||||
if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
|
||||
return -EINVAL;
|
||||
|
||||
return fixed_size_llseek(file, offset, origin, priv->fw_size);
|
||||
return fixed_size_llseek(filp, offset, origin, priv->fw_size);
|
||||
}
|
||||
|
||||
static const struct file_operations fpga_fops = {
|
||||
@ -953,7 +1016,6 @@ static int fpga_of_probe(struct platform_device *op)
|
||||
priv->dev = &op->dev;
|
||||
mutex_init(&priv->lock);
|
||||
init_completion(&priv->completion);
|
||||
videobuf_dma_init(&priv->vb);
|
||||
|
||||
dev_set_drvdata(priv->dev, priv);
|
||||
dma_cap_zero(mask);
|
||||
|
@ -98,6 +98,7 @@
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/poll.h>
|
||||
@ -105,8 +106,6 @@
|
||||
#include <linux/kref.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <media/videobuf-dma-sg.h>
|
||||
|
||||
/* system controller registers */
|
||||
#define SYS_IRQ_SOURCE_CTL 0x24
|
||||
#define SYS_IRQ_OUTPUT_EN 0x28
|
||||
@ -142,7 +141,10 @@ struct fpga_info {
|
||||
|
||||
struct data_buf {
|
||||
struct list_head entry;
|
||||
struct videobuf_dmabuf vb;
|
||||
void *vaddr;
|
||||
struct scatterlist *sglist;
|
||||
int sglen;
|
||||
int nr_pages;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
@ -207,6 +209,68 @@ static void fpga_device_release(struct kref *ref)
|
||||
* Data Buffer Allocation Helpers
|
||||
*/
|
||||
|
||||
static int carma_dma_init(struct data_buf *buf, int nr_pages)
|
||||
{
|
||||
struct page *pg;
|
||||
int i;
|
||||
|
||||
buf->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT);
|
||||
if (NULL == buf->vaddr) {
|
||||
pr_debug("vmalloc_32(%d pages) failed\n", nr_pages);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pr_debug("vmalloc is at addr 0x%08lx, size=%d\n",
|
||||
(unsigned long)buf->vaddr,
|
||||
nr_pages << PAGE_SHIFT);
|
||||
|
||||
memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT);
|
||||
buf->nr_pages = nr_pages;
|
||||
|
||||
buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist));
|
||||
if (NULL == buf->sglist)
|
||||
goto vzalloc_err;
|
||||
|
||||
sg_init_table(buf->sglist, buf->nr_pages);
|
||||
for (i = 0; i < buf->nr_pages; i++) {
|
||||
pg = vmalloc_to_page(buf->vaddr + i * PAGE_SIZE);
|
||||
if (NULL == pg)
|
||||
goto vmalloc_to_page_err;
|
||||
sg_set_page(&buf->sglist[i], pg, PAGE_SIZE, 0);
|
||||
}
|
||||
return 0;
|
||||
|
||||
vmalloc_to_page_err:
|
||||
vfree(buf->sglist);
|
||||
buf->sglist = NULL;
|
||||
vzalloc_err:
|
||||
vfree(buf->vaddr);
|
||||
buf->vaddr = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int carma_dma_map(struct device *dev, struct data_buf *buf)
|
||||
{
|
||||
buf->sglen = dma_map_sg(dev, buf->sglist,
|
||||
buf->nr_pages, DMA_FROM_DEVICE);
|
||||
|
||||
if (0 == buf->sglen) {
|
||||
pr_warn("%s: dma_map_sg failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int carma_dma_unmap(struct device *dev, struct data_buf *buf)
|
||||
{
|
||||
if (!buf->sglen)
|
||||
return 0;
|
||||
|
||||
dma_unmap_sg(dev, buf->sglist, buf->sglen, DMA_FROM_DEVICE);
|
||||
buf->sglen = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* data_free_buffer() - free a single data buffer and all allocated memory
|
||||
* @buf: the buffer to free
|
||||
@ -221,7 +285,8 @@ static void data_free_buffer(struct data_buf *buf)
|
||||
return;
|
||||
|
||||
/* free all memory */
|
||||
videobuf_dma_free(&buf->vb);
|
||||
vfree(buf->sglist);
|
||||
vfree(buf->vaddr);
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
@ -230,7 +295,7 @@ static void data_free_buffer(struct data_buf *buf)
|
||||
* @bytes: the number of bytes required
|
||||
*
|
||||
* This allocates all space needed for a data buffer. It must be mapped before
|
||||
* use in a DMA transaction using videobuf_dma_map().
|
||||
* use in a DMA transaction using carma_dma_map().
|
||||
*
|
||||
* Returns NULL on failure
|
||||
*/
|
||||
@ -252,9 +317,8 @@ static struct data_buf *data_alloc_buffer(const size_t bytes)
|
||||
INIT_LIST_HEAD(&buf->entry);
|
||||
buf->size = bytes;
|
||||
|
||||
/* allocate the videobuf */
|
||||
videobuf_dma_init(&buf->vb);
|
||||
ret = videobuf_dma_init_kernel(&buf->vb, DMA_FROM_DEVICE, nr_pages);
|
||||
/* allocate the buffer */
|
||||
ret = carma_dma_init(buf, nr_pages);
|
||||
if (ret)
|
||||
goto out_free_buf;
|
||||
|
||||
@ -285,13 +349,13 @@ static void data_free_buffers(struct fpga_device *priv)
|
||||
|
||||
list_for_each_entry_safe(buf, tmp, &priv->free, entry) {
|
||||
list_del_init(&buf->entry);
|
||||
videobuf_dma_unmap(priv->dev, &buf->vb);
|
||||
carma_dma_unmap(priv->dev, buf);
|
||||
data_free_buffer(buf);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(buf, tmp, &priv->used, entry) {
|
||||
list_del_init(&buf->entry);
|
||||
videobuf_dma_unmap(priv->dev, &buf->vb);
|
||||
carma_dma_unmap(priv->dev, buf);
|
||||
data_free_buffer(buf);
|
||||
}
|
||||
|
||||
@ -330,7 +394,7 @@ static int data_alloc_buffers(struct fpga_device *priv)
|
||||
break;
|
||||
|
||||
/* map it for DMA */
|
||||
ret = videobuf_dma_map(priv->dev, &buf->vb);
|
||||
ret = carma_dma_map(priv->dev, buf);
|
||||
if (ret) {
|
||||
data_free_buffer(buf);
|
||||
break;
|
||||
@ -634,8 +698,8 @@ static int data_submit_dma(struct fpga_device *priv, struct data_buf *buf)
|
||||
dma_addr_t dst, src;
|
||||
unsigned long dma_flags = 0;
|
||||
|
||||
dst_sg = buf->vb.sglist;
|
||||
dst_nents = buf->vb.sglen;
|
||||
dst_sg = buf->sglist;
|
||||
dst_nents = buf->sglen;
|
||||
|
||||
src_sg = priv->corl_table.sgl;
|
||||
src_nents = priv->corl_nents;
|
||||
@ -1134,7 +1198,7 @@ static ssize_t data_read(struct file *filp, char __user *ubuf, size_t count,
|
||||
spin_unlock_irq(&priv->lock);
|
||||
|
||||
/* Buffers are always mapped: unmap it */
|
||||
videobuf_dma_unmap(priv->dev, &dbuf->vb);
|
||||
carma_dma_unmap(priv->dev, dbuf);
|
||||
|
||||
/* save the buffer for later */
|
||||
reader->buf = dbuf;
|
||||
@ -1143,7 +1207,7 @@ static ssize_t data_read(struct file *filp, char __user *ubuf, size_t count,
|
||||
have_buffer:
|
||||
/* Get the number of bytes available */
|
||||
avail = dbuf->size - reader->buf_start;
|
||||
data = dbuf->vb.vaddr + reader->buf_start;
|
||||
data = dbuf->vaddr + reader->buf_start;
|
||||
|
||||
/* Get the number of bytes we can transfer */
|
||||
count = min(count, avail);
|
||||
@ -1171,7 +1235,7 @@ have_buffer:
|
||||
* If it fails, we pretend that the read never happed and return
|
||||
* -EFAULT to userspace. The read will be retried.
|
||||
*/
|
||||
ret = videobuf_dma_map(priv->dev, &dbuf->vb);
|
||||
ret = carma_dma_map(priv->dev, dbuf);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "unable to remap buffer for DMA\n");
|
||||
return -EFAULT;
|
||||
@ -1203,7 +1267,7 @@ out_unlock:
|
||||
spin_unlock_irq(&priv->lock);
|
||||
|
||||
if (drop_buffer) {
|
||||
videobuf_dma_unmap(priv->dev, &dbuf->vb);
|
||||
carma_dma_unmap(priv->dev, dbuf);
|
||||
data_free_buffer(dbuf);
|
||||
}
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
@ -590,6 +590,8 @@ int genwqe_user_vmap(struct genwqe_dev *cd, struct dma_mapping *m, void *uaddr,
|
||||
m->nr_pages,
|
||||
1, /* write by caller */
|
||||
m->page_list); /* ptrs to pages */
|
||||
if (rc < 0)
|
||||
goto fail_get_user_pages;
|
||||
|
||||
/* assumption: get_user_pages can be killed by signals. */
|
||||
if (rc < m->nr_pages) {
|
||||
|
@ -262,6 +262,7 @@ out:
|
||||
static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
|
||||
{
|
||||
struct mei_msg_hdr mei_hdr;
|
||||
struct mei_cl *cl;
|
||||
int ret;
|
||||
|
||||
if (!dev || !cb)
|
||||
@ -277,8 +278,9 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
|
||||
dev->iamthif_msg_buf_size = cb->request_buffer.size;
|
||||
memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
|
||||
cb->request_buffer.size);
|
||||
cl = &dev->iamthif_cl;
|
||||
|
||||
ret = mei_cl_flow_ctrl_creds(&dev->iamthif_cl);
|
||||
ret = mei_cl_flow_ctrl_creds(cl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -292,8 +294,8 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
|
||||
mei_hdr.msg_complete = 1;
|
||||
}
|
||||
|
||||
mei_hdr.host_addr = dev->iamthif_cl.host_client_id;
|
||||
mei_hdr.me_addr = dev->iamthif_cl.me_client_id;
|
||||
mei_hdr.host_addr = cl->host_client_id;
|
||||
mei_hdr.me_addr = cl->me_client_id;
|
||||
mei_hdr.reserved = 0;
|
||||
mei_hdr.internal = 0;
|
||||
dev->iamthif_msg_buf_index += mei_hdr.length;
|
||||
@ -302,7 +304,7 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
|
||||
return ret;
|
||||
|
||||
if (mei_hdr.msg_complete) {
|
||||
if (mei_cl_flow_ctrl_reduce(&dev->iamthif_cl))
|
||||
if (mei_cl_flow_ctrl_reduce(cl))
|
||||
return -EIO;
|
||||
dev->iamthif_flow_control_pending = true;
|
||||
dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
|
||||
@ -360,8 +362,7 @@ int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb)
|
||||
void mei_amthif_run_next_cmd(struct mei_device *dev)
|
||||
{
|
||||
struct mei_cl_cb *cb;
|
||||
struct mei_cl_cb *next;
|
||||
int status;
|
||||
int ret;
|
||||
|
||||
if (!dev)
|
||||
return;
|
||||
@ -376,16 +377,14 @@ void mei_amthif_run_next_cmd(struct mei_device *dev)
|
||||
|
||||
dev_dbg(dev->dev, "complete amthif cmd_list cb.\n");
|
||||
|
||||
list_for_each_entry_safe(cb, next, &dev->amthif_cmd_list.list, list) {
|
||||
list_del(&cb->list);
|
||||
if (!cb->cl)
|
||||
continue;
|
||||
status = mei_amthif_send_cmd(dev, cb);
|
||||
if (status)
|
||||
dev_warn(dev->dev, "amthif write failed status = %d\n",
|
||||
status);
|
||||
break;
|
||||
}
|
||||
cb = list_first_entry_or_null(&dev->amthif_cmd_list.list,
|
||||
typeof(*cb), list);
|
||||
if (!cb)
|
||||
return;
|
||||
list_del(&cb->list);
|
||||
ret = mei_amthif_send_cmd(dev, cb);
|
||||
if (ret)
|
||||
dev_warn(dev->dev, "amthif write failed status = %d\n", ret);
|
||||
}
|
||||
|
||||
|
||||
@ -536,9 +535,6 @@ int mei_amthif_irq_read_msg(struct mei_device *dev,
|
||||
cb = dev->iamthif_current_cb;
|
||||
dev->iamthif_current_cb = NULL;
|
||||
|
||||
if (!cb->cl)
|
||||
return -ENODEV;
|
||||
|
||||
dev->iamthif_stall_timer = 0;
|
||||
cb->buf_idx = dev->iamthif_msg_buf_index;
|
||||
cb->read_time = jiffies;
|
||||
|
@ -140,7 +140,7 @@ static struct device_type mei_cl_device_type = {
|
||||
.release = mei_cl_dev_release,
|
||||
};
|
||||
|
||||
static struct mei_cl *mei_bus_find_mei_cl_by_uuid(struct mei_device *dev,
|
||||
struct mei_cl *mei_cl_bus_find_cl_by_uuid(struct mei_device *dev,
|
||||
uuid_le uuid)
|
||||
{
|
||||
struct mei_cl *cl;
|
||||
@ -160,7 +160,7 @@ struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
|
||||
struct mei_cl *cl;
|
||||
int status;
|
||||
|
||||
cl = mei_bus_find_mei_cl_by_uuid(dev, uuid);
|
||||
cl = mei_cl_bus_find_cl_by_uuid(dev, uuid);
|
||||
if (cl == NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -146,7 +146,7 @@ static void __mei_io_list_flush(struct mei_cl_cb *list,
|
||||
|
||||
/* enable removing everything if no cl is specified */
|
||||
list_for_each_entry_safe(cb, next, &list->list, list) {
|
||||
if (!cl || (cb->cl && mei_cl_cmp_id(cl, cb->cl))) {
|
||||
if (!cl || mei_cl_cmp_id(cl, cb->cl)) {
|
||||
list_del(&cb->list);
|
||||
if (free)
|
||||
mei_io_cb_free(cb);
|
||||
|
@ -34,7 +34,7 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
|
||||
int pos = 0;
|
||||
int ret;
|
||||
|
||||
#define HDR " |id|addr| UUID |con|msg len|sb|\n"
|
||||
#define HDR " |id|fix| UUID |con|msg len|sb|\n"
|
||||
|
||||
mutex_lock(&dev->device_lock);
|
||||
|
||||
@ -56,12 +56,8 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
|
||||
|
||||
list_for_each_entry(me_cl, &dev->me_clients, list) {
|
||||
|
||||
/* skip me clients that cannot be connected */
|
||||
if (me_cl->props.max_number_of_connections == 0)
|
||||
continue;
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"%2d|%2d|%4d|%pUl|%3d|%7d|%2d|\n",
|
||||
"%2d|%2d|%3d|%pUl|%3d|%7d|%2d|\n",
|
||||
i++, me_cl->client_id,
|
||||
me_cl->props.fixed_address,
|
||||
&me_cl->props.protocol_name,
|
||||
|
@ -562,17 +562,17 @@ int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl)
|
||||
* mei_hbm_cl_disconnect_res - update the client state according
|
||||
* disconnect response
|
||||
*
|
||||
* @dev: the device structure
|
||||
* @cl: mei host client
|
||||
* @cmd: disconnect client response host bus message
|
||||
*/
|
||||
static void mei_hbm_cl_disconnect_res(struct mei_cl *cl,
|
||||
static void mei_hbm_cl_disconnect_res(struct mei_device *dev, struct mei_cl *cl,
|
||||
struct mei_hbm_cl_cmd *cmd)
|
||||
{
|
||||
struct hbm_client_connect_response *rs =
|
||||
(struct hbm_client_connect_response *)cmd;
|
||||
|
||||
dev_dbg(cl->dev->dev, "hbm: disconnect response cl:host=%02d me=%02d status=%d\n",
|
||||
rs->me_addr, rs->host_addr, rs->status);
|
||||
cl_dbg(dev, cl, "hbm: disconnect response status=%d\n", rs->status);
|
||||
|
||||
if (rs->status == MEI_CL_DISCONN_SUCCESS)
|
||||
cl->state = MEI_FILE_DISCONNECTED;
|
||||
@ -598,17 +598,17 @@ int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl)
|
||||
* mei_hbm_cl_connect_res - update the client state according
|
||||
* connection response
|
||||
*
|
||||
* @dev: the device structure
|
||||
* @cl: mei host client
|
||||
* @cmd: connect client response host bus message
|
||||
*/
|
||||
static void mei_hbm_cl_connect_res(struct mei_cl *cl,
|
||||
static void mei_hbm_cl_connect_res(struct mei_device *dev, struct mei_cl *cl,
|
||||
struct mei_hbm_cl_cmd *cmd)
|
||||
{
|
||||
struct hbm_client_connect_response *rs =
|
||||
(struct hbm_client_connect_response *)cmd;
|
||||
|
||||
dev_dbg(cl->dev->dev, "hbm: connect response cl:host=%02d me=%02d status=%s\n",
|
||||
rs->me_addr, rs->host_addr,
|
||||
cl_dbg(dev, cl, "hbm: connect response status=%s\n",
|
||||
mei_cl_conn_status_str(rs->status));
|
||||
|
||||
if (rs->status == MEI_CL_CONN_SUCCESS)
|
||||
@ -637,11 +637,6 @@ static void mei_hbm_cl_res(struct mei_device *dev,
|
||||
list_for_each_entry_safe(cb, next, &dev->ctrl_rd_list.list, list) {
|
||||
|
||||
cl = cb->cl;
|
||||
/* this should not happen */
|
||||
if (WARN_ON(!cl)) {
|
||||
list_del_init(&cb->list);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cb->fop_type != fop_type)
|
||||
continue;
|
||||
@ -657,10 +652,10 @@ static void mei_hbm_cl_res(struct mei_device *dev,
|
||||
|
||||
switch (fop_type) {
|
||||
case MEI_FOP_CONNECT:
|
||||
mei_hbm_cl_connect_res(cl, rs);
|
||||
mei_hbm_cl_connect_res(dev, cl, rs);
|
||||
break;
|
||||
case MEI_FOP_DISCONNECT:
|
||||
mei_hbm_cl_disconnect_res(cl, rs);
|
||||
mei_hbm_cl_disconnect_res(dev, cl, rs);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
@ -811,8 +806,6 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
dev->hbm_state = MEI_HBM_STARTED;
|
||||
|
||||
if (mei_hbm_enum_clients_req(dev)) {
|
||||
dev_err(dev->dev, "hbm: start: failed to send enumeration request\n");
|
||||
return -EIO;
|
||||
|
@ -26,17 +26,17 @@ struct mei_cl;
|
||||
*
|
||||
* @MEI_HBM_IDLE : protocol not started
|
||||
* @MEI_HBM_STARTING : start request message was sent
|
||||
* @MEI_HBM_STARTED : start reply message was received
|
||||
* @MEI_HBM_ENUM_CLIENTS : enumeration request was sent
|
||||
* @MEI_HBM_CLIENT_PROPERTIES : acquiring clients properties
|
||||
* @MEI_HBM_STARTED : enumeration was completed
|
||||
* @MEI_HBM_STOPPED : stopping exchange
|
||||
*/
|
||||
enum mei_hbm_state {
|
||||
MEI_HBM_IDLE = 0,
|
||||
MEI_HBM_STARTING,
|
||||
MEI_HBM_STARTED,
|
||||
MEI_HBM_ENUM_CLIENTS,
|
||||
MEI_HBM_CLIENT_PROPERTIES,
|
||||
MEI_HBM_STARTED,
|
||||
MEI_HBM_STOPPED,
|
||||
};
|
||||
|
||||
|
@ -117,14 +117,18 @@
|
||||
#define MEI_DEV_ID_WPT_LP 0x9CBA /* Wildcat Point LP */
|
||||
#define MEI_DEV_ID_WPT_LP_2 0x9CBB /* Wildcat Point LP 2 */
|
||||
|
||||
/* Host Firmware Status Registers in PCI Config Space */
|
||||
#define PCI_CFG_HFS_1 0x40
|
||||
#define PCI_CFG_HFS_2 0x48
|
||||
|
||||
/*
|
||||
* MEI HW Section
|
||||
*/
|
||||
|
||||
/* Host Firmware Status Registers in PCI Config Space */
|
||||
#define PCI_CFG_HFS_1 0x40
|
||||
#define PCI_CFG_HFS_2 0x48
|
||||
#define PCI_CFG_HFS_3 0x60
|
||||
#define PCI_CFG_HFS_4 0x64
|
||||
#define PCI_CFG_HFS_5 0x68
|
||||
#define PCI_CFG_HFS_6 0x6C
|
||||
|
||||
/* MEI registers */
|
||||
/* H_CB_WW - Host Circular Buffer (CB) Write Window register */
|
||||
#define H_CB_WW 0
|
||||
|
@ -270,10 +270,10 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
|
||||
static void mei_me_host_set_ready(struct mei_device *dev)
|
||||
{
|
||||
struct mei_me_hw *hw = to_me_hw(dev);
|
||||
u32 hcsr = mei_hcsr_read(hw);
|
||||
|
||||
hw->host_hw_state = mei_hcsr_read(hw);
|
||||
hw->host_hw_state |= H_IE | H_IG | H_RDY;
|
||||
mei_hcsr_set(hw, hw->host_hw_state);
|
||||
hcsr |= H_IE | H_IG | H_RDY;
|
||||
mei_hcsr_set(hw, hcsr);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -285,9 +285,9 @@ static void mei_me_host_set_ready(struct mei_device *dev)
|
||||
static bool mei_me_host_is_ready(struct mei_device *dev)
|
||||
{
|
||||
struct mei_me_hw *hw = to_me_hw(dev);
|
||||
u32 hcsr = mei_hcsr_read(hw);
|
||||
|
||||
hw->host_hw_state = mei_hcsr_read(hw);
|
||||
return (hw->host_hw_state & H_RDY) == H_RDY;
|
||||
return (hcsr & H_RDY) == H_RDY;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -299,9 +299,9 @@ static bool mei_me_host_is_ready(struct mei_device *dev)
|
||||
static bool mei_me_hw_is_ready(struct mei_device *dev)
|
||||
{
|
||||
struct mei_me_hw *hw = to_me_hw(dev);
|
||||
u32 mecsr = mei_me_mecsr_read(hw);
|
||||
|
||||
hw->me_hw_state = mei_me_mecsr_read(hw);
|
||||
return (hw->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA;
|
||||
return (mecsr & ME_RDY_HRA) == ME_RDY_HRA;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -356,12 +356,13 @@ static int mei_me_hw_start(struct mei_device *dev)
|
||||
static unsigned char mei_hbuf_filled_slots(struct mei_device *dev)
|
||||
{
|
||||
struct mei_me_hw *hw = to_me_hw(dev);
|
||||
u32 hcsr;
|
||||
char read_ptr, write_ptr;
|
||||
|
||||
hw->host_hw_state = mei_hcsr_read(hw);
|
||||
hcsr = mei_hcsr_read(hw);
|
||||
|
||||
read_ptr = (char) ((hw->host_hw_state & H_CBRP) >> 8);
|
||||
write_ptr = (char) ((hw->host_hw_state & H_CBWP) >> 16);
|
||||
read_ptr = (char) ((hcsr & H_CBRP) >> 8);
|
||||
write_ptr = (char) ((hcsr & H_CBWP) >> 16);
|
||||
|
||||
return (unsigned char) (write_ptr - read_ptr);
|
||||
}
|
||||
@ -474,13 +475,14 @@ static int mei_me_write_message(struct mei_device *dev,
|
||||
static int mei_me_count_full_read_slots(struct mei_device *dev)
|
||||
{
|
||||
struct mei_me_hw *hw = to_me_hw(dev);
|
||||
u32 me_csr;
|
||||
char read_ptr, write_ptr;
|
||||
unsigned char buffer_depth, filled_slots;
|
||||
|
||||
hw->me_hw_state = mei_me_mecsr_read(hw);
|
||||
buffer_depth = (unsigned char)((hw->me_hw_state & ME_CBD_HRA) >> 24);
|
||||
read_ptr = (char) ((hw->me_hw_state & ME_CBRP_HRA) >> 8);
|
||||
write_ptr = (char) ((hw->me_hw_state & ME_CBWP_HRA) >> 16);
|
||||
me_csr = mei_me_mecsr_read(hw);
|
||||
buffer_depth = (unsigned char)((me_csr & ME_CBD_HRA) >> 24);
|
||||
read_ptr = (char) ((me_csr & ME_CBRP_HRA) >> 8);
|
||||
write_ptr = (char) ((me_csr & ME_CBWP_HRA) >> 16);
|
||||
filled_slots = (unsigned char) (write_ptr - read_ptr);
|
||||
|
||||
/* check for overflow */
|
||||
@ -833,6 +835,14 @@ static bool mei_me_fw_type_sps(struct pci_dev *pdev)
|
||||
.fw_status.status[0] = PCI_CFG_HFS_1, \
|
||||
.fw_status.status[1] = PCI_CFG_HFS_2
|
||||
|
||||
#define MEI_CFG_PCH8_HFS \
|
||||
.fw_status.count = 6, \
|
||||
.fw_status.status[0] = PCI_CFG_HFS_1, \
|
||||
.fw_status.status[1] = PCI_CFG_HFS_2, \
|
||||
.fw_status.status[2] = PCI_CFG_HFS_3, \
|
||||
.fw_status.status[3] = PCI_CFG_HFS_4, \
|
||||
.fw_status.status[4] = PCI_CFG_HFS_5, \
|
||||
.fw_status.status[5] = PCI_CFG_HFS_6
|
||||
|
||||
/* ICH Legacy devices */
|
||||
const struct mei_cfg mei_me_legacy_cfg = {
|
||||
@ -856,9 +866,14 @@ const struct mei_cfg mei_me_pch_cpt_pbg_cfg = {
|
||||
MEI_CFG_FW_NM,
|
||||
};
|
||||
|
||||
/* PCH Lynx Point with quirk for SPS Firmware exclusion */
|
||||
const struct mei_cfg mei_me_lpt_cfg = {
|
||||
MEI_CFG_PCH_HFS,
|
||||
/* PCH8 Lynx Point and newer devices */
|
||||
const struct mei_cfg mei_me_pch8_cfg = {
|
||||
MEI_CFG_PCH8_HFS,
|
||||
};
|
||||
|
||||
/* PCH8 Lynx Point with quirk for SPS Firmware exclusion */
|
||||
const struct mei_cfg mei_me_pch8_sps_cfg = {
|
||||
MEI_CFG_PCH8_HFS,
|
||||
MEI_CFG_FW_SPS,
|
||||
};
|
||||
|
||||
|
@ -51,18 +51,11 @@ struct mei_cfg {
|
||||
*
|
||||
* @cfg: per device generation config and ops
|
||||
* @mem_addr: io memory address
|
||||
* @host_hw_state: cached host state
|
||||
* @me_hw_state: cached me (fw) state
|
||||
* @pg_state: power gating state
|
||||
*/
|
||||
struct mei_me_hw {
|
||||
const struct mei_cfg *cfg;
|
||||
void __iomem *mem_addr;
|
||||
/*
|
||||
* hw states of host and fw(ME)
|
||||
*/
|
||||
u32 host_hw_state;
|
||||
u32 me_hw_state;
|
||||
enum mei_pg_state pg_state;
|
||||
};
|
||||
|
||||
@ -72,7 +65,8 @@ extern const struct mei_cfg mei_me_legacy_cfg;
|
||||
extern const struct mei_cfg mei_me_ich_cfg;
|
||||
extern const struct mei_cfg mei_me_pch_cfg;
|
||||
extern const struct mei_cfg mei_me_pch_cpt_pbg_cfg;
|
||||
extern const struct mei_cfg mei_me_lpt_cfg;
|
||||
extern const struct mei_cfg mei_me_pch8_cfg;
|
||||
extern const struct mei_cfg mei_me_pch8_sps_cfg;
|
||||
|
||||
struct mei_device *mei_me_dev_init(struct pci_dev *pdev,
|
||||
const struct mei_cfg *cfg);
|
||||
|
@ -700,11 +700,10 @@ static int mei_txe_write(struct mei_device *dev,
|
||||
mei_txe_input_ready_interrupt_enable(dev);
|
||||
|
||||
if (!mei_txe_is_input_ready(dev)) {
|
||||
struct mei_fw_status fw_status;
|
||||
char fw_sts_str[MEI_FW_STATUS_STR_SZ];
|
||||
|
||||
mei_fw_status(dev, &fw_status);
|
||||
dev_err(dev->dev, "Input is not ready " FW_STS_FMT "\n",
|
||||
FW_STS_PRM(fw_status));
|
||||
mei_fw_status_str(dev, fw_sts_str, MEI_FW_STATUS_STR_SZ);
|
||||
dev_err(dev->dev, "Input is not ready %s\n", fw_sts_str);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,35 @@ const char *mei_pg_state_str(enum mei_pg_state state)
|
||||
#undef MEI_PG_STATE
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_fw_status2str - convert fw status registers to printable string
|
||||
*
|
||||
* @fw_status: firmware status
|
||||
* @buf: string buffer at minimal size MEI_FW_STATUS_STR_SZ
|
||||
* @len: buffer len must be >= MEI_FW_STATUS_STR_SZ
|
||||
*
|
||||
* Return: number of bytes written or -EINVAL if buffer is to small
|
||||
*/
|
||||
ssize_t mei_fw_status2str(struct mei_fw_status *fw_status,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
ssize_t cnt = 0;
|
||||
int i;
|
||||
|
||||
buf[0] = '\0';
|
||||
|
||||
if (len < MEI_FW_STATUS_STR_SZ)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < fw_status->count; i++)
|
||||
cnt += scnprintf(buf + cnt, len - cnt, "%08X ",
|
||||
fw_status->status[i]);
|
||||
|
||||
/* drop last space */
|
||||
buf[cnt] = '\0';
|
||||
return cnt;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mei_fw_status2str);
|
||||
|
||||
/**
|
||||
* mei_cancel_work - Cancel mei background jobs
|
||||
@ -86,12 +115,11 @@ int mei_reset(struct mei_device *dev)
|
||||
state != MEI_DEV_DISABLED &&
|
||||
state != MEI_DEV_POWER_DOWN &&
|
||||
state != MEI_DEV_POWER_UP) {
|
||||
struct mei_fw_status fw_status;
|
||||
char fw_sts_str[MEI_FW_STATUS_STR_SZ];
|
||||
|
||||
mei_fw_status(dev, &fw_status);
|
||||
dev_warn(dev->dev,
|
||||
"unexpected reset: dev_state = %s " FW_STS_FMT "\n",
|
||||
mei_dev_state_str(state), FW_STS_PRM(fw_status));
|
||||
mei_fw_status_str(dev, fw_sts_str, MEI_FW_STATUS_STR_SZ);
|
||||
dev_warn(dev->dev, "unexpected reset: dev_state = %s fw status = %s\n",
|
||||
mei_dev_state_str(state), fw_sts_str);
|
||||
}
|
||||
|
||||
/* we're already in reset, cancel the init timer
|
||||
|
@ -44,8 +44,6 @@ void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *compl_list)
|
||||
list_for_each_entry_safe(cb, next, &compl_list->list, list) {
|
||||
cl = cb->cl;
|
||||
list_del(&cb->list);
|
||||
if (!cl)
|
||||
continue;
|
||||
|
||||
dev_dbg(dev->dev, "completing call back.\n");
|
||||
if (cl == &dev->iamthif_cl)
|
||||
@ -105,7 +103,7 @@ static int mei_cl_irq_read_msg(struct mei_device *dev,
|
||||
|
||||
list_for_each_entry_safe(cb, next, &dev->read_list.list, list) {
|
||||
cl = cb->cl;
|
||||
if (!cl || !mei_cl_is_reading(cl, mei_hdr))
|
||||
if (!mei_cl_is_reading(cl, mei_hdr))
|
||||
continue;
|
||||
|
||||
cl->reading_state = MEI_READING;
|
||||
@ -449,8 +447,6 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
|
||||
list = &dev->write_waiting_list;
|
||||
list_for_each_entry_safe(cb, next, &list->list, list) {
|
||||
cl = cb->cl;
|
||||
if (cl == NULL)
|
||||
continue;
|
||||
|
||||
cl->status = 0;
|
||||
list_del(&cb->list);
|
||||
@ -489,10 +485,6 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
|
||||
dev_dbg(dev->dev, "complete control write list cb.\n");
|
||||
list_for_each_entry_safe(cb, next, &dev->ctrl_wr_list.list, list) {
|
||||
cl = cb->cl;
|
||||
if (!cl) {
|
||||
list_del(&cb->list);
|
||||
return -ENODEV;
|
||||
}
|
||||
switch (cb->fop_type) {
|
||||
case MEI_FOP_DISCONNECT:
|
||||
/* send disconnect message */
|
||||
@ -530,8 +522,6 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
|
||||
dev_dbg(dev->dev, "complete write list cb.\n");
|
||||
list_for_each_entry_safe(cb, next, &dev->write_list.list, list) {
|
||||
cl = cb->cl;
|
||||
if (cl == NULL)
|
||||
continue;
|
||||
if (cl == &dev->iamthif_cl)
|
||||
ret = mei_amthif_irq_write(cl, cb, cmpl_list);
|
||||
else
|
||||
|
@ -631,6 +631,44 @@ out:
|
||||
return mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* fw_status_show - mei device attribute show method
|
||||
*
|
||||
* @device: device pointer
|
||||
* @attr: attribute pointer
|
||||
* @buf: char out buffer
|
||||
*
|
||||
* Return: number of the bytes printed into buf or error
|
||||
*/
|
||||
static ssize_t fw_status_show(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct mei_device *dev = dev_get_drvdata(device);
|
||||
struct mei_fw_status fw_status;
|
||||
int err, i;
|
||||
ssize_t cnt = 0;
|
||||
|
||||
mutex_lock(&dev->device_lock);
|
||||
err = mei_fw_status(dev, &fw_status);
|
||||
mutex_unlock(&dev->device_lock);
|
||||
if (err) {
|
||||
dev_err(device, "read fw_status error = %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
for (i = 0; i < fw_status.count; i++)
|
||||
cnt += scnprintf(buf + cnt, PAGE_SIZE - cnt, "%08X\n",
|
||||
fw_status.status[i]);
|
||||
return cnt;
|
||||
}
|
||||
static DEVICE_ATTR_RO(fw_status);
|
||||
|
||||
static struct attribute *mei_attrs[] = {
|
||||
&dev_attr_fw_status.attr,
|
||||
NULL
|
||||
};
|
||||
ATTRIBUTE_GROUPS(mei);
|
||||
|
||||
/*
|
||||
* file operations structure will be used for mei char device.
|
||||
*/
|
||||
@ -710,8 +748,9 @@ int mei_register(struct mei_device *dev, struct device *parent)
|
||||
goto err_dev_add;
|
||||
}
|
||||
|
||||
clsdev = device_create(mei_class, parent, devno,
|
||||
NULL, "mei%d", dev->minor);
|
||||
clsdev = device_create_with_groups(mei_class, parent, devno,
|
||||
dev, mei_groups,
|
||||
"mei%d", dev->minor);
|
||||
|
||||
if (IS_ERR(clsdev)) {
|
||||
dev_err(parent, "unable to create device %d:%d\n",
|
||||
|
@ -152,7 +152,10 @@ struct mei_msg_data {
|
||||
};
|
||||
|
||||
/* Maximum number of processed FW status registers */
|
||||
#define MEI_FW_STATUS_MAX 2
|
||||
#define MEI_FW_STATUS_MAX 6
|
||||
/* Minimal buffer for FW status string (8 bytes in dw + space or '\0') */
|
||||
#define MEI_FW_STATUS_STR_SZ (MEI_FW_STATUS_MAX * (8 + 1))
|
||||
|
||||
|
||||
/*
|
||||
* struct mei_fw_status - storage of FW status data
|
||||
@ -349,6 +352,7 @@ void mei_cl_bus_rx_event(struct mei_cl *cl);
|
||||
void mei_cl_bus_remove_devices(struct mei_device *dev);
|
||||
int mei_cl_bus_init(void);
|
||||
void mei_cl_bus_exit(void);
|
||||
struct mei_cl *mei_cl_bus_find_cl_by_uuid(struct mei_device *dev, uuid_le uuid);
|
||||
|
||||
|
||||
/**
|
||||
@ -804,11 +808,6 @@ static inline int mei_fw_status(struct mei_device *dev,
|
||||
return dev->ops->fw_status(dev, fw_status);
|
||||
}
|
||||
|
||||
#define FW_STS_FMT "%08X %08X"
|
||||
#define FW_STS_PRM(fw_status) \
|
||||
(fw_status).count > 0 ? (fw_status).status[0] : 0xDEADBEEF, \
|
||||
(fw_status).count > 1 ? (fw_status).status[1] : 0xDEADBEEF
|
||||
|
||||
bool mei_hbuf_acquire(struct mei_device *dev);
|
||||
|
||||
bool mei_write_is_idle(struct mei_device *dev);
|
||||
@ -832,4 +831,32 @@ void mei_deregister(struct mei_device *dev);
|
||||
(hdr)->host_addr, (hdr)->me_addr, \
|
||||
(hdr)->length, (hdr)->internal, (hdr)->msg_complete
|
||||
|
||||
ssize_t mei_fw_status2str(struct mei_fw_status *fw_sts, char *buf, size_t len);
|
||||
/**
|
||||
* mei_fw_status_str - fetch and convert fw status registers to printable string
|
||||
*
|
||||
* @dev: the device structure
|
||||
* @buf: string buffer at minimal size MEI_FW_STATUS_STR_SZ
|
||||
* @len: buffer len must be >= MEI_FW_STATUS_STR_SZ
|
||||
*
|
||||
* Return: number of bytes written or < 0 on failure
|
||||
*/
|
||||
static inline ssize_t mei_fw_status_str(struct mei_device *dev,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
struct mei_fw_status fw_status;
|
||||
int ret;
|
||||
|
||||
buf[0] = '\0';
|
||||
|
||||
ret = mei_fw_status(dev, &fw_status);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mei_fw_status2str(&fw_status, buf, MEI_FW_STATUS_STR_SZ);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -117,8 +117,6 @@ struct mei_nfc_dev {
|
||||
u16 recv_req_id;
|
||||
};
|
||||
|
||||
static struct mei_nfc_dev nfc_dev;
|
||||
|
||||
/* UUIDs for NFC F/W clients */
|
||||
const uuid_le mei_nfc_guid = UUID_LE(0x0bb17a78, 0x2a8e, 0x4c50,
|
||||
0x94, 0xd4, 0x50, 0x26,
|
||||
@ -138,6 +136,9 @@ static const uuid_le mei_nfc_info_guid = UUID_LE(0xd2de1625, 0x382d, 0x417d,
|
||||
|
||||
static void mei_nfc_free(struct mei_nfc_dev *ndev)
|
||||
{
|
||||
if (!ndev)
|
||||
return;
|
||||
|
||||
if (ndev->cl) {
|
||||
list_del(&ndev->cl->device_link);
|
||||
mei_cl_unlink(ndev->cl);
|
||||
@ -150,7 +151,7 @@ static void mei_nfc_free(struct mei_nfc_dev *ndev)
|
||||
kfree(ndev->cl_info);
|
||||
}
|
||||
|
||||
memset(ndev, 0, sizeof(struct mei_nfc_dev));
|
||||
kfree(ndev);
|
||||
}
|
||||
|
||||
static int mei_nfc_build_bus_name(struct mei_nfc_dev *ndev)
|
||||
@ -319,9 +320,10 @@ err:
|
||||
static int mei_nfc_enable(struct mei_cl_device *cldev)
|
||||
{
|
||||
struct mei_device *dev;
|
||||
struct mei_nfc_dev *ndev = &nfc_dev;
|
||||
struct mei_nfc_dev *ndev;
|
||||
int ret;
|
||||
|
||||
ndev = (struct mei_nfc_dev *)cldev->priv_data;
|
||||
dev = ndev->cl->dev;
|
||||
|
||||
ret = mei_nfc_connect(ndev);
|
||||
@ -479,15 +481,25 @@ err:
|
||||
|
||||
int mei_nfc_host_init(struct mei_device *dev)
|
||||
{
|
||||
struct mei_nfc_dev *ndev = &nfc_dev;
|
||||
struct mei_nfc_dev *ndev;
|
||||
struct mei_cl *cl_info, *cl = NULL;
|
||||
struct mei_me_client *me_cl;
|
||||
int ret;
|
||||
|
||||
/* already initialized */
|
||||
if (ndev->cl_info)
|
||||
|
||||
/* in case of internal reset bail out
|
||||
* as the device is already setup
|
||||
*/
|
||||
cl = mei_cl_bus_find_cl_by_uuid(dev, mei_nfc_guid);
|
||||
if (cl)
|
||||
return 0;
|
||||
|
||||
ndev = kzalloc(sizeof(struct mei_nfc_dev), GFP_KERNEL);
|
||||
if (!ndev) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ndev->cl_info = mei_cl_allocate(dev);
|
||||
ndev->cl = mei_cl_allocate(dev);
|
||||
|
||||
@ -550,9 +562,31 @@ err:
|
||||
|
||||
void mei_nfc_host_exit(struct mei_device *dev)
|
||||
{
|
||||
struct mei_nfc_dev *ndev = &nfc_dev;
|
||||
struct mei_nfc_dev *ndev;
|
||||
struct mei_cl *cl;
|
||||
struct mei_cl_device *cldev;
|
||||
|
||||
cancel_work_sync(&ndev->init_work);
|
||||
cl = mei_cl_bus_find_cl_by_uuid(dev, mei_nfc_guid);
|
||||
if (!cl)
|
||||
return;
|
||||
|
||||
cldev = cl->device;
|
||||
if (!cldev)
|
||||
return;
|
||||
|
||||
ndev = (struct mei_nfc_dev *)cldev->priv_data;
|
||||
if (ndev)
|
||||
cancel_work_sync(&ndev->init_work);
|
||||
|
||||
cldev->priv_data = NULL;
|
||||
|
||||
mutex_lock(&dev->device_lock);
|
||||
/* Need to remove the device here
|
||||
* since mei_nfc_free will unlink the clients
|
||||
*/
|
||||
mei_cl_remove_device(cldev);
|
||||
mei_nfc_free(ndev);
|
||||
mutex_unlock(&dev->device_lock);
|
||||
}
|
||||
|
||||
|
||||
|
@ -76,12 +76,12 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_PPT_1, mei_me_pch_cfg)},
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_PPT_2, mei_me_pch_cfg)},
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_PPT_3, mei_me_pch_cfg)},
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_LPT_H, mei_me_lpt_cfg)},
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_LPT_W, mei_me_lpt_cfg)},
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_LPT_LP, mei_me_pch_cfg)},
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_LPT_HR, mei_me_lpt_cfg)},
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP, mei_me_pch_cfg)},
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP_2, mei_me_pch_cfg)},
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_LPT_H, mei_me_pch8_sps_cfg)},
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_LPT_W, mei_me_pch8_sps_cfg)},
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_LPT_LP, mei_me_pch8_cfg)},
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_LPT_HR, mei_me_pch8_sps_cfg)},
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP, mei_me_pch8_cfg)},
|
||||
{MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP_2, mei_me_pch8_cfg)},
|
||||
|
||||
/* required last entry */
|
||||
{0, }
|
||||
|
@ -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, }
|
||||
};
|
||||
|
@ -270,15 +270,18 @@ static int mei_wd_ops_stop(struct watchdog_device *wd_dev)
|
||||
static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
|
||||
{
|
||||
struct mei_device *dev;
|
||||
struct mei_cl *cl;
|
||||
int ret;
|
||||
|
||||
dev = watchdog_get_drvdata(wd_dev);
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
cl = &dev->wd_cl;
|
||||
|
||||
mutex_lock(&dev->device_lock);
|
||||
|
||||
if (dev->wd_cl.state != MEI_FILE_CONNECTED) {
|
||||
if (cl->state != MEI_FILE_CONNECTED) {
|
||||
dev_err(dev->dev, "wd: not connected.\n");
|
||||
ret = -ENODEV;
|
||||
goto end;
|
||||
@ -286,12 +289,12 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
|
||||
|
||||
dev->wd_state = MEI_WD_RUNNING;
|
||||
|
||||
ret = mei_cl_flow_ctrl_creds(&dev->wd_cl);
|
||||
ret = mei_cl_flow_ctrl_creds(cl);
|
||||
if (ret < 0)
|
||||
goto end;
|
||||
|
||||
/* Check if we can send the ping to HW*/
|
||||
if (ret && mei_hbuf_acquire(dev)) {
|
||||
|
||||
dev_dbg(dev->dev, "wd: sending ping\n");
|
||||
|
||||
ret = mei_wd_send(dev);
|
||||
|
@ -158,6 +158,7 @@ static void pch_phub_read_modify_write_reg(struct pch_phub_reg *chip,
|
||||
iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/* pch_phub_save_reg_conf - saves register configuration */
|
||||
static void pch_phub_save_reg_conf(struct pci_dev *pdev)
|
||||
{
|
||||
@ -280,6 +281,7 @@ static void pch_phub_restore_reg_conf(struct pci_dev *pdev)
|
||||
if ((chip->ioh_type == 2) || (chip->ioh_type == 4))
|
||||
iowrite32(chip->funcsel_reg, p + FUNCSEL_REG_OFFSET);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* pch_phub_read_serial_rom() - Reading Serial ROM
|
||||
|
@ -3339,13 +3339,14 @@ static void __exit parport_pc_exit(void)
|
||||
while (!list_empty(&ports_list)) {
|
||||
struct parport_pc_private *priv;
|
||||
struct parport *port;
|
||||
struct device *dev;
|
||||
priv = list_entry(ports_list.next,
|
||||
struct parport_pc_private, list);
|
||||
port = priv->port;
|
||||
if (port->dev && port->dev->bus == &platform_bus_type)
|
||||
platform_device_unregister(
|
||||
to_platform_device(port->dev));
|
||||
dev = port->dev;
|
||||
parport_pc_unregister_port(port);
|
||||
if (dev && dev->bus == &platform_bus_type)
|
||||
platform_device_unregister(to_platform_device(dev));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ static struct pcmcia_low_level badge4_pcmcia_ops = {
|
||||
.nr = 2,
|
||||
};
|
||||
|
||||
int pcmcia_badge4_init(struct device *dev)
|
||||
int pcmcia_badge4_init(struct sa1111_dev *dev)
|
||||
{
|
||||
int ret = -ENODEV;
|
||||
|
||||
|
@ -203,10 +203,10 @@ static int pcmcia_probe(struct sa1111_dev *dev)
|
||||
sa1111_writel(PCCR_S0_FLT | PCCR_S1_FLT, base + PCCR);
|
||||
|
||||
#ifdef CONFIG_SA1100_BADGE4
|
||||
pcmcia_badge4_init(&dev->dev);
|
||||
pcmcia_badge4_init(dev);
|
||||
#endif
|
||||
#ifdef CONFIG_SA1100_JORNADA720
|
||||
pcmcia_jornada720_init(&dev->dev);
|
||||
pcmcia_jornada720_init(dev);
|
||||
#endif
|
||||
#ifdef CONFIG_ARCH_LUBBOCK
|
||||
pcmcia_lubbock_init(dev);
|
||||
|
@ -18,8 +18,8 @@ int sa1111_pcmcia_add(struct sa1111_dev *dev, struct pcmcia_low_level *ops,
|
||||
extern void sa1111_pcmcia_socket_state(struct soc_pcmcia_socket *, struct pcmcia_state *);
|
||||
extern int sa1111_pcmcia_configure_socket(struct soc_pcmcia_socket *, const socket_state_t *);
|
||||
|
||||
extern int pcmcia_badge4_init(struct device *);
|
||||
extern int pcmcia_jornada720_init(struct device *);
|
||||
extern int pcmcia_badge4_init(struct sa1111_dev *);
|
||||
extern int pcmcia_jornada720_init(struct sa1111_dev *);
|
||||
extern int pcmcia_lubbock_init(struct sa1111_dev *);
|
||||
extern int pcmcia_neponset_init(struct sa1111_dev *);
|
||||
|
||||
|
@ -92,10 +92,9 @@ static struct pcmcia_low_level jornada720_pcmcia_ops = {
|
||||
.nr = 2,
|
||||
};
|
||||
|
||||
int pcmcia_jornada720_init(struct device *dev)
|
||||
int pcmcia_jornada720_init(struct sa1111_dev *sadev)
|
||||
{
|
||||
int ret = -ENODEV;
|
||||
struct sa1111_dev *sadev = SA1111_DEV(dev);
|
||||
|
||||
if (machine_is_jornada720()) {
|
||||
unsigned int pin = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3;
|
||||
|
@ -56,12 +56,12 @@ static ssize_t map_name_show(struct uio_mem *mem, char *buf)
|
||||
|
||||
static ssize_t map_addr_show(struct uio_mem *mem, char *buf)
|
||||
{
|
||||
return sprintf(buf, "0x%llx\n", (unsigned long long)mem->addr);
|
||||
return sprintf(buf, "%pa\n", &mem->addr);
|
||||
}
|
||||
|
||||
static ssize_t map_size_show(struct uio_mem *mem, char *buf)
|
||||
{
|
||||
return sprintf(buf, "0x%lx\n", mem->size);
|
||||
return sprintf(buf, "%pa\n", &mem->size);
|
||||
}
|
||||
|
||||
static ssize_t map_offset_show(struct uio_mem *mem, char *buf)
|
||||
|
@ -253,7 +253,7 @@ static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
|
||||
|
||||
count = 0;
|
||||
err = usb_interrupt_msg(dev->udev, usb_rcvintpipe(dev->udev,
|
||||
dev->ep[EP_STATUS]), buf, size, &count, 100);
|
||||
dev->ep[EP_STATUS]), buf, size, &count, 1000);
|
||||
if (err < 0) {
|
||||
pr_err("Failed to read 1-wire data from 0x%x: err=%d.\n",
|
||||
dev->ep[EP_STATUS], err);
|
||||
|
@ -88,7 +88,7 @@ static struct w1_family_ops w1_bq27000_fops = {
|
||||
};
|
||||
|
||||
static struct w1_family w1_bq27000_family = {
|
||||
.fid = 1,
|
||||
.fid = W1_FAMILY_BQ27000,
|
||||
.fops = &w1_bq27000_fops,
|
||||
};
|
||||
|
||||
@ -111,7 +111,7 @@ module_exit(w1_bq27000_exit);
|
||||
|
||||
module_param(F_ID, int, S_IRUSR);
|
||||
MODULE_PARM_DESC(F_ID, "1-wire slave FID for BQ device");
|
||||
|
||||
MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_BQ27000));
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Texas Instruments Ltd");
|
||||
MODULE_DESCRIPTION("HDQ/1-wire slave driver bq27000 battery monitor chip");
|
||||
|
@ -727,7 +727,7 @@ int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
|
||||
|
||||
/* slave modules need to be loaded in a context with unlocked mutex */
|
||||
mutex_unlock(&dev->mutex);
|
||||
request_module("w1-family-0x%0x", rn->family);
|
||||
request_module("w1-family-0x%02x", rn->family);
|
||||
mutex_lock(&dev->mutex);
|
||||
|
||||
spin_lock(&w1_flock);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <linux/atomic.h>
|
||||
|
||||
#define W1_FAMILY_DEFAULT 0
|
||||
#define W1_FAMILY_BQ27000 0x01
|
||||
#define W1_FAMILY_SMEM_01 0x01
|
||||
#define W1_FAMILY_SMEM_81 0x81
|
||||
#define W1_THERM_DS18S20 0x10
|
||||
|
@ -598,7 +598,7 @@ static void w1_cn_callback(struct cn_msg *cn, struct netlink_skb_parms *nsp)
|
||||
msg = (struct w1_netlink_msg *)(cn + 1);
|
||||
if (node_count) {
|
||||
int size;
|
||||
u16 reply_size = sizeof(*cn) + cn->len + slave_len;
|
||||
int reply_size = sizeof(*cn) + cn->len + slave_len;
|
||||
if (cn->flags & W1_CN_BUNDLE) {
|
||||
/* bundling duplicats some of the messages */
|
||||
reply_size += 2 * cmd_count * (sizeof(struct cn_msg) +
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#define AMBA_NR_IRQS 9
|
||||
#define AMBA_CID 0xb105f00d
|
||||
#define CORESIGHT_CID 0xb105900d
|
||||
|
||||
struct clk;
|
||||
|
||||
|
263
include/linux/coresight.h
Normal file
263
include/linux/coresight.h
Normal file
@ -0,0 +1,263 @@
|
||||
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_CORESIGHT_H
|
||||
#define _LINUX_CORESIGHT_H
|
||||
|
||||
#include <linux/device.h>
|
||||
|
||||
/* Peripheral id registers (0xFD0-0xFEC) */
|
||||
#define CORESIGHT_PERIPHIDR4 0xfd0
|
||||
#define CORESIGHT_PERIPHIDR5 0xfd4
|
||||
#define CORESIGHT_PERIPHIDR6 0xfd8
|
||||
#define CORESIGHT_PERIPHIDR7 0xfdC
|
||||
#define CORESIGHT_PERIPHIDR0 0xfe0
|
||||
#define CORESIGHT_PERIPHIDR1 0xfe4
|
||||
#define CORESIGHT_PERIPHIDR2 0xfe8
|
||||
#define CORESIGHT_PERIPHIDR3 0xfeC
|
||||
/* Component id registers (0xFF0-0xFFC) */
|
||||
#define CORESIGHT_COMPIDR0 0xff0
|
||||
#define CORESIGHT_COMPIDR1 0xff4
|
||||
#define CORESIGHT_COMPIDR2 0xff8
|
||||
#define CORESIGHT_COMPIDR3 0xffC
|
||||
|
||||
#define ETM_ARCH_V3_3 0x23
|
||||
#define ETM_ARCH_V3_5 0x25
|
||||
#define PFT_ARCH_V1_0 0x30
|
||||
#define PFT_ARCH_V1_1 0x31
|
||||
|
||||
#define CORESIGHT_UNLOCK 0xc5acce55
|
||||
|
||||
extern struct bus_type coresight_bustype;
|
||||
|
||||
enum coresight_dev_type {
|
||||
CORESIGHT_DEV_TYPE_NONE,
|
||||
CORESIGHT_DEV_TYPE_SINK,
|
||||
CORESIGHT_DEV_TYPE_LINK,
|
||||
CORESIGHT_DEV_TYPE_LINKSINK,
|
||||
CORESIGHT_DEV_TYPE_SOURCE,
|
||||
};
|
||||
|
||||
enum coresight_dev_subtype_sink {
|
||||
CORESIGHT_DEV_SUBTYPE_SINK_NONE,
|
||||
CORESIGHT_DEV_SUBTYPE_SINK_PORT,
|
||||
CORESIGHT_DEV_SUBTYPE_SINK_BUFFER,
|
||||
};
|
||||
|
||||
enum coresight_dev_subtype_link {
|
||||
CORESIGHT_DEV_SUBTYPE_LINK_NONE,
|
||||
CORESIGHT_DEV_SUBTYPE_LINK_MERG,
|
||||
CORESIGHT_DEV_SUBTYPE_LINK_SPLIT,
|
||||
CORESIGHT_DEV_SUBTYPE_LINK_FIFO,
|
||||
};
|
||||
|
||||
enum coresight_dev_subtype_source {
|
||||
CORESIGHT_DEV_SUBTYPE_SOURCE_NONE,
|
||||
CORESIGHT_DEV_SUBTYPE_SOURCE_PROC,
|
||||
CORESIGHT_DEV_SUBTYPE_SOURCE_BUS,
|
||||
CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct coresight_dev_subtype - further characterisation of a type
|
||||
* @sink_subtype: type of sink this component is, as defined
|
||||
by @coresight_dev_subtype_sink.
|
||||
* @link_subtype: type of link this component is, as defined
|
||||
by @coresight_dev_subtype_link.
|
||||
* @source_subtype: type of source this component is, as defined
|
||||
by @coresight_dev_subtype_source.
|
||||
*/
|
||||
struct coresight_dev_subtype {
|
||||
enum coresight_dev_subtype_sink sink_subtype;
|
||||
enum coresight_dev_subtype_link link_subtype;
|
||||
enum coresight_dev_subtype_source source_subtype;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct coresight_platform_data - data harvested from the DT specification
|
||||
* @cpu: the CPU a source belongs to. Only applicable for ETM/PTMs.
|
||||
* @name: name of the component as shown under sysfs.
|
||||
* @nr_inport: number of input ports for this component.
|
||||
* @outports: list of remote endpoint port number.
|
||||
* @child_names:name of all child components connected to this device.
|
||||
* @child_ports:child component port number the current component is
|
||||
connected to.
|
||||
* @nr_outport: number of output ports for this component.
|
||||
* @clk: The clock this component is associated to.
|
||||
*/
|
||||
struct coresight_platform_data {
|
||||
int cpu;
|
||||
const char *name;
|
||||
int nr_inport;
|
||||
int *outports;
|
||||
const char **child_names;
|
||||
int *child_ports;
|
||||
int nr_outport;
|
||||
struct clk *clk;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct coresight_desc - description of a component required from drivers
|
||||
* @type: as defined by @coresight_dev_type.
|
||||
* @subtype: as defined by @coresight_dev_subtype.
|
||||
* @ops: generic operations for this component, as defined
|
||||
by @coresight_ops.
|
||||
* @pdata: platform data collected from DT.
|
||||
* @dev: The device entity associated to this component.
|
||||
* @groups: operations specific to this component. These will end up
|
||||
in the component's sysfs sub-directory.
|
||||
*/
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct coresight_connection - representation of a single connection
|
||||
* @outport: a connection's output port number.
|
||||
* @chid_name: remote component's name.
|
||||
* @child_port: remote component's port number @output is connected to.
|
||||
* @child_dev: a @coresight_device representation of the component
|
||||
connected to @outport.
|
||||
*/
|
||||
struct coresight_connection {
|
||||
int outport;
|
||||
const char *child_name;
|
||||
int child_port;
|
||||
struct coresight_device *child_dev;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct coresight_device - representation of a device as used by the framework
|
||||
* @conns: array of coresight_connections associated to this component.
|
||||
* @nr_inport: number of input port associated to this component.
|
||||
* @nr_outport: number of output port associated to this component.
|
||||
* @type: as defined by @coresight_dev_type.
|
||||
* @subtype: as defined by @coresight_dev_subtype.
|
||||
* @ops: generic operations for this component, as defined
|
||||
by @coresight_ops.
|
||||
* @dev: The device entity associated to this component.
|
||||
* @refcnt: keep track of what is in use.
|
||||
* @path_link: link of current component into the path being enabled.
|
||||
* @orphan: true if the component has connections that haven't been linked.
|
||||
* @enable: 'true' if component is currently part of an active path.
|
||||
* @activated: 'true' only if a _sink_ has been activated. A sink can be
|
||||
activated but not yet enabled. Enabling for a _sink_
|
||||
happens when a source has been selected for that it.
|
||||
*/
|
||||
struct coresight_device {
|
||||
struct coresight_connection *conns;
|
||||
int nr_inport;
|
||||
int nr_outport;
|
||||
enum coresight_dev_type type;
|
||||
struct coresight_dev_subtype subtype;
|
||||
const struct coresight_ops *ops;
|
||||
struct device dev;
|
||||
atomic_t *refcnt;
|
||||
struct list_head path_link;
|
||||
bool orphan;
|
||||
bool enable; /* true only if configured as part of a path */
|
||||
bool activated; /* true only if a sink is part of a path */
|
||||
};
|
||||
|
||||
#define to_coresight_device(d) container_of(d, struct coresight_device, dev)
|
||||
|
||||
#define source_ops(csdev) csdev->ops->source_ops
|
||||
#define sink_ops(csdev) csdev->ops->sink_ops
|
||||
#define link_ops(csdev) csdev->ops->link_ops
|
||||
|
||||
#define CORESIGHT_DEBUGFS_ENTRY(__name, __entry_name, \
|
||||
__mode, __get, __set, __fmt) \
|
||||
DEFINE_SIMPLE_ATTRIBUTE(__name ## _ops, __get, __set, __fmt); \
|
||||
static const struct coresight_ops_entry __name ## _entry = { \
|
||||
.name = __entry_name, \
|
||||
.mode = __mode, \
|
||||
.ops = &__name ## _ops \
|
||||
}
|
||||
|
||||
/**
|
||||
* struct coresight_ops_sink - basic operations for a sink
|
||||
* Operations available for sinks
|
||||
* @enable: enables the sink.
|
||||
* @disable: disables the sink.
|
||||
*/
|
||||
struct coresight_ops_sink {
|
||||
int (*enable)(struct coresight_device *csdev);
|
||||
void (*disable)(struct coresight_device *csdev);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct coresight_ops_link - basic operations for a link
|
||||
* Operations available for links.
|
||||
* @enable: enables flow between iport and oport.
|
||||
* @disable: disables flow between iport and oport.
|
||||
*/
|
||||
struct coresight_ops_link {
|
||||
int (*enable)(struct coresight_device *csdev, int iport, int oport);
|
||||
void (*disable)(struct coresight_device *csdev, int iport, int oport);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct coresight_ops_source - basic operations for a source
|
||||
* Operations available for sources.
|
||||
* @trace_id: returns the value of the component's trace ID as known
|
||||
to the HW.
|
||||
* @enable: enables tracing from a source.
|
||||
* @disable: disables tracing for a source.
|
||||
*/
|
||||
struct coresight_ops_source {
|
||||
int (*trace_id)(struct coresight_device *csdev);
|
||||
int (*enable)(struct coresight_device *csdev);
|
||||
void (*disable)(struct coresight_device *csdev);
|
||||
};
|
||||
|
||||
struct coresight_ops {
|
||||
const struct coresight_ops_sink *sink_ops;
|
||||
const struct coresight_ops_link *link_ops;
|
||||
const struct coresight_ops_source *source_ops;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_CORESIGHT
|
||||
extern struct coresight_device *
|
||||
coresight_register(struct coresight_desc *desc);
|
||||
extern void coresight_unregister(struct coresight_device *csdev);
|
||||
extern int coresight_enable(struct coresight_device *csdev);
|
||||
extern void coresight_disable(struct coresight_device *csdev);
|
||||
extern int coresight_is_bit_set(u32 val, int position, int value);
|
||||
extern int coresight_timeout(void __iomem *addr, u32 offset,
|
||||
int position, int value);
|
||||
#ifdef CONFIG_OF
|
||||
extern struct coresight_platform_data *of_get_coresight_platform_data(
|
||||
struct device *dev, struct device_node *node);
|
||||
#endif
|
||||
#else
|
||||
static inline struct coresight_device *
|
||||
coresight_register(struct coresight_desc *desc) { return NULL; }
|
||||
static inline void coresight_unregister(struct coresight_device *csdev) {}
|
||||
static inline int
|
||||
coresight_enable(struct coresight_device *csdev) { return -ENOSYS; }
|
||||
static inline void coresight_disable(struct coresight_device *csdev) {}
|
||||
static inline int coresight_is_bit_set(u32 val, int position, int value)
|
||||
{ return 0; }
|
||||
static inline int coresight_timeout(void __iomem *addr, u32 offset,
|
||||
int position, int value) { return 1; }
|
||||
#ifdef CONFIG_OF
|
||||
static inline struct coresight_platform_data *of_get_coresight_platform_data(
|
||||
struct device *dev, struct device_node *node) { return NULL; }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
@ -61,9 +61,9 @@ static inline void devm_ioport_unmap(struct device *dev, void __iomem *addr)
|
||||
#define IOMEM_ERR_PTR(err) (__force void __iomem *)ERR_PTR(err)
|
||||
|
||||
void __iomem *devm_ioremap(struct device *dev, resource_size_t offset,
|
||||
unsigned long size);
|
||||
resource_size_t size);
|
||||
void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset,
|
||||
unsigned long size);
|
||||
resource_size_t size);
|
||||
void devm_iounmap(struct device *dev, void __iomem *addr);
|
||||
int check_signature(const volatile void __iomem *io_addr,
|
||||
const unsigned char *signature, int length);
|
||||
|
@ -134,9 +134,6 @@ void spmi_controller_remove(struct spmi_controller *ctrl);
|
||||
* this structure.
|
||||
* @probe: binds this driver to a SPMI device.
|
||||
* @remove: unbinds this driver from the SPMI device.
|
||||
* @shutdown: standard shutdown callback used during powerdown/halt.
|
||||
* @suspend: standard suspend callback used during system suspend.
|
||||
* @resume: standard resume callback used during system resume.
|
||||
*
|
||||
* If PM runtime support is desired for a slave, a device driver can call
|
||||
* pm_runtime_put() from their probe() routine (and a balancing
|
||||
|
@ -35,7 +35,7 @@ struct uio_map;
|
||||
struct uio_mem {
|
||||
const char *name;
|
||||
phys_addr_t addr;
|
||||
unsigned long size;
|
||||
resource_size_t size;
|
||||
int memtype;
|
||||
void __iomem *internal_addr;
|
||||
struct uio_map *map;
|
||||
|
@ -134,6 +134,7 @@ struct hv_start_fcopy {
|
||||
|
||||
struct hv_do_fcopy {
|
||||
struct hv_fcopy_hdr hdr;
|
||||
__u32 pad;
|
||||
__u64 offset;
|
||||
__u32 size;
|
||||
__u8 data[DATA_FRAGMENT];
|
||||
|
@ -23,7 +23,7 @@ static int devm_ioremap_match(struct device *dev, void *res, void *match_data)
|
||||
* Managed ioremap(). Map is automatically unmapped on driver detach.
|
||||
*/
|
||||
void __iomem *devm_ioremap(struct device *dev, resource_size_t offset,
|
||||
unsigned long size)
|
||||
resource_size_t size)
|
||||
{
|
||||
void __iomem **ptr, *addr;
|
||||
|
||||
@ -52,7 +52,7 @@ EXPORT_SYMBOL(devm_ioremap);
|
||||
* detach.
|
||||
*/
|
||||
void __iomem *devm_ioremap_nocache(struct device *dev, resource_size_t offset,
|
||||
unsigned long size)
|
||||
resource_size_t size)
|
||||
{
|
||||
void __iomem **ptr, *addr;
|
||||
|
||||
|
139
scripts/checkkconfigsymbols.py
Normal file
139
scripts/checkkconfigsymbols.py
Normal file
@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""Find Kconfig identifiers that are referenced but not defined."""
|
||||
|
||||
# (c) 2014 Valentin Rothberg <valentinrothberg@gmail.com>
|
||||
# (c) 2014 Stefan Hengelein <stefan.hengelein@fau.de>
|
||||
#
|
||||
# Licensed under the terms of the GNU GPL License version 2
|
||||
|
||||
|
||||
import os
|
||||
import re
|
||||
from subprocess import Popen, PIPE, STDOUT
|
||||
|
||||
|
||||
# regex expressions
|
||||
OPERATORS = r"&|\(|\)|\||\!"
|
||||
FEATURE = r"(?:\w*[A-Z0-9]\w*){2,}"
|
||||
DEF = r"^\s*(?:menu){,1}config\s+(" + FEATURE + r")\s*"
|
||||
EXPR = r"(?:" + OPERATORS + r"|\s|" + FEATURE + r")+"
|
||||
STMT = r"^\s*(?:if|select|depends\s+on)\s+" + EXPR
|
||||
SOURCE_FEATURE = r"(?:\W|\b)+[D]{,1}CONFIG_(" + FEATURE + r")"
|
||||
|
||||
# regex objects
|
||||
REGEX_FILE_KCONFIG = re.compile(r".*Kconfig[\.\w+\-]*$")
|
||||
REGEX_FEATURE = re.compile(r"(" + FEATURE + r")")
|
||||
REGEX_SOURCE_FEATURE = re.compile(SOURCE_FEATURE)
|
||||
REGEX_KCONFIG_DEF = re.compile(DEF)
|
||||
REGEX_KCONFIG_EXPR = re.compile(EXPR)
|
||||
REGEX_KCONFIG_STMT = re.compile(STMT)
|
||||
REGEX_KCONFIG_HELP = re.compile(r"^\s+(help|---help---)\s*$")
|
||||
REGEX_FILTER_FEATURES = re.compile(r"[A-Za-z0-9]$")
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function of this module."""
|
||||
source_files = []
|
||||
kconfig_files = []
|
||||
defined_features = set()
|
||||
referenced_features = dict() # {feature: [files]}
|
||||
|
||||
# use 'git ls-files' to get the worklist
|
||||
pop = Popen("git ls-files", stdout=PIPE, stderr=STDOUT, shell=True)
|
||||
(stdout, _) = pop.communicate() # wait until finished
|
||||
if len(stdout) > 0 and stdout[-1] == "\n":
|
||||
stdout = stdout[:-1]
|
||||
|
||||
for gitfile in stdout.rsplit("\n"):
|
||||
if ".git" in gitfile or "ChangeLog" in gitfile or \
|
||||
".log" in gitfile or os.path.isdir(gitfile):
|
||||
continue
|
||||
if REGEX_FILE_KCONFIG.match(gitfile):
|
||||
kconfig_files.append(gitfile)
|
||||
else:
|
||||
# all non-Kconfig files are checked for consistency
|
||||
source_files.append(gitfile)
|
||||
|
||||
for sfile in source_files:
|
||||
parse_source_file(sfile, referenced_features)
|
||||
|
||||
for kfile in kconfig_files:
|
||||
parse_kconfig_file(kfile, defined_features, referenced_features)
|
||||
|
||||
print "Undefined symbol used\tFile list"
|
||||
for feature in sorted(referenced_features):
|
||||
# filter some false positives
|
||||
if feature == "FOO" or feature == "BAR" or \
|
||||
feature == "FOO_BAR" or feature == "XXX":
|
||||
continue
|
||||
if feature not in defined_features:
|
||||
if feature.endswith("_MODULE"):
|
||||
# avoid false positives for kernel modules
|
||||
if feature[:-len("_MODULE")] in defined_features:
|
||||
continue
|
||||
files = referenced_features.get(feature)
|
||||
print "%s\t%s" % (feature, ", ".join(files))
|
||||
|
||||
|
||||
def parse_source_file(sfile, referenced_features):
|
||||
"""Parse @sfile for referenced Kconfig features."""
|
||||
lines = []
|
||||
with open(sfile, "r") as stream:
|
||||
lines = stream.readlines()
|
||||
|
||||
for line in lines:
|
||||
if not "CONFIG_" in line:
|
||||
continue
|
||||
features = REGEX_SOURCE_FEATURE.findall(line)
|
||||
for feature in features:
|
||||
if not REGEX_FILTER_FEATURES.search(feature):
|
||||
continue
|
||||
sfiles = referenced_features.get(feature, set())
|
||||
sfiles.add(sfile)
|
||||
referenced_features[feature] = sfiles
|
||||
|
||||
|
||||
def get_features_in_line(line):
|
||||
"""Return mentioned Kconfig features in @line."""
|
||||
return REGEX_FEATURE.findall(line)
|
||||
|
||||
|
||||
def parse_kconfig_file(kfile, defined_features, referenced_features):
|
||||
"""Parse @kfile and update feature definitions and references."""
|
||||
lines = []
|
||||
skip = False
|
||||
|
||||
with open(kfile, "r") as stream:
|
||||
lines = stream.readlines()
|
||||
|
||||
for i in range(len(lines)):
|
||||
line = lines[i]
|
||||
line = line.strip('\n')
|
||||
line = line.split("#")[0] # ignore comments
|
||||
|
||||
if REGEX_KCONFIG_DEF.match(line):
|
||||
feature_def = REGEX_KCONFIG_DEF.findall(line)
|
||||
defined_features.add(feature_def[0])
|
||||
skip = False
|
||||
elif REGEX_KCONFIG_HELP.match(line):
|
||||
skip = True
|
||||
elif skip:
|
||||
# ignore content of help messages
|
||||
pass
|
||||
elif REGEX_KCONFIG_STMT.match(line):
|
||||
features = get_features_in_line(line)
|
||||
# multi-line statements
|
||||
while line.endswith("\\"):
|
||||
i += 1
|
||||
line = lines[i]
|
||||
line = line.strip('\n')
|
||||
features.extend(get_features_in_line(line))
|
||||
for feature in set(features):
|
||||
paths = referenced_features.get(feature, set())
|
||||
paths.add(kfile)
|
||||
referenced_features[feature] = paths
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,59 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Find Kconfig variables used in source code but never defined in Kconfig
|
||||
# Copyright (C) 2007, Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
|
||||
|
||||
# Tested with dash.
|
||||
paths="$@"
|
||||
[ -z "$paths" ] && paths=.
|
||||
|
||||
# Doing this once at the beginning saves a lot of time, on a cache-hot tree.
|
||||
Kconfigs="`find . -name 'Kconfig' -o -name 'Kconfig*[^~]'`"
|
||||
|
||||
printf "File list \tundefined symbol used\n"
|
||||
find $paths -name '*.[chS]' -o -name 'Makefile' -o -name 'Makefile*[^~]'| while read i
|
||||
do
|
||||
# Output the bare Kconfig variable and the filename; the _MODULE part at
|
||||
# the end is not removed here (would need perl an not-hungry regexp for that).
|
||||
sed -ne 's!^.*\<\(UML_\)\?CONFIG_\([0-9A-Za-z_]\+\).*!\2 '$i'!p' < $i
|
||||
done | \
|
||||
# Smart "sort|uniq" implemented in awk and tuned to collect the names of all
|
||||
# files which use a given symbol
|
||||
awk '{map[$1, count[$1]++] = $2; }
|
||||
END {
|
||||
for (combIdx in map) {
|
||||
split(combIdx, separate, SUBSEP);
|
||||
# The value may have been removed.
|
||||
if (! ( (separate[1], separate[2]) in map ) )
|
||||
continue;
|
||||
symb=separate[1];
|
||||
printf "%s ", symb;
|
||||
#Use gawk extension to delete the names vector
|
||||
delete names;
|
||||
#Portably delete the names vector
|
||||
#split("", names);
|
||||
for (i=0; i < count[symb]; i++) {
|
||||
names[map[symb, i]] = 1;
|
||||
# Unfortunately, we may still encounter symb, i in the
|
||||
# outside iteration.
|
||||
delete map[symb, i];
|
||||
}
|
||||
i=0;
|
||||
for (name in names) {
|
||||
if (i > 0)
|
||||
printf ", %s", name;
|
||||
else
|
||||
printf "%s", name;
|
||||
i++;
|
||||
}
|
||||
printf "\n";
|
||||
}
|
||||
}' |
|
||||
while read symb files; do
|
||||
# Remove the _MODULE suffix when checking the variable name. This should
|
||||
# be done only on tristate symbols, actually, but Kconfig parsing is
|
||||
# beyond the purpose of this script.
|
||||
symb_bare=`echo $symb | sed -e 's/_MODULE//'`
|
||||
if ! grep -q "\<$symb_bare\>" $Kconfigs; then
|
||||
printf "$files: \t$symb\n"
|
||||
fi
|
||||
done|sort
|
@ -33,6 +33,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <getopt.h>
|
||||
|
||||
static int target_fd;
|
||||
static char target_fname[W_MAX_PATH];
|
||||
@ -126,15 +127,43 @@ static int hv_copy_cancel(void)
|
||||
|
||||
}
|
||||
|
||||
int main(void)
|
||||
void print_usage(char *argv[])
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [options]\n"
|
||||
"Options are:\n"
|
||||
" -n, --no-daemon stay in foreground, don't daemonize\n"
|
||||
" -h, --help print this help\n", argv[0]);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int fd, fcopy_fd, len;
|
||||
int error;
|
||||
int daemonize = 1, long_index = 0, opt;
|
||||
int version = FCOPY_CURRENT_VERSION;
|
||||
char *buffer[4096 * 2];
|
||||
struct hv_fcopy_hdr *in_msg;
|
||||
|
||||
if (daemon(1, 0)) {
|
||||
static struct option long_options[] = {
|
||||
{"help", no_argument, 0, 'h' },
|
||||
{"no-daemon", no_argument, 0, 'n' },
|
||||
{0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "hn", long_options,
|
||||
&long_index)) != -1) {
|
||||
switch (opt) {
|
||||
case 'n':
|
||||
daemonize = 0;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
print_usage(argv);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (daemonize && daemon(1, 0)) {
|
||||
syslog(LOG_ERR, "daemon() failed; error: %s", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <net/if.h>
|
||||
#include <getopt.h>
|
||||
|
||||
/*
|
||||
* KVP protocol: The user mode component first registers with the
|
||||
@ -1417,7 +1418,15 @@ netlink_send(int fd, struct cn_msg *msg)
|
||||
return sendmsg(fd, &message, 0);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
void print_usage(char *argv[])
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [options]\n"
|
||||
"Options are:\n"
|
||||
" -n, --no-daemon stay in foreground, don't daemonize\n"
|
||||
" -h, --help print this help\n", argv[0]);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int fd, len, nl_group;
|
||||
int error;
|
||||
@ -1435,9 +1444,30 @@ int main(void)
|
||||
struct hv_kvp_ipaddr_value *kvp_ip_val;
|
||||
char *kvp_recv_buffer;
|
||||
size_t kvp_recv_buffer_len;
|
||||
int daemonize = 1, long_index = 0, opt;
|
||||
|
||||
if (daemon(1, 0))
|
||||
static struct option long_options[] = {
|
||||
{"help", no_argument, 0, 'h' },
|
||||
{"no-daemon", no_argument, 0, 'n' },
|
||||
{0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "hn", long_options,
|
||||
&long_index)) != -1) {
|
||||
switch (opt) {
|
||||
case 'n':
|
||||
daemonize = 0;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
print_usage(argv);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (daemonize && daemon(1, 0))
|
||||
return 1;
|
||||
|
||||
openlog("KVP", 0, LOG_USER);
|
||||
syslog(LOG_INFO, "KVP starting; pid is:%d", getpid());
|
||||
|
||||
@ -1529,8 +1559,15 @@ int main(void)
|
||||
addr_p, &addr_l);
|
||||
|
||||
if (len < 0) {
|
||||
int saved_errno = errno;
|
||||
syslog(LOG_ERR, "recvfrom failed; pid:%u error:%d %s",
|
||||
addr.nl_pid, errno, strerror(errno));
|
||||
|
||||
if (saved_errno == ENOBUFS) {
|
||||
syslog(LOG_ERR, "receive error: ignored");
|
||||
continue;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
@ -1733,8 +1770,15 @@ kvp_done:
|
||||
|
||||
len = netlink_send(fd, incoming_cn_msg);
|
||||
if (len < 0) {
|
||||
int saved_errno = errno;
|
||||
syslog(LOG_ERR, "net_link send failed; error: %d %s", errno,
|
||||
strerror(errno));
|
||||
|
||||
if (saved_errno == ENOMEM || saved_errno == ENOBUFS) {
|
||||
syslog(LOG_ERR, "send error: ignored");
|
||||
continue;
|
||||
}
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <linux/hyperv.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <syslog.h>
|
||||
#include <getopt.h>
|
||||
|
||||
static struct sockaddr_nl addr;
|
||||
|
||||
@ -44,35 +45,51 @@ static struct sockaddr_nl addr;
|
||||
#endif
|
||||
|
||||
|
||||
static int vss_do_freeze(char *dir, unsigned int cmd, char *fs_op)
|
||||
/* Don't use syslog() in the function since that can cause write to disk */
|
||||
static int vss_do_freeze(char *dir, unsigned int cmd)
|
||||
{
|
||||
int ret, fd = open(dir, O_RDONLY);
|
||||
|
||||
if (fd < 0)
|
||||
return 1;
|
||||
|
||||
ret = ioctl(fd, cmd, 0);
|
||||
syslog(LOG_INFO, "VSS: %s of %s: %s\n", fs_op, dir, strerror(errno));
|
||||
|
||||
/*
|
||||
* If a partition is mounted more than once, only the first
|
||||
* FREEZE/THAW can succeed and the later ones will get
|
||||
* EBUSY/EINVAL respectively: there could be 2 cases:
|
||||
* 1) a user may mount the same partition to differnt directories
|
||||
* by mistake or on purpose;
|
||||
* 2) The subvolume of btrfs appears to have the same partition
|
||||
* mounted more than once.
|
||||
*/
|
||||
if (ret) {
|
||||
if ((cmd == FIFREEZE && errno == EBUSY) ||
|
||||
(cmd == FITHAW && errno == EINVAL)) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return !!ret;
|
||||
}
|
||||
|
||||
static int vss_operate(int operation)
|
||||
{
|
||||
char *fs_op;
|
||||
char match[] = "/dev/";
|
||||
FILE *mounts;
|
||||
struct mntent *ent;
|
||||
unsigned int cmd;
|
||||
int error = 0, root_seen = 0;
|
||||
int error = 0, root_seen = 0, save_errno = 0;
|
||||
|
||||
switch (operation) {
|
||||
case VSS_OP_FREEZE:
|
||||
cmd = FIFREEZE;
|
||||
fs_op = "freeze";
|
||||
break;
|
||||
case VSS_OP_THAW:
|
||||
cmd = FITHAW;
|
||||
fs_op = "thaw";
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
@ -85,7 +102,7 @@ static int vss_operate(int operation)
|
||||
while ((ent = getmntent(mounts))) {
|
||||
if (strncmp(ent->mnt_fsname, match, strlen(match)))
|
||||
continue;
|
||||
if (strcmp(ent->mnt_type, "iso9660") == 0)
|
||||
if (hasmntopt(ent, MNTOPT_RO) != NULL)
|
||||
continue;
|
||||
if (strcmp(ent->mnt_type, "vfat") == 0)
|
||||
continue;
|
||||
@ -93,14 +110,30 @@ static int vss_operate(int operation)
|
||||
root_seen = 1;
|
||||
continue;
|
||||
}
|
||||
error |= vss_do_freeze(ent->mnt_dir, cmd, fs_op);
|
||||
error |= vss_do_freeze(ent->mnt_dir, cmd);
|
||||
if (error && operation == VSS_OP_FREEZE)
|
||||
goto err;
|
||||
}
|
||||
endmntent(mounts);
|
||||
|
||||
if (root_seen) {
|
||||
error |= vss_do_freeze("/", cmd, fs_op);
|
||||
error |= vss_do_freeze("/", cmd);
|
||||
if (error && operation == VSS_OP_FREEZE)
|
||||
goto err;
|
||||
}
|
||||
|
||||
goto out;
|
||||
err:
|
||||
save_errno = errno;
|
||||
vss_operate(VSS_OP_THAW);
|
||||
/* Call syslog after we thaw all filesystems */
|
||||
if (ent)
|
||||
syslog(LOG_ERR, "FREEZE of %s failed; error:%d %s",
|
||||
ent->mnt_dir, save_errno, strerror(save_errno));
|
||||
else
|
||||
syslog(LOG_ERR, "FREEZE of / failed; error:%d %s", save_errno,
|
||||
strerror(save_errno));
|
||||
out:
|
||||
endmntent(mounts);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -131,7 +164,15 @@ static int netlink_send(int fd, struct cn_msg *msg)
|
||||
return sendmsg(fd, &message, 0);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
void print_usage(char *argv[])
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [options]\n"
|
||||
"Options are:\n"
|
||||
" -n, --no-daemon stay in foreground, don't daemonize\n"
|
||||
" -h, --help print this help\n", argv[0]);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int fd, len, nl_group;
|
||||
int error;
|
||||
@ -143,8 +184,28 @@ int main(void)
|
||||
struct hv_vss_msg *vss_msg;
|
||||
char *vss_recv_buffer;
|
||||
size_t vss_recv_buffer_len;
|
||||
int daemonize = 1, long_index = 0, opt;
|
||||
|
||||
if (daemon(1, 0))
|
||||
static struct option long_options[] = {
|
||||
{"help", no_argument, 0, 'h' },
|
||||
{"no-daemon", no_argument, 0, 'n' },
|
||||
{0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "hn", long_options,
|
||||
&long_index)) != -1) {
|
||||
switch (opt) {
|
||||
case 'n':
|
||||
daemonize = 0;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
print_usage(argv);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (daemonize && daemon(1, 0))
|
||||
return 1;
|
||||
|
||||
openlog("Hyper-V VSS", 0, LOG_USER);
|
||||
@ -249,8 +310,16 @@ int main(void)
|
||||
case VSS_OP_FREEZE:
|
||||
case VSS_OP_THAW:
|
||||
error = vss_operate(op);
|
||||
if (error)
|
||||
syslog(LOG_INFO, "VSS: op=%s: %s\n",
|
||||
op == VSS_OP_FREEZE ? "FREEZE" : "THAW",
|
||||
error ? "failed" : "succeeded");
|
||||
|
||||
if (error) {
|
||||
error = HV_E_FAIL;
|
||||
syslog(LOG_ERR, "op=%d failed!", op);
|
||||
syslog(LOG_ERR, "report it with these files:");
|
||||
syslog(LOG_ERR, "/etc/fstab and /proc/mounts");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_ERR, "Illegal op:%d\n", op);
|
||||
|
Loading…
Reference in New Issue
Block a user