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:
Linus Torvalds 2023-07-03 12:46:47 -07:00
commit 44aeec836d
438 changed files with 8593 additions and 2569 deletions

View File

@ -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

View File

@ -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.

View File

@ -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>;
};
};
};
};
...

View File

@ -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>;
};
};
};
};
...

View File

@ -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>;

View File

@ -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

View File

@ -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;

View File

@ -26,6 +26,7 @@ properties:
- mediatek,mt2712-auxadc
- mediatek,mt6765-auxadc
- mediatek,mt7622-auxadc
- mediatek,mt7986-auxadc
- mediatek,mt8173-auxadc
- items:
- enum:

View File

@ -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";
};
};
};

View File

@ -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

View File

@ -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 ----.
|

View File

@ -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

View File

@ -98,6 +98,7 @@ required:
- reg
allOf:
- $ref: /schemas/iio/iio.yaml#
- $ref: /schemas/spi/spi-peripheral-props.yaml#
unevaluatedProperties: false

View File

@ -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>;
};
};
...

View File

@ -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>;
};
};
...

View File

@ -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>;
};
};

View File

@ -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>;
};
};

View File

@ -84,6 +84,7 @@ properties:
- st,lps35hw
- description: IMUs
enum:
- st,lsm303d-imu
- st,lsm9ds0-imu
- description: Deprecated bindings
enum:

View File

@ -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

View File

@ -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>;
};
};

View File

@ -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.

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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>;
};
};

View File

@ -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

View File

@ -27,6 +27,7 @@ properties:
- enum:
- mediatek,mt7622-efuse
- mediatek,mt7623-efuse
- mediatek,mt7986-efuse
- mediatek,mt8173-efuse
- mediatek,mt8183-efuse
- mediatek,mt8186-efuse

View File

@ -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:
- |

View File

@ -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>;
};
};
};

View File

@ -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

View File

@ -25,12 +25,6 @@ properties:
reg:
maxItems: 1
"#address-cells":
const: 1
"#size-cells":
const: 1
ranges: true
required:

View File

@ -17,6 +17,7 @@ properties:
items:
- enum:
- raspberrypi,bootloader-config
- raspberrypi,bootloader-public-key
- const: nvmem-rmem
reg:

View File

@ -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>;
};
};
};

View File

@ -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";
};

View File

@ -14,9 +14,6 @@ allOf:
- $ref: nvmem.yaml#
properties:
"#address-cells": true
"#size-cells": true
compatible:
const: socionext,uniphier-efuse

View File

@ -28,12 +28,6 @@ properties:
clocks:
maxItems: 1
"#address-cells":
const: 1
"#size-cells":
const: 1
thermal-calibration:
type: object
description: thermal calibration values

View File

@ -364,6 +364,7 @@ MEM
devm_kmalloc_array()
devm_kmemdup()
devm_krealloc()
devm_krealloc_array()
devm_kstrdup()
devm_kstrdup_const()
devm_kvasprintf()

View File

@ -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.

View File

@ -28,5 +28,6 @@ fit into other categories.
oxsemi-tornado
pci-endpoint-test
spear-pcie-gadget
tps6594-pfsm
uacce
xilinx_sdfec

View File

@ -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

View File

@ -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

View File

@ -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
-------

View File

@ -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!

View File

@ -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

View File

@ -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"

View File

@ -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} },

View File

@ -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) {

View File

@ -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;
/**

View File

@ -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;
}

View File

@ -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,
};

View File

@ -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

View File

@ -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 */

View File

@ -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
};
/**

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -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,
},
};

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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[] = {

447
drivers/counter/i8254.c Normal file
View File

@ -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);

View File

@ -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)

View File

@ -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.

View File

@ -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);

View File

@ -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,
};

View File

@ -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>

View File

@ -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);

View File

@ -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,

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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, &reg8);
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,

View File

@ -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);
}

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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),

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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),

View File

@ -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;

View File

@ -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);
}

View File

@ -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);

View File

@ -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