Char/Misc and other driver subsystem updates for 6.5-rc1
Here is the big set of char/misc and other driver subsystem updates for 6.5-rc1. Lots of different, tiny, stuff in here, from a range of smaller driver subsystems, including pulls from some substems directly: - IIO driver updates and additions - W1 driver updates and fixes (and a new maintainer!) - FPGA driver updates and fixes - Counter driver updates - Extcon driver updates - Interconnect driver updates - Coresight driver updates - mfd tree tag merge needed for other updates on top of that, lots of small driver updates as patches, including: - static const updates for class structures - nvmem driver updates - pcmcia driver fix - lots of other small driver updates and fixes All of these have been in linux-next for a while with no reported problems. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCZKKNMw8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ylhlQCfZrtz8RIbau8zbzh/CKpKBOmvHp4An3V64hbz recBPLH0ZACKl0wPl4iZ =A83A -----END PGP SIGNATURE----- Merge tag 'char-misc-6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc Pull Char/Misc updates from Greg KH: "Here is the big set of char/misc and other driver subsystem updates for 6.5-rc1. Lots of different, tiny, stuff in here, from a range of smaller driver subsystems, including pulls from some substems directly: - IIO driver updates and additions - W1 driver updates and fixes (and a new maintainer!) - FPGA driver updates and fixes - Counter driver updates - Extcon driver updates - Interconnect driver updates - Coresight driver updates - mfd tree tag merge needed for other updates on top of that, lots of small driver updates as patches, including: - static const updates for class structures - nvmem driver updates - pcmcia driver fix - lots of other small driver updates and fixes All of these have been in linux-next for a while with no reported problems" * tag 'char-misc-6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (243 commits) bsr: fix build problem with bsr_class static cleanup comedi: make all 'class' structures const char: xillybus: make xillybus_class a static const structure xilinx_hwicap: make icap_class a static const structure virtio_console: make port class a static const structure ppdev: make ppdev_class a static const structure char: misc: make misc_class a static const structure /dev/mem: make mem_class a static const structure char: lp: make lp_class a static const structure dsp56k: make dsp56k_class a static const structure bsr: make bsr_class a static const structure oradax: make 'cl' a static const structure hwtracing: hisi_ptt: Fix potential sleep in atomic context hwtracing: hisi_ptt: Advertise PERF_PMU_CAP_NO_EXCLUDE for PTT PMU hwtracing: hisi_ptt: Export available filters through sysfs hwtracing: hisi_ptt: Add support for dynamically updating the filter list hwtracing: hisi_ptt: Factor out filter allocation and release operation samples: pfsm: add CC_CAN_LINK dependency misc: fastrpc: check return value of devm_kasprintf() coresight: dummy: Update type of mode parameter in dummy_{sink,source}_enable() ...
This commit is contained in:
commit
44aeec836d
|
@ -90,6 +90,60 @@ Description:
|
|||
counter does not freeze at the boundary points, but
|
||||
counts continuously throughout.
|
||||
|
||||
interrupt on terminal count:
|
||||
The output signal is initially low, and will remain low
|
||||
until the counter reaches zero. The output signal then
|
||||
goes high and remains high until a new preset value is
|
||||
set.
|
||||
|
||||
hardware retriggerable one-shot:
|
||||
The output signal is initially high. The output signal
|
||||
will go low by a trigger input signal, and will remain
|
||||
low until the counter reaches zero. The output will then
|
||||
go high and remain high until the next trigger. A
|
||||
trigger results in loading the counter to the preset
|
||||
value and setting the output signal low, thus starting
|
||||
the one-shot pulse.
|
||||
|
||||
rate generator:
|
||||
The output signal is initially high. When the counter
|
||||
has decremented to 1, the output signal goes low for one
|
||||
clock pulse. The output signal then goes high again, the
|
||||
counter is reloaded to the preset value, and the process
|
||||
repeats in a periodic manner as such.
|
||||
|
||||
square wave mode:
|
||||
The output signal is initially high.
|
||||
|
||||
If the initial count is even, the counter is decremented
|
||||
by two on succeeding clock pulses. When the count
|
||||
expires, the output signal changes value and the
|
||||
counter is reloaded to the preset value. The process
|
||||
repeats in periodic manner as such.
|
||||
|
||||
If the initial count is odd, the initial count minus one
|
||||
(an even number) is loaded and then is decremented by
|
||||
two on succeeding clock pulses. One clock pulse after
|
||||
the count expires, the output signal goes low and the
|
||||
counter is reloaded to the preset value minus one.
|
||||
Succeeding clock pulses decrement the count by two. When
|
||||
the count expires, the output goes high again and the
|
||||
counter is reloaded to the preset value minus one. The
|
||||
process repeats in a periodic manner as such.
|
||||
|
||||
software triggered strobe:
|
||||
The output signal is initially high. When the count
|
||||
expires, the output will go low for one clock pulse and
|
||||
then go high again. The counting sequence is "triggered"
|
||||
by setting the preset value.
|
||||
|
||||
hardware triggered strobe:
|
||||
The output signal is initially high. Counting is started
|
||||
by a trigger input signal. When the count expires, the
|
||||
output signal will go low for one clock pulse and then
|
||||
go high again. A trigger results in loading the counter
|
||||
to the preset value.
|
||||
|
||||
What: /sys/bus/counter/devices/counterX/countY/count_mode_available
|
||||
What: /sys/bus/counter/devices/counterX/countY/error_noise_available
|
||||
What: /sys/bus/counter/devices/counterX/countY/function_available
|
||||
|
|
|
@ -59,3 +59,55 @@ Description: (RW) Control the allocated buffer watermark of outbound packets.
|
|||
The available tune data is [0, 1, 2]. Writing a negative value
|
||||
will return an error, and out of range values will be converted
|
||||
to 2. The value indicates a probable level of the event.
|
||||
|
||||
What: /sys/devices/hisi_ptt<sicl_id>_<core_id>/root_port_filters
|
||||
Date: May 2023
|
||||
KernelVersion: 6.5
|
||||
Contact: Yicong Yang <yangyicong@hisilicon.com>
|
||||
Description: This directory contains the files providing the PCIe Root Port filters
|
||||
information used for PTT trace. Each file is named after the supported
|
||||
Root Port device name <domain>:<bus>:<device>.<function>.
|
||||
|
||||
See the description of the "filter" in Documentation/trace/hisi-ptt.rst
|
||||
for more information.
|
||||
|
||||
What: /sys/devices/hisi_ptt<sicl_id>_<core_id>/root_port_filters/multiselect
|
||||
Date: May 2023
|
||||
KernelVersion: 6.5
|
||||
Contact: Yicong Yang <yangyicong@hisilicon.com>
|
||||
Description: (Read) Indicates if this kind of filter can be selected at the same
|
||||
time as others filters, or must be used on it's own. 1 indicates
|
||||
the former case and 0 indicates the latter.
|
||||
|
||||
What: /sys/devices/hisi_ptt<sicl_id>_<core_id>/root_port_filters/<bdf>
|
||||
Date: May 2023
|
||||
KernelVersion: 6.5
|
||||
Contact: Yicong Yang <yangyicong@hisilicon.com>
|
||||
Description: (Read) Indicates the filter value of this Root Port filter, which
|
||||
can be used to control the TLP headers to trace by the PTT trace.
|
||||
|
||||
What: /sys/devices/hisi_ptt<sicl_id>_<core_id>/requester_filters
|
||||
Date: May 2023
|
||||
KernelVersion: 6.5
|
||||
Contact: Yicong Yang <yangyicong@hisilicon.com>
|
||||
Description: This directory contains the files providing the PCIe Requester filters
|
||||
information used for PTT trace. Each file is named after the supported
|
||||
Endpoint device name <domain>:<bus>:<device>.<function>.
|
||||
|
||||
See the description of the "filter" in Documentation/trace/hisi-ptt.rst
|
||||
for more information.
|
||||
|
||||
What: /sys/devices/hisi_ptt<sicl_id>_<core_id>/requester_filters/multiselect
|
||||
Date: May 2023
|
||||
KernelVersion: 6.5
|
||||
Contact: Yicong Yang <yangyicong@hisilicon.com>
|
||||
Description: (Read) Indicates if this kind of filter can be selected at the same
|
||||
time as others filters, or must be used on it's own. 1 indicates
|
||||
the former case and 0 indicates the latter.
|
||||
|
||||
What: /sys/devices/hisi_ptt<sicl_id>_<core_id>/requester_filters/<bdf>
|
||||
Date: May 2023
|
||||
KernelVersion: 6.5
|
||||
Contact: Yicong Yang <yangyicong@hisilicon.com>
|
||||
Description: (Read) Indicates the filter value of this Requester filter, which
|
||||
can be used to control the TLP headers to trace by the PTT trace.
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/arm/arm,coresight-dummy-sink.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ARM Coresight Dummy sink component
|
||||
|
||||
description: |
|
||||
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.
|
||||
|
||||
The Coresight dummy sink component is for the specific coresight sink devices
|
||||
kernel don't have permission to access or configure, e.g., CoreSight EUD on
|
||||
Qualcomm platforms. It is a mini-USB hub implemented to support the USB-based
|
||||
debug and trace capabilities. For this device, a dummy driver is needed to
|
||||
register it as Coresight sink device in kernel side, so that path can be
|
||||
created in the driver. Then the trace flow would be transferred to EUD via
|
||||
coresight link of AP processor. It provides Coresight API for operations on
|
||||
dummy source devices, such as enabling and disabling them. It also provides
|
||||
the Coresight dummy source paths for debugging.
|
||||
|
||||
The primary use case of the coresight dummy sink is to build path in kernel
|
||||
side for dummy sink component.
|
||||
|
||||
maintainers:
|
||||
- Mike Leach <mike.leach@linaro.org>
|
||||
- Suzuki K Poulose <suzuki.poulose@arm.com>
|
||||
- James Clark <james.clark@arm.com>
|
||||
- Mao Jinlong <quic_jinlmao@quicinc.com>
|
||||
- Hao Zhang <quic_hazha@quicinc.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- arm,coresight-dummy-sink
|
||||
|
||||
in-ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
port:
|
||||
description: Input connection from the Coresight Trace bus to
|
||||
dummy sink, such as Embedded USB debugger(EUD).
|
||||
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- in-ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
# Minimum dummy sink definition. Dummy sink connect to coresight replicator.
|
||||
- |
|
||||
sink {
|
||||
compatible = "arm,coresight-dummy-sink";
|
||||
|
||||
in-ports {
|
||||
port {
|
||||
eud_in_replicator_swao: endpoint {
|
||||
remote-endpoint = <&replicator_swao_out_eud>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -0,0 +1,71 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/arm/arm,coresight-dummy-source.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ARM Coresight Dummy source component
|
||||
|
||||
description: |
|
||||
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.
|
||||
|
||||
The Coresight dummy source component is for the specific coresight source
|
||||
devices kernel don't have permission to access or configure. For some SOCs,
|
||||
there would be Coresight source trace components on sub-processor which
|
||||
are conneted to AP processor via debug bus. For these devices, a dummy driver
|
||||
is needed to register them as Coresight source devices, so that paths can be
|
||||
created in the driver. It provides Coresight API for operations on dummy
|
||||
source devices, such as enabling and disabling them. It also provides the
|
||||
Coresight dummy source paths for debugging.
|
||||
|
||||
The primary use case of the coresight dummy source is to build path in kernel
|
||||
side for dummy source component.
|
||||
|
||||
maintainers:
|
||||
- Mike Leach <mike.leach@linaro.org>
|
||||
- Suzuki K Poulose <suzuki.poulose@arm.com>
|
||||
- James Clark <james.clark@arm.com>
|
||||
- Mao Jinlong <quic_jinlmao@quicinc.com>
|
||||
- Hao Zhang <quic_hazha@quicinc.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- arm,coresight-dummy-source
|
||||
|
||||
out-ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
port:
|
||||
description: Output connection from the source to Coresight
|
||||
Trace bus.
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- out-ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
# Minimum dummy source definition. Dummy source connect to coresight funnel.
|
||||
- |
|
||||
source {
|
||||
compatible = "arm,coresight-dummy-source";
|
||||
|
||||
out-ports {
|
||||
port {
|
||||
dummy_riscv_out_funnel_swao: endpoint {
|
||||
remote-endpoint = <&funnel_swao_in_dummy_riscv>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -27,10 +27,14 @@ properties:
|
|||
|
||||
interrupt-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- const: usb_id
|
||||
- const: usb_vbus
|
||||
|
||||
anyOf:
|
||||
- items:
|
||||
- const: usb_id
|
||||
- const: usb_vbus
|
||||
- items:
|
||||
- const: usb_id
|
||||
- items:
|
||||
- const: usb_vbus
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -49,7 +53,7 @@ examples:
|
|||
interrupt-controller;
|
||||
#interrupt-cells = <4>;
|
||||
|
||||
usb_id: misc@900 {
|
||||
usb_id: usb-detect@900 {
|
||||
compatible = "qcom,pm8941-misc";
|
||||
reg = <0x900>;
|
||||
interrupts = <0x0 0x9 0 IRQ_TYPE_EDGE_BOTH>;
|
||||
|
|
|
@ -23,7 +23,7 @@ properties:
|
|||
headphone detect mode to HPDETL, ARIZONA_ACCDET_MODE_HPR/2 sets it
|
||||
to HPDETR. If this node is not included or if the value is unknown,
|
||||
then headphone detection mode is set to HPDETL.
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 1
|
||||
maximum: 2
|
||||
|
||||
|
@ -51,7 +51,7 @@ properties:
|
|||
description:
|
||||
Additional software microphone detection debounce specified in
|
||||
milliseconds.
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
wlf,micd-pol-gpio:
|
||||
description:
|
||||
|
@ -63,7 +63,7 @@ properties:
|
|||
description:
|
||||
Time allowed for MICBIAS to startup prior to performing microphone
|
||||
detection, specified as per the ARIZONA_MICD_TIME_XXX defines.
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 12
|
||||
|
||||
|
@ -71,7 +71,7 @@ properties:
|
|||
description:
|
||||
Delay between successive microphone detection measurements, specified
|
||||
as per the ARIZONA_MICD_TIME_XXX defines.
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 12
|
||||
|
||||
|
@ -79,7 +79,7 @@ properties:
|
|||
description:
|
||||
Microphone detection hardware debounces specified as the number of
|
||||
measurements to take.
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [2, 4]
|
||||
|
||||
wlf,micd-timeout-ms:
|
||||
|
@ -97,7 +97,7 @@ properties:
|
|||
CTIA / OMTP headsets), the field can be of variable length but
|
||||
should always be a multiple of 3 cells long, each three cell group
|
||||
represents one polarity configuration.
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32-matrix"
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-matrix
|
||||
items:
|
||||
items:
|
||||
- description:
|
||||
|
@ -119,7 +119,7 @@ properties:
|
|||
description:
|
||||
Settings for the general purpose switch, set as one of the
|
||||
ARIZONA_GPSW_XXX defines.
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 3
|
||||
|
||||
|
|
|
@ -47,6 +47,9 @@ properties:
|
|||
avdd-supply:
|
||||
description: AVdd voltage supply
|
||||
|
||||
vref-supply:
|
||||
description: VRef voltage supply
|
||||
|
||||
adi,rejection-60-Hz-enable:
|
||||
description: |
|
||||
This bit enables a notch at 60 Hz when the first notch of the sinc
|
||||
|
@ -89,6 +92,7 @@ required:
|
|||
- interrupts
|
||||
- dvdd-supply
|
||||
- avdd-supply
|
||||
- vref-supply
|
||||
- spi-cpol
|
||||
- spi-cpha
|
||||
|
||||
|
@ -115,6 +119,7 @@ examples:
|
|||
interrupt-parent = <&gpio>;
|
||||
dvdd-supply = <&dvdd>;
|
||||
avdd-supply = <&avdd>;
|
||||
vref-supply = <&vref>;
|
||||
|
||||
adi,refin2-pins-enable;
|
||||
adi,rejection-60-Hz-enable;
|
||||
|
|
|
@ -26,6 +26,7 @@ properties:
|
|||
- mediatek,mt2712-auxadc
|
||||
- mediatek,mt6765-auxadc
|
||||
- mediatek,mt7622-auxadc
|
||||
- mediatek,mt7986-auxadc
|
||||
- mediatek,mt8173-auxadc
|
||||
- items:
|
||||
- enum:
|
||||
|
|
|
@ -54,7 +54,7 @@ required:
|
|||
- '#io-channel-cells'
|
||||
|
||||
patternProperties:
|
||||
"^.*@[0-9a-f]+$":
|
||||
"^channel@[0-9a-f]+$":
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description: |
|
||||
|
@ -101,7 +101,7 @@ patternProperties:
|
|||
oneOf:
|
||||
- items:
|
||||
- const: 1
|
||||
- enum: [ 1, 3, 4, 6, 20, 8, 10 ]
|
||||
- enum: [ 1, 3, 4, 6, 20, 8, 10, 16 ]
|
||||
- items:
|
||||
- const: 10
|
||||
- const: 81
|
||||
|
@ -148,7 +148,7 @@ allOf:
|
|||
|
||||
then:
|
||||
patternProperties:
|
||||
"^.*@[0-9a-f]+$":
|
||||
"^channel@[0-9a-f]+$":
|
||||
properties:
|
||||
qcom,decimation:
|
||||
enum: [ 512, 1024, 2048, 4096 ]
|
||||
|
@ -171,7 +171,7 @@ allOf:
|
|||
|
||||
then:
|
||||
patternProperties:
|
||||
"^.*@[0-9a-f]+$":
|
||||
"^channel@[0-9a-f]+$":
|
||||
properties:
|
||||
qcom,decimation:
|
||||
enum: [ 256, 512, 1024 ]
|
||||
|
@ -194,7 +194,7 @@ allOf:
|
|||
|
||||
then:
|
||||
patternProperties:
|
||||
"^.*@[0-9a-f]+$":
|
||||
"^channel@[0-9a-f]+$":
|
||||
properties:
|
||||
qcom,decimation:
|
||||
enum: [ 250, 420, 840 ]
|
||||
|
@ -217,7 +217,7 @@ allOf:
|
|||
|
||||
then:
|
||||
patternProperties:
|
||||
"^.*@[0-9a-f]+$":
|
||||
"^channel@[0-9a-f]+$":
|
||||
properties:
|
||||
qcom,decimation:
|
||||
enum: [ 85, 340, 1360 ]
|
||||
|
@ -249,7 +249,7 @@ examples:
|
|||
#io-channel-cells = <1>;
|
||||
|
||||
/* Channel node */
|
||||
adc-chan@39 {
|
||||
channel@39 {
|
||||
reg = <0x39>;
|
||||
qcom,decimation = <512>;
|
||||
qcom,ratiometric;
|
||||
|
@ -258,19 +258,19 @@ examples:
|
|||
qcom,pre-scaling = <1 3>;
|
||||
};
|
||||
|
||||
adc-chan@9 {
|
||||
channel@9 {
|
||||
reg = <0x9>;
|
||||
};
|
||||
|
||||
adc-chan@a {
|
||||
channel@a {
|
||||
reg = <0xa>;
|
||||
};
|
||||
|
||||
adc-chan@e {
|
||||
channel@e {
|
||||
reg = <0xe>;
|
||||
};
|
||||
|
||||
adc-chan@f {
|
||||
channel@f {
|
||||
reg = <0xf>;
|
||||
};
|
||||
};
|
||||
|
@ -292,16 +292,18 @@ examples:
|
|||
#io-channel-cells = <1>;
|
||||
|
||||
/* Other properties are omitted */
|
||||
xo-therm@44 {
|
||||
channel@44 {
|
||||
reg = <PMK8350_ADC7_AMUX_THM1_100K_PU>;
|
||||
qcom,ratiometric;
|
||||
qcom,hw-settle-time = <200>;
|
||||
label = "xo_therm";
|
||||
};
|
||||
|
||||
conn-therm@47 {
|
||||
channel@47 {
|
||||
reg = <PM8350_ADC7_AMUX_THM4_100K_PU(1)>;
|
||||
qcom,ratiometric;
|
||||
qcom,hw-settle-time = <200>;
|
||||
label = "conn_therm";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -15,6 +15,7 @@ properties:
|
|||
- const: rockchip,saradc
|
||||
- const: rockchip,rk3066-tsadc
|
||||
- const: rockchip,rk3399-saradc
|
||||
- const: rockchip,rk3588-saradc
|
||||
- items:
|
||||
- enum:
|
||||
- rockchip,px30-saradc
|
||||
|
|
|
@ -13,7 +13,7 @@ description: |
|
|||
When an io-channel measures the midpoint of a voltage divider, the
|
||||
interesting voltage is often the voltage over the full resistance
|
||||
of the divider. This binding describes the voltage divider in such
|
||||
a curcuit.
|
||||
a circuit.
|
||||
|
||||
Vin ----.
|
||||
|
|
||||
|
|
|
@ -30,6 +30,9 @@ properties:
|
|||
- invensense,mpu9150
|
||||
- invensense,mpu9250
|
||||
- invensense,mpu9255
|
||||
- items:
|
||||
- const: invensense,icm20600
|
||||
- const: invensense,icm20602
|
||||
- items:
|
||||
- const: invensense,icm20608d
|
||||
- const: invensense,icm20608
|
||||
|
|
|
@ -98,6 +98,7 @@ required:
|
|||
- reg
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/iio/iio.yaml#
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/light/rohm,bu27008.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ROHM BU27008 color sensor
|
||||
|
||||
maintainers:
|
||||
- Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
|
||||
description:
|
||||
The ROHM BU27008 is a sensor with 5 photodiodes (red, green, blue, clear
|
||||
and IR) with four configurable channels. Red and green being always
|
||||
available and two out of the rest three (blue, clear, IR) can be
|
||||
selected to be simultaneously measured. Typical application is adjusting
|
||||
LCD backlight of TVs, mobile phones and tablet PCs.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rohm,bu27008
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
light-sensor@38 {
|
||||
compatible = "rohm,bu27008";
|
||||
reg = <0x38>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -0,0 +1,68 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/light/ti,opt4001.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Texas Instruments OPT4001 Ambient Light Sensor
|
||||
|
||||
maintainers:
|
||||
- Stefan Windfeldt-Prytz <stefan.windfeldt-prytz@axis.com>
|
||||
|
||||
description:
|
||||
Ambient light sensor with an i2c interface.
|
||||
Last part of compatible is for the packaging used.
|
||||
Picostar is a 4 pinned SMT and sot-5x3 is a 8 pinned SOT.
|
||||
https://www.ti.com/lit/gpn/opt4001
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,opt4001-picostar
|
||||
- ti,opt4001-sot-5x3
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply:
|
||||
description: Regulator that provides power to the sensor
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: ti,opt4001-sot-5x3
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
else:
|
||||
properties:
|
||||
interrupts: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
light-sensor@44 {
|
||||
compatible = "ti,opt4001-sot-5x3";
|
||||
reg = <0x44>;
|
||||
vdd-supply = <&vdd_reg>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <28 IRQ_TYPE_EDGE_FALLING>;
|
||||
};
|
||||
};
|
||||
...
|
|
@ -0,0 +1,78 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/potentiometer/renesas,x9250.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas X9250 quad potentiometers
|
||||
|
||||
maintainers:
|
||||
- Herve Codina <herve.codina@bootlin.com>
|
||||
|
||||
description:
|
||||
The Renesas X9250 integrates four digitally controlled potentiometers.
|
||||
On each potentiometer, the X9250T has a 100 kOhms total resistance and the
|
||||
X9250U has a 50 kOhms total resistance.
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- renesas,x9250t
|
||||
- renesas,x9250u
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vcc-supply:
|
||||
description:
|
||||
Regulator for the VCC power supply.
|
||||
|
||||
avp-supply:
|
||||
description:
|
||||
Regulator for the analog V+ power supply.
|
||||
|
||||
avn-supply:
|
||||
description:
|
||||
Regulator for the analog V- power supply.
|
||||
|
||||
'#io-channel-cells':
|
||||
const: 1
|
||||
|
||||
spi-max-frequency:
|
||||
maximum: 2000000
|
||||
|
||||
wp-gpios:
|
||||
maxItems: 1
|
||||
description:
|
||||
GPIO connected to the write-protect pin.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vcc-supply
|
||||
- avp-supply
|
||||
- avn-supply
|
||||
- '#io-channel-cells'
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
potentiometer@0 {
|
||||
compatible = "renesas,x9250t";
|
||||
reg = <0>;
|
||||
vcc-supply = <&vcc_regulator>;
|
||||
avp-supply = <&avp_regulator>;
|
||||
avn-supply = <&avp_regulator>;
|
||||
wp-gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
|
||||
spi-max-frequency = <2000000>;
|
||||
#io-channel-cells = <1>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,104 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/pressure/honeywell,mprls0025pa.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Honeywell mprls0025pa pressure sensor
|
||||
|
||||
maintainers:
|
||||
- Andreas Klinger <ak@it-klinger.de>
|
||||
|
||||
description: |
|
||||
Honeywell pressure sensor of model mprls0025pa.
|
||||
|
||||
This sensor has an I2C and SPI interface. Only the I2C interface is
|
||||
implemented.
|
||||
|
||||
There are many models with different pressure ranges available. The vendor
|
||||
calls them "mpr series". All of them have the identical programming model and
|
||||
differ in the pressure range, unit and transfer function.
|
||||
|
||||
To support different models one need to specify the pressure range as well as
|
||||
the transfer function. Pressure range needs to be converted from its unit to
|
||||
pascal.
|
||||
|
||||
The transfer function defines the ranges of numerical values delivered by the
|
||||
sensor. The minimal range value stands for the minimum pressure and the
|
||||
maximum value also for the maximum pressure with linear relation inside the
|
||||
range.
|
||||
|
||||
Specifications about the devices can be found at:
|
||||
https://prod-edam.honeywell.com/content/dam/honeywell-edam/sps/siot/en-us/
|
||||
products/sensors/pressure-sensors/board-mount-pressure-sensors/
|
||||
micropressure-mpr-series/documents/
|
||||
sps-siot-mpr-series-datasheet-32332628-ciid-172626.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: honeywell,mprls0025pa
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description:
|
||||
Optional GPIO for resetting the device.
|
||||
If not present the device is not resetted during the probe.
|
||||
maxItems: 1
|
||||
|
||||
honeywell,pmin-pascal:
|
||||
description:
|
||||
Minimum pressure value the sensor can measure in pascal.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
honeywell,pmax-pascal:
|
||||
description:
|
||||
Maximum pressure value the sensor can measure in pascal.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
honeywell,transfer-function:
|
||||
description: |
|
||||
Transfer function which defines the range of valid values delivered by the
|
||||
sensor.
|
||||
1 - A, 10% to 90% of 2^24 (1677722 .. 15099494)
|
||||
2 - B, 2.5% to 22.5% of 2^24 (419430 .. 3774874)
|
||||
3 - C, 20% to 80% of 2^24 (3355443 .. 13421773)
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
vdd-supply:
|
||||
description: provide VDD power to the sensor.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- honeywell,pmin-pascal
|
||||
- honeywell,pmax-pascal
|
||||
- honeywell,transfer-function
|
||||
- vdd-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pressure@18 {
|
||||
compatible = "honeywell,mprls0025pa";
|
||||
reg = <0x18>;
|
||||
reset-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
|
||||
interrupt-parent = <&gpio3>;
|
||||
interrupts = <21 IRQ_TYPE_EDGE_FALLING>;
|
||||
honeywell,pmin-pascal = <0>;
|
||||
honeywell,pmax-pascal = <172369>;
|
||||
honeywell,transfer-function = <1>;
|
||||
vdd-supply = <&vcc_3v3>;
|
||||
};
|
||||
};
|
|
@ -84,6 +84,7 @@ properties:
|
|||
- st,lps35hw
|
||||
- description: IMUs
|
||||
enum:
|
||||
- st,lsm303d-imu
|
||||
- st,lsm9ds0-imu
|
||||
- description: Deprecated bindings
|
||||
enum:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
$id: http://devicetree.org/schemas/iio/temperature/melexis,mlx90614.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Melexis MLX90614 contactless IR temperature sensor
|
||||
title: Melexis MLX90614/MLX90615 contactless IR temperature sensor
|
||||
|
||||
maintainers:
|
||||
- Peter Meerwald <pmeerw@pmeerw.net>
|
||||
|
@ -15,7 +15,9 @@ description: |
|
|||
|
||||
properties:
|
||||
compatible:
|
||||
const: melexis,mlx90614
|
||||
enum:
|
||||
- melexis,mlx90614
|
||||
- melexis,mlx90615
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/temperature/ti,tmp006.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: TI TMP006 IR thermopile sensor
|
||||
|
||||
maintainers:
|
||||
- Peter Meerwald <pmeerw@pmeerw.net>
|
||||
|
||||
description: |
|
||||
TI TMP006 - Infrared Thermopile Sensor in Chip-Scale Package.
|
||||
https://cdn.sparkfun.com/datasheets/Sensors/Temp/tmp006.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ti,tmp006
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply:
|
||||
description: provide VDD power to the sensor.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
temperature-sensor@40 {
|
||||
compatible = "ti,tmp006";
|
||||
reg = <0x40>;
|
||||
vdd-supply = <&ldo4_reg>;
|
||||
};
|
||||
};
|
|
@ -51,7 +51,7 @@ properties:
|
|||
type: object
|
||||
|
||||
fsl,ddrc:
|
||||
$ref: "/schemas/types.yaml#/definitions/phandle"
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
Phandle to DDR Controller.
|
||||
|
||||
|
|
|
@ -36,14 +36,29 @@ properties:
|
|||
et0macaddr:
|
||||
type: object
|
||||
description: First Ethernet interface's MAC address
|
||||
properties:
|
||||
"#nvmem-cell-cells":
|
||||
description: The first argument is a MAC address offset.
|
||||
const: 1
|
||||
additionalProperties: false
|
||||
|
||||
et1macaddr:
|
||||
type: object
|
||||
description: Second Ethernet interface's MAC address
|
||||
properties:
|
||||
"#nvmem-cell-cells":
|
||||
description: The first argument is a MAC address offset.
|
||||
const: 1
|
||||
additionalProperties: false
|
||||
|
||||
et2macaddr:
|
||||
type: object
|
||||
description: Third Ethernet interface's MAC address
|
||||
properties:
|
||||
"#nvmem-cell-cells":
|
||||
description: The first argument is a MAC address offset.
|
||||
const: 1
|
||||
additionalProperties: false
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
$id: http://devicetree.org/schemas/nvmem/imx-ocotp.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Freescale i.MX6 On-Chip OTP Controller (OCOTP)
|
||||
title: Freescale i.MX On-Chip OTP Controller (OCOTP)
|
||||
|
||||
maintainers:
|
||||
- Anson Huang <Anson.Huang@nxp.com>
|
||||
|
@ -12,7 +12,7 @@ maintainers:
|
|||
description: |
|
||||
This binding represents the on-chip eFuse OTP controller found on
|
||||
i.MX6Q/D, i.MX6DL/S, i.MX6SL, i.MX6SX, i.MX6UL, i.MX6ULL/ULZ, i.MX6SLL,
|
||||
i.MX7D/S, i.MX7ULP, i.MX8MQ, i.MX8MM, i.MX8MN and i.MX8MP SoCs.
|
||||
i.MX7D/S, i.MX7ULP, i.MX8MQ, i.MX8MM, i.MX8MN i.MX8MP and i.MX93 SoCs.
|
||||
|
||||
allOf:
|
||||
- $ref: nvmem.yaml#
|
||||
|
@ -32,6 +32,7 @@ properties:
|
|||
- fsl,imx7ulp-ocotp
|
||||
- fsl,imx8mq-ocotp
|
||||
- fsl,imx8mm-ocotp
|
||||
- fsl,imx93-ocotp
|
||||
- const: syscon
|
||||
- items:
|
||||
- enum:
|
||||
|
@ -46,12 +47,6 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
|
@ -61,21 +56,6 @@ required:
|
|||
- compatible
|
||||
- reg
|
||||
|
||||
patternProperties:
|
||||
"^.*@[0-9a-f]+$":
|
||||
type: object
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
description:
|
||||
Offset and size in bytes within the storage device.
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/nvmem/layouts/fixed-cell.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Fixed offset & size NVMEM cell
|
||||
|
||||
maintainers:
|
||||
- Rafał Miłecki <rafal@milecki.pl>
|
||||
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
bits:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
items:
|
||||
- minimum: 0
|
||||
maximum: 7
|
||||
description:
|
||||
Offset in bit within the address range specified by reg.
|
||||
- minimum: 1
|
||||
description:
|
||||
Size in bit within the address range specified by reg.
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
additionalProperties: true
|
|
@ -0,0 +1,50 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/nvmem/layouts/fixed-layout.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NVMEM layout for fixed NVMEM cells
|
||||
|
||||
description:
|
||||
Many NVMEM devices have hardcoded cells layout (offset and size of defined
|
||||
NVMEM content doesn't change).
|
||||
|
||||
This binding allows defining such NVMEM layout with its cells. It can be used
|
||||
on top of any NVMEM device.
|
||||
|
||||
maintainers:
|
||||
- Rafał Miłecki <rafal@milecki.pl>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: fixed-layout
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 1
|
||||
|
||||
patternProperties:
|
||||
"@[a-f0-9]+$":
|
||||
type: object
|
||||
$ref: fixed-cell.yaml
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
nvmem-layout {
|
||||
compatible = "fixed-layout";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
calibration@4000 {
|
||||
reg = <0x4000 0x100>;
|
||||
};
|
||||
};
|
|
@ -18,16 +18,13 @@ description: |
|
|||
perform their parsing. The nvmem-layout container is here to describe these.
|
||||
|
||||
oneOf:
|
||||
- $ref: fixed-layout.yaml
|
||||
- $ref: kontron,sl28-vpd.yaml
|
||||
- $ref: onie,tlv-layout.yaml
|
||||
|
||||
properties:
|
||||
compatible: true
|
||||
|
||||
'#address-cells': false
|
||||
|
||||
'#size-cells': false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ properties:
|
|||
- enum:
|
||||
- mediatek,mt7622-efuse
|
||||
- mediatek,mt7623-efuse
|
||||
- mediatek,mt7986-efuse
|
||||
- mediatek,mt8173-efuse
|
||||
- mediatek,mt8183-efuse
|
||||
- mediatek,mt8186-efuse
|
||||
|
|
|
@ -18,12 +18,6 @@ properties:
|
|||
- fsl,imx23-ocotp
|
||||
- fsl,imx28-ocotp
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
|
@ -35,7 +29,7 @@ required:
|
|||
- reg
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
@ -49,23 +49,8 @@ properties:
|
|||
patternProperties:
|
||||
"@[0-9a-f]+(,[0-7])?$":
|
||||
type: object
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
description:
|
||||
Offset and size in bytes within the storage device.
|
||||
|
||||
bits:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
items:
|
||||
- minimum: 0
|
||||
maximum: 7
|
||||
description:
|
||||
Offset in bit within the address range specified by reg.
|
||||
- minimum: 1
|
||||
description:
|
||||
Size in bit within the address range specified by reg.
|
||||
$ref: layouts/fixed-cell.yaml
|
||||
deprecated: true
|
||||
|
||||
additionalProperties: true
|
||||
|
||||
|
@ -83,24 +68,30 @@ examples:
|
|||
|
||||
/* ... */
|
||||
|
||||
/* Data cells */
|
||||
tsens_calibration: calib@404 {
|
||||
reg = <0x404 0x10>;
|
||||
};
|
||||
nvmem-layout {
|
||||
compatible = "fixed-layout";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
tsens_calibration_bckp: calib_bckp@504 {
|
||||
reg = <0x504 0x11>;
|
||||
bits = <6 128>;
|
||||
};
|
||||
/* Data cells */
|
||||
tsens_calibration: calib@404 {
|
||||
reg = <0x404 0x10>;
|
||||
};
|
||||
|
||||
pvs_version: pvs-version@6 {
|
||||
reg = <0x6 0x2>;
|
||||
bits = <7 2>;
|
||||
};
|
||||
tsens_calibration_bckp: calib_bckp@504 {
|
||||
reg = <0x504 0x11>;
|
||||
bits = <6 128>;
|
||||
};
|
||||
|
||||
speed_bin: speed-bin@c{
|
||||
reg = <0xc 0x1>;
|
||||
bits = <2 3>;
|
||||
pvs_version: pvs-version@6 {
|
||||
reg = <0x6 0x2>;
|
||||
bits = <7 2>;
|
||||
};
|
||||
|
||||
speed_bin: speed-bin@c{
|
||||
reg = <0xc 0x1>;
|
||||
bits = <2 3>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -67,12 +67,6 @@ properties:
|
|||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
# Needed if any child nodes are present.
|
||||
"#address-cells":
|
||||
const: 1
|
||||
"#size-cells":
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
@ -25,12 +25,6 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 1
|
||||
|
||||
ranges: true
|
||||
|
||||
required:
|
||||
|
|
|
@ -17,6 +17,7 @@ properties:
|
|||
items:
|
||||
- enum:
|
||||
- raspberrypi,bootloader-config
|
||||
- raspberrypi,bootloader-public-key
|
||||
- const: nvmem-rmem
|
||||
|
||||
reg:
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/nvmem/rockchip,otp.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Rockchip internal OTP (One Time Programmable) memory
|
||||
|
||||
maintainers:
|
||||
- Heiko Stuebner <heiko@sntech.de>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- rockchip,px30-otp
|
||||
- rockchip,rk3308-otp
|
||||
- rockchip,rk3588-otp
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 3
|
||||
maxItems: 4
|
||||
|
||||
clock-names:
|
||||
minItems: 3
|
||||
items:
|
||||
- const: otp
|
||||
- const: apb_pclk
|
||||
- const: phy
|
||||
- const: arb
|
||||
|
||||
resets:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
reset-names:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- reset-names
|
||||
|
||||
allOf:
|
||||
- $ref: nvmem.yaml#
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- rockchip,px30-otp
|
||||
- rockchip,rk3308-otp
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 3
|
||||
resets:
|
||||
maxItems: 1
|
||||
reset-names:
|
||||
items:
|
||||
- const: phy
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- rockchip,rk3588-otp
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 4
|
||||
resets:
|
||||
minItems: 3
|
||||
reset-names:
|
||||
items:
|
||||
- const: otp
|
||||
- const: apb
|
||||
- const: arb
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/px30-cru.h>
|
||||
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
otp: efuse@ff290000 {
|
||||
compatible = "rockchip,px30-otp";
|
||||
reg = <0x0 0xff290000 0x0 0x4000>;
|
||||
clocks = <&cru SCLK_OTP_USR>, <&cru PCLK_OTP_NS>,
|
||||
<&cru PCLK_OTP_PHY>;
|
||||
clock-names = "otp", "apb_pclk", "phy";
|
||||
resets = <&cru SRST_OTP_PHY>;
|
||||
reset-names = "phy";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
cpu_id: id@7 {
|
||||
reg = <0x07 0x10>;
|
||||
};
|
||||
|
||||
cpu_leakage: cpu-leakage@17 {
|
||||
reg = <0x17 0x1>;
|
||||
};
|
||||
|
||||
performance: performance@1e {
|
||||
reg = <0x1e 0x1>;
|
||||
bits = <4 3>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -1,25 +0,0 @@
|
|||
Rockchip internal OTP (One Time Programmable) memory device tree bindings
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be one of the following.
|
||||
- "rockchip,px30-otp" - for PX30 SoCs.
|
||||
- "rockchip,rk3308-otp" - for RK3308 SoCs.
|
||||
- reg: Should contain the registers location and size
|
||||
- clocks: Must contain an entry for each entry in clock-names.
|
||||
- clock-names: Should be "otp", "apb_pclk" and "phy".
|
||||
- resets: Must contain an entry for each entry in reset-names.
|
||||
See ../../reset/reset.txt for details.
|
||||
- reset-names: Should be "phy".
|
||||
|
||||
See nvmem.txt for more information.
|
||||
|
||||
Example:
|
||||
otp: otp@ff290000 {
|
||||
compatible = "rockchip,px30-otp";
|
||||
reg = <0x0 0xff290000 0x0 0x4000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
clocks = <&cru SCLK_OTP_USR>, <&cru PCLK_OTP_NS>,
|
||||
<&cru PCLK_OTP_PHY>;
|
||||
clock-names = "otp", "apb_pclk", "phy";
|
||||
};
|
|
@ -14,9 +14,6 @@ allOf:
|
|||
- $ref: nvmem.yaml#
|
||||
|
||||
properties:
|
||||
"#address-cells": true
|
||||
"#size-cells": true
|
||||
|
||||
compatible:
|
||||
const: socionext,uniphier-efuse
|
||||
|
||||
|
|
|
@ -28,12 +28,6 @@ properties:
|
|||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 1
|
||||
|
||||
thermal-calibration:
|
||||
type: object
|
||||
description: thermal calibration values
|
||||
|
|
|
@ -364,6 +364,7 @@ MEM
|
|||
devm_kmalloc_array()
|
||||
devm_kmemdup()
|
||||
devm_krealloc()
|
||||
devm_krealloc_array()
|
||||
devm_kstrdup()
|
||||
devm_kstrdup_const()
|
||||
devm_kvasprintf()
|
||||
|
|
|
@ -29,7 +29,7 @@ recur_count
|
|||
cpoint_name
|
||||
Where in the kernel to trigger the action. It can be
|
||||
one of INT_HARDWARE_ENTRY, INT_HW_IRQ_EN, INT_TASKLET_ENTRY,
|
||||
FS_DEVRW, MEM_SWAPOUT, TIMERADD, SCSI_QUEUE_RQ, or DIRECT.
|
||||
FS_SUBMIT_BH, MEM_SWAPOUT, TIMERADD, SCSI_QUEUE_RQ, or DIRECT.
|
||||
|
||||
cpoint_type
|
||||
Indicates the action to be taken on hitting the crash point.
|
||||
|
|
|
@ -28,5 +28,6 @@ fit into other categories.
|
|||
oxsemi-tornado
|
||||
pci-endpoint-test
|
||||
spear-pcie-gadget
|
||||
tps6594-pfsm
|
||||
uacce
|
||||
xilinx_sdfec
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=====================================
|
||||
Texas Instruments TPS6594 PFSM driver
|
||||
=====================================
|
||||
|
||||
Author: Julien Panis (jpanis@baylibre.com)
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
Strictly speaking, PFSM (Pre-configurable Finite State Machine) is not
|
||||
hardware. It is a piece of code.
|
||||
|
||||
The TPS6594 PMIC (Power Management IC) integrates a state machine which
|
||||
manages operational modes. Depending on the current operational mode,
|
||||
some voltage domains remain energized while others can be off.
|
||||
|
||||
The PFSM driver can be used to trigger transitions between configured
|
||||
states. It also provides R/W access to the device registers.
|
||||
|
||||
Supported chips
|
||||
---------------
|
||||
|
||||
- tps6594-q1
|
||||
- tps6593-q1
|
||||
- lp8764-q1
|
||||
|
||||
Driver location
|
||||
===============
|
||||
|
||||
drivers/misc/tps6594-pfsm.c
|
||||
|
||||
Driver type definitions
|
||||
=======================
|
||||
|
||||
include/uapi/linux/tps6594_pfsm.h
|
||||
|
||||
Driver IOCTLs
|
||||
=============
|
||||
|
||||
:c:macro::`PMIC_GOTO_STANDBY`
|
||||
All device resources are powered down. The processor is off, and
|
||||
no voltage domains are energized.
|
||||
|
||||
:c:macro::`PMIC_GOTO_LP_STANDBY`
|
||||
The digital and analog functions of the PMIC, which are not
|
||||
required to be always-on, are turned off (low-power).
|
||||
|
||||
:c:macro::`PMIC_UPDATE_PGM`
|
||||
Triggers a firmware update.
|
||||
|
||||
:c:macro::`PMIC_SET_ACTIVE_STATE`
|
||||
One of the operational modes.
|
||||
The PMICs are fully functional and supply power to all PDN loads.
|
||||
All voltage domains are energized in both MCU and Main processor
|
||||
sections.
|
||||
|
||||
:c:macro::`PMIC_SET_MCU_ONLY_STATE`
|
||||
One of the operational modes.
|
||||
Only the power resources assigned to the MCU Safety Island are on.
|
||||
|
||||
:c:macro::`PMIC_SET_RETENTION_STATE`
|
||||
One of the operational modes.
|
||||
Depending on the triggers set, some DDR/GPIO voltage domains can
|
||||
remain energized, while all other domains are off to minimize
|
||||
total system power.
|
||||
|
||||
Driver usage
|
||||
============
|
||||
|
||||
See available PFSMs::
|
||||
|
||||
# ls /dev/pfsm*
|
||||
|
||||
Dump the registers of pages 0 and 1::
|
||||
|
||||
# hexdump -C /dev/pfsm-0-0x48
|
||||
|
||||
See PFSM events::
|
||||
|
||||
# cat /proc/interrupts
|
||||
|
||||
Userspace code example
|
||||
----------------------
|
||||
|
||||
samples/pfsm/pfsm-wakeup.c
|
|
@ -0,0 +1,32 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=============================
|
||||
Coresight Dummy Trace Module
|
||||
=============================
|
||||
|
||||
:Author: Hao Zhang <quic_hazha@quicinc.com>
|
||||
:Date: June 2023
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
The Coresight dummy trace module is for the specific devices that kernel don't
|
||||
have permission to access or configure, e.g., CoreSight TPDMs on Qualcomm
|
||||
platforms. For these devices, a dummy driver is needed to register them as
|
||||
Coresight devices. The module may also be used to define components that may
|
||||
not have any programming interfaces, so that paths can be created in the driver.
|
||||
It provides Coresight API for operations on dummy devices, such as enabling and
|
||||
disabling them. It also provides the Coresight dummy sink/source paths for
|
||||
debugging.
|
||||
|
||||
Config details
|
||||
--------------
|
||||
|
||||
There are two types of nodes, dummy sink and dummy source. These nodes
|
||||
are available at ``/sys/bus/coresight/devices``.
|
||||
|
||||
Example output::
|
||||
|
||||
$ ls -l /sys/bus/coresight/devices | grep dummy
|
||||
dummy_sink0 -> ../../../devices/platform/soc@0/soc@0:sink/dummy_sink0
|
||||
dummy_source0 -> ../../../devices/platform/soc@0/soc@0:source/dummy_source0
|
|
@ -148,14 +148,20 @@ For example, if the desired filter is Endpoint function 0000:01:00.1 the filter
|
|||
value will be 0x00101. If the desired filter is Root Port 0000:00:10.0 then
|
||||
then filter value is calculated as 0x80001.
|
||||
|
||||
The driver also presents every supported Root Port and Requester filter through
|
||||
sysfs. Each filter will be an individual file with name of its related PCIe
|
||||
device name (domain:bus:device.function). The files of Root Port filters are
|
||||
under $(PTT PMU dir)/root_port_filters and files of Requester filters
|
||||
are under $(PTT PMU dir)/requester_filters.
|
||||
|
||||
Note that multiple Root Ports can be specified at one time, but only one
|
||||
Endpoint function can be specified in one trace. Specifying both Root Port
|
||||
and function at the same time is not supported. Driver maintains a list of
|
||||
available filters and will check the invalid inputs.
|
||||
|
||||
Currently the available filters are detected in driver's probe. If the supported
|
||||
devices are removed/added after probe, you may need to reload the driver to update
|
||||
the filters.
|
||||
The available filters will be dynamically updated, which means you will always
|
||||
get correct filter information when hotplug events happen, or when you manually
|
||||
remove/rescan the devices.
|
||||
|
||||
2. Type
|
||||
-------
|
||||
|
|
|
@ -180,6 +180,7 @@ Code Seq# Include File Comments
|
|||
'P' 00-0F drivers/usb/class/usblp.c conflict!
|
||||
'P' 01-09 drivers/misc/pci_endpoint_test.c conflict!
|
||||
'P' 00-0F xen/privcmd.h conflict!
|
||||
'P' 00-05 linux/tps6594_pfsm.h conflict!
|
||||
'Q' all linux/soundcard.h
|
||||
'R' 00-1F linux/random.h conflict!
|
||||
'R' 01 linux/rfkill.h conflict!
|
||||
|
|
25
MAINTAINERS
25
MAINTAINERS
|
@ -2103,6 +2103,7 @@ N: digicolor
|
|||
ARM/CORESIGHT FRAMEWORK AND DRIVERS
|
||||
M: Suzuki K Poulose <suzuki.poulose@arm.com>
|
||||
R: Mike Leach <mike.leach@linaro.org>
|
||||
R: James Clark <james.clark@arm.com>
|
||||
R: Leo Yan <leo.yan@linaro.org>
|
||||
L: coresight@lists.linaro.org (moderated for non-subscribers)
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
|
@ -9490,6 +9491,13 @@ F: lib/test_hmm*
|
|||
F: mm/hmm*
|
||||
F: tools/testing/selftests/mm/*hmm*
|
||||
|
||||
HONEYWELL MPRLS0025PA PRESSURE SENSOR SERIES IIO DRIVER
|
||||
M: Andreas Klinger <ak@it-klinger.de>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml
|
||||
F: drivers/iio/pressure/mprls0025pa.c
|
||||
|
||||
HOST AP DRIVER
|
||||
M: Jouni Malinen <j@w1.fi>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
|
@ -10334,6 +10342,13 @@ L: linux-fbdev@vger.kernel.org
|
|||
S: Maintained
|
||||
F: drivers/video/fbdev/i810/
|
||||
|
||||
INTEL 8254 COUNTER DRIVER
|
||||
M: William Breathitt Gray <william.gray@linaro.org>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/counter/i8254.c
|
||||
F: include/linux/i8254.h
|
||||
|
||||
INTEL 8255 GPIO DRIVER
|
||||
M: William Breathitt Gray <william.gray@linaro.org>
|
||||
L: linux-gpio@vger.kernel.org
|
||||
|
@ -18186,6 +18201,13 @@ S: Maintained
|
|||
F: Documentation/devicetree/bindings/clock/renesas,versaclock7.yaml
|
||||
F: drivers/clk/clk-versaclock7.c
|
||||
|
||||
RENESAS X9250 DIGITAL POTENTIOMETERS DRIVER
|
||||
M: Herve Codina <herve.codina@bootlin.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/potentiometer/renesas,x9250.yaml
|
||||
F: drivers/iio/potentiometer/x9250.c
|
||||
|
||||
RESET CONTROLLER FRAMEWORK
|
||||
M: Philipp Zabel <p.zabel@pengutronix.de>
|
||||
S: Maintained
|
||||
|
@ -18398,10 +18420,11 @@ S: Maintained
|
|||
F: Documentation/devicetree/bindings/iio/light/bh1750.yaml
|
||||
F: drivers/iio/light/bh1750.c
|
||||
|
||||
ROHM BU27034 AMBIENT LIGHT SENSOR DRIVER
|
||||
ROHM BU270xx LIGHT SENSOR DRIVERs
|
||||
M: Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/iio/light/rohm-bu27008.c
|
||||
F: drivers/iio/light/rohm-bu27034.c
|
||||
|
||||
ROHM MULTIFUNCTION BD9571MWV-M PMIC DEVICE DRIVERS
|
||||
|
|
|
@ -46,6 +46,7 @@ if SPEAKUP
|
|||
config SPEAKUP_SERIALIO
|
||||
def_bool y
|
||||
depends on ISA || COMPILE_TEST
|
||||
depends on HAS_IOPORT
|
||||
|
||||
config SPEAKUP_SYNTH_ACNTSA
|
||||
tristate "Accent SA synthesizer support"
|
||||
|
|
|
@ -1287,7 +1287,7 @@ static struct var_t spk_vars[NB_ID] = {
|
|||
[PUNC_LEVEL_ID] = { PUNC_LEVEL, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} },
|
||||
[READING_PUNC_ID] = { READING_PUNC, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} },
|
||||
[CURSOR_TIME_ID] = { CURSOR_TIME, .u.n = {NULL, 120, 50, 600, 0, 0, NULL} },
|
||||
[SAY_CONTROL_ID] { SAY_CONTROL, TOGGLE_0},
|
||||
[SAY_CONTROL_ID] = { SAY_CONTROL, TOGGLE_0},
|
||||
[SAY_WORD_CTL_ID] = {SAY_WORD_CTL, TOGGLE_0},
|
||||
[NO_INTERRUPT_ID] = { NO_INTERRUPT, TOGGLE_0},
|
||||
[KEY_ECHO_ID] = { KEY_ECHO, .u.n = {NULL, 1, 0, 2, 0, 0, NULL} },
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
#include <linux/syscalls.h>
|
||||
#include <linux/task_work.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <linux/ktime.h>
|
||||
|
||||
#include <uapi/linux/android/binder.h>
|
||||
|
||||
|
@ -2918,6 +2919,7 @@ static void binder_transaction(struct binder_proc *proc,
|
|||
binder_size_t last_fixup_min_off = 0;
|
||||
struct binder_context *context = proc->context;
|
||||
int t_debug_id = atomic_inc_return(&binder_last_id);
|
||||
ktime_t t_start_time = ktime_get();
|
||||
char *secctx = NULL;
|
||||
u32 secctx_sz = 0;
|
||||
struct list_head sgc_head;
|
||||
|
@ -3159,6 +3161,7 @@ static void binder_transaction(struct binder_proc *proc,
|
|||
binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE);
|
||||
|
||||
t->debug_id = t_debug_id;
|
||||
t->start_time = t_start_time;
|
||||
|
||||
if (reply)
|
||||
binder_debug(BINDER_DEBUG_TRANSACTION,
|
||||
|
@ -3183,6 +3186,8 @@ static void binder_transaction(struct binder_proc *proc,
|
|||
t->from = thread;
|
||||
else
|
||||
t->from = NULL;
|
||||
t->from_pid = proc->pid;
|
||||
t->from_tid = thread->pid;
|
||||
t->sender_euid = task_euid(proc->tsk);
|
||||
t->to_proc = target_proc;
|
||||
t->to_thread = target_thread;
|
||||
|
@ -5944,17 +5949,19 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
|
|||
{
|
||||
struct binder_proc *to_proc;
|
||||
struct binder_buffer *buffer = t->buffer;
|
||||
ktime_t current_time = ktime_get();
|
||||
|
||||
spin_lock(&t->lock);
|
||||
to_proc = t->to_proc;
|
||||
seq_printf(m,
|
||||
"%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld r%d",
|
||||
"%s %d: %pK from %d:%d to %d:%d code %x flags %x pri %ld r%d elapsed %lldms",
|
||||
prefix, t->debug_id, t,
|
||||
t->from ? t->from->proc->pid : 0,
|
||||
t->from ? t->from->pid : 0,
|
||||
t->from_pid,
|
||||
t->from_tid,
|
||||
to_proc ? to_proc->pid : 0,
|
||||
t->to_thread ? t->to_thread->pid : 0,
|
||||
t->code, t->flags, t->priority, t->need_reply);
|
||||
t->code, t->flags, t->priority, t->need_reply,
|
||||
ktime_ms_delta(current_time, t->start_time));
|
||||
spin_unlock(&t->lock);
|
||||
|
||||
if (proc != to_proc) {
|
||||
|
|
|
@ -515,6 +515,8 @@ struct binder_transaction {
|
|||
int debug_id;
|
||||
struct binder_work work;
|
||||
struct binder_thread *from;
|
||||
pid_t from_pid;
|
||||
pid_t from_tid;
|
||||
struct binder_transaction *from_parent;
|
||||
struct binder_proc *to_proc;
|
||||
struct binder_thread *to_thread;
|
||||
|
@ -528,6 +530,7 @@ struct binder_transaction {
|
|||
long priority;
|
||||
long saved_priority;
|
||||
kuid_t sender_euid;
|
||||
ktime_t start_time;
|
||||
struct list_head fd_fixups;
|
||||
binder_uintptr_t security_ctx;
|
||||
/**
|
||||
|
|
|
@ -45,6 +45,9 @@ static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
|
|||
struct fsl_mc_child_objs *objs;
|
||||
struct fsl_mc_device *mc_dev;
|
||||
|
||||
if (!dev_is_fsl_mc(dev))
|
||||
return 0;
|
||||
|
||||
mc_dev = to_fsl_mc_device(dev);
|
||||
objs = data;
|
||||
|
||||
|
@ -64,6 +67,9 @@ static int __fsl_mc_device_remove_if_not_in_mc(struct device *dev, void *data)
|
|||
|
||||
static int __fsl_mc_device_remove(struct device *dev, void *data)
|
||||
{
|
||||
if (!dev_is_fsl_mc(dev))
|
||||
return 0;
|
||||
|
||||
fsl_mc_device_remove(to_fsl_mc_device(dev));
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -62,6 +62,8 @@
|
|||
#include <linux/mm.h>
|
||||
#include <linux/xarray.h>
|
||||
#include <linux/cdx/cdx_bus.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/dma-map-ops.h>
|
||||
#include "cdx.h"
|
||||
|
||||
/* Default DMA mask for devices on a CDX bus */
|
||||
|
@ -257,6 +259,7 @@ static void cdx_shutdown(struct device *dev)
|
|||
|
||||
static int cdx_dma_configure(struct device *dev)
|
||||
{
|
||||
struct cdx_driver *cdx_drv = to_cdx_driver(dev->driver);
|
||||
struct cdx_device *cdx_dev = to_cdx_device(dev);
|
||||
u32 input_id = cdx_dev->req_id;
|
||||
int ret;
|
||||
|
@ -267,9 +270,23 @@ static int cdx_dma_configure(struct device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (!ret && !cdx_drv->driver_managed_dma) {
|
||||
ret = iommu_device_use_default_domain(dev);
|
||||
if (ret)
|
||||
arch_teardown_dma_ops(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cdx_dma_cleanup(struct device *dev)
|
||||
{
|
||||
struct cdx_driver *cdx_drv = to_cdx_driver(dev->driver);
|
||||
|
||||
if (!cdx_drv->driver_managed_dma)
|
||||
iommu_device_unuse_default_domain(dev);
|
||||
}
|
||||
|
||||
/* show configuration fields */
|
||||
#define cdx_config_attr(field, format_string) \
|
||||
static ssize_t \
|
||||
|
@ -405,6 +422,7 @@ struct bus_type cdx_bus_type = {
|
|||
.remove = cdx_remove,
|
||||
.shutdown = cdx_shutdown,
|
||||
.dma_configure = cdx_dma_configure,
|
||||
.dma_cleanup = cdx_dma_cleanup,
|
||||
.bus_groups = cdx_bus_groups,
|
||||
.dev_groups = cdx_dev_groups,
|
||||
};
|
||||
|
|
|
@ -18,14 +18,4 @@ config CDX_CONTROLLER
|
|||
|
||||
If unsure, say N.
|
||||
|
||||
config MCDI_LOGGING
|
||||
bool "MCDI Logging for the CDX controller"
|
||||
depends on CDX_CONTROLLER
|
||||
help
|
||||
Enable MCDI Logging for
|
||||
the CDX Controller for debug
|
||||
purpose.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
endif
|
||||
|
|
|
@ -31,10 +31,6 @@ struct cdx_mcdi_copy_buffer {
|
|||
struct cdx_dword buffer[DIV_ROUND_UP(MCDI_CTL_SDU_LEN_MAX, 4)];
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MCDI_LOGGING
|
||||
#define LOG_LINE_MAX (1024 - 32)
|
||||
#endif
|
||||
|
||||
static void cdx_mcdi_cancel_cmd(struct cdx_mcdi *cdx, struct cdx_mcdi_cmd *cmd);
|
||||
static void cdx_mcdi_wait_for_cleanup(struct cdx_mcdi *cdx);
|
||||
static int cdx_mcdi_rpc_async_internal(struct cdx_mcdi *cdx,
|
||||
|
@ -119,14 +115,9 @@ int cdx_mcdi_init(struct cdx_mcdi *cdx)
|
|||
mcdi = cdx_mcdi_if(cdx);
|
||||
mcdi->cdx = cdx;
|
||||
|
||||
#ifdef CONFIG_MCDI_LOGGING
|
||||
mcdi->logging_buffer = kmalloc(LOG_LINE_MAX, GFP_KERNEL);
|
||||
if (!mcdi->logging_buffer)
|
||||
goto fail2;
|
||||
#endif
|
||||
mcdi->workqueue = alloc_ordered_workqueue("mcdi_wq", 0);
|
||||
if (!mcdi->workqueue)
|
||||
goto fail3;
|
||||
goto fail2;
|
||||
mutex_init(&mcdi->iface_lock);
|
||||
mcdi->mode = MCDI_MODE_EVENTS;
|
||||
INIT_LIST_HEAD(&mcdi->cmd_list);
|
||||
|
@ -135,11 +126,7 @@ int cdx_mcdi_init(struct cdx_mcdi *cdx)
|
|||
mcdi->new_epoch = true;
|
||||
|
||||
return 0;
|
||||
fail3:
|
||||
#ifdef CONFIG_MCDI_LOGGING
|
||||
kfree(mcdi->logging_buffer);
|
||||
fail2:
|
||||
#endif
|
||||
kfree(cdx->mcdi);
|
||||
cdx->mcdi = NULL;
|
||||
fail:
|
||||
|
@ -156,10 +143,6 @@ void cdx_mcdi_finish(struct cdx_mcdi *cdx)
|
|||
|
||||
cdx_mcdi_wait_for_cleanup(cdx);
|
||||
|
||||
#ifdef CONFIG_MCDI_LOGGING
|
||||
kfree(mcdi->logging_buffer);
|
||||
#endif
|
||||
|
||||
destroy_workqueue(mcdi->workqueue);
|
||||
kfree(cdx->mcdi);
|
||||
cdx->mcdi = NULL;
|
||||
|
@ -246,15 +229,9 @@ static void cdx_mcdi_send_request(struct cdx_mcdi *cdx,
|
|||
size_t hdr_len;
|
||||
bool not_epoch;
|
||||
u32 xflags;
|
||||
#ifdef CONFIG_MCDI_LOGGING
|
||||
char *buf;
|
||||
#endif
|
||||
|
||||
if (!mcdi)
|
||||
return;
|
||||
#ifdef CONFIG_MCDI_LOGGING
|
||||
buf = mcdi->logging_buffer; /* page-sized */
|
||||
#endif
|
||||
|
||||
mcdi->prev_seq = cmd->seq;
|
||||
mcdi->seq_held_by[cmd->seq] = cmd;
|
||||
|
@ -281,39 +258,12 @@ static void cdx_mcdi_send_request(struct cdx_mcdi *cdx,
|
|||
MC_CMD_V2_EXTN_IN_MCDI_MESSAGE_TYPE_PLATFORM);
|
||||
hdr_len = 8;
|
||||
|
||||
#ifdef CONFIG_MCDI_LOGGING
|
||||
if (!WARN_ON_ONCE(!buf)) {
|
||||
const struct cdx_dword *frags[] = { hdr, inbuf };
|
||||
const size_t frag_len[] = { hdr_len, round_up(inlen, 4) };
|
||||
int bytes = 0;
|
||||
int i, j;
|
||||
|
||||
for (j = 0; j < ARRAY_SIZE(frags); j++) {
|
||||
const struct cdx_dword *frag;
|
||||
|
||||
frag = frags[j];
|
||||
for (i = 0;
|
||||
i < frag_len[j] / 4;
|
||||
i++) {
|
||||
/*
|
||||
* Do not exceed the internal printk limit.
|
||||
* The string before that is just over 70 bytes.
|
||||
*/
|
||||
if ((bytes + 75) > LOG_LINE_MAX) {
|
||||
pr_info("MCDI RPC REQ:%s \\\n", buf);
|
||||
bytes = 0;
|
||||
}
|
||||
bytes += snprintf(buf + bytes,
|
||||
LOG_LINE_MAX - bytes, " %08x",
|
||||
le32_to_cpu(frag[i].cdx_u32));
|
||||
}
|
||||
}
|
||||
|
||||
pr_info("MCDI RPC REQ:%s\n", buf);
|
||||
}
|
||||
#endif
|
||||
hdr[0].cdx_u32 |= (__force __le32)(cdx_mcdi_payload_csum(hdr, hdr_len, inbuf, inlen) <<
|
||||
MCDI_HEADER_XFLAGS_LBN);
|
||||
|
||||
print_hex_dump_debug("MCDI REQ HEADER: ", DUMP_PREFIX_NONE, 32, 4, hdr, hdr_len, false);
|
||||
print_hex_dump_debug("MCDI REQ PAYLOAD: ", DUMP_PREFIX_NONE, 32, 4, inbuf, inlen, false);
|
||||
|
||||
cdx->mcdi_ops->mcdi_request(cdx, hdr, hdr_len, inbuf, inlen);
|
||||
|
||||
mcdi->new_epoch = false;
|
||||
|
@ -700,28 +650,10 @@ static bool cdx_mcdi_complete_cmd(struct cdx_mcdi_iface *mcdi,
|
|||
resp_data_len = 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MCDI_LOGGING
|
||||
if (!WARN_ON_ONCE(!mcdi->logging_buffer)) {
|
||||
char *log = mcdi->logging_buffer;
|
||||
int i, bytes = 0;
|
||||
size_t rlen;
|
||||
|
||||
WARN_ON_ONCE(resp_hdr_len % 4);
|
||||
|
||||
rlen = resp_hdr_len / 4 + DIV_ROUND_UP(resp_data_len, 4);
|
||||
|
||||
for (i = 0; i < rlen; i++) {
|
||||
if ((bytes + 75) > LOG_LINE_MAX) {
|
||||
pr_info("MCDI RPC RESP:%s \\\n", log);
|
||||
bytes = 0;
|
||||
}
|
||||
bytes += snprintf(log + bytes, LOG_LINE_MAX - bytes,
|
||||
" %08x", le32_to_cpu(outbuf[i].cdx_u32));
|
||||
}
|
||||
|
||||
pr_info("MCDI RPC RESP:%s\n", log);
|
||||
}
|
||||
#endif
|
||||
print_hex_dump_debug("MCDI RESP HEADER: ", DUMP_PREFIX_NONE, 32, 4,
|
||||
outbuf, resp_hdr_len, false);
|
||||
print_hex_dump_debug("MCDI RESP PAYLOAD: ", DUMP_PREFIX_NONE, 32, 4,
|
||||
outbuf + (resp_hdr_len / 4), resp_data_len, false);
|
||||
|
||||
if (error && resp_data_len == 0) {
|
||||
/* MC rebooted during command */
|
||||
|
|
|
@ -153,8 +153,6 @@ struct cdx_mcdi_cmd {
|
|||
* @mode: Poll for mcdi completion, or wait for an mcdi_event
|
||||
* @prev_seq: The last used sequence number
|
||||
* @new_epoch: Indicates start of day or start of MC reboot recovery
|
||||
* @logging_buffer: Buffer that may be used to build MCDI tracing messages
|
||||
* @logging_enabled: Whether to trace MCDI
|
||||
*/
|
||||
struct cdx_mcdi_iface {
|
||||
struct cdx_mcdi *cdx;
|
||||
|
@ -170,10 +168,6 @@ struct cdx_mcdi_iface {
|
|||
enum cdx_mcdi_mode mode;
|
||||
u8 prev_seq;
|
||||
bool new_epoch;
|
||||
#ifdef CONFIG_MCDI_LOGGING
|
||||
bool logging_enabled;
|
||||
char *logging_buffer;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -34,6 +34,7 @@ config TTY_PRINTK_LEVEL
|
|||
config PRINTER
|
||||
tristate "Parallel printer support"
|
||||
depends on PARPORT
|
||||
depends on HAS_IOPORT || PARPORT_NOT_PC
|
||||
help
|
||||
If you intend to attach a printer to the parallel port of your Linux
|
||||
box (as opposed to using a serial printer; if the connector at the
|
||||
|
@ -340,7 +341,7 @@ config NVRAM
|
|||
|
||||
config DEVPORT
|
||||
bool "/dev/port character device"
|
||||
depends on ISA || PCI
|
||||
depends on HAS_IOPORT
|
||||
default y
|
||||
help
|
||||
Say Y here if you want to support the /dev/port device. The /dev/port
|
||||
|
|
|
@ -61,7 +61,6 @@ struct bsr_dev {
|
|||
|
||||
static unsigned total_bsr_devs;
|
||||
static LIST_HEAD(bsr_devs);
|
||||
static struct class *bsr_class;
|
||||
static int bsr_major;
|
||||
|
||||
enum {
|
||||
|
@ -108,6 +107,11 @@ static struct attribute *bsr_dev_attrs[] = {
|
|||
};
|
||||
ATTRIBUTE_GROUPS(bsr_dev);
|
||||
|
||||
static const struct class bsr_class = {
|
||||
.name = "bsr",
|
||||
.dev_groups = bsr_dev_groups,
|
||||
};
|
||||
|
||||
static int bsr_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
unsigned long size = vma->vm_end - vma->vm_start;
|
||||
|
@ -244,7 +248,7 @@ static int bsr_add_node(struct device_node *bn)
|
|||
goto out_err;
|
||||
}
|
||||
|
||||
cur->bsr_device = device_create(bsr_class, NULL, cur->bsr_dev,
|
||||
cur->bsr_device = device_create(&bsr_class, NULL, cur->bsr_dev,
|
||||
cur, "%s", cur->bsr_name);
|
||||
if (IS_ERR(cur->bsr_device)) {
|
||||
printk(KERN_ERR "device_create failed for %s\n",
|
||||
|
@ -293,13 +297,9 @@ static int __init bsr_init(void)
|
|||
if (!np)
|
||||
goto out_err;
|
||||
|
||||
bsr_class = class_create("bsr");
|
||||
if (IS_ERR(bsr_class)) {
|
||||
printk(KERN_ERR "class_create() failed for bsr_class\n");
|
||||
ret = PTR_ERR(bsr_class);
|
||||
ret = class_register(&bsr_class);
|
||||
if (ret)
|
||||
goto out_err_1;
|
||||
}
|
||||
bsr_class->dev_groups = bsr_dev_groups;
|
||||
|
||||
ret = alloc_chrdev_region(&bsr_dev, 0, BSR_MAX_DEVS, "bsr");
|
||||
bsr_major = MAJOR(bsr_dev);
|
||||
|
@ -320,7 +320,7 @@ static int __init bsr_init(void)
|
|||
unregister_chrdev_region(bsr_dev, BSR_MAX_DEVS);
|
||||
|
||||
out_err_2:
|
||||
class_destroy(bsr_class);
|
||||
class_unregister(&bsr_class);
|
||||
|
||||
out_err_1:
|
||||
of_node_put(np);
|
||||
|
@ -335,8 +335,7 @@ static void __exit bsr_exit(void)
|
|||
|
||||
bsr_cleanup_devs();
|
||||
|
||||
if (bsr_class)
|
||||
class_destroy(bsr_class);
|
||||
class_unregister(&bsr_class);
|
||||
|
||||
if (bsr_major)
|
||||
unregister_chrdev_region(MKDEV(bsr_major, 0), BSR_MAX_DEVS);
|
||||
|
|
|
@ -101,7 +101,9 @@ static struct dsp56k_device {
|
|||
int tx_wsize, rx_wsize;
|
||||
} dsp56k;
|
||||
|
||||
static struct class *dsp56k_class;
|
||||
static const struct class dsp56k_class = {
|
||||
.name = "dsp56k",
|
||||
};
|
||||
|
||||
static int dsp56k_reset(void)
|
||||
{
|
||||
|
@ -493,7 +495,7 @@ static const char banner[] __initconst = KERN_INFO "DSP56k driver installed\n";
|
|||
|
||||
static int __init dsp56k_init_driver(void)
|
||||
{
|
||||
int err = 0;
|
||||
int err;
|
||||
|
||||
if(!MACH_IS_ATARI || !ATARIHW_PRESENT(DSP56K)) {
|
||||
printk("DSP56k driver: Hardware not present\n");
|
||||
|
@ -504,12 +506,10 @@ static int __init dsp56k_init_driver(void)
|
|||
printk("DSP56k driver: Unable to register driver\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
dsp56k_class = class_create("dsp56k");
|
||||
if (IS_ERR(dsp56k_class)) {
|
||||
err = PTR_ERR(dsp56k_class);
|
||||
err = class_register(&dsp56k_class);
|
||||
if (err)
|
||||
goto out_chrdev;
|
||||
}
|
||||
device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), NULL,
|
||||
device_create(&dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), NULL,
|
||||
"dsp56k");
|
||||
|
||||
printk(banner);
|
||||
|
@ -524,8 +524,8 @@ module_init(dsp56k_init_driver);
|
|||
|
||||
static void __exit dsp56k_cleanup_driver(void)
|
||||
{
|
||||
device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0));
|
||||
class_destroy(dsp56k_class);
|
||||
device_destroy(&dsp56k_class, MKDEV(DSP56K_MAJOR, 0));
|
||||
class_unregister(&dsp56k_class);
|
||||
unregister_chrdev(DSP56K_MAJOR, "dsp56k");
|
||||
}
|
||||
module_exit(dsp56k_cleanup_driver);
|
||||
|
|
|
@ -145,7 +145,9 @@ static struct lp_struct lp_table[LP_NO];
|
|||
static int port_num[LP_NO];
|
||||
|
||||
static unsigned int lp_count = 0;
|
||||
static struct class *lp_class;
|
||||
static const struct class lp_class = {
|
||||
.name = "printer",
|
||||
};
|
||||
|
||||
#ifdef CONFIG_LP_CONSOLE
|
||||
static struct parport *console_registered;
|
||||
|
@ -932,7 +934,7 @@ static int lp_register(int nr, struct parport *port)
|
|||
if (reset)
|
||||
lp_reset(nr);
|
||||
|
||||
device_create(lp_class, port->dev, MKDEV(LP_MAJOR, nr), NULL,
|
||||
device_create(&lp_class, port->dev, MKDEV(LP_MAJOR, nr), NULL,
|
||||
"lp%d", nr);
|
||||
|
||||
printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name,
|
||||
|
@ -1004,7 +1006,7 @@ static void lp_detach(struct parport *port)
|
|||
if (port_num[n] == port->number) {
|
||||
port_num[n] = -1;
|
||||
lp_count--;
|
||||
device_destroy(lp_class, MKDEV(LP_MAJOR, n));
|
||||
device_destroy(&lp_class, MKDEV(LP_MAJOR, n));
|
||||
parport_unregister_device(lp_table[n].dev);
|
||||
}
|
||||
}
|
||||
|
@ -1049,11 +1051,9 @@ static int __init lp_init(void)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
lp_class = class_create("printer");
|
||||
if (IS_ERR(lp_class)) {
|
||||
err = PTR_ERR(lp_class);
|
||||
err = class_register(&lp_class);
|
||||
if (err)
|
||||
goto out_reg;
|
||||
}
|
||||
|
||||
if (parport_register_driver(&lp_driver)) {
|
||||
printk(KERN_ERR "lp: unable to register with parport\n");
|
||||
|
@ -1072,7 +1072,7 @@ static int __init lp_init(void)
|
|||
return 0;
|
||||
|
||||
out_class:
|
||||
class_destroy(lp_class);
|
||||
class_unregister(&lp_class);
|
||||
out_reg:
|
||||
unregister_chrdev(LP_MAJOR, "lp");
|
||||
return err;
|
||||
|
@ -1115,7 +1115,7 @@ static void lp_cleanup_module(void)
|
|||
#endif
|
||||
|
||||
unregister_chrdev(LP_MAJOR, "lp");
|
||||
class_destroy(lp_class);
|
||||
class_unregister(&lp_class);
|
||||
}
|
||||
|
||||
__setup("lp=", lp_setup);
|
||||
|
|
|
@ -746,20 +746,23 @@ static char *mem_devnode(const struct device *dev, umode_t *mode)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct class *mem_class;
|
||||
static const struct class mem_class = {
|
||||
.name = "mem",
|
||||
.devnode = mem_devnode,
|
||||
};
|
||||
|
||||
static int __init chr_dev_init(void)
|
||||
{
|
||||
int retval;
|
||||
int minor;
|
||||
|
||||
if (register_chrdev(MEM_MAJOR, "mem", &memory_fops))
|
||||
printk("unable to get major %d for memory devs\n", MEM_MAJOR);
|
||||
|
||||
mem_class = class_create("mem");
|
||||
if (IS_ERR(mem_class))
|
||||
return PTR_ERR(mem_class);
|
||||
retval = class_register(&mem_class);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
mem_class->devnode = mem_devnode;
|
||||
for (minor = 1; minor < ARRAY_SIZE(devlist); minor++) {
|
||||
if (!devlist[minor].name)
|
||||
continue;
|
||||
|
@ -770,7 +773,7 @@ static int __init chr_dev_init(void)
|
|||
if ((minor == DEVPORT_MINOR) && !arch_has_dev_port())
|
||||
continue;
|
||||
|
||||
device_create(mem_class, NULL, MKDEV(MEM_MAJOR, minor),
|
||||
device_create(&mem_class, NULL, MKDEV(MEM_MAJOR, minor),
|
||||
NULL, devlist[minor].name);
|
||||
}
|
||||
|
||||
|
|
|
@ -168,7 +168,21 @@ fail:
|
|||
return err;
|
||||
}
|
||||
|
||||
static struct class *misc_class;
|
||||
static char *misc_devnode(const struct device *dev, umode_t *mode)
|
||||
{
|
||||
const struct miscdevice *c = dev_get_drvdata(dev);
|
||||
|
||||
if (mode && c->mode)
|
||||
*mode = c->mode;
|
||||
if (c->nodename)
|
||||
return kstrdup(c->nodename, GFP_KERNEL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct class misc_class = {
|
||||
.name = "misc",
|
||||
.devnode = misc_devnode,
|
||||
};
|
||||
|
||||
static const struct file_operations misc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -226,7 +240,7 @@ int misc_register(struct miscdevice *misc)
|
|||
dev = MKDEV(MISC_MAJOR, misc->minor);
|
||||
|
||||
misc->this_device =
|
||||
device_create_with_groups(misc_class, misc->parent, dev,
|
||||
device_create_with_groups(&misc_class, misc->parent, dev,
|
||||
misc, misc->groups, "%s", misc->name);
|
||||
if (IS_ERR(misc->this_device)) {
|
||||
if (is_dynamic) {
|
||||
|
@ -263,43 +277,30 @@ void misc_deregister(struct miscdevice *misc)
|
|||
|
||||
mutex_lock(&misc_mtx);
|
||||
list_del(&misc->list);
|
||||
device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
|
||||
device_destroy(&misc_class, MKDEV(MISC_MAJOR, misc->minor));
|
||||
misc_minor_free(misc->minor);
|
||||
mutex_unlock(&misc_mtx);
|
||||
}
|
||||
EXPORT_SYMBOL(misc_deregister);
|
||||
|
||||
static char *misc_devnode(const struct device *dev, umode_t *mode)
|
||||
{
|
||||
const struct miscdevice *c = dev_get_drvdata(dev);
|
||||
|
||||
if (mode && c->mode)
|
||||
*mode = c->mode;
|
||||
if (c->nodename)
|
||||
return kstrdup(c->nodename, GFP_KERNEL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int __init misc_init(void)
|
||||
{
|
||||
int err;
|
||||
struct proc_dir_entry *ret;
|
||||
|
||||
ret = proc_create_seq("misc", 0, NULL, &misc_seq_ops);
|
||||
misc_class = class_create("misc");
|
||||
err = PTR_ERR(misc_class);
|
||||
if (IS_ERR(misc_class))
|
||||
err = class_register(&misc_class);
|
||||
if (err)
|
||||
goto fail_remove;
|
||||
|
||||
err = -EIO;
|
||||
if (register_chrdev(MISC_MAJOR, "misc", &misc_fops))
|
||||
goto fail_printk;
|
||||
misc_class->devnode = misc_devnode;
|
||||
return 0;
|
||||
|
||||
fail_printk:
|
||||
pr_err("unable to get major %d for misc devices\n", MISC_MAJOR);
|
||||
class_destroy(misc_class);
|
||||
class_unregister(&misc_class);
|
||||
fail_remove:
|
||||
if (ret)
|
||||
remove_proc_entry("misc", NULL);
|
||||
|
|
|
@ -773,7 +773,9 @@ static __poll_t pp_poll(struct file *file, poll_table *wait)
|
|||
return mask;
|
||||
}
|
||||
|
||||
static struct class *ppdev_class;
|
||||
static const struct class ppdev_class = {
|
||||
.name = CHRDEV,
|
||||
};
|
||||
|
||||
static const struct file_operations pp_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -794,7 +796,7 @@ static void pp_attach(struct parport *port)
|
|||
if (devices[port->number])
|
||||
return;
|
||||
|
||||
ret = device_create(ppdev_class, port->dev,
|
||||
ret = device_create(&ppdev_class, port->dev,
|
||||
MKDEV(PP_MAJOR, port->number), NULL,
|
||||
"parport%d", port->number);
|
||||
if (IS_ERR(ret)) {
|
||||
|
@ -810,7 +812,7 @@ static void pp_detach(struct parport *port)
|
|||
if (!devices[port->number])
|
||||
return;
|
||||
|
||||
device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number));
|
||||
device_destroy(&ppdev_class, MKDEV(PP_MAJOR, port->number));
|
||||
devices[port->number] = NULL;
|
||||
}
|
||||
|
||||
|
@ -841,11 +843,10 @@ static int __init ppdev_init(void)
|
|||
pr_warn(CHRDEV ": unable to get major %d\n", PP_MAJOR);
|
||||
return -EIO;
|
||||
}
|
||||
ppdev_class = class_create(CHRDEV);
|
||||
if (IS_ERR(ppdev_class)) {
|
||||
err = PTR_ERR(ppdev_class);
|
||||
err = class_register(&ppdev_class);
|
||||
if (err)
|
||||
goto out_chrdev;
|
||||
}
|
||||
|
||||
err = parport_register_driver(&pp_driver);
|
||||
if (err < 0) {
|
||||
pr_warn(CHRDEV ": unable to register with parport\n");
|
||||
|
@ -856,7 +857,7 @@ static int __init ppdev_init(void)
|
|||
goto out;
|
||||
|
||||
out_class:
|
||||
class_destroy(ppdev_class);
|
||||
class_unregister(&ppdev_class);
|
||||
out_chrdev:
|
||||
unregister_chrdev(PP_MAJOR, CHRDEV);
|
||||
out:
|
||||
|
@ -867,7 +868,7 @@ static void __exit ppdev_cleanup(void)
|
|||
{
|
||||
/* Clean up all parport stuff */
|
||||
parport_unregister_driver(&pp_driver);
|
||||
class_destroy(ppdev_class);
|
||||
class_unregister(&ppdev_class);
|
||||
unregister_chrdev(PP_MAJOR, CHRDEV);
|
||||
}
|
||||
|
||||
|
|
|
@ -40,9 +40,6 @@
|
|||
* across multiple devices and multiple ports per device.
|
||||
*/
|
||||
struct ports_driver_data {
|
||||
/* Used for registering chardevs */
|
||||
struct class *class;
|
||||
|
||||
/* Used for exporting per-port information to debugfs */
|
||||
struct dentry *debugfs_dir;
|
||||
|
||||
|
@ -55,6 +52,10 @@ struct ports_driver_data {
|
|||
|
||||
static struct ports_driver_data pdrvdata;
|
||||
|
||||
static const struct class port_class = {
|
||||
.name = "virtio-ports",
|
||||
};
|
||||
|
||||
static DEFINE_SPINLOCK(pdrvdata_lock);
|
||||
static DECLARE_COMPLETION(early_console_added);
|
||||
|
||||
|
@ -1399,7 +1400,7 @@ static int add_port(struct ports_device *portdev, u32 id)
|
|||
"Error %d adding cdev for port %u\n", err, id);
|
||||
goto free_cdev;
|
||||
}
|
||||
port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev,
|
||||
port->dev = device_create(&port_class, &port->portdev->vdev->dev,
|
||||
devt, port, "vport%up%u",
|
||||
port->portdev->vdev->index, id);
|
||||
if (IS_ERR(port->dev)) {
|
||||
|
@ -1465,7 +1466,7 @@ static int add_port(struct ports_device *portdev, u32 id)
|
|||
|
||||
free_inbufs:
|
||||
free_device:
|
||||
device_destroy(pdrvdata.class, port->dev->devt);
|
||||
device_destroy(&port_class, port->dev->devt);
|
||||
free_cdev:
|
||||
cdev_del(port->cdev);
|
||||
free_port:
|
||||
|
@ -1540,7 +1541,7 @@ static void unplug_port(struct port *port)
|
|||
port->portdev = NULL;
|
||||
|
||||
sysfs_remove_group(&port->dev->kobj, &port_attribute_group);
|
||||
device_destroy(pdrvdata.class, port->dev->devt);
|
||||
device_destroy(&port_class, port->dev->devt);
|
||||
cdev_del(port->cdev);
|
||||
|
||||
debugfs_remove(port->debugfs_file);
|
||||
|
@ -2244,12 +2245,9 @@ static int __init virtio_console_init(void)
|
|||
{
|
||||
int err;
|
||||
|
||||
pdrvdata.class = class_create("virtio-ports");
|
||||
if (IS_ERR(pdrvdata.class)) {
|
||||
err = PTR_ERR(pdrvdata.class);
|
||||
pr_err("Error %d creating virtio-ports class\n", err);
|
||||
err = class_register(&port_class);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
pdrvdata.debugfs_dir = debugfs_create_dir("virtio-ports", NULL);
|
||||
INIT_LIST_HEAD(&pdrvdata.consoles);
|
||||
|
@ -2271,7 +2269,7 @@ unregister:
|
|||
unregister_virtio_driver(&virtio_console);
|
||||
free:
|
||||
debugfs_remove_recursive(pdrvdata.debugfs_dir);
|
||||
class_destroy(pdrvdata.class);
|
||||
class_unregister(&port_class);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -2282,7 +2280,7 @@ static void __exit virtio_console_fini(void)
|
|||
unregister_virtio_driver(&virtio_console);
|
||||
unregister_virtio_driver(&virtio_rproc_serial);
|
||||
|
||||
class_destroy(pdrvdata.class);
|
||||
class_unregister(&port_class);
|
||||
debugfs_remove_recursive(pdrvdata.debugfs_dir);
|
||||
}
|
||||
module_init(virtio_console_init);
|
||||
|
|
|
@ -113,7 +113,9 @@ static DEFINE_MUTEX(hwicap_mutex);
|
|||
static bool probed_devices[HWICAP_DEVICES];
|
||||
static struct mutex icap_sem;
|
||||
|
||||
static struct class *icap_class;
|
||||
static const struct class icap_class = {
|
||||
.name = "xilinx_config",
|
||||
};
|
||||
|
||||
#define UNIMPLEMENTED 0xFFFF
|
||||
|
||||
|
@ -687,7 +689,7 @@ static int hwicap_setup(struct device *dev, int id,
|
|||
goto failed3;
|
||||
}
|
||||
|
||||
device_create(icap_class, dev, devt, NULL, "%s%d", DRIVER_NAME, id);
|
||||
device_create(&icap_class, dev, devt, NULL, "%s%d", DRIVER_NAME, id);
|
||||
return 0; /* success */
|
||||
|
||||
failed3:
|
||||
|
@ -721,27 +723,6 @@ static struct hwicap_driver_config fifo_icap_config = {
|
|||
.reset = fifo_icap_reset,
|
||||
};
|
||||
|
||||
static int hwicap_remove(struct device *dev)
|
||||
{
|
||||
struct hwicap_drvdata *drvdata;
|
||||
|
||||
drvdata = dev_get_drvdata(dev);
|
||||
|
||||
if (!drvdata)
|
||||
return 0;
|
||||
|
||||
device_destroy(icap_class, drvdata->devt);
|
||||
cdev_del(&drvdata->cdev);
|
||||
iounmap(drvdata->base_address);
|
||||
release_mem_region(drvdata->mem_start, drvdata->mem_size);
|
||||
kfree(drvdata);
|
||||
|
||||
mutex_lock(&icap_sem);
|
||||
probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0;
|
||||
mutex_unlock(&icap_sem);
|
||||
return 0; /* success */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static int hwicap_of_probe(struct platform_device *op,
|
||||
const struct hwicap_driver_config *config)
|
||||
|
@ -825,9 +806,22 @@ static int hwicap_drv_probe(struct platform_device *pdev)
|
|||
&buffer_icap_config, regs);
|
||||
}
|
||||
|
||||
static int hwicap_drv_remove(struct platform_device *pdev)
|
||||
static void hwicap_drv_remove(struct platform_device *pdev)
|
||||
{
|
||||
return hwicap_remove(&pdev->dev);
|
||||
struct device *dev = &pdev->dev;
|
||||
struct hwicap_drvdata *drvdata;
|
||||
|
||||
drvdata = dev_get_drvdata(dev);
|
||||
|
||||
device_destroy(&icap_class, drvdata->devt);
|
||||
cdev_del(&drvdata->cdev);
|
||||
iounmap(drvdata->base_address);
|
||||
release_mem_region(drvdata->mem_start, drvdata->mem_size);
|
||||
kfree(drvdata);
|
||||
|
||||
mutex_lock(&icap_sem);
|
||||
probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0;
|
||||
mutex_unlock(&icap_sem);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
@ -844,7 +838,7 @@ MODULE_DEVICE_TABLE(of, hwicap_of_match);
|
|||
|
||||
static struct platform_driver hwicap_platform_driver = {
|
||||
.probe = hwicap_drv_probe,
|
||||
.remove = hwicap_drv_remove,
|
||||
.remove_new = hwicap_drv_remove,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.of_match_table = hwicap_of_match,
|
||||
|
@ -856,7 +850,9 @@ static int __init hwicap_module_init(void)
|
|||
dev_t devt;
|
||||
int retval;
|
||||
|
||||
icap_class = class_create("xilinx_config");
|
||||
retval = class_register(&icap_class);
|
||||
if (retval)
|
||||
return retval;
|
||||
mutex_init(&icap_sem);
|
||||
|
||||
devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR);
|
||||
|
@ -882,7 +878,7 @@ static void __exit hwicap_module_cleanup(void)
|
|||
{
|
||||
dev_t devt = MKDEV(XHWICAP_MAJOR, XHWICAP_MINOR);
|
||||
|
||||
class_destroy(icap_class);
|
||||
class_unregister(&icap_class);
|
||||
|
||||
platform_driver_unregister(&hwicap_platform_driver);
|
||||
|
||||
|
|
|
@ -23,7 +23,9 @@ MODULE_LICENSE("GPL v2");
|
|||
|
||||
static DEFINE_MUTEX(unit_mutex);
|
||||
static LIST_HEAD(unit_list);
|
||||
static struct class *xillybus_class;
|
||||
static const struct class xillybus_class = {
|
||||
.name = "xillybus",
|
||||
};
|
||||
|
||||
#define UNITNAMELEN 16
|
||||
|
||||
|
@ -121,7 +123,7 @@ int xillybus_init_chrdev(struct device *dev,
|
|||
len -= namelen + 1;
|
||||
idt += namelen + 1;
|
||||
|
||||
device = device_create(xillybus_class,
|
||||
device = device_create(&xillybus_class,
|
||||
NULL,
|
||||
MKDEV(unit->major,
|
||||
i + unit->lowest_minor),
|
||||
|
@ -152,7 +154,7 @@ int xillybus_init_chrdev(struct device *dev,
|
|||
|
||||
unroll_device_create:
|
||||
for (i--; i >= 0; i--)
|
||||
device_destroy(xillybus_class, MKDEV(unit->major,
|
||||
device_destroy(&xillybus_class, MKDEV(unit->major,
|
||||
i + unit->lowest_minor));
|
||||
|
||||
cdev_del(unit->cdev);
|
||||
|
@ -193,7 +195,7 @@ void xillybus_cleanup_chrdev(void *private_data,
|
|||
for (minor = unit->lowest_minor;
|
||||
minor < (unit->lowest_minor + unit->num_nodes);
|
||||
minor++)
|
||||
device_destroy(xillybus_class, MKDEV(unit->major, minor));
|
||||
device_destroy(&xillybus_class, MKDEV(unit->major, minor));
|
||||
|
||||
cdev_del(unit->cdev);
|
||||
|
||||
|
@ -242,19 +244,12 @@ EXPORT_SYMBOL(xillybus_find_inode);
|
|||
|
||||
static int __init xillybus_class_init(void)
|
||||
{
|
||||
xillybus_class = class_create("xillybus");
|
||||
|
||||
if (IS_ERR(xillybus_class)) {
|
||||
pr_warn("Failed to register xillybus class\n");
|
||||
|
||||
return PTR_ERR(xillybus_class);
|
||||
}
|
||||
return 0;
|
||||
return class_register(&xillybus_class);
|
||||
}
|
||||
|
||||
static void __exit xillybus_class_exit(void)
|
||||
{
|
||||
class_destroy(xillybus_class);
|
||||
class_unregister(&xillybus_class);
|
||||
}
|
||||
|
||||
module_init(xillybus_class_init);
|
||||
|
|
|
@ -48,6 +48,7 @@ config QCOM_CLK_APCS_MSM8916
|
|||
config QCOM_CLK_APCC_MSM8996
|
||||
tristate "MSM8996 CPU Clock Controller"
|
||||
select QCOM_KRYO_L2_ACCESSORS
|
||||
select INTERCONNECT_CLK if INTERCONNECT
|
||||
depends on ARM64
|
||||
help
|
||||
Support for the CPU clock controller on msm8996 devices.
|
||||
|
|
|
@ -5,11 +5,15 @@
|
|||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/interconnect-clk.h>
|
||||
#include <linux/interconnect-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <dt-bindings/interconnect/qcom,msm8996-cbf.h>
|
||||
|
||||
#include "clk-alpha-pll.h"
|
||||
#include "clk-regmap.h"
|
||||
|
||||
|
@ -223,6 +227,49 @@ static const struct regmap_config cbf_msm8996_regmap_config = {
|
|||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_INTERCONNECT
|
||||
|
||||
/* Random ID that doesn't clash with main qnoc and OSM */
|
||||
#define CBF_MASTER_NODE 2000
|
||||
|
||||
static int qcom_msm8996_cbf_icc_register(struct platform_device *pdev, struct clk_hw *cbf_hw)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct clk *clk = devm_clk_hw_get_clk(dev, cbf_hw, "cbf");
|
||||
const struct icc_clk_data data[] = {
|
||||
{ .clk = clk, .name = "cbf", },
|
||||
};
|
||||
struct icc_provider *provider;
|
||||
|
||||
provider = icc_clk_register(dev, CBF_MASTER_NODE, ARRAY_SIZE(data), data);
|
||||
if (IS_ERR(provider))
|
||||
return PTR_ERR(provider);
|
||||
|
||||
platform_set_drvdata(pdev, provider);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcom_msm8996_cbf_icc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct icc_provider *provider = platform_get_drvdata(pdev);
|
||||
|
||||
icc_clk_unregister(provider);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#define qcom_msm8996_cbf_icc_sync_state icc_sync_state
|
||||
#else
|
||||
static int qcom_msm8996_cbf_icc_register(struct platform_device *pdev, struct clk_hw *cbf_hw)
|
||||
{
|
||||
dev_warn(&pdev->dev, "CONFIG_INTERCONNECT is disabled, CBF clock is fixed\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
#define qcom_msm8996_cbf_icc_remove(pdev) (0)
|
||||
#define qcom_msm8996_cbf_icc_sync_state NULL
|
||||
#endif
|
||||
|
||||
static int qcom_msm8996_cbf_probe(struct platform_device *pdev)
|
||||
{
|
||||
void __iomem *base;
|
||||
|
@ -281,7 +328,16 @@ static int qcom_msm8996_cbf_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &cbf_mux.clkr.hw);
|
||||
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &cbf_mux.clkr.hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return qcom_msm8996_cbf_icc_register(pdev, &cbf_mux.clkr.hw);
|
||||
}
|
||||
|
||||
static int qcom_msm8996_cbf_remove(struct platform_device *pdev)
|
||||
{
|
||||
return qcom_msm8996_cbf_icc_remove(pdev);
|
||||
}
|
||||
|
||||
static const struct of_device_id qcom_msm8996_cbf_match_table[] = {
|
||||
|
@ -292,9 +348,11 @@ MODULE_DEVICE_TABLE(of, qcom_msm8996_cbf_match_table);
|
|||
|
||||
static struct platform_driver qcom_msm8996_cbf_driver = {
|
||||
.probe = qcom_msm8996_cbf_probe,
|
||||
.remove = qcom_msm8996_cbf_remove,
|
||||
.driver = {
|
||||
.name = "qcom-msm8996-cbf",
|
||||
.of_match_table = qcom_msm8996_cbf_match_table,
|
||||
.sync_state = qcom_msm8996_cbf_icc_sync_state,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ config COMEDI_TEST
|
|||
|
||||
config COMEDI_PARPORT
|
||||
tristate "Parallel port support"
|
||||
depends on HAS_IOPORT
|
||||
help
|
||||
Enable support for the standard parallel port.
|
||||
A cheap and easy way to get a few more digital I/O lines. Steal
|
||||
|
@ -79,6 +80,7 @@ config COMEDI_PARPORT
|
|||
config COMEDI_SSV_DNP
|
||||
tristate "SSV Embedded Systems DIL/Net-PC support"
|
||||
depends on X86_32 || COMPILE_TEST
|
||||
depends on HAS_IOPORT
|
||||
help
|
||||
Enable support for SSV Embedded Systems DIL/Net-PC
|
||||
|
||||
|
@ -89,6 +91,7 @@ endif # COMEDI_MISC_DRIVERS
|
|||
|
||||
menuconfig COMEDI_ISA_DRIVERS
|
||||
bool "Comedi ISA and PC/104 drivers"
|
||||
depends on ISA
|
||||
help
|
||||
Enable comedi ISA and PC/104 drivers to be built
|
||||
|
||||
|
@ -100,7 +103,8 @@ if COMEDI_ISA_DRIVERS
|
|||
|
||||
config COMEDI_PCL711
|
||||
tristate "Advantech PCL-711/711b and ADlink ACL-8112 ISA card support"
|
||||
select COMEDI_8254
|
||||
depends on HAS_IOPORT
|
||||
depends on COMEDI_8254
|
||||
help
|
||||
Enable support for Advantech PCL-711 and 711b, ADlink ACL-8112
|
||||
|
||||
|
@ -161,8 +165,9 @@ config COMEDI_PCL730
|
|||
|
||||
config COMEDI_PCL812
|
||||
tristate "Advantech PCL-812/813 and ADlink ACL-8112/8113/8113/8216"
|
||||
depends on HAS_IOPORT
|
||||
select COMEDI_ISADMA if ISA_DMA_API
|
||||
select COMEDI_8254
|
||||
depends on COMEDI_8254
|
||||
help
|
||||
Enable support for Advantech PCL-812/PG, PCL-813/B, ADLink
|
||||
ACL-8112DG/HG/PG, ACL-8113, ACL-8216, ICP DAS A-821PGH/PGL/PGL-NDA,
|
||||
|
@ -173,8 +178,9 @@ config COMEDI_PCL812
|
|||
|
||||
config COMEDI_PCL816
|
||||
tristate "Advantech PCL-814 and PCL-816 ISA card support"
|
||||
depends on HAS_IOPORT
|
||||
select COMEDI_ISADMA if ISA_DMA_API
|
||||
select COMEDI_8254
|
||||
depends on COMEDI_8254
|
||||
help
|
||||
Enable support for Advantech PCL-814 and PCL-816 ISA cards
|
||||
|
||||
|
@ -183,8 +189,9 @@ config COMEDI_PCL816
|
|||
|
||||
config COMEDI_PCL818
|
||||
tristate "Advantech PCL-718 and PCL-818 ISA card support"
|
||||
depends on HAS_IOPORT
|
||||
select COMEDI_ISADMA if ISA_DMA_API
|
||||
select COMEDI_8254
|
||||
depends on COMEDI_8254
|
||||
help
|
||||
Enable support for Advantech PCL-818 ISA cards
|
||||
PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818 and PCL-718
|
||||
|
@ -203,7 +210,7 @@ config COMEDI_PCM3724
|
|||
|
||||
config COMEDI_AMPLC_DIO200_ISA
|
||||
tristate "Amplicon PC212E/PC214E/PC215E/PC218E/PC272E"
|
||||
select COMEDI_AMPLC_DIO200
|
||||
depends on COMEDI_AMPLC_DIO200
|
||||
help
|
||||
Enable support for Amplicon PC212E, PC214E, PC215E, PC218E and
|
||||
PC272E ISA DIO boards
|
||||
|
@ -255,7 +262,8 @@ config COMEDI_DAC02
|
|||
|
||||
config COMEDI_DAS16M1
|
||||
tristate "MeasurementComputing CIO-DAS16/M1DAS-16 ISA card support"
|
||||
select COMEDI_8254
|
||||
depends on HAS_IOPORT
|
||||
depends on COMEDI_8254
|
||||
select COMEDI_8255
|
||||
help
|
||||
Enable support for Measurement Computing CIO-DAS16/M1 ISA cards.
|
||||
|
@ -265,7 +273,7 @@ config COMEDI_DAS16M1
|
|||
|
||||
config COMEDI_DAS08_ISA
|
||||
tristate "DAS-08 compatible ISA and PC/104 card support"
|
||||
select COMEDI_DAS08
|
||||
depends on COMEDI_DAS08
|
||||
help
|
||||
Enable support for Keithley Metrabyte/ComputerBoards DAS08
|
||||
and compatible ISA and PC/104 cards:
|
||||
|
@ -278,8 +286,9 @@ config COMEDI_DAS08_ISA
|
|||
|
||||
config COMEDI_DAS16
|
||||
tristate "DAS-16 compatible ISA and PC/104 card support"
|
||||
depends on HAS_IOPORT
|
||||
select COMEDI_ISADMA if ISA_DMA_API
|
||||
select COMEDI_8254
|
||||
depends on COMEDI_8254
|
||||
select COMEDI_8255
|
||||
help
|
||||
Enable support for Keithley Metrabyte/ComputerBoards DAS16
|
||||
|
@ -296,7 +305,8 @@ config COMEDI_DAS16
|
|||
|
||||
config COMEDI_DAS800
|
||||
tristate "DAS800 and compatible ISA card support"
|
||||
select COMEDI_8254
|
||||
depends on HAS_IOPORT
|
||||
depends on COMEDI_8254
|
||||
help
|
||||
Enable support for Keithley Metrabyte DAS800 and compatible ISA cards
|
||||
Keithley Metrabyte DAS-800, DAS-801, DAS-802
|
||||
|
@ -308,8 +318,9 @@ config COMEDI_DAS800
|
|||
|
||||
config COMEDI_DAS1800
|
||||
tristate "DAS1800 and compatible ISA card support"
|
||||
depends on HAS_IOPORT
|
||||
select COMEDI_ISADMA if ISA_DMA_API
|
||||
select COMEDI_8254
|
||||
depends on COMEDI_8254
|
||||
help
|
||||
Enable support for DAS1800 and compatible ISA cards
|
||||
Keithley Metrabyte DAS-1701ST, DAS-1701ST-DA, DAS-1701/AO,
|
||||
|
@ -323,7 +334,8 @@ config COMEDI_DAS1800
|
|||
|
||||
config COMEDI_DAS6402
|
||||
tristate "DAS6402 and compatible ISA card support"
|
||||
select COMEDI_8254
|
||||
depends on HAS_IOPORT
|
||||
depends on COMEDI_8254
|
||||
help
|
||||
Enable support for DAS6402 and compatible ISA cards
|
||||
Computerboards, Keithley Metrabyte DAS6402 and compatibles
|
||||
|
@ -402,7 +414,8 @@ config COMEDI_FL512
|
|||
|
||||
config COMEDI_AIO_AIO12_8
|
||||
tristate "I/O Products PC/104 AIO12-8 Analog I/O Board support"
|
||||
select COMEDI_8254
|
||||
depends on HAS_IOPORT
|
||||
depends on COMEDI_8254
|
||||
select COMEDI_8255
|
||||
help
|
||||
Enable support for I/O Products PC/104 AIO12-8 Analog I/O Board
|
||||
|
@ -456,8 +469,9 @@ config COMEDI_ADQ12B
|
|||
|
||||
config COMEDI_NI_AT_A2150
|
||||
tristate "NI AT-A2150 ISA card support"
|
||||
depends on HAS_IOPORT
|
||||
select COMEDI_ISADMA if ISA_DMA_API
|
||||
select COMEDI_8254
|
||||
depends on COMEDI_8254
|
||||
help
|
||||
Enable support for National Instruments AT-A2150 cards
|
||||
|
||||
|
@ -466,7 +480,8 @@ config COMEDI_NI_AT_A2150
|
|||
|
||||
config COMEDI_NI_AT_AO
|
||||
tristate "NI AT-AO-6/10 EISA card support"
|
||||
select COMEDI_8254
|
||||
depends on HAS_IOPORT
|
||||
depends on COMEDI_8254
|
||||
help
|
||||
Enable support for National Instruments AT-AO-6/10 cards
|
||||
|
||||
|
@ -497,7 +512,7 @@ config COMEDI_NI_ATMIO16D
|
|||
|
||||
config COMEDI_NI_LABPC_ISA
|
||||
tristate "NI Lab-PC and compatibles ISA support"
|
||||
select COMEDI_NI_LABPC
|
||||
depends on COMEDI_NI_LABPC
|
||||
help
|
||||
Enable support for National Instruments Lab-PC and compatibles
|
||||
Lab-PC-1200, Lab-PC-1200AI, Lab-PC+.
|
||||
|
@ -561,7 +576,7 @@ endif # COMEDI_ISA_DRIVERS
|
|||
|
||||
menuconfig COMEDI_PCI_DRIVERS
|
||||
tristate "Comedi PCI drivers"
|
||||
depends on PCI
|
||||
depends on PCI && HAS_IOPORT
|
||||
help
|
||||
Enable support for comedi PCI drivers.
|
||||
|
||||
|
@ -710,7 +725,8 @@ config COMEDI_ADL_PCI8164
|
|||
|
||||
config COMEDI_ADL_PCI9111
|
||||
tristate "ADLink PCI-9111HR support"
|
||||
select COMEDI_8254
|
||||
depends on HAS_IOPORT
|
||||
depends on COMEDI_8254
|
||||
help
|
||||
Enable support for ADlink PCI9111 cards
|
||||
|
||||
|
@ -720,7 +736,7 @@ config COMEDI_ADL_PCI9111
|
|||
config COMEDI_ADL_PCI9118
|
||||
tristate "ADLink PCI-9118DG, PCI-9118HG, PCI-9118HR support"
|
||||
depends on HAS_DMA
|
||||
select COMEDI_8254
|
||||
depends on COMEDI_8254
|
||||
help
|
||||
Enable support for ADlink PCI-9118DG, PCI-9118HG, PCI-9118HR cards
|
||||
|
||||
|
@ -729,7 +745,8 @@ config COMEDI_ADL_PCI9118
|
|||
|
||||
config COMEDI_ADV_PCI1710
|
||||
tristate "Advantech PCI-171x and PCI-1731 support"
|
||||
select COMEDI_8254
|
||||
depends on HAS_IOPORT
|
||||
depends on COMEDI_8254
|
||||
help
|
||||
Enable support for Advantech PCI-1710, PCI-1710HG, PCI-1711,
|
||||
PCI-1713 and PCI-1731
|
||||
|
@ -773,7 +790,8 @@ config COMEDI_ADV_PCI1760
|
|||
|
||||
config COMEDI_ADV_PCI_DIO
|
||||
tristate "Advantech PCI DIO card support"
|
||||
select COMEDI_8254
|
||||
depends on HAS_IOPORT
|
||||
depends on COMEDI_8254
|
||||
select COMEDI_8255
|
||||
help
|
||||
Enable support for Advantech PCI DIO cards
|
||||
|
@ -786,7 +804,7 @@ config COMEDI_ADV_PCI_DIO
|
|||
|
||||
config COMEDI_AMPLC_DIO200_PCI
|
||||
tristate "Amplicon PCI215/PCI272/PCIe215/PCIe236/PCIe296 DIO support"
|
||||
select COMEDI_AMPLC_DIO200
|
||||
depends on COMEDI_AMPLC_DIO200
|
||||
help
|
||||
Enable support for Amplicon PCI215, PCI272, PCIe215, PCIe236
|
||||
and PCIe296 DIO boards.
|
||||
|
@ -814,7 +832,8 @@ config COMEDI_AMPLC_PC263_PCI
|
|||
|
||||
config COMEDI_AMPLC_PCI224
|
||||
tristate "Amplicon PCI224 and PCI234 support"
|
||||
select COMEDI_8254
|
||||
depends on HAS_IOPORT
|
||||
depends on COMEDI_8254
|
||||
help
|
||||
Enable support for Amplicon PCI224 and PCI234 AO boards
|
||||
|
||||
|
@ -823,7 +842,8 @@ config COMEDI_AMPLC_PCI224
|
|||
|
||||
config COMEDI_AMPLC_PCI230
|
||||
tristate "Amplicon PCI230 and PCI260 support"
|
||||
select COMEDI_8254
|
||||
depends on HAS_IOPORT
|
||||
depends on COMEDI_8254
|
||||
select COMEDI_8255
|
||||
help
|
||||
Enable support for Amplicon PCI230 and PCI260 Multifunction I/O
|
||||
|
@ -842,7 +862,7 @@ config COMEDI_CONTEC_PCI_DIO
|
|||
|
||||
config COMEDI_DAS08_PCI
|
||||
tristate "DAS-08 PCI support"
|
||||
select COMEDI_DAS08
|
||||
depends on COMEDI_DAS08
|
||||
help
|
||||
Enable support for PCI DAS-08 cards.
|
||||
|
||||
|
@ -929,7 +949,8 @@ config COMEDI_CB_PCIDAS64
|
|||
|
||||
config COMEDI_CB_PCIDAS
|
||||
tristate "MeasurementComputing PCI-DAS support"
|
||||
select COMEDI_8254
|
||||
depends on HAS_IOPORT
|
||||
depends on COMEDI_8254
|
||||
select COMEDI_8255
|
||||
help
|
||||
Enable support for ComputerBoards/MeasurementComputing PCI-DAS with
|
||||
|
@ -953,7 +974,8 @@ config COMEDI_CB_PCIDDA
|
|||
|
||||
config COMEDI_CB_PCIMDAS
|
||||
tristate "MeasurementComputing PCIM-DAS1602/16, PCIe-DAS1602/16 support"
|
||||
select COMEDI_8254
|
||||
depends on HAS_IOPORT
|
||||
depends on COMEDI_8254
|
||||
select COMEDI_8255
|
||||
help
|
||||
Enable support for ComputerBoards/MeasurementComputing PCI Migration
|
||||
|
@ -973,7 +995,8 @@ config COMEDI_CB_PCIMDDA
|
|||
|
||||
config COMEDI_ME4000
|
||||
tristate "Meilhaus ME-4000 support"
|
||||
select COMEDI_8254
|
||||
depends on HAS_IOPORT
|
||||
depends on COMEDI_8254
|
||||
help
|
||||
Enable support for Meilhaus PCI data acquisition cards
|
||||
ME-4650, ME-4670i, ME-4680, ME-4680i and ME-4680is
|
||||
|
@ -1031,7 +1054,7 @@ config COMEDI_NI_670X
|
|||
|
||||
config COMEDI_NI_LABPC_PCI
|
||||
tristate "NI Lab-PC PCI-1200 support"
|
||||
select COMEDI_NI_LABPC
|
||||
depends on COMEDI_NI_LABPC
|
||||
help
|
||||
Enable support for National Instruments Lab-PC PCI-1200.
|
||||
|
||||
|
@ -1053,6 +1076,7 @@ config COMEDI_NI_PCIDIO
|
|||
config COMEDI_NI_PCIMIO
|
||||
tristate "NI PCI-MIO-E series and M series support"
|
||||
depends on HAS_DMA
|
||||
depends on HAS_IOPORT
|
||||
select COMEDI_NI_TIOCMD
|
||||
select COMEDI_8255
|
||||
help
|
||||
|
@ -1074,7 +1098,8 @@ config COMEDI_NI_PCIMIO
|
|||
|
||||
config COMEDI_RTD520
|
||||
tristate "Real Time Devices PCI4520/DM7520 support"
|
||||
select COMEDI_8254
|
||||
depends on HAS_IOPORT
|
||||
depends on COMEDI_8254
|
||||
help
|
||||
Enable support for Real Time Devices PCI4520/DM7520
|
||||
|
||||
|
@ -1114,7 +1139,8 @@ if COMEDI_PCMCIA_DRIVERS
|
|||
|
||||
config COMEDI_CB_DAS16_CS
|
||||
tristate "CB DAS16 series PCMCIA support"
|
||||
select COMEDI_8254
|
||||
depends on HAS_IOPORT
|
||||
depends on COMEDI_8254
|
||||
help
|
||||
Enable support for the ComputerBoards/MeasurementComputing PCMCIA
|
||||
cards DAS16/16, PCM-DAS16D/12 and PCM-DAS16s/16
|
||||
|
@ -1124,7 +1150,7 @@ config COMEDI_CB_DAS16_CS
|
|||
|
||||
config COMEDI_DAS08_CS
|
||||
tristate "CB DAS08 PCMCIA support"
|
||||
select COMEDI_DAS08
|
||||
depends on COMEDI_DAS08
|
||||
help
|
||||
Enable support for the ComputerBoards/MeasurementComputing DAS-08
|
||||
PCMCIA card
|
||||
|
@ -1134,6 +1160,7 @@ config COMEDI_DAS08_CS
|
|||
|
||||
config COMEDI_NI_DAQ_700_CS
|
||||
tristate "NI DAQCard-700 PCMCIA support"
|
||||
depends on HAS_IOPORT
|
||||
help
|
||||
Enable support for the National Instruments PCMCIA DAQCard-700 DIO
|
||||
|
||||
|
@ -1142,6 +1169,7 @@ config COMEDI_NI_DAQ_700_CS
|
|||
|
||||
config COMEDI_NI_DAQ_DIO24_CS
|
||||
tristate "NI DAQ-Card DIO-24 PCMCIA support"
|
||||
depends on HAS_IOPORT
|
||||
select COMEDI_8255
|
||||
help
|
||||
Enable support for the National Instruments PCMCIA DAQ-Card DIO-24
|
||||
|
@ -1151,7 +1179,7 @@ config COMEDI_NI_DAQ_DIO24_CS
|
|||
|
||||
config COMEDI_NI_LABPC_CS
|
||||
tristate "NI DAQCard-1200 PCMCIA support"
|
||||
select COMEDI_NI_LABPC
|
||||
depends on COMEDI_NI_LABPC
|
||||
help
|
||||
Enable support for the National Instruments PCMCIA DAQCard-1200
|
||||
|
||||
|
@ -1160,6 +1188,7 @@ config COMEDI_NI_LABPC_CS
|
|||
|
||||
config COMEDI_NI_MIO_CS
|
||||
tristate "NI DAQCard E series PCMCIA support"
|
||||
depends on HAS_IOPORT
|
||||
select COMEDI_NI_TIO
|
||||
select COMEDI_8255
|
||||
help
|
||||
|
@ -1172,6 +1201,7 @@ config COMEDI_NI_MIO_CS
|
|||
|
||||
config COMEDI_QUATECH_DAQP_CS
|
||||
tristate "Quatech DAQP PCMCIA data capture card support"
|
||||
depends on HAS_IOPORT
|
||||
help
|
||||
Enable support for the Quatech DAQP PCMCIA data capture cards
|
||||
DAQP-208 and DAQP-308
|
||||
|
@ -1248,12 +1278,14 @@ endif # COMEDI_USB_DRIVERS
|
|||
|
||||
config COMEDI_8254
|
||||
tristate
|
||||
depends on HAS_IOPORT
|
||||
|
||||
config COMEDI_8255
|
||||
tristate
|
||||
|
||||
config COMEDI_8255_SA
|
||||
tristate "Standalone 8255 support"
|
||||
depends on HAS_IOPORT
|
||||
select COMEDI_8255
|
||||
help
|
||||
Enable support for 8255 digital I/O as a standalone driver.
|
||||
|
@ -1285,7 +1317,7 @@ config COMEDI_KCOMEDILIB
|
|||
called kcomedilib.
|
||||
|
||||
config COMEDI_AMPLC_DIO200
|
||||
select COMEDI_8254
|
||||
depends on COMEDI_8254
|
||||
tristate
|
||||
|
||||
config COMEDI_AMPLC_PC236
|
||||
|
@ -1294,7 +1326,7 @@ config COMEDI_AMPLC_PC236
|
|||
|
||||
config COMEDI_DAS08
|
||||
tristate
|
||||
select COMEDI_8254
|
||||
depends on COMEDI_8254
|
||||
select COMEDI_8255
|
||||
|
||||
config COMEDI_ISADMA
|
||||
|
@ -1302,7 +1334,8 @@ config COMEDI_ISADMA
|
|||
|
||||
config COMEDI_NI_LABPC
|
||||
tristate
|
||||
select COMEDI_8254
|
||||
depends on HAS_IOPORT
|
||||
depends on COMEDI_8254
|
||||
select COMEDI_8255
|
||||
|
||||
config COMEDI_NI_LABPC_ISADMA
|
||||
|
|
|
@ -97,7 +97,6 @@ static DEFINE_MUTEX(comedi_subdevice_minor_table_lock);
|
|||
static struct comedi_subdevice
|
||||
*comedi_subdevice_minor_table[COMEDI_NUM_SUBDEVICE_MINORS];
|
||||
|
||||
static struct class *comedi_class;
|
||||
static struct cdev comedi_cdev;
|
||||
|
||||
static void comedi_device_init(struct comedi_device *dev)
|
||||
|
@ -187,18 +186,6 @@ static struct comedi_device *comedi_clear_board_minor(unsigned int minor)
|
|||
return dev;
|
||||
}
|
||||
|
||||
static void comedi_free_board_dev(struct comedi_device *dev)
|
||||
{
|
||||
if (dev) {
|
||||
comedi_device_cleanup(dev);
|
||||
if (dev->class_dev) {
|
||||
device_destroy(comedi_class,
|
||||
MKDEV(COMEDI_MAJOR, dev->minor));
|
||||
}
|
||||
comedi_dev_put(dev);
|
||||
}
|
||||
}
|
||||
|
||||
static struct comedi_subdevice *
|
||||
comedi_subdevice_from_minor(const struct comedi_device *dev, unsigned int minor)
|
||||
{
|
||||
|
@ -611,6 +598,23 @@ static struct attribute *comedi_dev_attrs[] = {
|
|||
};
|
||||
ATTRIBUTE_GROUPS(comedi_dev);
|
||||
|
||||
static const struct class comedi_class = {
|
||||
.name = "comedi",
|
||||
.dev_groups = comedi_dev_groups,
|
||||
};
|
||||
|
||||
static void comedi_free_board_dev(struct comedi_device *dev)
|
||||
{
|
||||
if (dev) {
|
||||
comedi_device_cleanup(dev);
|
||||
if (dev->class_dev) {
|
||||
device_destroy(&comedi_class,
|
||||
MKDEV(COMEDI_MAJOR, dev->minor));
|
||||
}
|
||||
comedi_dev_put(dev);
|
||||
}
|
||||
}
|
||||
|
||||
static void __comedi_clear_subdevice_runflags(struct comedi_subdevice *s,
|
||||
unsigned int bits)
|
||||
{
|
||||
|
@ -3263,7 +3267,7 @@ struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device)
|
|||
return ERR_PTR(-EBUSY);
|
||||
}
|
||||
dev->minor = i;
|
||||
csdev = device_create(comedi_class, hardware_device,
|
||||
csdev = device_create(&comedi_class, hardware_device,
|
||||
MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i", i);
|
||||
if (!IS_ERR(csdev))
|
||||
dev->class_dev = get_device(csdev);
|
||||
|
@ -3312,7 +3316,7 @@ int comedi_alloc_subdevice_minor(struct comedi_subdevice *s)
|
|||
}
|
||||
i += COMEDI_NUM_BOARD_MINORS;
|
||||
s->minor = i;
|
||||
csdev = device_create(comedi_class, dev->class_dev,
|
||||
csdev = device_create(&comedi_class, dev->class_dev,
|
||||
MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i_subd%i",
|
||||
dev->minor, s->index);
|
||||
if (!IS_ERR(csdev))
|
||||
|
@ -3337,7 +3341,7 @@ void comedi_free_subdevice_minor(struct comedi_subdevice *s)
|
|||
comedi_subdevice_minor_table[i] = NULL;
|
||||
mutex_unlock(&comedi_subdevice_minor_table_lock);
|
||||
if (s->class_dev) {
|
||||
device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, s->minor));
|
||||
device_destroy(&comedi_class, MKDEV(COMEDI_MAJOR, s->minor));
|
||||
s->class_dev = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -3383,15 +3387,12 @@ static int __init comedi_init(void)
|
|||
if (retval)
|
||||
goto out_unregister_chrdev_region;
|
||||
|
||||
comedi_class = class_create("comedi");
|
||||
if (IS_ERR(comedi_class)) {
|
||||
retval = PTR_ERR(comedi_class);
|
||||
retval = class_register(&comedi_class);
|
||||
if (retval) {
|
||||
pr_err("failed to create class\n");
|
||||
goto out_cdev_del;
|
||||
}
|
||||
|
||||
comedi_class->dev_groups = comedi_dev_groups;
|
||||
|
||||
/* create devices files for legacy/manual use */
|
||||
for (i = 0; i < comedi_num_legacy_minors; i++) {
|
||||
struct comedi_device *dev;
|
||||
|
@ -3413,7 +3414,7 @@ static int __init comedi_init(void)
|
|||
|
||||
out_cleanup_board_minors:
|
||||
comedi_cleanup_board_minors();
|
||||
class_destroy(comedi_class);
|
||||
class_unregister(&comedi_class);
|
||||
out_cdev_del:
|
||||
cdev_del(&comedi_cdev);
|
||||
out_unregister_chrdev_region:
|
||||
|
@ -3425,7 +3426,7 @@ module_init(comedi_init);
|
|||
static void __exit comedi_cleanup(void)
|
||||
{
|
||||
comedi_cleanup_board_minors();
|
||||
class_destroy(comedi_class);
|
||||
class_unregister(&comedi_class);
|
||||
cdev_del(&comedi_cdev);
|
||||
unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
|
||||
|
||||
|
|
|
@ -60,7 +60,9 @@
|
|||
static bool config_mode;
|
||||
static unsigned int set_amplitude;
|
||||
static unsigned int set_period;
|
||||
static struct class *ctcls;
|
||||
static const struct class ctcls = {
|
||||
.name = CLASS_NAME,
|
||||
};
|
||||
static struct device *ctdev;
|
||||
|
||||
module_param_named(noauto, config_mode, bool, 0444);
|
||||
|
@ -795,13 +797,13 @@ static int __init comedi_test_init(void)
|
|||
}
|
||||
|
||||
if (!config_mode) {
|
||||
ctcls = class_create(CLASS_NAME);
|
||||
if (IS_ERR(ctcls)) {
|
||||
ret = class_register(&ctcls);
|
||||
if (ret) {
|
||||
pr_warn("comedi_test: unable to create class\n");
|
||||
goto clean3;
|
||||
}
|
||||
|
||||
ctdev = device_create(ctcls, NULL, MKDEV(0, 0), NULL, DEV_NAME);
|
||||
ctdev = device_create(&ctcls, NULL, MKDEV(0, 0), NULL, DEV_NAME);
|
||||
if (IS_ERR(ctdev)) {
|
||||
pr_warn("comedi_test: unable to create device\n");
|
||||
goto clean2;
|
||||
|
@ -817,13 +819,10 @@ static int __init comedi_test_init(void)
|
|||
return 0;
|
||||
|
||||
clean:
|
||||
device_destroy(ctcls, MKDEV(0, 0));
|
||||
device_destroy(&ctcls, MKDEV(0, 0));
|
||||
clean2:
|
||||
class_destroy(ctcls);
|
||||
ctdev = NULL;
|
||||
class_unregister(&ctcls);
|
||||
clean3:
|
||||
ctcls = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
module_init(comedi_test_init);
|
||||
|
@ -833,9 +832,9 @@ static void __exit comedi_test_exit(void)
|
|||
if (ctdev)
|
||||
comedi_auto_unconfig(ctdev);
|
||||
|
||||
if (ctcls) {
|
||||
device_destroy(ctcls, MKDEV(0, 0));
|
||||
class_destroy(ctcls);
|
||||
if (class_is_registered(&ctcls)) {
|
||||
device_destroy(&ctcls, MKDEV(0, 0));
|
||||
class_unregister(&ctcls);
|
||||
}
|
||||
|
||||
comedi_driver_unregister(&waveform_driver);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,20 +10,37 @@ menuconfig COUNTER
|
|||
interface. You only need to enable this, if you also want to enable
|
||||
one or more of the counter device drivers below.
|
||||
|
||||
config I8254
|
||||
tristate
|
||||
select COUNTER
|
||||
select REGMAP
|
||||
help
|
||||
Enables support for the i8254 interface library functions. The i8254
|
||||
interface library provides functions to facilitate communication with
|
||||
interfaces compatible with the venerable Intel 8254 Programmable
|
||||
Interval Timer (PIT). The Intel 825x family of chips was first
|
||||
released in the early 1980s but compatible interfaces are nowadays
|
||||
typically found embedded in larger VLSI processing chips and FPGA
|
||||
components.
|
||||
|
||||
If built as a module its name will be i8254.
|
||||
|
||||
if COUNTER
|
||||
|
||||
config 104_QUAD_8
|
||||
tristate "ACCES 104-QUAD-8 driver"
|
||||
depends on (PC104 && X86) || COMPILE_TEST
|
||||
depends on HAS_IOPORT_MAP
|
||||
select ISA_BUS_API
|
||||
select REGMAP_MMIO
|
||||
help
|
||||
Say yes here to build support for the ACCES 104-QUAD-8 quadrature
|
||||
encoder counter/interface device family (104-QUAD-8, 104-QUAD-4).
|
||||
|
||||
A counter's respective error flag may be cleared by performing a write
|
||||
operation on the respective count value attribute. Although the
|
||||
104-QUAD-8 counters have a 25-bit range, only the lower 24 bits may be
|
||||
set, either directly or via the counter's preset attribute.
|
||||
operation on the respective count value attribute. The 104-QUAD-8
|
||||
counters may be set either directly or via the counter's preset
|
||||
attribute.
|
||||
|
||||
The base port addresses for the devices may be configured via the base
|
||||
array module parameter. The interrupt line numbers for the devices may
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
obj-$(CONFIG_COUNTER) += counter.o
|
||||
counter-y := counter-core.o counter-sysfs.o counter-chrdev.o
|
||||
|
||||
obj-$(CONFIG_I8254) += i8254.o
|
||||
obj-$(CONFIG_104_QUAD_8) += 104-quad-8.o
|
||||
obj-$(CONFIG_INTERRUPT_CNT) += interrupt-cnt.o
|
||||
obj-$(CONFIG_RZ_MTU3_CNT) += rz-mtu3-cnt.o
|
||||
|
|
|
@ -88,7 +88,13 @@ static const char *const counter_count_mode_str[] = {
|
|||
[COUNTER_COUNT_MODE_NORMAL] = "normal",
|
||||
[COUNTER_COUNT_MODE_RANGE_LIMIT] = "range limit",
|
||||
[COUNTER_COUNT_MODE_NON_RECYCLE] = "non-recycle",
|
||||
[COUNTER_COUNT_MODE_MODULO_N] = "modulo-n"
|
||||
[COUNTER_COUNT_MODE_MODULO_N] = "modulo-n",
|
||||
[COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT] = "interrupt on terminal count",
|
||||
[COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT] = "hardware retriggerable one-shot",
|
||||
[COUNTER_COUNT_MODE_RATE_GENERATOR] = "rate generator",
|
||||
[COUNTER_COUNT_MODE_SQUARE_WAVE_MODE] = "square wave mode",
|
||||
[COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE] = "software triggered strobe",
|
||||
[COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE] = "hardware triggered strobe",
|
||||
};
|
||||
|
||||
static const char *const counter_signal_polarity_str[] = {
|
||||
|
|
|
@ -0,0 +1,447 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Intel 8254 Programmable Interval Timer
|
||||
* Copyright (C) William Breathitt Gray
|
||||
*/
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/counter.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/i8254.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#define I8254_COUNTER_REG(_counter) (_counter)
|
||||
#define I8254_CONTROL_REG 0x3
|
||||
|
||||
#define I8254_SC GENMASK(7, 6)
|
||||
#define I8254_RW GENMASK(5, 4)
|
||||
#define I8254_M GENMASK(3, 1)
|
||||
#define I8254_CONTROL(_sc, _rw, _m) \
|
||||
(u8_encode_bits(_sc, I8254_SC) | u8_encode_bits(_rw, I8254_RW) | \
|
||||
u8_encode_bits(_m, I8254_M))
|
||||
|
||||
#define I8254_RW_TWO_BYTE 0x3
|
||||
#define I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT 0
|
||||
#define I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT 1
|
||||
#define I8254_MODE_RATE_GENERATOR 2
|
||||
#define I8254_MODE_SQUARE_WAVE_MODE 3
|
||||
#define I8254_MODE_SOFTWARE_TRIGGERED_STROBE 4
|
||||
#define I8254_MODE_HARDWARE_TRIGGERED_STROBE 5
|
||||
|
||||
#define I8254_COUNTER_LATCH(_counter) I8254_CONTROL(_counter, 0x0, 0x0)
|
||||
#define I8254_PROGRAM_COUNTER(_counter, _mode) I8254_CONTROL(_counter, I8254_RW_TWO_BYTE, _mode)
|
||||
|
||||
#define I8254_NUM_COUNTERS 3
|
||||
|
||||
/**
|
||||
* struct i8254 - I8254 device private data structure
|
||||
* @lock: synchronization lock to prevent I/O race conditions
|
||||
* @preset: array of Counter Register states
|
||||
* @out_mode: array of mode configuration states
|
||||
* @map: Regmap for the device
|
||||
*/
|
||||
struct i8254 {
|
||||
struct mutex lock;
|
||||
u16 preset[I8254_NUM_COUNTERS];
|
||||
u8 out_mode[I8254_NUM_COUNTERS];
|
||||
struct regmap *map;
|
||||
};
|
||||
|
||||
static int i8254_count_read(struct counter_device *const counter, struct counter_count *const count,
|
||||
u64 *const val)
|
||||
{
|
||||
struct i8254 *const priv = counter_priv(counter);
|
||||
int ret;
|
||||
u8 value[2];
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
|
||||
ret = regmap_write(priv->map, I8254_CONTROL_REG, I8254_COUNTER_LATCH(count->id));
|
||||
if (ret) {
|
||||
mutex_unlock(&priv->lock);
|
||||
return ret;
|
||||
}
|
||||
ret = regmap_noinc_read(priv->map, I8254_COUNTER_REG(count->id), value, sizeof(value));
|
||||
if (ret) {
|
||||
mutex_unlock(&priv->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
*val = get_unaligned_le16(value);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int i8254_function_read(struct counter_device *const counter,
|
||||
struct counter_count *const count,
|
||||
enum counter_function *const function)
|
||||
{
|
||||
*function = COUNTER_FUNCTION_DECREASE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define I8254_SYNAPSES_PER_COUNT 2
|
||||
#define I8254_SIGNAL_ID_CLK 0
|
||||
#define I8254_SIGNAL_ID_GATE 1
|
||||
|
||||
static int i8254_action_read(struct counter_device *const counter,
|
||||
struct counter_count *const count,
|
||||
struct counter_synapse *const synapse,
|
||||
enum counter_synapse_action *const action)
|
||||
{
|
||||
struct i8254 *const priv = counter_priv(counter);
|
||||
|
||||
switch (synapse->signal->id % I8254_SYNAPSES_PER_COUNT) {
|
||||
case I8254_SIGNAL_ID_CLK:
|
||||
*action = COUNTER_SYNAPSE_ACTION_FALLING_EDGE;
|
||||
return 0;
|
||||
case I8254_SIGNAL_ID_GATE:
|
||||
switch (priv->out_mode[count->id]) {
|
||||
case I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT:
|
||||
case I8254_MODE_RATE_GENERATOR:
|
||||
case I8254_MODE_SQUARE_WAVE_MODE:
|
||||
case I8254_MODE_HARDWARE_TRIGGERED_STROBE:
|
||||
*action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
|
||||
return 0;
|
||||
default:
|
||||
*action = COUNTER_SYNAPSE_ACTION_NONE;
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
/* should never reach this path */
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int i8254_count_ceiling_read(struct counter_device *const counter,
|
||||
struct counter_count *const count, u64 *const ceiling)
|
||||
{
|
||||
struct i8254 *const priv = counter_priv(counter);
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
|
||||
switch (priv->out_mode[count->id]) {
|
||||
case I8254_MODE_RATE_GENERATOR:
|
||||
/* Rate Generator decrements 0 by one and the counter "wraps around" */
|
||||
*ceiling = (priv->preset[count->id] == 0) ? U16_MAX : priv->preset[count->id];
|
||||
break;
|
||||
case I8254_MODE_SQUARE_WAVE_MODE:
|
||||
if (priv->preset[count->id] % 2)
|
||||
*ceiling = priv->preset[count->id] - 1;
|
||||
else if (priv->preset[count->id] == 0)
|
||||
/* Square Wave Mode decrements 0 by two and the counter "wraps around" */
|
||||
*ceiling = U16_MAX - 1;
|
||||
else
|
||||
*ceiling = priv->preset[count->id];
|
||||
break;
|
||||
default:
|
||||
*ceiling = U16_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i8254_count_mode_read(struct counter_device *const counter,
|
||||
struct counter_count *const count,
|
||||
enum counter_count_mode *const count_mode)
|
||||
{
|
||||
const struct i8254 *const priv = counter_priv(counter);
|
||||
|
||||
switch (priv->out_mode[count->id]) {
|
||||
case I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT:
|
||||
*count_mode = COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT;
|
||||
return 0;
|
||||
case I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT:
|
||||
*count_mode = COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT;
|
||||
return 0;
|
||||
case I8254_MODE_RATE_GENERATOR:
|
||||
*count_mode = COUNTER_COUNT_MODE_RATE_GENERATOR;
|
||||
return 0;
|
||||
case I8254_MODE_SQUARE_WAVE_MODE:
|
||||
*count_mode = COUNTER_COUNT_MODE_SQUARE_WAVE_MODE;
|
||||
return 0;
|
||||
case I8254_MODE_SOFTWARE_TRIGGERED_STROBE:
|
||||
*count_mode = COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE;
|
||||
return 0;
|
||||
case I8254_MODE_HARDWARE_TRIGGERED_STROBE:
|
||||
*count_mode = COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE;
|
||||
return 0;
|
||||
default:
|
||||
/* should never reach this path */
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int i8254_count_mode_write(struct counter_device *const counter,
|
||||
struct counter_count *const count,
|
||||
const enum counter_count_mode count_mode)
|
||||
{
|
||||
struct i8254 *const priv = counter_priv(counter);
|
||||
u8 out_mode;
|
||||
int ret;
|
||||
|
||||
switch (count_mode) {
|
||||
case COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT:
|
||||
out_mode = I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT;
|
||||
break;
|
||||
case COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT:
|
||||
out_mode = I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT;
|
||||
break;
|
||||
case COUNTER_COUNT_MODE_RATE_GENERATOR:
|
||||
out_mode = I8254_MODE_RATE_GENERATOR;
|
||||
break;
|
||||
case COUNTER_COUNT_MODE_SQUARE_WAVE_MODE:
|
||||
out_mode = I8254_MODE_SQUARE_WAVE_MODE;
|
||||
break;
|
||||
case COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE:
|
||||
out_mode = I8254_MODE_SOFTWARE_TRIGGERED_STROBE;
|
||||
break;
|
||||
case COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE:
|
||||
out_mode = I8254_MODE_HARDWARE_TRIGGERED_STROBE;
|
||||
break;
|
||||
default:
|
||||
/* should never reach this path */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
|
||||
/* Counter Register is cleared when the counter is programmed */
|
||||
priv->preset[count->id] = 0;
|
||||
priv->out_mode[count->id] = out_mode;
|
||||
ret = regmap_write(priv->map, I8254_CONTROL_REG,
|
||||
I8254_PROGRAM_COUNTER(count->id, out_mode));
|
||||
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int i8254_count_floor_read(struct counter_device *const counter,
|
||||
struct counter_count *const count, u64 *const floor)
|
||||
{
|
||||
struct i8254 *const priv = counter_priv(counter);
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
|
||||
switch (priv->out_mode[count->id]) {
|
||||
case I8254_MODE_RATE_GENERATOR:
|
||||
/* counter is always reloaded after 1, but 0 is a possible reload value */
|
||||
*floor = (priv->preset[count->id] == 0) ? 0 : 1;
|
||||
break;
|
||||
case I8254_MODE_SQUARE_WAVE_MODE:
|
||||
/* counter is always reloaded after 2 for even preset values */
|
||||
*floor = (priv->preset[count->id] % 2 || priv->preset[count->id] == 0) ? 0 : 2;
|
||||
break;
|
||||
default:
|
||||
*floor = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i8254_count_preset_read(struct counter_device *const counter,
|
||||
struct counter_count *const count, u64 *const preset)
|
||||
{
|
||||
const struct i8254 *const priv = counter_priv(counter);
|
||||
|
||||
*preset = priv->preset[count->id];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i8254_count_preset_write(struct counter_device *const counter,
|
||||
struct counter_count *const count, const u64 preset)
|
||||
{
|
||||
struct i8254 *const priv = counter_priv(counter);
|
||||
int ret;
|
||||
u8 value[2];
|
||||
|
||||
if (preset > U16_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
|
||||
if (priv->out_mode[count->id] == I8254_MODE_RATE_GENERATOR ||
|
||||
priv->out_mode[count->id] == I8254_MODE_SQUARE_WAVE_MODE) {
|
||||
if (preset == 1) {
|
||||
mutex_unlock(&priv->lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
priv->preset[count->id] = preset;
|
||||
|
||||
put_unaligned_le16(preset, value);
|
||||
ret = regmap_noinc_write(priv->map, I8254_COUNTER_REG(count->id), value, 2);
|
||||
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int i8254_init_hw(struct regmap *const map)
|
||||
{
|
||||
unsigned long i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < I8254_NUM_COUNTERS; i++) {
|
||||
/* Initialize each counter to Mode 0 */
|
||||
ret = regmap_write(map, I8254_CONTROL_REG,
|
||||
I8254_PROGRAM_COUNTER(i, I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct counter_ops i8254_ops = {
|
||||
.count_read = i8254_count_read,
|
||||
.function_read = i8254_function_read,
|
||||
.action_read = i8254_action_read,
|
||||
};
|
||||
|
||||
#define I8254_SIGNAL(_id, _name) { \
|
||||
.id = (_id), \
|
||||
.name = (_name), \
|
||||
}
|
||||
|
||||
static struct counter_signal i8254_signals[] = {
|
||||
I8254_SIGNAL(0, "CLK 0"), I8254_SIGNAL(1, "GATE 0"),
|
||||
I8254_SIGNAL(2, "CLK 1"), I8254_SIGNAL(3, "GATE 1"),
|
||||
I8254_SIGNAL(4, "CLK 2"), I8254_SIGNAL(5, "GATE 2"),
|
||||
};
|
||||
|
||||
static const enum counter_synapse_action i8254_clk_actions[] = {
|
||||
COUNTER_SYNAPSE_ACTION_FALLING_EDGE,
|
||||
};
|
||||
static const enum counter_synapse_action i8254_gate_actions[] = {
|
||||
COUNTER_SYNAPSE_ACTION_NONE,
|
||||
COUNTER_SYNAPSE_ACTION_RISING_EDGE,
|
||||
};
|
||||
|
||||
#define I8254_SYNAPSES_BASE(_id) ((_id) * I8254_SYNAPSES_PER_COUNT)
|
||||
#define I8254_SYNAPSE_CLK(_id) { \
|
||||
.actions_list = i8254_clk_actions, \
|
||||
.num_actions = ARRAY_SIZE(i8254_clk_actions), \
|
||||
.signal = &i8254_signals[I8254_SYNAPSES_BASE(_id) + 0], \
|
||||
}
|
||||
#define I8254_SYNAPSE_GATE(_id) { \
|
||||
.actions_list = i8254_gate_actions, \
|
||||
.num_actions = ARRAY_SIZE(i8254_gate_actions), \
|
||||
.signal = &i8254_signals[I8254_SYNAPSES_BASE(_id) + 1], \
|
||||
}
|
||||
|
||||
static struct counter_synapse i8254_synapses[] = {
|
||||
I8254_SYNAPSE_CLK(0), I8254_SYNAPSE_GATE(0),
|
||||
I8254_SYNAPSE_CLK(1), I8254_SYNAPSE_GATE(1),
|
||||
I8254_SYNAPSE_CLK(2), I8254_SYNAPSE_GATE(2),
|
||||
};
|
||||
|
||||
static const enum counter_function i8254_functions_list[] = {
|
||||
COUNTER_FUNCTION_DECREASE,
|
||||
};
|
||||
|
||||
static const enum counter_count_mode i8254_count_modes[] = {
|
||||
COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT,
|
||||
COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT,
|
||||
COUNTER_COUNT_MODE_RATE_GENERATOR,
|
||||
COUNTER_COUNT_MODE_SQUARE_WAVE_MODE,
|
||||
COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE,
|
||||
COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE,
|
||||
};
|
||||
|
||||
static DEFINE_COUNTER_AVAILABLE(i8254_count_modes_available, i8254_count_modes);
|
||||
|
||||
static struct counter_comp i8254_count_ext[] = {
|
||||
COUNTER_COMP_CEILING(i8254_count_ceiling_read, NULL),
|
||||
COUNTER_COMP_COUNT_MODE(i8254_count_mode_read, i8254_count_mode_write,
|
||||
i8254_count_modes_available),
|
||||
COUNTER_COMP_FLOOR(i8254_count_floor_read, NULL),
|
||||
COUNTER_COMP_PRESET(i8254_count_preset_read, i8254_count_preset_write),
|
||||
};
|
||||
|
||||
#define I8254_COUNT(_id, _name) { \
|
||||
.id = (_id), \
|
||||
.name = (_name), \
|
||||
.functions_list = i8254_functions_list, \
|
||||
.num_functions = ARRAY_SIZE(i8254_functions_list), \
|
||||
.synapses = &i8254_synapses[I8254_SYNAPSES_BASE(_id)], \
|
||||
.num_synapses = I8254_SYNAPSES_PER_COUNT, \
|
||||
.ext = i8254_count_ext, \
|
||||
.num_ext = ARRAY_SIZE(i8254_count_ext) \
|
||||
}
|
||||
|
||||
static struct counter_count i8254_counts[I8254_NUM_COUNTERS] = {
|
||||
I8254_COUNT(0, "Counter 0"), I8254_COUNT(1, "Counter 1"), I8254_COUNT(2, "Counter 2"),
|
||||
};
|
||||
|
||||
/**
|
||||
* devm_i8254_regmap_register - Register an i8254 Counter device
|
||||
* @dev: device that is registering this i8254 Counter device
|
||||
* @config: configuration for i8254_regmap_config
|
||||
*
|
||||
* Registers an Intel 8254 Programmable Interval Timer Counter device. Returns 0 on success and
|
||||
* negative error number on failure.
|
||||
*/
|
||||
int devm_i8254_regmap_register(struct device *const dev,
|
||||
const struct i8254_regmap_config *const config)
|
||||
{
|
||||
struct counter_device *counter;
|
||||
struct i8254 *priv;
|
||||
int err;
|
||||
|
||||
if (!config->parent)
|
||||
return -EINVAL;
|
||||
|
||||
if (!config->map)
|
||||
return -EINVAL;
|
||||
|
||||
counter = devm_counter_alloc(dev, sizeof(*priv));
|
||||
if (!counter)
|
||||
return -ENOMEM;
|
||||
priv = counter_priv(counter);
|
||||
priv->map = config->map;
|
||||
|
||||
counter->name = dev_name(config->parent);
|
||||
counter->parent = config->parent;
|
||||
counter->ops = &i8254_ops;
|
||||
counter->counts = i8254_counts;
|
||||
counter->num_counts = ARRAY_SIZE(i8254_counts);
|
||||
counter->signals = i8254_signals;
|
||||
counter->num_signals = ARRAY_SIZE(i8254_signals);
|
||||
|
||||
mutex_init(&priv->lock);
|
||||
|
||||
err = i8254_init_hw(priv->map);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = devm_counter_add(dev, counter);
|
||||
if (err < 0)
|
||||
return dev_err_probe(dev, err, "Failed to add counter\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(devm_i8254_regmap_register, I8254);
|
||||
|
||||
MODULE_AUTHOR("William Breathitt Gray");
|
||||
MODULE_DESCRIPTION("Intel 8254 Programmable Interval Timer");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_IMPORT_NS(COUNTER);
|
|
@ -342,6 +342,9 @@ static int stm32_timer_cnt_probe(struct platform_device *pdev)
|
|||
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
/* Reset input selector to its default input */
|
||||
regmap_write(priv->regmap, TIM_TISEL, 0x0);
|
||||
|
||||
/* Register Counter device */
|
||||
ret = devm_counter_add(dev, counter);
|
||||
if (ret < 0)
|
||||
|
|
|
@ -185,6 +185,7 @@ config EXTCON_USBC_TUSB320
|
|||
tristate "TI TUSB320 USB-C extcon support"
|
||||
depends on I2C && TYPEC
|
||||
select REGMAP_I2C
|
||||
depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH
|
||||
help
|
||||
Say Y here to enable support for USB Type C cable detection extcon
|
||||
support using a TUSB320.
|
||||
|
|
|
@ -393,7 +393,7 @@ static int axp288_extcon_probe(struct platform_device *pdev)
|
|||
adev = acpi_dev_get_first_match_dev("INT3496", NULL, -1);
|
||||
if (adev) {
|
||||
info->id_extcon = extcon_get_extcon_dev(acpi_dev_name(adev));
|
||||
put_device(&adev->dev);
|
||||
acpi_dev_put(adev);
|
||||
if (IS_ERR(info->id_extcon))
|
||||
return PTR_ERR(info->id_extcon);
|
||||
|
||||
|
|
|
@ -369,7 +369,7 @@ static struct i2c_driver fsa9480_i2c_driver = {
|
|||
.pm = &fsa9480_pm_ops,
|
||||
.of_match_table = fsa9480_of_match,
|
||||
},
|
||||
.probe_new = fsa9480_probe,
|
||||
.probe = fsa9480_probe,
|
||||
.id_table = fsa9480_id,
|
||||
};
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include <linux/mfd/palmas.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
|
|
|
@ -348,7 +348,7 @@ static struct i2c_driver ptn5150_i2c_driver = {
|
|||
.name = "ptn5150",
|
||||
.of_match_table = ptn5150_dt_match,
|
||||
},
|
||||
.probe_new = ptn5150_i2c_probe,
|
||||
.probe = ptn5150_i2c_probe,
|
||||
.id_table = ptn5150_i2c_id,
|
||||
};
|
||||
module_i2c_driver(ptn5150_i2c_driver);
|
||||
|
|
|
@ -123,7 +123,7 @@ static int qcom_usb_extcon_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
info->id_irq = platform_get_irq_byname(pdev, "usb_id");
|
||||
info->id_irq = platform_get_irq_byname_optional(pdev, "usb_id");
|
||||
if (info->id_irq > 0) {
|
||||
ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
|
||||
qcom_usb_irq_handler,
|
||||
|
@ -136,7 +136,7 @@ static int qcom_usb_extcon_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
info->vbus_irq = platform_get_irq_byname(pdev, "usb_vbus");
|
||||
info->vbus_irq = platform_get_irq_byname_optional(pdev, "usb_vbus");
|
||||
if (info->vbus_irq > 0) {
|
||||
ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL,
|
||||
qcom_usb_irq_handler,
|
||||
|
|
|
@ -695,7 +695,7 @@ static struct i2c_driver rt8973a_muic_i2c_driver = {
|
|||
.pm = &rt8973a_muic_pm_ops,
|
||||
.of_match_table = rt8973a_dt_match,
|
||||
},
|
||||
.probe_new = rt8973a_muic_i2c_probe,
|
||||
.probe = rt8973a_muic_i2c_probe,
|
||||
.remove = rt8973a_muic_i2c_remove,
|
||||
.id_table = rt8973a_i2c_id,
|
||||
};
|
||||
|
|
|
@ -840,7 +840,7 @@ static struct i2c_driver sm5502_muic_i2c_driver = {
|
|||
.pm = &sm5502_muic_pm_ops,
|
||||
.of_match_table = sm5502_dt_match,
|
||||
},
|
||||
.probe_new = sm5022_muic_i2c_probe,
|
||||
.probe = sm5022_muic_i2c_probe,
|
||||
.id_table = sm5502_i2c_id,
|
||||
};
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/usb/typec.h>
|
||||
#include <linux/usb/typec_altmode.h>
|
||||
#include <linux/usb/role.h>
|
||||
|
||||
#define TUSB320_REG8 0x8
|
||||
#define TUSB320_REG8_CURRENT_MODE_ADVERTISE GENMASK(7, 6)
|
||||
|
@ -26,16 +28,16 @@
|
|||
#define TUSB320_REG8_CURRENT_MODE_DETECT_MED 0x1
|
||||
#define TUSB320_REG8_CURRENT_MODE_DETECT_ACC 0x2
|
||||
#define TUSB320_REG8_CURRENT_MODE_DETECT_HI 0x3
|
||||
#define TUSB320_REG8_ACCESSORY_CONNECTED GENMASK(3, 2)
|
||||
#define TUSB320_REG8_ACCESSORY_CONNECTED GENMASK(3, 1)
|
||||
#define TUSB320_REG8_ACCESSORY_CONNECTED_NONE 0x0
|
||||
#define TUSB320_REG8_ACCESSORY_CONNECTED_AUDIO 0x4
|
||||
#define TUSB320_REG8_ACCESSORY_CONNECTED_ACC 0x5
|
||||
#define TUSB320_REG8_ACCESSORY_CONNECTED_DEBUG 0x6
|
||||
#define TUSB320_REG8_ACCESSORY_CONNECTED_ACHRG 0x5
|
||||
#define TUSB320_REG8_ACCESSORY_CONNECTED_DBGDFP 0x6
|
||||
#define TUSB320_REG8_ACCESSORY_CONNECTED_DBGUFP 0x7
|
||||
#define TUSB320_REG8_ACTIVE_CABLE_DETECTION BIT(0)
|
||||
|
||||
#define TUSB320_REG9 0x9
|
||||
#define TUSB320_REG9_ATTACHED_STATE_SHIFT 6
|
||||
#define TUSB320_REG9_ATTACHED_STATE_MASK 0x3
|
||||
#define TUSB320_REG9_ATTACHED_STATE GENMASK(7, 6)
|
||||
#define TUSB320_REG9_CABLE_DIRECTION BIT(5)
|
||||
#define TUSB320_REG9_INTERRUPT_STATUS BIT(4)
|
||||
|
||||
|
@ -78,6 +80,8 @@ struct tusb320_priv {
|
|||
struct typec_capability cap;
|
||||
enum typec_port_type port_type;
|
||||
enum typec_pwr_opmode pwr_opmode;
|
||||
struct fwnode_handle *connector_fwnode;
|
||||
struct usb_role_switch *role_sw;
|
||||
};
|
||||
|
||||
static const char * const tusb_attached_states[] = {
|
||||
|
@ -249,8 +253,7 @@ static void tusb320_extcon_irq_handler(struct tusb320_priv *priv, u8 reg)
|
|||
{
|
||||
int state, polarity;
|
||||
|
||||
state = (reg >> TUSB320_REG9_ATTACHED_STATE_SHIFT) &
|
||||
TUSB320_REG9_ATTACHED_STATE_MASK;
|
||||
state = FIELD_GET(TUSB320_REG9_ATTACHED_STATE, reg);
|
||||
polarity = !!(reg & TUSB320_REG9_CABLE_DIRECTION);
|
||||
|
||||
dev_dbg(priv->dev, "attached state: %s, polarity: %d\n",
|
||||
|
@ -276,32 +279,86 @@ static void tusb320_typec_irq_handler(struct tusb320_priv *priv, u8 reg9)
|
|||
{
|
||||
struct typec_port *port = priv->port;
|
||||
struct device *dev = priv->dev;
|
||||
u8 mode, role, state;
|
||||
int typec_mode;
|
||||
enum usb_role usb_role;
|
||||
enum typec_role pwr_role;
|
||||
enum typec_data_role data_role;
|
||||
u8 state, mode, accessory;
|
||||
int ret, reg8;
|
||||
bool ori;
|
||||
|
||||
ori = reg9 & TUSB320_REG9_CABLE_DIRECTION;
|
||||
typec_set_orientation(port, ori ? TYPEC_ORIENTATION_REVERSE :
|
||||
TYPEC_ORIENTATION_NORMAL);
|
||||
|
||||
state = (reg9 >> TUSB320_REG9_ATTACHED_STATE_SHIFT) &
|
||||
TUSB320_REG9_ATTACHED_STATE_MASK;
|
||||
if (state == TUSB320_ATTACHED_STATE_DFP)
|
||||
role = TYPEC_SOURCE;
|
||||
else
|
||||
role = TYPEC_SINK;
|
||||
|
||||
typec_set_vconn_role(port, role);
|
||||
typec_set_pwr_role(port, role);
|
||||
typec_set_data_role(port, role == TYPEC_SOURCE ?
|
||||
TYPEC_HOST : TYPEC_DEVICE);
|
||||
|
||||
ret = regmap_read(priv->regmap, TUSB320_REG8, ®8);
|
||||
if (ret) {
|
||||
dev_err(dev, "error during reg8 i2c read, ret=%d!\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ori = reg9 & TUSB320_REG9_CABLE_DIRECTION;
|
||||
typec_set_orientation(port, ori ? TYPEC_ORIENTATION_REVERSE :
|
||||
TYPEC_ORIENTATION_NORMAL);
|
||||
|
||||
state = FIELD_GET(TUSB320_REG9_ATTACHED_STATE, reg9);
|
||||
accessory = FIELD_GET(TUSB320_REG8_ACCESSORY_CONNECTED, reg8);
|
||||
|
||||
switch (state) {
|
||||
case TUSB320_ATTACHED_STATE_DFP:
|
||||
typec_mode = TYPEC_MODE_USB2;
|
||||
usb_role = USB_ROLE_HOST;
|
||||
pwr_role = TYPEC_SOURCE;
|
||||
data_role = TYPEC_HOST;
|
||||
break;
|
||||
case TUSB320_ATTACHED_STATE_UFP:
|
||||
typec_mode = TYPEC_MODE_USB2;
|
||||
usb_role = USB_ROLE_DEVICE;
|
||||
pwr_role = TYPEC_SINK;
|
||||
data_role = TYPEC_DEVICE;
|
||||
break;
|
||||
case TUSB320_ATTACHED_STATE_ACC:
|
||||
/*
|
||||
* Accessory detected. For debug accessories, just make some
|
||||
* qualified guesses as to the role for lack of a better option.
|
||||
*/
|
||||
if (accessory == TUSB320_REG8_ACCESSORY_CONNECTED_AUDIO ||
|
||||
accessory == TUSB320_REG8_ACCESSORY_CONNECTED_ACHRG) {
|
||||
typec_mode = TYPEC_MODE_AUDIO;
|
||||
usb_role = USB_ROLE_NONE;
|
||||
pwr_role = TYPEC_SINK;
|
||||
data_role = TYPEC_DEVICE;
|
||||
break;
|
||||
} else if (accessory ==
|
||||
TUSB320_REG8_ACCESSORY_CONNECTED_DBGDFP) {
|
||||
typec_mode = TYPEC_MODE_DEBUG;
|
||||
pwr_role = TYPEC_SOURCE;
|
||||
usb_role = USB_ROLE_HOST;
|
||||
data_role = TYPEC_HOST;
|
||||
break;
|
||||
} else if (accessory ==
|
||||
TUSB320_REG8_ACCESSORY_CONNECTED_DBGUFP) {
|
||||
typec_mode = TYPEC_MODE_DEBUG;
|
||||
pwr_role = TYPEC_SINK;
|
||||
usb_role = USB_ROLE_DEVICE;
|
||||
data_role = TYPEC_DEVICE;
|
||||
break;
|
||||
}
|
||||
|
||||
dev_warn(priv->dev, "unexpected ACCESSORY_CONNECTED state %d\n",
|
||||
accessory);
|
||||
|
||||
fallthrough;
|
||||
default:
|
||||
typec_mode = TYPEC_MODE_USB2;
|
||||
usb_role = USB_ROLE_NONE;
|
||||
pwr_role = TYPEC_SINK;
|
||||
data_role = TYPEC_DEVICE;
|
||||
break;
|
||||
}
|
||||
|
||||
typec_set_vconn_role(port, pwr_role);
|
||||
typec_set_pwr_role(port, pwr_role);
|
||||
typec_set_data_role(port, data_role);
|
||||
typec_set_mode(port, typec_mode);
|
||||
usb_role_switch_set_role(priv->role_sw, usb_role);
|
||||
|
||||
mode = FIELD_GET(TUSB320_REG8_CURRENT_MODE_DETECT, reg8);
|
||||
if (mode == TUSB320_REG8_CURRENT_MODE_DETECT_DEF)
|
||||
typec_set_pwr_opmode(port, TYPEC_PWR_MODE_USB);
|
||||
|
@ -391,27 +448,25 @@ static int tusb320_typec_probe(struct i2c_client *client,
|
|||
/* Type-C connector found. */
|
||||
ret = typec_get_fw_cap(&priv->cap, connector);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_put;
|
||||
|
||||
priv->port_type = priv->cap.type;
|
||||
|
||||
/* This goes into register 0x8 field CURRENT_MODE_ADVERTISE */
|
||||
ret = fwnode_property_read_string(connector, "typec-power-opmode", &cap_str);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_put;
|
||||
|
||||
ret = typec_find_pwr_opmode(cap_str);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret == TYPEC_PWR_MODE_PD)
|
||||
return -EINVAL;
|
||||
goto err_put;
|
||||
|
||||
priv->pwr_opmode = ret;
|
||||
|
||||
/* Initialize the hardware with the devicetree settings. */
|
||||
ret = tusb320_set_adv_pwr_mode(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_put;
|
||||
|
||||
priv->cap.revision = USB_TYPEC_REV_1_1;
|
||||
priv->cap.accessory[0] = TYPEC_ACCESSORY_AUDIO;
|
||||
|
@ -422,10 +477,36 @@ static int tusb320_typec_probe(struct i2c_client *client,
|
|||
priv->cap.fwnode = connector;
|
||||
|
||||
priv->port = typec_register_port(&client->dev, &priv->cap);
|
||||
if (IS_ERR(priv->port))
|
||||
return PTR_ERR(priv->port);
|
||||
if (IS_ERR(priv->port)) {
|
||||
ret = PTR_ERR(priv->port);
|
||||
goto err_put;
|
||||
}
|
||||
|
||||
/* Find any optional USB role switch that needs reporting to */
|
||||
priv->role_sw = fwnode_usb_role_switch_get(connector);
|
||||
if (IS_ERR(priv->role_sw)) {
|
||||
ret = PTR_ERR(priv->role_sw);
|
||||
goto err_unreg;
|
||||
}
|
||||
|
||||
priv->connector_fwnode = connector;
|
||||
|
||||
return 0;
|
||||
|
||||
err_unreg:
|
||||
typec_unregister_port(priv->port);
|
||||
|
||||
err_put:
|
||||
fwnode_handle_put(connector);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void tusb320_typec_remove(struct tusb320_priv *priv)
|
||||
{
|
||||
usb_role_switch_put(priv->role_sw);
|
||||
typec_unregister_port(priv->port);
|
||||
fwnode_handle_put(priv->connector_fwnode);
|
||||
}
|
||||
|
||||
static int tusb320_probe(struct i2c_client *client)
|
||||
|
@ -438,7 +519,9 @@ static int tusb320_probe(struct i2c_client *client)
|
|||
priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->dev = &client->dev;
|
||||
i2c_set_clientdata(client, priv);
|
||||
|
||||
priv->regmap = devm_regmap_init_i2c(client, &tusb320_regmap_config);
|
||||
if (IS_ERR(priv->regmap))
|
||||
|
@ -489,10 +572,19 @@ static int tusb320_probe(struct i2c_client *client)
|
|||
tusb320_irq_handler,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
client->name, priv);
|
||||
if (ret)
|
||||
tusb320_typec_remove(priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void tusb320_remove(struct i2c_client *client)
|
||||
{
|
||||
struct tusb320_priv *priv = i2c_get_clientdata(client);
|
||||
|
||||
tusb320_typec_remove(priv);
|
||||
}
|
||||
|
||||
static const struct of_device_id tusb320_extcon_dt_match[] = {
|
||||
{ .compatible = "ti,tusb320", .data = &tusb320_ops, },
|
||||
{ .compatible = "ti,tusb320l", .data = &tusb320l_ops, },
|
||||
|
@ -501,7 +593,8 @@ static const struct of_device_id tusb320_extcon_dt_match[] = {
|
|||
MODULE_DEVICE_TABLE(of, tusb320_extcon_dt_match);
|
||||
|
||||
static struct i2c_driver tusb320_extcon_driver = {
|
||||
.probe_new = tusb320_probe,
|
||||
.probe = tusb320_probe,
|
||||
.remove = tusb320_remove,
|
||||
.driver = {
|
||||
.name = "extcon-tusb320",
|
||||
.of_match_table = tusb320_extcon_dt_match,
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/fs.h>
|
||||
|
@ -206,6 +207,14 @@ static const struct __extcon_info {
|
|||
* @attr_name: "name" sysfs entry
|
||||
* @attr_state: "state" sysfs entry
|
||||
* @attrs: the array pointing to attr_name and attr_state for attr_g
|
||||
* @usb_propval: the array of USB connector properties
|
||||
* @chg_propval: the array of charger connector properties
|
||||
* @jack_propval: the array of jack connector properties
|
||||
* @disp_propval: the array of display connector properties
|
||||
* @usb_bits: the bit array of the USB connector property capabilities
|
||||
* @chg_bits: the bit array of the charger connector property capabilities
|
||||
* @jack_bits: the bit array of the jack connector property capabilities
|
||||
* @disp_bits: the bit array of the display connector property capabilities
|
||||
*/
|
||||
struct extcon_cable {
|
||||
struct extcon_dev *edev;
|
||||
|
@ -222,20 +231,21 @@ struct extcon_cable {
|
|||
union extcon_property_value jack_propval[EXTCON_PROP_JACK_CNT];
|
||||
union extcon_property_value disp_propval[EXTCON_PROP_DISP_CNT];
|
||||
|
||||
unsigned long usb_bits[BITS_TO_LONGS(EXTCON_PROP_USB_CNT)];
|
||||
unsigned long chg_bits[BITS_TO_LONGS(EXTCON_PROP_CHG_CNT)];
|
||||
unsigned long jack_bits[BITS_TO_LONGS(EXTCON_PROP_JACK_CNT)];
|
||||
unsigned long disp_bits[BITS_TO_LONGS(EXTCON_PROP_DISP_CNT)];
|
||||
DECLARE_BITMAP(usb_bits, EXTCON_PROP_USB_CNT);
|
||||
DECLARE_BITMAP(chg_bits, EXTCON_PROP_CHG_CNT);
|
||||
DECLARE_BITMAP(jack_bits, EXTCON_PROP_JACK_CNT);
|
||||
DECLARE_BITMAP(disp_bits, EXTCON_PROP_DISP_CNT);
|
||||
};
|
||||
|
||||
static struct class *extcon_class;
|
||||
|
||||
static DEFINE_IDA(extcon_dev_ids);
|
||||
static LIST_HEAD(extcon_dev_list);
|
||||
static DEFINE_MUTEX(extcon_dev_list_lock);
|
||||
|
||||
static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state)
|
||||
{
|
||||
int i = 0;
|
||||
int i;
|
||||
|
||||
if (!edev->mutually_exclusive)
|
||||
return 0;
|
||||
|
@ -362,12 +372,12 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr,
|
|||
struct extcon_dev *edev = dev_get_drvdata(dev);
|
||||
|
||||
if (edev->max_supported == 0)
|
||||
return sprintf(buf, "%u\n", edev->state);
|
||||
return sysfs_emit(buf, "%u\n", edev->state);
|
||||
|
||||
for (i = 0; i < edev->max_supported; i++) {
|
||||
count += sprintf(buf + count, "%s=%d\n",
|
||||
extcon_info[edev->supported_cable[i]].name,
|
||||
!!(edev->state & BIT(i)));
|
||||
count += sysfs_emit_at(buf, count, "%s=%d\n",
|
||||
extcon_info[edev->supported_cable[i]].name,
|
||||
!!(edev->state & BIT(i)));
|
||||
}
|
||||
|
||||
return count;
|
||||
|
@ -379,7 +389,7 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr,
|
|||
{
|
||||
struct extcon_dev *edev = dev_get_drvdata(dev);
|
||||
|
||||
return sprintf(buf, "%s\n", edev->name);
|
||||
return sysfs_emit(buf, "%s\n", edev->name);
|
||||
}
|
||||
static DEVICE_ATTR_RO(name);
|
||||
|
||||
|
@ -390,8 +400,8 @@ static ssize_t cable_name_show(struct device *dev,
|
|||
attr_name);
|
||||
int i = cable->cable_index;
|
||||
|
||||
return sprintf(buf, "%s\n",
|
||||
extcon_info[cable->edev->supported_cable[i]].name);
|
||||
return sysfs_emit(buf, "%s\n",
|
||||
extcon_info[cable->edev->supported_cable[i]].name);
|
||||
}
|
||||
|
||||
static ssize_t cable_state_show(struct device *dev,
|
||||
|
@ -402,8 +412,8 @@ static ssize_t cable_state_show(struct device *dev,
|
|||
|
||||
int i = cable->cable_index;
|
||||
|
||||
return sprintf(buf, "%d\n",
|
||||
extcon_get_state(cable->edev, cable->edev->supported_cable[i]));
|
||||
return sysfs_emit(buf, "%d\n",
|
||||
extcon_get_state(cable->edev, cable->edev->supported_cable[i]));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1012,12 +1022,13 @@ ATTRIBUTE_GROUPS(extcon);
|
|||
|
||||
static int create_extcon_class(void)
|
||||
{
|
||||
if (!extcon_class) {
|
||||
extcon_class = class_create("extcon");
|
||||
if (IS_ERR(extcon_class))
|
||||
return PTR_ERR(extcon_class);
|
||||
extcon_class->dev_groups = extcon_groups;
|
||||
}
|
||||
if (extcon_class)
|
||||
return 0;
|
||||
|
||||
extcon_class = class_create("extcon");
|
||||
if (IS_ERR(extcon_class))
|
||||
return PTR_ERR(extcon_class);
|
||||
extcon_class->dev_groups = extcon_groups;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1069,6 +1080,156 @@ void extcon_dev_free(struct extcon_dev *edev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(extcon_dev_free);
|
||||
|
||||
/**
|
||||
* extcon_alloc_cables() - alloc the cables for extcon device
|
||||
* @edev: extcon device which has cables
|
||||
*
|
||||
* Returns 0 if success or error number if fail.
|
||||
*/
|
||||
static int extcon_alloc_cables(struct extcon_dev *edev)
|
||||
{
|
||||
int index;
|
||||
char *str;
|
||||
struct extcon_cable *cable;
|
||||
|
||||
if (!edev)
|
||||
return -EINVAL;
|
||||
|
||||
if (!edev->max_supported)
|
||||
return 0;
|
||||
|
||||
edev->cables = kcalloc(edev->max_supported, sizeof(*edev->cables),
|
||||
GFP_KERNEL);
|
||||
if (!edev->cables)
|
||||
return -ENOMEM;
|
||||
|
||||
for (index = 0; index < edev->max_supported; index++) {
|
||||
cable = &edev->cables[index];
|
||||
|
||||
str = kasprintf(GFP_KERNEL, "cable.%d", index);
|
||||
if (!str) {
|
||||
for (index--; index >= 0; index--) {
|
||||
cable = &edev->cables[index];
|
||||
kfree(cable->attr_g.name);
|
||||
}
|
||||
|
||||
kfree(edev->cables);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cable->edev = edev;
|
||||
cable->cable_index = index;
|
||||
cable->attrs[0] = &cable->attr_name.attr;
|
||||
cable->attrs[1] = &cable->attr_state.attr;
|
||||
cable->attrs[2] = NULL;
|
||||
cable->attr_g.name = str;
|
||||
cable->attr_g.attrs = cable->attrs;
|
||||
|
||||
sysfs_attr_init(&cable->attr_name.attr);
|
||||
cable->attr_name.attr.name = "name";
|
||||
cable->attr_name.attr.mode = 0444;
|
||||
cable->attr_name.show = cable_name_show;
|
||||
|
||||
sysfs_attr_init(&cable->attr_state.attr);
|
||||
cable->attr_state.attr.name = "state";
|
||||
cable->attr_state.attr.mode = 0444;
|
||||
cable->attr_state.show = cable_state_show;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* extcon_alloc_muex() - alloc the mutual exclusive for extcon device
|
||||
* @edev: extcon device
|
||||
*
|
||||
* Returns 0 if success or error number if fail.
|
||||
*/
|
||||
static int extcon_alloc_muex(struct extcon_dev *edev)
|
||||
{
|
||||
char *name;
|
||||
int index;
|
||||
|
||||
if (!edev)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(edev->max_supported && edev->mutually_exclusive))
|
||||
return 0;
|
||||
|
||||
/* Count the size of mutually_exclusive array */
|
||||
for (index = 0; edev->mutually_exclusive[index]; index++)
|
||||
;
|
||||
|
||||
edev->attrs_muex = kcalloc(index + 1, sizeof(*edev->attrs_muex),
|
||||
GFP_KERNEL);
|
||||
if (!edev->attrs_muex)
|
||||
return -ENOMEM;
|
||||
|
||||
edev->d_attrs_muex = kcalloc(index, sizeof(*edev->d_attrs_muex),
|
||||
GFP_KERNEL);
|
||||
if (!edev->d_attrs_muex) {
|
||||
kfree(edev->attrs_muex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (index = 0; edev->mutually_exclusive[index]; index++) {
|
||||
name = kasprintf(GFP_KERNEL, "0x%x",
|
||||
edev->mutually_exclusive[index]);
|
||||
if (!name) {
|
||||
for (index--; index >= 0; index--)
|
||||
kfree(edev->d_attrs_muex[index].attr.name);
|
||||
|
||||
kfree(edev->d_attrs_muex);
|
||||
kfree(edev->attrs_muex);
|
||||
return -ENOMEM;
|
||||
}
|
||||
sysfs_attr_init(&edev->d_attrs_muex[index].attr);
|
||||
edev->d_attrs_muex[index].attr.name = name;
|
||||
edev->d_attrs_muex[index].attr.mode = 0000;
|
||||
edev->attrs_muex[index] = &edev->d_attrs_muex[index].attr;
|
||||
}
|
||||
edev->attr_g_muex.name = muex_name;
|
||||
edev->attr_g_muex.attrs = edev->attrs_muex;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* extcon_alloc_groups() - alloc the groups for extcon device
|
||||
* @edev: extcon device
|
||||
*
|
||||
* Returns 0 if success or error number if fail.
|
||||
*/
|
||||
static int extcon_alloc_groups(struct extcon_dev *edev)
|
||||
{
|
||||
int index;
|
||||
|
||||
if (!edev)
|
||||
return -EINVAL;
|
||||
|
||||
if (!edev->max_supported)
|
||||
return 0;
|
||||
|
||||
edev->extcon_dev_type.groups = kcalloc(edev->max_supported + 2,
|
||||
sizeof(*edev->extcon_dev_type.groups),
|
||||
GFP_KERNEL);
|
||||
if (!edev->extcon_dev_type.groups)
|
||||
return -ENOMEM;
|
||||
|
||||
edev->extcon_dev_type.name = dev_name(&edev->dev);
|
||||
edev->extcon_dev_type.release = dummy_sysfs_dev_release;
|
||||
|
||||
for (index = 0; index < edev->max_supported; index++)
|
||||
edev->extcon_dev_type.groups[index] = &edev->cables[index].attr_g;
|
||||
|
||||
if (edev->mutually_exclusive)
|
||||
edev->extcon_dev_type.groups[index] = &edev->attr_g_muex;
|
||||
|
||||
edev->dev.type = &edev->extcon_dev_type;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* extcon_dev_register() - Register an new extcon device
|
||||
* @edev: the extcon device to be registered
|
||||
|
@ -1085,19 +1246,16 @@ EXPORT_SYMBOL_GPL(extcon_dev_free);
|
|||
*/
|
||||
int extcon_dev_register(struct extcon_dev *edev)
|
||||
{
|
||||
int ret, index = 0;
|
||||
static atomic_t edev_no = ATOMIC_INIT(-1);
|
||||
int ret, index;
|
||||
|
||||
if (!extcon_class) {
|
||||
ret = create_extcon_class();
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
ret = create_extcon_class();
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!edev || !edev->supported_cable)
|
||||
return -EINVAL;
|
||||
|
||||
for (; edev->supported_cable[index] != EXTCON_NONE; index++);
|
||||
for (index = 0; edev->supported_cable[index] != EXTCON_NONE; index++);
|
||||
|
||||
edev->max_supported = index;
|
||||
if (index > SUPPORTED_CABLE_MAX) {
|
||||
|
@ -1115,124 +1273,26 @@ int extcon_dev_register(struct extcon_dev *edev)
|
|||
"extcon device name is null\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
dev_set_name(&edev->dev, "extcon%lu",
|
||||
(unsigned long)atomic_inc_return(&edev_no));
|
||||
|
||||
if (edev->max_supported) {
|
||||
char *str;
|
||||
struct extcon_cable *cable;
|
||||
ret = ida_alloc(&extcon_dev_ids, GFP_KERNEL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
edev->cables = kcalloc(edev->max_supported,
|
||||
sizeof(struct extcon_cable),
|
||||
GFP_KERNEL);
|
||||
if (!edev->cables) {
|
||||
ret = -ENOMEM;
|
||||
goto err_sysfs_alloc;
|
||||
}
|
||||
for (index = 0; index < edev->max_supported; index++) {
|
||||
cable = &edev->cables[index];
|
||||
edev->id = ret;
|
||||
|
||||
str = kasprintf(GFP_KERNEL, "cable.%d", index);
|
||||
if (!str) {
|
||||
for (index--; index >= 0; index--) {
|
||||
cable = &edev->cables[index];
|
||||
kfree(cable->attr_g.name);
|
||||
}
|
||||
ret = -ENOMEM;
|
||||
dev_set_name(&edev->dev, "extcon%d", edev->id);
|
||||
|
||||
goto err_alloc_cables;
|
||||
}
|
||||
ret = extcon_alloc_cables(edev);
|
||||
if (ret < 0)
|
||||
goto err_alloc_cables;
|
||||
|
||||
cable->edev = edev;
|
||||
cable->cable_index = index;
|
||||
cable->attrs[0] = &cable->attr_name.attr;
|
||||
cable->attrs[1] = &cable->attr_state.attr;
|
||||
cable->attrs[2] = NULL;
|
||||
cable->attr_g.name = str;
|
||||
cable->attr_g.attrs = cable->attrs;
|
||||
ret = extcon_alloc_muex(edev);
|
||||
if (ret < 0)
|
||||
goto err_alloc_muex;
|
||||
|
||||
sysfs_attr_init(&cable->attr_name.attr);
|
||||
cable->attr_name.attr.name = "name";
|
||||
cable->attr_name.attr.mode = 0444;
|
||||
cable->attr_name.show = cable_name_show;
|
||||
|
||||
sysfs_attr_init(&cable->attr_state.attr);
|
||||
cable->attr_state.attr.name = "state";
|
||||
cable->attr_state.attr.mode = 0444;
|
||||
cable->attr_state.show = cable_state_show;
|
||||
}
|
||||
}
|
||||
|
||||
if (edev->max_supported && edev->mutually_exclusive) {
|
||||
char *name;
|
||||
|
||||
/* Count the size of mutually_exclusive array */
|
||||
for (index = 0; edev->mutually_exclusive[index]; index++)
|
||||
;
|
||||
|
||||
edev->attrs_muex = kcalloc(index + 1,
|
||||
sizeof(struct attribute *),
|
||||
GFP_KERNEL);
|
||||
if (!edev->attrs_muex) {
|
||||
ret = -ENOMEM;
|
||||
goto err_muex;
|
||||
}
|
||||
|
||||
edev->d_attrs_muex = kcalloc(index,
|
||||
sizeof(struct device_attribute),
|
||||
GFP_KERNEL);
|
||||
if (!edev->d_attrs_muex) {
|
||||
ret = -ENOMEM;
|
||||
kfree(edev->attrs_muex);
|
||||
goto err_muex;
|
||||
}
|
||||
|
||||
for (index = 0; edev->mutually_exclusive[index]; index++) {
|
||||
name = kasprintf(GFP_KERNEL, "0x%x",
|
||||
edev->mutually_exclusive[index]);
|
||||
if (!name) {
|
||||
for (index--; index >= 0; index--) {
|
||||
kfree(edev->d_attrs_muex[index].attr.
|
||||
name);
|
||||
}
|
||||
kfree(edev->d_attrs_muex);
|
||||
kfree(edev->attrs_muex);
|
||||
ret = -ENOMEM;
|
||||
goto err_muex;
|
||||
}
|
||||
sysfs_attr_init(&edev->d_attrs_muex[index].attr);
|
||||
edev->d_attrs_muex[index].attr.name = name;
|
||||
edev->d_attrs_muex[index].attr.mode = 0000;
|
||||
edev->attrs_muex[index] = &edev->d_attrs_muex[index]
|
||||
.attr;
|
||||
}
|
||||
edev->attr_g_muex.name = muex_name;
|
||||
edev->attr_g_muex.attrs = edev->attrs_muex;
|
||||
|
||||
}
|
||||
|
||||
if (edev->max_supported) {
|
||||
edev->extcon_dev_type.groups =
|
||||
kcalloc(edev->max_supported + 2,
|
||||
sizeof(struct attribute_group *),
|
||||
GFP_KERNEL);
|
||||
if (!edev->extcon_dev_type.groups) {
|
||||
ret = -ENOMEM;
|
||||
goto err_alloc_groups;
|
||||
}
|
||||
|
||||
edev->extcon_dev_type.name = dev_name(&edev->dev);
|
||||
edev->extcon_dev_type.release = dummy_sysfs_dev_release;
|
||||
|
||||
for (index = 0; index < edev->max_supported; index++)
|
||||
edev->extcon_dev_type.groups[index] =
|
||||
&edev->cables[index].attr_g;
|
||||
if (edev->mutually_exclusive)
|
||||
edev->extcon_dev_type.groups[index] =
|
||||
&edev->attr_g_muex;
|
||||
|
||||
edev->dev.type = &edev->extcon_dev_type;
|
||||
}
|
||||
ret = extcon_alloc_groups(edev);
|
||||
if (ret < 0)
|
||||
goto err_alloc_groups;
|
||||
|
||||
spin_lock_init(&edev->lock);
|
||||
if (edev->max_supported) {
|
||||
|
@ -1277,13 +1337,14 @@ err_alloc_groups:
|
|||
kfree(edev->d_attrs_muex);
|
||||
kfree(edev->attrs_muex);
|
||||
}
|
||||
err_muex:
|
||||
err_alloc_muex:
|
||||
for (index = 0; index < edev->max_supported; index++)
|
||||
kfree(edev->cables[index].attr_g.name);
|
||||
err_alloc_cables:
|
||||
if (edev->max_supported)
|
||||
kfree(edev->cables);
|
||||
err_sysfs_alloc:
|
||||
err_alloc_cables:
|
||||
ida_free(&extcon_dev_ids, edev->id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(extcon_dev_register);
|
||||
|
@ -1306,12 +1367,13 @@ void extcon_dev_unregister(struct extcon_dev *edev)
|
|||
list_del(&edev->entry);
|
||||
mutex_unlock(&extcon_dev_list_lock);
|
||||
|
||||
if (IS_ERR_OR_NULL(get_device(&edev->dev))) {
|
||||
dev_err(&edev->dev, "Failed to unregister extcon_dev (%s)\n",
|
||||
dev_name(&edev->dev));
|
||||
if (!get_device(&edev->dev)) {
|
||||
dev_err(&edev->dev, "Failed to unregister extcon_dev\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ida_free(&extcon_dev_ids, edev->id);
|
||||
|
||||
device_unregister(&edev->dev);
|
||||
|
||||
if (edev->mutually_exclusive && edev->max_supported) {
|
||||
|
@ -1349,7 +1411,7 @@ struct extcon_dev *extcon_find_edev_by_node(struct device_node *node)
|
|||
|
||||
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)
|
||||
if (edev->dev.parent && device_match_of_node(edev->dev.parent, node))
|
||||
goto out;
|
||||
edev = ERR_PTR(-EPROBE_DEFER);
|
||||
out:
|
||||
|
@ -1367,21 +1429,17 @@ out:
|
|||
*/
|
||||
struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
|
||||
{
|
||||
struct device_node *node;
|
||||
struct device_node *node, *np = dev_of_node(dev);
|
||||
struct extcon_dev *edev;
|
||||
|
||||
if (!dev)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (!dev->of_node) {
|
||||
if (!np) {
|
||||
dev_dbg(dev, "device does not have a device node entry\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
node = of_parse_phandle(dev->of_node, "extcon", index);
|
||||
node = of_parse_phandle(np, "extcon", index);
|
||||
if (!node) {
|
||||
dev_dbg(dev, "failed to get phandle in %pOF node\n",
|
||||
dev->of_node);
|
||||
dev_dbg(dev, "failed to get phandle in %pOF node\n", np);
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,13 +13,14 @@
|
|||
* are disabled.
|
||||
* @mutually_exclusive: Array of mutually exclusive set of cables that cannot
|
||||
* be attached simultaneously. The array should be
|
||||
* ending with NULL or be NULL (no mutually exclusive
|
||||
* cables). For example, if it is { 0x7, 0x30, 0}, then,
|
||||
* ending with 0 or be NULL (no mutually exclusive cables).
|
||||
* For example, if it is {0x7, 0x30, 0}, then,
|
||||
* {0, 1}, {0, 1, 2}, {0, 2}, {1, 2}, or {4, 5} cannot
|
||||
* be attached simulataneously. {0x7, 0} is equivalent to
|
||||
* {0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there
|
||||
* can be no simultaneous connections.
|
||||
* @dev: Device of this extcon.
|
||||
* @id: Unique device ID of this extcon.
|
||||
* @state: Attach/detach state of this extcon. Do not provide at
|
||||
* register-time.
|
||||
* @nh_all: Notifier for the state change events for all supported
|
||||
|
@ -27,7 +28,7 @@
|
|||
* @nh: Notifier for the state change events from this extcon
|
||||
* @entry: To support list of extcon devices so that users can
|
||||
* search for extcon devices based on the extcon name.
|
||||
* @lock:
|
||||
* @lock: Protects device state and serialises device registration
|
||||
* @max_supported: Internal value to store the number of cables.
|
||||
* @extcon_dev_type: Device_type struct to provide attribute_groups
|
||||
* customized for each extcon device.
|
||||
|
@ -46,6 +47,7 @@ struct extcon_dev {
|
|||
|
||||
/* Internal data. Please do not set. */
|
||||
struct device dev;
|
||||
unsigned int id;
|
||||
struct raw_notifier_head nh_all;
|
||||
struct raw_notifier_head *nh;
|
||||
struct list_head entry;
|
||||
|
|
|
@ -310,6 +310,7 @@ static const struct kobj_type dmi_system_event_log_ktype = {
|
|||
.default_groups = dmi_sysfs_sel_groups,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_HAS_IOPORT
|
||||
typedef u8 (*sel_io_reader)(const struct dmi_system_event_log *sel,
|
||||
loff_t offset);
|
||||
|
||||
|
@ -374,6 +375,7 @@ static ssize_t dmi_sel_raw_read_io(struct dmi_sysfs_entry *entry,
|
|||
|
||||
return wrote;
|
||||
}
|
||||
#endif
|
||||
|
||||
static ssize_t dmi_sel_raw_read_phys32(struct dmi_sysfs_entry *entry,
|
||||
const struct dmi_system_event_log *sel,
|
||||
|
@ -409,11 +411,13 @@ static ssize_t dmi_sel_raw_read_helper(struct dmi_sysfs_entry *entry,
|
|||
memcpy(&sel, dh, sizeof(sel));
|
||||
|
||||
switch (sel.access_method) {
|
||||
#ifdef CONFIG_HAS_IOPORT
|
||||
case DMI_SEL_ACCESS_METHOD_IO8:
|
||||
case DMI_SEL_ACCESS_METHOD_IO2x8:
|
||||
case DMI_SEL_ACCESS_METHOD_IO16:
|
||||
return dmi_sel_raw_read_io(entry, &sel, state->buf,
|
||||
state->pos, state->count);
|
||||
#endif
|
||||
case DMI_SEL_ACCESS_METHOD_PHYS32:
|
||||
return dmi_sel_raw_read_phys32(entry, &sel, state->buf,
|
||||
state->pos, state->count);
|
||||
|
|
|
@ -755,7 +755,7 @@ svc_create_memory_pool(struct platform_device *pdev,
|
|||
end = rounddown(sh_memory->addr + sh_memory->size, PAGE_SIZE);
|
||||
paddr = begin;
|
||||
size = end - begin;
|
||||
va = memremap(paddr, size, MEMREMAP_WC);
|
||||
va = devm_memremap(dev, paddr, size, MEMREMAP_WC);
|
||||
if (!va) {
|
||||
dev_err(dev, "fail to remap shared memory\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Copyright (C) 2014-2018 Xilinx, Inc.
|
||||
*
|
||||
* Michal Simek <michal.simek@xilinx.com>
|
||||
* Michal Simek <michal.simek@amd.com>
|
||||
* Davorin Mista <davorin.mista@aggios.com>
|
||||
* Jolly Shah <jollys@xilinx.com>
|
||||
* Rajan Vaja <rajanv@xilinx.com>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Copyright (C) 2014-2018 Xilinx
|
||||
*
|
||||
* Michal Simek <michal.simek@xilinx.com>
|
||||
* Michal Simek <michal.simek@amd.com>
|
||||
* Davorin Mista <davorin.mista@aggios.com>
|
||||
* Jolly Shah <jollys@xilinx.com>
|
||||
* Rajan Vaja <rajanv@xilinx.com>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Copyright (C) 2014-2022 Xilinx, Inc.
|
||||
*
|
||||
* Michal Simek <michal.simek@xilinx.com>
|
||||
* Michal Simek <michal.simek@amd.com>
|
||||
* Davorin Mista <davorin.mista@aggios.com>
|
||||
* Jolly Shah <jollys@xilinx.com>
|
||||
* Rajan Vaja <rajanv@xilinx.com>
|
||||
|
|
|
@ -265,7 +265,7 @@ static const struct hwmon_ops thermal_hwmon_ops = {
|
|||
.read = thermal_hwmon_read,
|
||||
};
|
||||
|
||||
static const struct hwmon_channel_info *thermal_hwmon_info[] = {
|
||||
static const struct hwmon_channel_info * const thermal_hwmon_info[] = {
|
||||
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_EMERGENCY |
|
||||
HWMON_T_MAX | HWMON_T_MAX_ALARM |
|
||||
HWMON_T_CRIT | HWMON_T_CRIT_ALARM),
|
||||
|
@ -465,7 +465,7 @@ static const struct hwmon_ops power_hwmon_ops = {
|
|||
.write = power_hwmon_write,
|
||||
};
|
||||
|
||||
static const struct hwmon_channel_info *power_hwmon_info[] = {
|
||||
static const struct hwmon_channel_info * const power_hwmon_info[] = {
|
||||
HWMON_CHANNEL_INFO(power, HWMON_P_INPUT |
|
||||
HWMON_P_MAX | HWMON_P_MAX_ALARM |
|
||||
HWMON_P_CRIT | HWMON_P_CRIT_ALARM),
|
||||
|
|
|
@ -493,15 +493,15 @@ static int zynq_fpga_ops_write_complete(struct fpga_manager *mgr,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
/* Release 'PR' control back to the ICAP */
|
||||
zynq_fpga_write(priv, CTRL_OFFSET,
|
||||
zynq_fpga_read(priv, CTRL_OFFSET) & ~CTRL_PCAP_PR_MASK);
|
||||
|
||||
err = zynq_fpga_poll_timeout(priv, INT_STS_OFFSET, intr_status,
|
||||
intr_status & IXR_PCFG_DONE_MASK,
|
||||
INIT_POLL_DELAY,
|
||||
INIT_POLL_TIMEOUT);
|
||||
|
||||
/* Release 'PR' control back to the ICAP */
|
||||
zynq_fpga_write(priv, CTRL_OFFSET,
|
||||
zynq_fpga_read(priv, CTRL_OFFSET) & ~CTRL_PCAP_PR_MASK);
|
||||
|
||||
clk_disable(priv->clk);
|
||||
|
||||
if (err)
|
||||
|
|
|
@ -236,4 +236,15 @@ config CORESIGHT_TPDA
|
|||
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called coresight-tpda.
|
||||
|
||||
config CORESIGHT_DUMMY
|
||||
tristate "Dummy driver support"
|
||||
help
|
||||
Enables support for dummy driver. Dummy driver can be used for
|
||||
CoreSight sources/sinks that are owned and configured by some
|
||||
other subsystem and use Linux drivers to configure rest of trace
|
||||
path.
|
||||
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called coresight-dummy.
|
||||
endif
|
||||
|
|
|
@ -30,3 +30,4 @@ obj-$(CONFIG_CORESIGHT_TPDA) += coresight-tpda.o
|
|||
coresight-cti-y := coresight-cti-core.o coresight-cti-platform.o \
|
||||
coresight-cti-sysfs.o
|
||||
obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
|
||||
obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
|
||||
|
|
|
@ -395,13 +395,18 @@ static inline int catu_wait_for_ready(struct catu_drvdata *drvdata)
|
|||
return coresight_timeout(csa, CATU_STATUS, CATU_STATUS_READY, 1);
|
||||
}
|
||||
|
||||
static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
|
||||
static int catu_enable_hw(struct catu_drvdata *drvdata, enum cs_mode cs_mode,
|
||||
void *data)
|
||||
{
|
||||
int rc;
|
||||
u32 control, mode;
|
||||
struct etr_buf *etr_buf = data;
|
||||
struct etr_buf *etr_buf = NULL;
|
||||
struct device *dev = &drvdata->csdev->dev;
|
||||
struct coresight_device *csdev = drvdata->csdev;
|
||||
struct coresight_device *etrdev;
|
||||
union coresight_dev_subtype etr_subtype = {
|
||||
.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM
|
||||
};
|
||||
|
||||
if (catu_wait_for_ready(drvdata))
|
||||
dev_warn(dev, "Timeout while waiting for READY\n");
|
||||
|
@ -416,6 +421,13 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
etrdev = coresight_find_input_type(
|
||||
csdev->pdata, CORESIGHT_DEV_TYPE_SINK, etr_subtype);
|
||||
if (etrdev) {
|
||||
etr_buf = tmc_etr_get_buffer(etrdev, cs_mode, data);
|
||||
if (IS_ERR(etr_buf))
|
||||
return PTR_ERR(etr_buf);
|
||||
}
|
||||
control |= BIT(CATU_CONTROL_ENABLE);
|
||||
|
||||
if (etr_buf && etr_buf->mode == ETR_MODE_CATU) {
|
||||
|
@ -441,13 +453,14 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int catu_enable(struct coresight_device *csdev, void *data)
|
||||
static int catu_enable(struct coresight_device *csdev, enum cs_mode mode,
|
||||
void *data)
|
||||
{
|
||||
int rc;
|
||||
struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
|
||||
|
||||
CS_UNLOCK(catu_drvdata->base);
|
||||
rc = catu_enable_hw(catu_drvdata, data);
|
||||
rc = catu_enable_hw(catu_drvdata, mode, data);
|
||||
CS_LOCK(catu_drvdata->base);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* Copyright (c) 2012, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/build_bug.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
|
@ -112,40 +113,24 @@ struct coresight_device *coresight_get_percpu_sink(int cpu)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_get_percpu_sink);
|
||||
|
||||
static int coresight_find_link_inport(struct coresight_device *csdev,
|
||||
struct coresight_device *parent)
|
||||
static struct coresight_connection *
|
||||
coresight_find_out_connection(struct coresight_device *src_dev,
|
||||
struct coresight_device *dest_dev)
|
||||
{
|
||||
int i;
|
||||
struct coresight_connection *conn;
|
||||
|
||||
for (i = 0; i < parent->pdata->nr_outport; i++) {
|
||||
conn = &parent->pdata->conns[i];
|
||||
if (conn->child_dev == csdev)
|
||||
return conn->child_port;
|
||||
for (i = 0; i < src_dev->pdata->nr_outconns; i++) {
|
||||
conn = src_dev->pdata->out_conns[i];
|
||||
if (conn->dest_dev == dest_dev)
|
||||
return conn;
|
||||
}
|
||||
|
||||
dev_err(&csdev->dev, "couldn't find inport, parent: %s, child: %s\n",
|
||||
dev_name(&parent->dev), dev_name(&csdev->dev));
|
||||
dev_err(&src_dev->dev,
|
||||
"couldn't find output connection, src_dev: %s, dest_dev: %s\n",
|
||||
dev_name(&src_dev->dev), dev_name(&dest_dev->dev));
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int coresight_find_link_outport(struct coresight_device *csdev,
|
||||
struct coresight_device *child)
|
||||
{
|
||||
int i;
|
||||
struct coresight_connection *conn;
|
||||
|
||||
for (i = 0; i < csdev->pdata->nr_outport; i++) {
|
||||
conn = &csdev->pdata->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 -ENODEV;
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static inline u32 coresight_read_claim_tags(struct coresight_device *csdev)
|
||||
|
@ -252,63 +237,47 @@ void coresight_disclaim_device(struct coresight_device *csdev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_disclaim_device);
|
||||
|
||||
/* enable or disable an associated CTI device of the supplied CS device */
|
||||
static int
|
||||
coresight_control_assoc_ectdev(struct coresight_device *csdev, bool enable)
|
||||
{
|
||||
int ect_ret = 0;
|
||||
struct coresight_device *ect_csdev = csdev->ect_dev;
|
||||
struct module *mod;
|
||||
|
||||
if (!ect_csdev)
|
||||
return 0;
|
||||
if ((!ect_ops(ect_csdev)->enable) || (!ect_ops(ect_csdev)->disable))
|
||||
return 0;
|
||||
|
||||
mod = ect_csdev->dev.parent->driver->owner;
|
||||
if (enable) {
|
||||
if (try_module_get(mod)) {
|
||||
ect_ret = ect_ops(ect_csdev)->enable(ect_csdev);
|
||||
if (ect_ret) {
|
||||
module_put(mod);
|
||||
} else {
|
||||
get_device(ect_csdev->dev.parent);
|
||||
csdev->ect_enabled = true;
|
||||
}
|
||||
} else
|
||||
ect_ret = -ENODEV;
|
||||
} else {
|
||||
if (csdev->ect_enabled) {
|
||||
ect_ret = ect_ops(ect_csdev)->disable(ect_csdev);
|
||||
put_device(ect_csdev->dev.parent);
|
||||
module_put(mod);
|
||||
csdev->ect_enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* output warning if ECT enable is preventing trace operation */
|
||||
if (ect_ret)
|
||||
dev_info(&csdev->dev, "Associated ECT device (%s) %s failed\n",
|
||||
dev_name(&ect_csdev->dev),
|
||||
enable ? "enable" : "disable");
|
||||
return ect_ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the associated ect / cti device while holding the coresight_mutex
|
||||
* to avoid a race with coresight_enable that may try to use this value.
|
||||
* Add a helper as an output device. This function takes the @coresight_mutex
|
||||
* because it's assumed that it's called from the helper device, outside of the
|
||||
* core code where the mutex would already be held. Don't add new calls to this
|
||||
* from inside the core code, instead try to add the new helper to the DT and
|
||||
* ACPI where it will be picked up and linked automatically.
|
||||
*/
|
||||
void coresight_set_assoc_ectdev_mutex(struct coresight_device *csdev,
|
||||
struct coresight_device *ect_csdev)
|
||||
void coresight_add_helper(struct coresight_device *csdev,
|
||||
struct coresight_device *helper)
|
||||
{
|
||||
int i;
|
||||
struct coresight_connection conn = {};
|
||||
struct coresight_connection *new_conn;
|
||||
|
||||
mutex_lock(&coresight_mutex);
|
||||
csdev->ect_dev = ect_csdev;
|
||||
conn.dest_fwnode = fwnode_handle_get(dev_fwnode(&helper->dev));
|
||||
conn.dest_dev = helper;
|
||||
conn.dest_port = conn.src_port = -1;
|
||||
conn.src_dev = csdev;
|
||||
|
||||
/*
|
||||
* Check for duplicates because this is called every time a helper
|
||||
* device is re-loaded. Existing connections will get re-linked
|
||||
* automatically.
|
||||
*/
|
||||
for (i = 0; i < csdev->pdata->nr_outconns; ++i)
|
||||
if (csdev->pdata->out_conns[i]->dest_fwnode == conn.dest_fwnode)
|
||||
goto unlock;
|
||||
|
||||
new_conn = coresight_add_out_conn(csdev->dev.parent, csdev->pdata,
|
||||
&conn);
|
||||
if (!IS_ERR(new_conn))
|
||||
coresight_add_in_conn(new_conn);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&coresight_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_set_assoc_ectdev_mutex);
|
||||
EXPORT_SYMBOL_GPL(coresight_add_helper);
|
||||
|
||||
static int coresight_enable_sink(struct coresight_device *csdev,
|
||||
u32 mode, void *data)
|
||||
enum cs_mode mode, void *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -319,14 +288,10 @@ static int coresight_enable_sink(struct coresight_device *csdev,
|
|||
if (!sink_ops(csdev)->enable)
|
||||
return -EINVAL;
|
||||
|
||||
ret = coresight_control_assoc_ectdev(csdev, true);
|
||||
ret = sink_ops(csdev)->enable(csdev, mode, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = sink_ops(csdev)->enable(csdev, mode, data);
|
||||
if (ret) {
|
||||
coresight_control_assoc_ectdev(csdev, false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
csdev->enable = true;
|
||||
|
||||
return 0;
|
||||
|
@ -342,7 +307,6 @@ static void coresight_disable_sink(struct coresight_device *csdev)
|
|||
ret = sink_ops(csdev)->disable(csdev);
|
||||
if (ret)
|
||||
return;
|
||||
coresight_control_assoc_ectdev(csdev, false);
|
||||
csdev->enable = false;
|
||||
}
|
||||
|
||||
|
@ -352,32 +316,26 @@ static int coresight_enable_link(struct coresight_device *csdev,
|
|||
{
|
||||
int ret = 0;
|
||||
int link_subtype;
|
||||
int inport, outport;
|
||||
struct coresight_connection *inconn, *outconn;
|
||||
|
||||
if (!parent || !child)
|
||||
return -EINVAL;
|
||||
|
||||
inport = coresight_find_link_inport(csdev, parent);
|
||||
outport = coresight_find_link_outport(csdev, child);
|
||||
inconn = coresight_find_out_connection(parent, csdev);
|
||||
outconn = coresight_find_out_connection(csdev, child);
|
||||
link_subtype = csdev->subtype.link_subtype;
|
||||
|
||||
if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG && inport < 0)
|
||||
return inport;
|
||||
if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && outport < 0)
|
||||
return outport;
|
||||
if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG && IS_ERR(inconn))
|
||||
return PTR_ERR(inconn);
|
||||
if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && IS_ERR(outconn))
|
||||
return PTR_ERR(outconn);
|
||||
|
||||
if (link_ops(csdev)->enable) {
|
||||
ret = coresight_control_assoc_ectdev(csdev, true);
|
||||
if (!ret) {
|
||||
ret = link_ops(csdev)->enable(csdev, inport, outport);
|
||||
if (ret)
|
||||
coresight_control_assoc_ectdev(csdev, false);
|
||||
}
|
||||
ret = link_ops(csdev)->enable(csdev, inconn, outconn);
|
||||
if (!ret)
|
||||
csdev->enable = true;
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
csdev->enable = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -385,78 +343,125 @@ static void coresight_disable_link(struct coresight_device *csdev,
|
|||
struct coresight_device *parent,
|
||||
struct coresight_device *child)
|
||||
{
|
||||
int i, nr_conns;
|
||||
int i;
|
||||
int link_subtype;
|
||||
int inport, outport;
|
||||
struct coresight_connection *inconn, *outconn;
|
||||
|
||||
if (!parent || !child)
|
||||
return;
|
||||
|
||||
inport = coresight_find_link_inport(csdev, parent);
|
||||
outport = coresight_find_link_outport(csdev, child);
|
||||
inconn = coresight_find_out_connection(parent, csdev);
|
||||
outconn = coresight_find_out_connection(csdev, child);
|
||||
link_subtype = csdev->subtype.link_subtype;
|
||||
|
||||
if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) {
|
||||
nr_conns = csdev->pdata->nr_inport;
|
||||
} else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) {
|
||||
nr_conns = csdev->pdata->nr_outport;
|
||||
} else {
|
||||
nr_conns = 1;
|
||||
}
|
||||
|
||||
if (link_ops(csdev)->disable) {
|
||||
link_ops(csdev)->disable(csdev, inport, outport);
|
||||
coresight_control_assoc_ectdev(csdev, false);
|
||||
link_ops(csdev)->disable(csdev, inconn, outconn);
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_conns; i++)
|
||||
if (atomic_read(&csdev->refcnt[i]) != 0)
|
||||
if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) {
|
||||
for (i = 0; i < csdev->pdata->nr_inconns; i++)
|
||||
if (atomic_read(&csdev->pdata->in_conns[i]->dest_refcnt) !=
|
||||
0)
|
||||
return;
|
||||
} else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) {
|
||||
for (i = 0; i < csdev->pdata->nr_outconns; i++)
|
||||
if (atomic_read(&csdev->pdata->out_conns[i]->src_refcnt) !=
|
||||
0)
|
||||
return;
|
||||
} else {
|
||||
if (atomic_read(&csdev->refcnt) != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
csdev->enable = false;
|
||||
}
|
||||
|
||||
static int coresight_enable_source(struct coresight_device *csdev, u32 mode)
|
||||
int coresight_enable_source(struct coresight_device *csdev, enum cs_mode mode,
|
||||
void *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!csdev->enable) {
|
||||
if (source_ops(csdev)->enable) {
|
||||
ret = coresight_control_assoc_ectdev(csdev, true);
|
||||
ret = source_ops(csdev)->enable(csdev, data, mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = source_ops(csdev)->enable(csdev, NULL, mode);
|
||||
if (ret) {
|
||||
coresight_control_assoc_ectdev(csdev, false);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
csdev->enable = true;
|
||||
}
|
||||
|
||||
atomic_inc(csdev->refcnt);
|
||||
atomic_inc(&csdev->refcnt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_enable_source);
|
||||
|
||||
static bool coresight_is_helper(struct coresight_device *csdev)
|
||||
{
|
||||
return csdev->type == CORESIGHT_DEV_TYPE_HELPER;
|
||||
}
|
||||
|
||||
static int coresight_enable_helper(struct coresight_device *csdev,
|
||||
enum cs_mode mode, void *data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!helper_ops(csdev)->enable)
|
||||
return 0;
|
||||
ret = helper_ops(csdev)->enable(csdev, mode, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
csdev->enable = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void coresight_disable_helper(struct coresight_device *csdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!helper_ops(csdev)->disable)
|
||||
return;
|
||||
|
||||
ret = helper_ops(csdev)->disable(csdev, NULL);
|
||||
if (ret)
|
||||
return;
|
||||
csdev->enable = false;
|
||||
}
|
||||
|
||||
static void coresight_disable_helpers(struct coresight_device *csdev)
|
||||
{
|
||||
int i;
|
||||
struct coresight_device *helper;
|
||||
|
||||
for (i = 0; i < csdev->pdata->nr_outconns; ++i) {
|
||||
helper = csdev->pdata->out_conns[i]->dest_dev;
|
||||
if (helper && coresight_is_helper(helper))
|
||||
coresight_disable_helper(helper);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* coresight_disable_source - Drop the reference count by 1 and disable
|
||||
* the device if there are no users left.
|
||||
*
|
||||
* @csdev: The coresight device to disable
|
||||
* @data: Opaque data to pass on to the disable function of the source device.
|
||||
* For example in perf mode this is a pointer to the struct perf_event.
|
||||
*
|
||||
* Returns true if the device has been disabled.
|
||||
*/
|
||||
static bool coresight_disable_source(struct coresight_device *csdev)
|
||||
bool coresight_disable_source(struct coresight_device *csdev, void *data)
|
||||
{
|
||||
if (atomic_dec_return(csdev->refcnt) == 0) {
|
||||
if (atomic_dec_return(&csdev->refcnt) == 0) {
|
||||
if (source_ops(csdev)->disable)
|
||||
source_ops(csdev)->disable(csdev, NULL);
|
||||
coresight_control_assoc_ectdev(csdev, false);
|
||||
source_ops(csdev)->disable(csdev, data);
|
||||
coresight_disable_helpers(csdev);
|
||||
csdev->enable = false;
|
||||
}
|
||||
return !csdev->enable;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_disable_source);
|
||||
|
||||
/*
|
||||
* coresight_disable_path_from : Disable components in the given path beyond
|
||||
|
@ -507,6 +512,9 @@ static void coresight_disable_path_from(struct list_head *path,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Disable all helpers adjacent along the path last */
|
||||
coresight_disable_helpers(csdev);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -516,9 +524,28 @@ void coresight_disable_path(struct list_head *path)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_disable_path);
|
||||
|
||||
int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data)
|
||||
static int coresight_enable_helpers(struct coresight_device *csdev,
|
||||
enum cs_mode mode, void *data)
|
||||
{
|
||||
int i, ret = 0;
|
||||
struct coresight_device *helper;
|
||||
|
||||
for (i = 0; i < csdev->pdata->nr_outconns; ++i) {
|
||||
helper = csdev->pdata->out_conns[i]->dest_dev;
|
||||
if (!helper || !coresight_is_helper(helper))
|
||||
continue;
|
||||
|
||||
ret = coresight_enable_helper(helper, mode, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int coresight_enable_path(struct list_head *path, enum cs_mode mode,
|
||||
void *sink_data)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 type;
|
||||
struct coresight_node *nd;
|
||||
|
@ -528,6 +555,10 @@ int coresight_enable_path(struct list_head *path, u32 mode, void *sink_data)
|
|||
csdev = nd->csdev;
|
||||
type = csdev->type;
|
||||
|
||||
/* Enable all helpers adjacent to the path first */
|
||||
ret = coresight_enable_helpers(csdev, mode, sink_data);
|
||||
if (ret)
|
||||
goto err;
|
||||
/*
|
||||
* ETF devices are tricky... They can be a link or a sink,
|
||||
* depending on how they are configured. If an ETF has been
|
||||
|
@ -602,10 +633,10 @@ coresight_find_enabled_sink(struct coresight_device *csdev)
|
|||
/*
|
||||
* Recursively explore each port found on this element.
|
||||
*/
|
||||
for (i = 0; i < csdev->pdata->nr_outport; i++) {
|
||||
for (i = 0; i < csdev->pdata->nr_outconns; i++) {
|
||||
struct coresight_device *child_dev;
|
||||
|
||||
child_dev = csdev->pdata->conns[i].child_dev;
|
||||
child_dev = csdev->pdata->out_conns[i]->dest_dev;
|
||||
if (child_dev)
|
||||
sink = coresight_find_enabled_sink(child_dev);
|
||||
if (sink)
|
||||
|
@ -718,11 +749,11 @@ static int coresight_grab_device(struct coresight_device *csdev)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < csdev->pdata->nr_outport; i++) {
|
||||
for (i = 0; i < csdev->pdata->nr_outconns; i++) {
|
||||
struct coresight_device *child;
|
||||
|
||||
child = csdev->pdata->conns[i].child_dev;
|
||||
if (child && child->type == CORESIGHT_DEV_TYPE_HELPER)
|
||||
child = csdev->pdata->out_conns[i]->dest_dev;
|
||||
if (child && coresight_is_helper(child))
|
||||
if (!coresight_get_ref(child))
|
||||
goto err;
|
||||
}
|
||||
|
@ -732,8 +763,8 @@ err:
|
|||
for (i--; i >= 0; i--) {
|
||||
struct coresight_device *child;
|
||||
|
||||
child = csdev->pdata->conns[i].child_dev;
|
||||
if (child && child->type == CORESIGHT_DEV_TYPE_HELPER)
|
||||
child = csdev->pdata->out_conns[i]->dest_dev;
|
||||
if (child && coresight_is_helper(child))
|
||||
coresight_put_ref(child);
|
||||
}
|
||||
return -ENODEV;
|
||||
|
@ -748,11 +779,11 @@ static void coresight_drop_device(struct coresight_device *csdev)
|
|||
int i;
|
||||
|
||||
coresight_put_ref(csdev);
|
||||
for (i = 0; i < csdev->pdata->nr_outport; i++) {
|
||||
for (i = 0; i < csdev->pdata->nr_outconns; i++) {
|
||||
struct coresight_device *child;
|
||||
|
||||
child = csdev->pdata->conns[i].child_dev;
|
||||
if (child && child->type == CORESIGHT_DEV_TYPE_HELPER)
|
||||
child = csdev->pdata->out_conns[i]->dest_dev;
|
||||
if (child && coresight_is_helper(child))
|
||||
coresight_put_ref(child);
|
||||
}
|
||||
}
|
||||
|
@ -790,10 +821,10 @@ static int _coresight_build_path(struct coresight_device *csdev,
|
|||
}
|
||||
|
||||
/* Not a sink - recursively explore each port found on this element */
|
||||
for (i = 0; i < csdev->pdata->nr_outport; i++) {
|
||||
for (i = 0; i < csdev->pdata->nr_outconns; i++) {
|
||||
struct coresight_device *child_dev;
|
||||
|
||||
child_dev = csdev->pdata->conns[i].child_dev;
|
||||
child_dev = csdev->pdata->out_conns[i]->dest_dev;
|
||||
if (child_dev &&
|
||||
_coresight_build_path(child_dev, sink, path) == 0) {
|
||||
found = true;
|
||||
|
@ -959,11 +990,11 @@ coresight_find_sink(struct coresight_device *csdev, int *depth)
|
|||
* Not a sink we want - or possible child sink may be better.
|
||||
* recursively explore each port found on this element.
|
||||
*/
|
||||
for (i = 0; i < csdev->pdata->nr_outport; i++) {
|
||||
for (i = 0; i < csdev->pdata->nr_outconns; i++) {
|
||||
struct coresight_device *child_dev, *sink = NULL;
|
||||
int child_depth = curr_depth;
|
||||
|
||||
child_dev = csdev->pdata->conns[i].child_dev;
|
||||
child_dev = csdev->pdata->out_conns[i]->dest_dev;
|
||||
if (child_dev)
|
||||
sink = coresight_find_sink(child_dev, &child_depth);
|
||||
|
||||
|
@ -1093,7 +1124,7 @@ int coresight_enable(struct coresight_device *csdev)
|
|||
* source is already enabled.
|
||||
*/
|
||||
if (subtype == CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE)
|
||||
atomic_inc(csdev->refcnt);
|
||||
atomic_inc(&csdev->refcnt);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -1114,7 +1145,7 @@ int coresight_enable(struct coresight_device *csdev)
|
|||
if (ret)
|
||||
goto err_path;
|
||||
|
||||
ret = coresight_enable_source(csdev, CS_MODE_SYSFS);
|
||||
ret = coresight_enable_source(csdev, CS_MODE_SYSFS, NULL);
|
||||
if (ret)
|
||||
goto err_source;
|
||||
|
||||
|
@ -1171,7 +1202,7 @@ void coresight_disable(struct coresight_device *csdev)
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (!csdev->enable || !coresight_disable_source(csdev))
|
||||
if (!csdev->enable || !coresight_disable_source(csdev, NULL))
|
||||
goto out;
|
||||
|
||||
switch (csdev->subtype.source_subtype) {
|
||||
|
@ -1296,18 +1327,16 @@ static struct device_type coresight_dev_type[] = {
|
|||
},
|
||||
{
|
||||
.name = "helper",
|
||||
},
|
||||
{
|
||||
.name = "ect",
|
||||
},
|
||||
}
|
||||
};
|
||||
/* Ensure the enum matches the names and groups */
|
||||
static_assert(ARRAY_SIZE(coresight_dev_type) == CORESIGHT_DEV_TYPE_MAX);
|
||||
|
||||
static void coresight_device_release(struct device *dev)
|
||||
{
|
||||
struct coresight_device *csdev = to_coresight_device(dev);
|
||||
|
||||
fwnode_handle_put(csdev->dev.fwnode);
|
||||
kfree(csdev->refcnt);
|
||||
kfree(csdev);
|
||||
}
|
||||
|
||||
|
@ -1315,45 +1344,57 @@ static int coresight_orphan_match(struct device *dev, void *data)
|
|||
{
|
||||
int i, ret = 0;
|
||||
bool still_orphan = false;
|
||||
struct coresight_device *csdev, *i_csdev;
|
||||
struct coresight_device *dst_csdev = data;
|
||||
struct coresight_device *src_csdev = to_coresight_device(dev);
|
||||
struct coresight_connection *conn;
|
||||
|
||||
csdev = data;
|
||||
i_csdev = to_coresight_device(dev);
|
||||
|
||||
/* No need to check oneself */
|
||||
if (csdev == i_csdev)
|
||||
return 0;
|
||||
bool fixup_self = (src_csdev == dst_csdev);
|
||||
|
||||
/* Move on to another component if no connection is orphan */
|
||||
if (!i_csdev->orphan)
|
||||
if (!src_csdev->orphan)
|
||||
return 0;
|
||||
/*
|
||||
* Circle throuch all the connection of that component. If we find
|
||||
* an orphan connection whose name matches @csdev, link it.
|
||||
* Circle through all the connections of that component. If we find
|
||||
* an orphan connection whose name matches @dst_csdev, link it.
|
||||
*/
|
||||
for (i = 0; i < i_csdev->pdata->nr_outport; i++) {
|
||||
conn = &i_csdev->pdata->conns[i];
|
||||
for (i = 0; i < src_csdev->pdata->nr_outconns; i++) {
|
||||
conn = src_csdev->pdata->out_conns[i];
|
||||
|
||||
/* Skip the port if FW doesn't describe it */
|
||||
if (!conn->child_fwnode)
|
||||
/* Skip the port if it's already connected. */
|
||||
if (conn->dest_dev)
|
||||
continue;
|
||||
/* We have found at least one orphan connection */
|
||||
if (conn->child_dev == NULL) {
|
||||
/* Does it match this newly added device? */
|
||||
if (conn->child_fwnode == csdev->dev.fwnode) {
|
||||
ret = coresight_make_links(i_csdev,
|
||||
conn, csdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
/* This component still has an orphan */
|
||||
still_orphan = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are at the "new" device, which triggered this search,
|
||||
* we must find the remote device from the fwnode in the
|
||||
* connection.
|
||||
*/
|
||||
if (fixup_self)
|
||||
dst_csdev = coresight_find_csdev_by_fwnode(
|
||||
conn->dest_fwnode);
|
||||
|
||||
/* Does it match this newly added device? */
|
||||
if (dst_csdev && conn->dest_fwnode == dst_csdev->dev.fwnode) {
|
||||
ret = coresight_make_links(src_csdev, conn, dst_csdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Install the device connection. This also indicates that
|
||||
* the links are operational on both ends.
|
||||
*/
|
||||
conn->dest_dev = dst_csdev;
|
||||
conn->src_dev = src_csdev;
|
||||
|
||||
ret = coresight_add_in_conn(conn);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
/* This component still has an orphan */
|
||||
still_orphan = true;
|
||||
}
|
||||
}
|
||||
|
||||
i_csdev->orphan = still_orphan;
|
||||
src_csdev->orphan = still_orphan;
|
||||
|
||||
/*
|
||||
* Returning '0' in case we didn't encounter any error,
|
||||
|
@ -1368,91 +1409,43 @@ static int coresight_fixup_orphan_conns(struct coresight_device *csdev)
|
|||
csdev, coresight_orphan_match);
|
||||
}
|
||||
|
||||
|
||||
static int coresight_fixup_device_conns(struct coresight_device *csdev)
|
||||
{
|
||||
int i, ret = 0;
|
||||
|
||||
for (i = 0; i < csdev->pdata->nr_outport; i++) {
|
||||
struct coresight_connection *conn = &csdev->pdata->conns[i];
|
||||
|
||||
if (!conn->child_fwnode)
|
||||
continue;
|
||||
conn->child_dev =
|
||||
coresight_find_csdev_by_fwnode(conn->child_fwnode);
|
||||
if (conn->child_dev && conn->child_dev->has_conns_grp) {
|
||||
ret = coresight_make_links(csdev, conn,
|
||||
conn->child_dev);
|
||||
if (ret)
|
||||
break;
|
||||
} else {
|
||||
csdev->orphan = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int coresight_remove_match(struct device *dev, void *data)
|
||||
{
|
||||
int i;
|
||||
struct coresight_device *csdev, *iterator;
|
||||
struct coresight_connection *conn;
|
||||
|
||||
csdev = data;
|
||||
iterator = to_coresight_device(dev);
|
||||
|
||||
/* No need to check oneself */
|
||||
if (csdev == iterator)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Circle throuch all the connection of that component. If we find
|
||||
* a connection whose name matches @csdev, remove it.
|
||||
*/
|
||||
for (i = 0; i < iterator->pdata->nr_outport; i++) {
|
||||
conn = &iterator->pdata->conns[i];
|
||||
|
||||
if (conn->child_dev == NULL || conn->child_fwnode == NULL)
|
||||
continue;
|
||||
|
||||
if (csdev->dev.fwnode == conn->child_fwnode) {
|
||||
iterator->orphan = true;
|
||||
coresight_remove_links(iterator, conn);
|
||||
/*
|
||||
* Drop the reference to the handle for the remote
|
||||
* device acquired in parsing the connections from
|
||||
* platform data.
|
||||
*/
|
||||
fwnode_handle_put(conn->child_fwnode);
|
||||
conn->child_fwnode = NULL;
|
||||
/* No need to continue */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returning '0' ensures that all known component on the
|
||||
* bus will be checked.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* coresight_remove_conns - Remove references to this given devices
|
||||
* from the connections of other devices.
|
||||
*/
|
||||
/* coresight_remove_conns - Remove other device's references to this device */
|
||||
static void coresight_remove_conns(struct coresight_device *csdev)
|
||||
{
|
||||
int i, j;
|
||||
struct coresight_connection *conn;
|
||||
|
||||
/*
|
||||
* Another device will point to this device only if there is
|
||||
* an output port connected to this one. i.e, if the device
|
||||
* doesn't have at least one input port, there is no point
|
||||
* in searching all the devices.
|
||||
* Remove the input connection references from the destination device
|
||||
* for each output connection.
|
||||
*/
|
||||
if (csdev->pdata->nr_inport)
|
||||
bus_for_each_dev(&coresight_bustype, NULL,
|
||||
csdev, coresight_remove_match);
|
||||
for (i = 0; i < csdev->pdata->nr_outconns; i++) {
|
||||
conn = csdev->pdata->out_conns[i];
|
||||
if (!conn->dest_dev)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < conn->dest_dev->pdata->nr_inconns; ++j)
|
||||
if (conn->dest_dev->pdata->in_conns[j] == conn) {
|
||||
conn->dest_dev->pdata->in_conns[j] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* For all input connections, remove references to this device.
|
||||
* Connection objects are shared so modifying this device's input
|
||||
* connections affects the other device's output connection.
|
||||
*/
|
||||
for (i = 0; i < csdev->pdata->nr_inconns; ++i) {
|
||||
conn = csdev->pdata->in_conns[i];
|
||||
/* Input conns array is sparse */
|
||||
if (!conn)
|
||||
continue;
|
||||
|
||||
conn->src_dev->orphan = true;
|
||||
coresight_remove_links(conn->src_dev, conn);
|
||||
conn->dest_dev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1544,24 +1537,27 @@ void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset)
|
|||
* to the output port of this device.
|
||||
*/
|
||||
void coresight_release_platform_data(struct coresight_device *csdev,
|
||||
struct device *dev,
|
||||
struct coresight_platform_data *pdata)
|
||||
{
|
||||
int i;
|
||||
struct coresight_connection *conns = pdata->conns;
|
||||
struct coresight_connection **conns = pdata->out_conns;
|
||||
|
||||
for (i = 0; i < pdata->nr_outport; i++) {
|
||||
for (i = 0; i < pdata->nr_outconns; i++) {
|
||||
/* If we have made the links, remove them now */
|
||||
if (csdev && conns[i].child_dev)
|
||||
coresight_remove_links(csdev, &conns[i]);
|
||||
if (csdev && conns[i]->dest_dev)
|
||||
coresight_remove_links(csdev, conns[i]);
|
||||
/*
|
||||
* Drop the refcount and clear the handle as this device
|
||||
* is going away
|
||||
*/
|
||||
if (conns[i].child_fwnode) {
|
||||
fwnode_handle_put(conns[i].child_fwnode);
|
||||
pdata->conns[i].child_fwnode = NULL;
|
||||
}
|
||||
fwnode_handle_put(conns[i]->dest_fwnode);
|
||||
conns[i]->dest_fwnode = NULL;
|
||||
devm_kfree(dev, conns[i]);
|
||||
}
|
||||
devm_kfree(dev, pdata->out_conns);
|
||||
devm_kfree(dev, pdata->in_conns);
|
||||
devm_kfree(dev, pdata);
|
||||
if (csdev)
|
||||
coresight_remove_conns_sysfs_group(csdev);
|
||||
}
|
||||
|
@ -1569,9 +1565,6 @@ void coresight_release_platform_data(struct coresight_device *csdev,
|
|||
struct coresight_device *coresight_register(struct coresight_desc *desc)
|
||||
{
|
||||
int ret;
|
||||
int link_subtype;
|
||||
int nr_refcnts = 1;
|
||||
atomic_t *refcnts = NULL;
|
||||
struct coresight_device *csdev;
|
||||
bool registered = false;
|
||||
|
||||
|
@ -1581,32 +1574,13 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
|
|||
goto err_out;
|
||||
}
|
||||
|
||||
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;
|
||||
kfree(csdev);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
csdev->refcnt = refcnts;
|
||||
|
||||
csdev->pdata = desc->pdata;
|
||||
|
||||
csdev->type = desc->type;
|
||||
csdev->subtype = desc->subtype;
|
||||
csdev->ops = desc->ops;
|
||||
csdev->access = desc->access;
|
||||
csdev->orphan = false;
|
||||
csdev->orphan = true;
|
||||
|
||||
csdev->dev.type = &coresight_dev_type[desc->type];
|
||||
csdev->dev.groups = desc->groups;
|
||||
|
@ -1656,8 +1630,6 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
|
|||
registered = true;
|
||||
|
||||
ret = coresight_create_conns_sysfs_group(csdev);
|
||||
if (!ret)
|
||||
ret = coresight_fixup_device_conns(csdev);
|
||||
if (!ret)
|
||||
ret = coresight_fixup_orphan_conns(csdev);
|
||||
|
||||
|
@ -1678,7 +1650,7 @@ out_unlock:
|
|||
|
||||
err_out:
|
||||
/* Cleanup the connection information */
|
||||
coresight_release_platform_data(NULL, desc->pdata);
|
||||
coresight_release_platform_data(NULL, desc->dev, desc->pdata);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_register);
|
||||
|
@ -1691,7 +1663,7 @@ void coresight_unregister(struct coresight_device *csdev)
|
|||
cti_assoc_ops->remove(csdev);
|
||||
coresight_remove_conns(csdev);
|
||||
coresight_clear_default_sink(csdev);
|
||||
coresight_release_platform_data(csdev, csdev->pdata);
|
||||
coresight_release_platform_data(csdev, csdev->dev.parent, csdev->pdata);
|
||||
device_unregister(&csdev->dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_unregister);
|
||||
|
@ -1714,6 +1686,69 @@ static inline int coresight_search_device_idx(struct coresight_dev_list *dict,
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
static bool coresight_compare_type(enum coresight_dev_type type_a,
|
||||
union coresight_dev_subtype subtype_a,
|
||||
enum coresight_dev_type type_b,
|
||||
union coresight_dev_subtype subtype_b)
|
||||
{
|
||||
if (type_a != type_b)
|
||||
return false;
|
||||
|
||||
switch (type_a) {
|
||||
case CORESIGHT_DEV_TYPE_SINK:
|
||||
return subtype_a.sink_subtype == subtype_b.sink_subtype;
|
||||
case CORESIGHT_DEV_TYPE_LINK:
|
||||
return subtype_a.link_subtype == subtype_b.link_subtype;
|
||||
case CORESIGHT_DEV_TYPE_LINKSINK:
|
||||
return subtype_a.link_subtype == subtype_b.link_subtype &&
|
||||
subtype_a.sink_subtype == subtype_b.sink_subtype;
|
||||
case CORESIGHT_DEV_TYPE_SOURCE:
|
||||
return subtype_a.source_subtype == subtype_b.source_subtype;
|
||||
case CORESIGHT_DEV_TYPE_HELPER:
|
||||
return subtype_a.helper_subtype == subtype_b.helper_subtype;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
struct coresight_device *
|
||||
coresight_find_input_type(struct coresight_platform_data *pdata,
|
||||
enum coresight_dev_type type,
|
||||
union coresight_dev_subtype subtype)
|
||||
{
|
||||
int i;
|
||||
struct coresight_connection *conn;
|
||||
|
||||
for (i = 0; i < pdata->nr_inconns; ++i) {
|
||||
conn = pdata->in_conns[i];
|
||||
if (conn &&
|
||||
coresight_compare_type(type, subtype, conn->src_dev->type,
|
||||
conn->src_dev->subtype))
|
||||
return conn->src_dev;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_find_input_type);
|
||||
|
||||
struct coresight_device *
|
||||
coresight_find_output_type(struct coresight_platform_data *pdata,
|
||||
enum coresight_dev_type type,
|
||||
union coresight_dev_subtype subtype)
|
||||
{
|
||||
int i;
|
||||
struct coresight_connection *conn;
|
||||
|
||||
for (i = 0; i < pdata->nr_outconns; ++i) {
|
||||
conn = pdata->out_conns[i];
|
||||
if (conn->dest_dev &&
|
||||
coresight_compare_type(type, subtype, conn->dest_dev->type,
|
||||
conn->dest_dev->subtype))
|
||||
return conn->dest_dev;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_find_output_type);
|
||||
|
||||
bool coresight_loses_context_with_cpu(struct device *dev)
|
||||
{
|
||||
return fwnode_property_present(dev_fwnode(dev),
|
||||
|
|
|
@ -555,7 +555,10 @@ static void cti_add_assoc_to_csdev(struct coresight_device *csdev)
|
|||
mutex_lock(&ect_mutex);
|
||||
|
||||
/* exit if current is an ECT device.*/
|
||||
if ((csdev->type == CORESIGHT_DEV_TYPE_ECT) || list_empty(&ect_net))
|
||||
if ((csdev->type == CORESIGHT_DEV_TYPE_HELPER &&
|
||||
csdev->subtype.helper_subtype ==
|
||||
CORESIGHT_DEV_SUBTYPE_HELPER_ECT_CTI) ||
|
||||
list_empty(&ect_net))
|
||||
goto cti_add_done;
|
||||
|
||||
/* if we didn't find the csdev previously we used the fwnode name */
|
||||
|
@ -571,8 +574,7 @@ static void cti_add_assoc_to_csdev(struct coresight_device *csdev)
|
|||
* if we found a matching csdev then update the ECT
|
||||
* association pointer for the device with this CTI.
|
||||
*/
|
||||
coresight_set_assoc_ectdev_mutex(csdev,
|
||||
ect_item->csdev);
|
||||
coresight_add_helper(csdev, ect_item->csdev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -582,26 +584,30 @@ cti_add_done:
|
|||
|
||||
/*
|
||||
* Removing the associated devices is easier.
|
||||
* A CTI will not have a value for csdev->ect_dev.
|
||||
*/
|
||||
static void cti_remove_assoc_from_csdev(struct coresight_device *csdev)
|
||||
{
|
||||
struct cti_drvdata *ctidrv;
|
||||
struct cti_trig_con *tc;
|
||||
struct cti_device *ctidev;
|
||||
union coresight_dev_subtype cti_subtype = {
|
||||
.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_ECT_CTI
|
||||
};
|
||||
struct coresight_device *cti_csdev = coresight_find_output_type(
|
||||
csdev->pdata, CORESIGHT_DEV_TYPE_HELPER, cti_subtype);
|
||||
|
||||
if (!cti_csdev)
|
||||
return;
|
||||
|
||||
mutex_lock(&ect_mutex);
|
||||
if (csdev->ect_dev) {
|
||||
ctidrv = csdev_to_cti_drvdata(csdev->ect_dev);
|
||||
ctidev = &ctidrv->ctidev;
|
||||
list_for_each_entry(tc, &ctidev->trig_cons, node) {
|
||||
if (tc->con_dev == csdev) {
|
||||
cti_remove_sysfs_link(ctidrv, tc);
|
||||
tc->con_dev = NULL;
|
||||
break;
|
||||
}
|
||||
ctidrv = csdev_to_cti_drvdata(cti_csdev);
|
||||
ctidev = &ctidrv->ctidev;
|
||||
list_for_each_entry(tc, &ctidev->trig_cons, node) {
|
||||
if (tc->con_dev == csdev) {
|
||||
cti_remove_sysfs_link(ctidrv, tc);
|
||||
tc->con_dev = NULL;
|
||||
break;
|
||||
}
|
||||
csdev->ect_dev = NULL;
|
||||
}
|
||||
mutex_unlock(&ect_mutex);
|
||||
}
|
||||
|
@ -630,8 +636,8 @@ static void cti_update_conn_xrefs(struct cti_drvdata *drvdata)
|
|||
/* if we can set the sysfs link */
|
||||
if (cti_add_sysfs_link(drvdata, tc))
|
||||
/* set the CTI/csdev association */
|
||||
coresight_set_assoc_ectdev_mutex(tc->con_dev,
|
||||
drvdata->csdev);
|
||||
coresight_add_helper(tc->con_dev,
|
||||
drvdata->csdev);
|
||||
else
|
||||
/* otherwise remove reference from CTI */
|
||||
tc->con_dev = NULL;
|
||||
|
@ -646,8 +652,6 @@ static void cti_remove_conn_xrefs(struct cti_drvdata *drvdata)
|
|||
|
||||
list_for_each_entry(tc, &ctidev->trig_cons, node) {
|
||||
if (tc->con_dev) {
|
||||
coresight_set_assoc_ectdev_mutex(tc->con_dev,
|
||||
NULL);
|
||||
cti_remove_sysfs_link(drvdata, tc);
|
||||
tc->con_dev = NULL;
|
||||
}
|
||||
|
@ -795,27 +799,27 @@ static void cti_pm_release(struct cti_drvdata *drvdata)
|
|||
}
|
||||
|
||||
/** cti ect operations **/
|
||||
int cti_enable(struct coresight_device *csdev)
|
||||
int cti_enable(struct coresight_device *csdev, enum cs_mode mode, void *data)
|
||||
{
|
||||
struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
|
||||
|
||||
return cti_enable_hw(drvdata);
|
||||
}
|
||||
|
||||
int cti_disable(struct coresight_device *csdev)
|
||||
int cti_disable(struct coresight_device *csdev, void *data)
|
||||
{
|
||||
struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
|
||||
|
||||
return cti_disable_hw(drvdata);
|
||||
}
|
||||
|
||||
static const struct coresight_ops_ect cti_ops_ect = {
|
||||
static const struct coresight_ops_helper cti_ops_ect = {
|
||||
.enable = cti_enable,
|
||||
.disable = cti_disable,
|
||||
};
|
||||
|
||||
static const struct coresight_ops cti_ops = {
|
||||
.ect_ops = &cti_ops_ect,
|
||||
.helper_ops = &cti_ops_ect,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -922,8 +926,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
|
||||
/* set up coresight component description */
|
||||
cti_desc.pdata = pdata;
|
||||
cti_desc.type = CORESIGHT_DEV_TYPE_ECT;
|
||||
cti_desc.subtype.ect_subtype = CORESIGHT_DEV_SUBTYPE_ECT_CTI;
|
||||
cti_desc.type = CORESIGHT_DEV_TYPE_HELPER;
|
||||
cti_desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_ECT_CTI;
|
||||
cti_desc.ops = &cti_ops;
|
||||
cti_desc.groups = drvdata->ctidev.con_groups;
|
||||
cti_desc.dev = dev;
|
||||
|
|
|
@ -112,11 +112,11 @@ static ssize_t enable_store(struct device *dev,
|
|||
ret = pm_runtime_resume_and_get(dev->parent);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = cti_enable(drvdata->csdev);
|
||||
ret = cti_enable(drvdata->csdev, CS_MODE_SYSFS, NULL);
|
||||
if (ret)
|
||||
pm_runtime_put(dev->parent);
|
||||
} else {
|
||||
ret = cti_disable(drvdata->csdev);
|
||||
ret = cti_disable(drvdata->csdev, NULL);
|
||||
if (!ret)
|
||||
pm_runtime_put(dev->parent);
|
||||
}
|
||||
|
|
|
@ -215,8 +215,8 @@ int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata,
|
|||
const char *assoc_dev_name);
|
||||
struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
|
||||
int out_sigs);
|
||||
int cti_enable(struct coresight_device *csdev);
|
||||
int cti_disable(struct coresight_device *csdev);
|
||||
int cti_enable(struct coresight_device *csdev, enum cs_mode mode, void *data);
|
||||
int cti_disable(struct coresight_device *csdev, void *data);
|
||||
void cti_write_all_hw_regs(struct cti_drvdata *drvdata);
|
||||
void cti_write_intack(struct device *dev, u32 ackval);
|
||||
void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value);
|
||||
|
|
|
@ -0,0 +1,163 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/coresight.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include "coresight-priv.h"
|
||||
|
||||
struct dummy_drvdata {
|
||||
struct device *dev;
|
||||
struct coresight_device *csdev;
|
||||
};
|
||||
|
||||
DEFINE_CORESIGHT_DEVLIST(source_devs, "dummy_source");
|
||||
DEFINE_CORESIGHT_DEVLIST(sink_devs, "dummy_sink");
|
||||
|
||||
static int dummy_source_enable(struct coresight_device *csdev,
|
||||
struct perf_event *event, enum cs_mode mode)
|
||||
{
|
||||
dev_dbg(csdev->dev.parent, "Dummy source enabled\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dummy_source_disable(struct coresight_device *csdev,
|
||||
struct perf_event *event)
|
||||
{
|
||||
dev_dbg(csdev->dev.parent, "Dummy source disabled\n");
|
||||
}
|
||||
|
||||
static int dummy_sink_enable(struct coresight_device *csdev, enum cs_mode mode,
|
||||
void *data)
|
||||
{
|
||||
dev_dbg(csdev->dev.parent, "Dummy sink enabled\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_sink_disable(struct coresight_device *csdev)
|
||||
{
|
||||
dev_dbg(csdev->dev.parent, "Dummy sink disabled\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct coresight_ops_source dummy_source_ops = {
|
||||
.enable = dummy_source_enable,
|
||||
.disable = dummy_source_disable,
|
||||
};
|
||||
|
||||
static const struct coresight_ops dummy_source_cs_ops = {
|
||||
.source_ops = &dummy_source_ops,
|
||||
};
|
||||
|
||||
static const struct coresight_ops_sink dummy_sink_ops = {
|
||||
.enable = dummy_sink_enable,
|
||||
.disable = dummy_sink_disable,
|
||||
};
|
||||
|
||||
static const struct coresight_ops dummy_sink_cs_ops = {
|
||||
.sink_ops = &dummy_sink_ops,
|
||||
};
|
||||
|
||||
static int dummy_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *node = dev->of_node;
|
||||
struct coresight_platform_data *pdata;
|
||||
struct dummy_drvdata *drvdata;
|
||||
struct coresight_desc desc = { 0 };
|
||||
|
||||
if (of_device_is_compatible(node, "arm,coresight-dummy-source")) {
|
||||
|
||||
desc.name = coresight_alloc_device_name(&source_devs, dev);
|
||||
if (!desc.name)
|
||||
return -ENOMEM;
|
||||
|
||||
desc.type = CORESIGHT_DEV_TYPE_SOURCE;
|
||||
desc.subtype.source_subtype =
|
||||
CORESIGHT_DEV_SUBTYPE_SOURCE_OTHERS;
|
||||
desc.ops = &dummy_source_cs_ops;
|
||||
} else if (of_device_is_compatible(node, "arm,coresight-dummy-sink")) {
|
||||
desc.name = coresight_alloc_device_name(&sink_devs, dev);
|
||||
if (!desc.name)
|
||||
return -ENOMEM;
|
||||
|
||||
desc.type = CORESIGHT_DEV_TYPE_SINK;
|
||||
desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_DUMMY;
|
||||
desc.ops = &dummy_sink_cs_ops;
|
||||
} else {
|
||||
dev_err(dev, "Device type not set\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pdata = coresight_get_platform_data(dev);
|
||||
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.pdata = pdev->dev.platform_data;
|
||||
desc.dev = &pdev->dev;
|
||||
drvdata->csdev = coresight_register(&desc);
|
||||
if (IS_ERR(drvdata->csdev))
|
||||
return PTR_ERR(drvdata->csdev);
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
dev_dbg(dev, "Dummy device initialized\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct dummy_drvdata *drvdata = platform_get_drvdata(pdev);
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
coresight_unregister(drvdata->csdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id dummy_match[] = {
|
||||
{.compatible = "arm,coresight-dummy-source"},
|
||||
{.compatible = "arm,coresight-dummy-sink"},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver dummy_driver = {
|
||||
.probe = dummy_probe,
|
||||
.remove = dummy_remove,
|
||||
.driver = {
|
||||
.name = "coresight-dummy",
|
||||
.of_match_table = dummy_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init dummy_init(void)
|
||||
{
|
||||
return platform_driver_register(&dummy_driver);
|
||||
}
|
||||
module_init(dummy_init);
|
||||
|
||||
static void __exit dummy_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&dummy_driver);
|
||||
}
|
||||
module_exit(dummy_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("CoreSight dummy driver");
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue