mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-06-07 15:57:35 +09:00
Char/Misc/IIO pull request for 6.16-rc1
Here is the big char/misc/iio and other small driver subsystem pull request for 6.16-rc1. Overall, a lot of individual changes, but nothing major, just the normal constant forward progress of new device support and cleanups to existing subsystems. Highlights in here are: - Large IIO driver updates and additions and device tree changes - Android binder bugfixes and logfile fixes - mhi driver updates - comedi driver updates - counter driver updates and additions - coresight driver updates and additions - echo driver removal as there are no in-kernel users of it - nvmem driver updates - spmi driver updates - new amd-sbi driver "subsystem" and drivers added - rust miscdriver binding documentation fix - other small driver fixes and updates (uio, w1, acrn, hpet, xillybus, cardreader drivers, fastrpc and others.) All of these have been in linux-next for quite a while with no reported problems. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCaEKg5Q8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ykUyACgmAzrzKMoQUwwhQ6ed2l7tHdrlOcAoIORI1/x pNqQdrE1EbmAAyl47IN4 =ts6J -----END PGP SIGNATURE----- Merge tag 'char-misc-6.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc Pull char / misc / iio driver updates from Greg KH: "Here is the big char/misc/iio and other small driver subsystem pull request for 6.16-rc1. Overall, a lot of individual changes, but nothing major, just the normal constant forward progress of new device support and cleanups to existing subsystems. Highlights in here are: - Large IIO driver updates and additions and device tree changes - Android binder bugfixes and logfile fixes - mhi driver updates - comedi driver updates - counter driver updates and additions - coresight driver updates and additions - echo driver removal as there are no in-kernel users of it - nvmem driver updates - spmi driver updates - new amd-sbi driver "subsystem" and drivers added - rust miscdriver binding documentation fix - other small driver fixes and updates (uio, w1, acrn, hpet, xillybus, cardreader drivers, fastrpc and others) All of these have been in linux-next for quite a while with no reported problems" * tag 'char-misc-6.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (390 commits) binder: fix yet another UAF in binder_devices counter: microchip-tcb-capture: Add watch validation support dt-bindings: iio: adc: Add ROHM BD79100G iio: adc: add support for Nuvoton NCT7201 dt-bindings: iio: adc: add NCT7201 ADCs iio: chemical: Add driver for SEN0322 dt-bindings: trivial-devices: Document SEN0322 iio: adc: ad7768-1: reorganize driver headers iio: bmp280: zero-init buffer iio: ssp_sensors: optimalize -> optimize HID: sensor-hub: Fix typo and improve documentation iio: admv1013: replace redundant ternary operator with just len iio: chemical: mhz19b: Fix error code in probe() iio: adc: at91-sama5d2: use IIO_DECLARE_BUFFER_WITH_TS iio: accel: sca3300: use IIO_DECLARE_BUFFER_WITH_TS iio: adc: ad7380: use IIO_DECLARE_DMA_BUFFER_WITH_TS iio: adc: ad4695: rename AD4695_MAX_VIN_CHANNELS iio: adc: ad4695: use IIO_DECLARE_DMA_BUFFER_WITH_TS iio: introduce IIO_DECLARE_BUFFER_WITH_TS macros iio: make IIO_DMA_MINALIGN minimum of 8 bytes ...
This commit is contained in:
commit
c26f4fbd58
601 changed files with 12372 additions and 6148 deletions
|
@ -94,6 +94,7 @@ Description:
|
|||
What: /sys/bus/iio/devices/iio:deviceX/sampling_frequency
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_sampling_frequency
|
||||
What: /sys/bus/iio/devices/iio:deviceX/buffer/sampling_frequency
|
||||
What: /sys/bus/iio/devices/iio:deviceX/events/sampling_frequency
|
||||
What: /sys/bus/iio/devices/triggerX/sampling_frequency
|
||||
KernelVersion: 2.6.35
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
|
@ -740,7 +741,9 @@ Description:
|
|||
1kohm_to_gnd: connected to ground via an 1kOhm resistor,
|
||||
2.5kohm_to_gnd: connected to ground via a 2.5kOhm resistor,
|
||||
6kohm_to_gnd: connected to ground via a 6kOhm resistor,
|
||||
7.7kohm_to_gnd: connected to ground via a 7.7kOhm resistor,
|
||||
20kohm_to_gnd: connected to ground via a 20kOhm resistor,
|
||||
32kohm_to_gnd: connected to ground via a 32kOhm resistor,
|
||||
42kohm_to_gnd: connected to ground via a 42kOhm resistor,
|
||||
90kohm_to_gnd: connected to ground via a 90kOhm resistor,
|
||||
100kohm_to_gnd: connected to ground via an 100kOhm resistor,
|
||||
|
|
|
@ -17,7 +17,7 @@ Description: Read only. Returns the firmware version of Intel MAX10
|
|||
What: /sys/bus/.../drivers/intel-m10-bmc/.../mac_address
|
||||
Date: January 2021
|
||||
KernelVersion: 5.12
|
||||
Contact: Peter Colberg <peter.colberg@altera.com>
|
||||
Contact: Matthew Gerlach <matthew.gerlach@altera.com>
|
||||
Description: Read only. Returns the first MAC address in a block
|
||||
of sequential MAC addresses assigned to the board
|
||||
that is managed by the Intel MAX10 BMC. It is stored in
|
||||
|
@ -28,7 +28,7 @@ Description: Read only. Returns the first MAC address in a block
|
|||
What: /sys/bus/.../drivers/intel-m10-bmc/.../mac_count
|
||||
Date: January 2021
|
||||
KernelVersion: 5.12
|
||||
Contact: Peter Colberg <peter.colberg@altera.com>
|
||||
Contact: Matthew Gerlach <matthew.gerlach@altera.com>
|
||||
Description: Read only. Returns the number of sequential MAC
|
||||
addresses assigned to the board managed by the Intel
|
||||
MAX10 BMC. This value is stored in FLASH and is mirrored
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/sr_root_entry_hash
|
||||
Date: Sep 2022
|
||||
KernelVersion: 5.20
|
||||
Contact: Peter Colberg <peter.colberg@altera.com>
|
||||
Contact: Matthew Gerlach <matthew.gerlach@altera.com>
|
||||
Description: Read only. Returns the root entry hash for the static
|
||||
region if one is programmed, else it returns the
|
||||
string: "hash not programmed". This file is only
|
||||
|
@ -11,7 +11,7 @@ Description: Read only. Returns the root entry hash for the static
|
|||
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/pr_root_entry_hash
|
||||
Date: Sep 2022
|
||||
KernelVersion: 5.20
|
||||
Contact: Peter Colberg <peter.colberg@altera.com>
|
||||
Contact: Matthew Gerlach <matthew.gerlach@altera.com>
|
||||
Description: Read only. Returns the root entry hash for the partial
|
||||
reconfiguration region if one is programmed, else it
|
||||
returns the string: "hash not programmed". This file
|
||||
|
@ -21,7 +21,7 @@ Description: Read only. Returns the root entry hash for the partial
|
|||
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/bmc_root_entry_hash
|
||||
Date: Sep 2022
|
||||
KernelVersion: 5.20
|
||||
Contact: Peter Colberg <peter.colberg@altera.com>
|
||||
Contact: Matthew Gerlach <matthew.gerlach@altera.com>
|
||||
Description: Read only. Returns the root entry hash for the BMC image
|
||||
if one is programmed, else it returns the string:
|
||||
"hash not programmed". This file is only visible if the
|
||||
|
@ -31,7 +31,7 @@ Description: Read only. Returns the root entry hash for the BMC image
|
|||
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/sr_canceled_csks
|
||||
Date: Sep 2022
|
||||
KernelVersion: 5.20
|
||||
Contact: Peter Colberg <peter.colberg@altera.com>
|
||||
Contact: Matthew Gerlach <matthew.gerlach@altera.com>
|
||||
Description: Read only. Returns a list of indices for canceled code
|
||||
signing keys for the static region. The standard bitmap
|
||||
list format is used (e.g. "1,2-6,9").
|
||||
|
@ -39,7 +39,7 @@ Description: Read only. Returns a list of indices for canceled code
|
|||
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/pr_canceled_csks
|
||||
Date: Sep 2022
|
||||
KernelVersion: 5.20
|
||||
Contact: Peter Colberg <peter.colberg@altera.com>
|
||||
Contact: Matthew Gerlach <matthew.gerlach@altera.com>
|
||||
Description: Read only. Returns a list of indices for canceled code
|
||||
signing keys for the partial reconfiguration region. The
|
||||
standard bitmap list format is used (e.g. "1,2-6,9").
|
||||
|
@ -47,7 +47,7 @@ Description: Read only. Returns a list of indices for canceled code
|
|||
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/bmc_canceled_csks
|
||||
Date: Sep 2022
|
||||
KernelVersion: 5.20
|
||||
Contact: Peter Colberg <peter.colberg@altera.com>
|
||||
Contact: Matthew Gerlach <matthew.gerlach@altera.com>
|
||||
Description: Read only. Returns a list of indices for canceled code
|
||||
signing keys for the BMC. The standard bitmap list format
|
||||
is used (e.g. "1,2-6,9").
|
||||
|
@ -55,7 +55,7 @@ Description: Read only. Returns a list of indices for canceled code
|
|||
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/flash_count
|
||||
Date: Sep 2022
|
||||
KernelVersion: 5.20
|
||||
Contact: Peter Colberg <peter.colberg@altera.com>
|
||||
Contact: Matthew Gerlach <matthew.gerlach@altera.com>
|
||||
Description: Read only. Returns number of times the secure update
|
||||
staging area has been flashed.
|
||||
Format: "%u".
|
||||
|
|
|
@ -30,6 +30,19 @@ properties:
|
|||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
||||
clock-names:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum: [apb_pclk, atclk]
|
||||
- items: # Zynq-700
|
||||
- const: apb_pclk
|
||||
- const: dbg_trc
|
||||
- const: dbg_apb
|
||||
|
||||
in-ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
additionalProperties: false
|
||||
|
|
|
@ -25,6 +25,7 @@ description: |
|
|||
* https://www.analog.com/en/products/ad7386-4.html
|
||||
* https://www.analog.com/en/products/ad7387-4.html
|
||||
* https://www.analog.com/en/products/ad7388-4.html
|
||||
* https://www.analog.com/en/products/ad7389-4.html
|
||||
* https://www.analog.com/en/products/adaq4370-4.html
|
||||
* https://www.analog.com/en/products/adaq4380-4.html
|
||||
* https://www.analog.com/en/products/adaq4381-4.html
|
||||
|
@ -49,6 +50,7 @@ properties:
|
|||
- adi,ad7386-4
|
||||
- adi,ad7387-4
|
||||
- adi,ad7388-4
|
||||
- adi,ad7389-4
|
||||
- adi,adaq4370-4
|
||||
- adi,adaq4380-4
|
||||
- adi,adaq4381-4
|
||||
|
@ -213,6 +215,15 @@ allOf:
|
|||
properties:
|
||||
refin-supply: false
|
||||
|
||||
# adi,ad7389-4 is internal reference only
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
const: adi,ad7389-4
|
||||
then:
|
||||
properties:
|
||||
refio-supply: false
|
||||
|
||||
# adaq devices need more supplies and using channel to declare gain property
|
||||
# only applies to adaq devices
|
||||
- if:
|
||||
|
|
|
@ -17,35 +17,40 @@ description: |
|
|||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,ad7091
|
||||
- adi,ad7091r
|
||||
- adi,ad7273
|
||||
- adi,ad7274
|
||||
- adi,ad7276
|
||||
- adi,ad7277
|
||||
- adi,ad7278
|
||||
- adi,ad7466
|
||||
- adi,ad7467
|
||||
- adi,ad7468
|
||||
- adi,ad7475
|
||||
- adi,ad7476
|
||||
- adi,ad7476a
|
||||
- adi,ad7477
|
||||
- adi,ad7477a
|
||||
- adi,ad7478
|
||||
- adi,ad7478a
|
||||
- adi,ad7495
|
||||
- adi,ad7910
|
||||
- adi,ad7920
|
||||
- adi,ad7940
|
||||
- ti,adc081s
|
||||
- ti,adc101s
|
||||
- ti,adc121s
|
||||
- ti,ads7866
|
||||
- ti,ads7867
|
||||
- ti,ads7868
|
||||
- lltc,ltc2314-14
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- adi,ad7091
|
||||
- adi,ad7091r
|
||||
- adi,ad7273
|
||||
- adi,ad7274
|
||||
- adi,ad7276
|
||||
- adi,ad7277
|
||||
- adi,ad7278
|
||||
- adi,ad7466
|
||||
- adi,ad7467
|
||||
- adi,ad7468
|
||||
- adi,ad7475
|
||||
- adi,ad7476
|
||||
- adi,ad7476a
|
||||
- adi,ad7477
|
||||
- adi,ad7477a
|
||||
- adi,ad7478
|
||||
- adi,ad7478a
|
||||
- adi,ad7495
|
||||
- adi,ad7910
|
||||
- adi,ad7920
|
||||
- adi,ad7940
|
||||
- ti,adc081s
|
||||
- ti,adc101s
|
||||
- ti,adc121s
|
||||
- ti,ads7866
|
||||
- ti,ads7867
|
||||
- ti,ads7868
|
||||
- lltc,ltc2314-14
|
||||
- items:
|
||||
- const: rohm,bu79100g
|
||||
- const: ti,ads7866
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
|
@ -45,6 +45,14 @@ properties:
|
|||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
'#trigger-source-cells':
|
||||
description: |
|
||||
Cell indicates the output signal: 0 = BUSY, 1 = FIRSTDATA.
|
||||
|
||||
For convenience, macros for these values are available in
|
||||
dt-bindings/iio/adc/adi,ad7606.h.
|
||||
const: 1
|
||||
|
||||
# According to the datasheet, "Data is clocked in from SDI on the falling
|
||||
# edge of SCLK, while data is clocked out on DOUTA on the rising edge of
|
||||
# SCLK". Also, even if not stated textually in the datasheet, it is made
|
||||
|
|
|
@ -23,6 +23,7 @@ properties:
|
|||
- amlogic,meson8m2-saradc
|
||||
- amlogic,meson-gxbb-saradc
|
||||
- amlogic,meson-gxl-saradc
|
||||
- amlogic,meson-gxlx-saradc
|
||||
- amlogic,meson-gxm-saradc
|
||||
- amlogic,meson-axg-saradc
|
||||
- amlogic,meson-g12a-saradc
|
||||
|
|
|
@ -34,6 +34,7 @@ properties:
|
|||
- const: mediatek,mt2701-auxadc
|
||||
- items:
|
||||
- enum:
|
||||
- mediatek,mt6893-auxadc
|
||||
- mediatek,mt8183-auxadc
|
||||
- mediatek,mt8186-auxadc
|
||||
- mediatek,mt8188-auxadc
|
||||
|
|
|
@ -32,6 +32,9 @@ properties:
|
|||
spi-max-frequency:
|
||||
maximum: 20000000
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
description: |
|
||||
Phandle and clock identifier for external sampling clock.
|
||||
|
@ -71,6 +74,7 @@ unevaluatedProperties: false
|
|||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
@ -80,6 +84,7 @@ examples:
|
|||
reg = <0>;
|
||||
interrupt-parent = <&gpio5>;
|
||||
interrupts = <15 2>;
|
||||
reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
|
||||
spi-max-frequency = <20000000>;
|
||||
microchip,device-addr = <0>;
|
||||
vref-supply = <&vref_reg>;
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/nuvoton,nct7201.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Nuvoton nct7201 and similar ADCs
|
||||
|
||||
maintainers:
|
||||
- Eason Yang <j2anfernee@gmail.com>
|
||||
|
||||
description: |
|
||||
The NCT7201/NCT7202 is a Nuvoton Hardware Monitor IC, contains up to 12
|
||||
voltage monitoring channels, with SMBus interface, and up to 4 sets SMBus
|
||||
address selection by ADDR connection. It also provides ALERT# signal for
|
||||
event notification and reset input RSTIN# to recover it from a fault
|
||||
condition.
|
||||
|
||||
NCT7201 contains 8 voltage monitor inputs (VIN1~VIN8).
|
||||
NCT7202 contains 12 voltage monitor inputs (VIN1~VIN12).
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- nuvoton,nct7201
|
||||
- nuvoton,nct7202
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply:
|
||||
description:
|
||||
A 3.3V to supply that powers the chip.
|
||||
|
||||
vref-supply:
|
||||
description:
|
||||
The regulator supply for the ADC reference voltage.
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adc@1d {
|
||||
compatible = "nuvoton,nct7202";
|
||||
reg = <0x1d>;
|
||||
vdd-supply = <&vdd>;
|
||||
vref-supply = <&vref>;
|
||||
interrupt-parent = <&gpio3>;
|
||||
interrupts = <30 IRQ_TYPE_LEVEL_LOW>;
|
||||
reset-gpios = <&gpio3 28 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
...
|
69
Documentation/devicetree/bindings/iio/adc/rohm,bd79104.yaml
Normal file
69
Documentation/devicetree/bindings/iio/adc/rohm,bd79104.yaml
Normal file
|
@ -0,0 +1,69 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/rohm,bd79104.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ROHM Semiconductor BD79104 ADC
|
||||
|
||||
maintainers:
|
||||
- Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
|
||||
description: |
|
||||
12 bit SPI ADC with 8 channels.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rohm,bd79104
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vdd-supply: true
|
||||
iovdd-supply: true
|
||||
|
||||
# The component data-sheet says the frequency is 20M. I, however, found
|
||||
# that the ROHM evaluation board BD79104FV-EVK-001 had problems with 20M.
|
||||
# I have successfully used it with 4M. My _assumption_ is that this is not
|
||||
# the limitation of the component itself, but a limitation of the EVK.
|
||||
spi-max-frequency:
|
||||
maximum: 20000000
|
||||
|
||||
"#io-channel-cells":
|
||||
const: 1
|
||||
|
||||
spi-cpha: true
|
||||
spi-cpol: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
- iovdd-supply
|
||||
- spi-cpha
|
||||
- spi-cpol
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
adc@0 {
|
||||
compatible = "rohm,bd79104";
|
||||
reg = <0>;
|
||||
vdd-supply = <&vdd_supply>;
|
||||
iovdd-supply = <&iovdd_supply>;
|
||||
spi-max-frequency = <4000000>;
|
||||
spi-cpha;
|
||||
spi-cpol;
|
||||
#io-channel-cells = <1>;
|
||||
};
|
||||
};
|
||||
...
|
114
Documentation/devicetree/bindings/iio/adc/rohm,bd79124.yaml
Normal file
114
Documentation/devicetree/bindings/iio/adc/rohm,bd79124.yaml
Normal file
|
@ -0,0 +1,114 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/adc/rohm,bd79124.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ROHM BD79124 ADC/GPO
|
||||
|
||||
maintainers:
|
||||
- Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
|
||||
description: |
|
||||
The ROHM BD79124 is a 12-bit, 8-channel, SAR ADC. The ADC supports
|
||||
an automatic measurement mode, with an alarm interrupt for out-of-window
|
||||
measurements. ADC input pins can be also configured as general purpose
|
||||
outputs.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rohm,bd79124
|
||||
|
||||
reg:
|
||||
description:
|
||||
I2C slave address.
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
gpio-controller: true
|
||||
|
||||
"#gpio-cells":
|
||||
const: 1
|
||||
description:
|
||||
The pin number.
|
||||
|
||||
vdd-supply: true
|
||||
|
||||
iovdd-supply: true
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
patternProperties:
|
||||
"^channel@[0-7]+$":
|
||||
type: object
|
||||
$ref: /schemas/iio/adc/adc.yaml#
|
||||
description: Represents ADC channel.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
description: AIN pin number
|
||||
minimum: 0
|
||||
maximum: 7
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- iovdd-supply
|
||||
- vdd-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/leds/common.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
adc: adc@10 {
|
||||
compatible = "rohm,bd79124";
|
||||
reg = <0x10>;
|
||||
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <29 8>;
|
||||
|
||||
vdd-supply = <&dummyreg>;
|
||||
iovdd-supply = <&dummyreg>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
channel@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
channel@1 {
|
||||
reg = <1>;
|
||||
};
|
||||
channel@2 {
|
||||
reg = <2>;
|
||||
};
|
||||
channel@3 {
|
||||
reg = <3>;
|
||||
};
|
||||
channel@4 {
|
||||
reg = <4>;
|
||||
};
|
||||
channel@5 {
|
||||
reg = <5>;
|
||||
};
|
||||
channel@6 {
|
||||
reg = <6>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -498,7 +498,7 @@ patternProperties:
|
|||
examples:
|
||||
- |
|
||||
// Example 1: with stm32f429, ADC1, single-ended channel 8
|
||||
adc123: adc@40012000 {
|
||||
adc123: adc@40012000 {
|
||||
compatible = "st,stm32f4-adc-core";
|
||||
reg = <0x40012000 0x400>;
|
||||
interrupts = <18>;
|
||||
|
@ -512,28 +512,28 @@ examples:
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
adc@0 {
|
||||
compatible = "st,stm32f4-adc";
|
||||
#io-channel-cells = <1>;
|
||||
reg = <0x0>;
|
||||
clocks = <&rcc 0 168>;
|
||||
interrupt-parent = <&adc123>;
|
||||
interrupts = <0>;
|
||||
st,adc-channels = <8>;
|
||||
dmas = <&dma2 0 0 0x400 0x0>;
|
||||
dma-names = "rx";
|
||||
assigned-resolution-bits = <8>;
|
||||
compatible = "st,stm32f4-adc";
|
||||
#io-channel-cells = <1>;
|
||||
reg = <0x0>;
|
||||
clocks = <&rcc 0 168>;
|
||||
interrupt-parent = <&adc123>;
|
||||
interrupts = <0>;
|
||||
st,adc-channels = <8>;
|
||||
dmas = <&dma2 0 0 0x400 0x0>;
|
||||
dma-names = "rx";
|
||||
assigned-resolution-bits = <8>;
|
||||
};
|
||||
// ...
|
||||
// other adc child nodes follow...
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
// Example 2: with stm32mp157c to setup ADC1 with:
|
||||
// - channels 0 & 1 as single-ended
|
||||
// - channels 2 & 3 as differential (with resp. 6 & 7 negative inputs)
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/stm32mp1-clks.h>
|
||||
adc12: adc@48003000 {
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/stm32mp1-clks.h>
|
||||
adc12: adc@48003000 {
|
||||
compatible = "st,stm32mp1-adc-core";
|
||||
reg = <0x48003000 0x400>;
|
||||
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
|
||||
|
@ -550,27 +550,27 @@ examples:
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
adc@0 {
|
||||
compatible = "st,stm32mp1-adc";
|
||||
#io-channel-cells = <1>;
|
||||
reg = <0x0>;
|
||||
interrupt-parent = <&adc12>;
|
||||
interrupts = <0>;
|
||||
st,adc-channels = <0 1>;
|
||||
st,adc-diff-channels = <2 6>, <3 7>;
|
||||
st,min-sample-time-nsecs = <5000>;
|
||||
dmas = <&dmamux1 9 0x400 0x05>;
|
||||
dma-names = "rx";
|
||||
compatible = "st,stm32mp1-adc";
|
||||
#io-channel-cells = <1>;
|
||||
reg = <0x0>;
|
||||
interrupt-parent = <&adc12>;
|
||||
interrupts = <0>;
|
||||
st,adc-channels = <0 1>;
|
||||
st,adc-diff-channels = <2 6>, <3 7>;
|
||||
st,min-sample-time-nsecs = <5000>;
|
||||
dmas = <&dmamux1 9 0x400 0x05>;
|
||||
dma-names = "rx";
|
||||
};
|
||||
// ...
|
||||
// other adc child node follow...
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
// Example 3: with stm32mp157c to setup ADC2 with:
|
||||
// - internal channels 13, 14, 15.
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/stm32mp1-clks.h>
|
||||
adc122: adc@48003000 {
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/clock/stm32mp1-clks.h>
|
||||
adc122: adc@48003000 {
|
||||
compatible = "st,stm32mp1-adc-core";
|
||||
reg = <0x48003000 0x400>;
|
||||
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
|
||||
|
@ -587,28 +587,28 @@ examples:
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
adc@100 {
|
||||
compatible = "st,stm32mp1-adc";
|
||||
#io-channel-cells = <1>;
|
||||
reg = <0x100>;
|
||||
interrupts = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
channel@13 {
|
||||
reg = <13>;
|
||||
label = "vrefint";
|
||||
st,min-sample-time-ns = <9000>;
|
||||
};
|
||||
channel@14 {
|
||||
reg = <14>;
|
||||
label = "vddcore";
|
||||
st,min-sample-time-ns = <9000>;
|
||||
};
|
||||
channel@15 {
|
||||
reg = <15>;
|
||||
label = "vbat";
|
||||
st,min-sample-time-ns = <9000>;
|
||||
};
|
||||
compatible = "st,stm32mp1-adc";
|
||||
#io-channel-cells = <1>;
|
||||
reg = <0x100>;
|
||||
interrupts = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
channel@13 {
|
||||
reg = <13>;
|
||||
label = "vrefint";
|
||||
st,min-sample-time-ns = <9000>;
|
||||
};
|
||||
channel@14 {
|
||||
reg = <14>;
|
||||
label = "vddcore";
|
||||
st,min-sample-time-ns = <9000>;
|
||||
};
|
||||
channel@15 {
|
||||
reg = <15>;
|
||||
label = "vbat";
|
||||
st,min-sample-time-ns = <9000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/chemical/winsen,mhz19b.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MHZ19B CO2 sensor
|
||||
|
||||
maintainers:
|
||||
- Gyeyoung Baek <gye976@gmail.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: winsen,mhz19b
|
||||
|
||||
vin-supply:
|
||||
description: Regulator that provides power to the sensor
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- vin-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
serial {
|
||||
co2-sensor {
|
||||
compatible = "winsen,mhz19b";
|
||||
vin-supply = <&vdd>;
|
||||
};
|
||||
};
|
||||
...
|
100
Documentation/devicetree/bindings/iio/dac/adi,ad3530r.yaml
Normal file
100
Documentation/devicetree/bindings/iio/dac/adi,ad3530r.yaml
Normal file
|
@ -0,0 +1,100 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/iio/dac/adi,ad3530r.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog Devices AD3530R and Similar DACs
|
||||
|
||||
maintainers:
|
||||
- Kim Seer Paller <kimseer.paller@analog.com>
|
||||
|
||||
description: |
|
||||
The AD3530/AD3530R (8-channel) and AD3531/AD3531R (4-channel) are low-power,
|
||||
16-bit, buffered voltage output digital-to-analog converters (DACs) with
|
||||
software-programmable gain controls, providing full-scale output spans of 2.5V
|
||||
or 5V for reference voltages of 2.5V. These devices operate from a single 2.7V
|
||||
to 5.5V supply and are guaranteed monotonic by design. The "R" variants
|
||||
include a 2.5V, 5ppm/°C internal reference, which is disabled by default.
|
||||
Datasheet can be found here:
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad3530_ad530r.pdf
|
||||
https://www.analog.com/media/en/technical-documentation/data-sheets/ad3531-ad3531r.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- adi,ad3530
|
||||
- adi,ad3530r
|
||||
- adi,ad3531
|
||||
- adi,ad3531r
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
spi-max-frequency:
|
||||
maximum: 50000000
|
||||
|
||||
vdd-supply:
|
||||
description: Power Supply Input.
|
||||
|
||||
iovdd-supply:
|
||||
description: Digital Power Supply Input.
|
||||
|
||||
io-channels:
|
||||
description:
|
||||
ADC channel used to monitor internal die temperature, output voltages, and
|
||||
current of a selected channel via the MUXOUT pin.
|
||||
maxItems: 1
|
||||
|
||||
ref-supply:
|
||||
description:
|
||||
Reference Input/Output. The voltage at the REF pin sets the full-scale
|
||||
range of all channels. If not provided the internal reference is used and
|
||||
also provided on the VREF pin.
|
||||
|
||||
reset-gpios:
|
||||
description:
|
||||
Active low signal that is falling edge sensitive. When it is deasserted,
|
||||
the digital core initialization is performed and all DAC registers except
|
||||
the Interface Configuration A register are reset to their default values.
|
||||
maxItems: 1
|
||||
|
||||
ldac-gpios:
|
||||
description:
|
||||
LDAC pin to be used as a hardware trigger to update the DAC channels. If
|
||||
not present, the DAC channels are updated by Software LDAC.
|
||||
maxItems: 1
|
||||
|
||||
adi,range-double:
|
||||
description:
|
||||
Configure the output range for all channels. If the property is present,
|
||||
the output will range from 0V to 2Vref. If the property is not present,
|
||||
the output will range from 0V to Vref.
|
||||
type: boolean
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd-supply
|
||||
- iovdd-supply
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
dac@0 {
|
||||
compatible = "adi,ad3530r";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <1000000>;
|
||||
|
||||
vdd-supply = <&vdd>;
|
||||
iovdd-supply = <&iovdd>;
|
||||
};
|
||||
};
|
||||
...
|
|
@ -217,7 +217,7 @@ required:
|
|||
- reg
|
||||
- spi-max-frequency
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
@ -27,6 +27,8 @@ properties:
|
|||
|
||||
vdrive-supply: true
|
||||
|
||||
vrefin-supply: true
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ required:
|
|||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
@ -124,7 +124,7 @@ required:
|
|||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
@ -64,7 +64,7 @@ required:
|
|||
- reg
|
||||
- vdd-supply
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
@ -5,19 +5,26 @@
|
|||
$id: http://devicetree.org/schemas/iio/dac/rohm,bd79703.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ROHM BD79703 DAC device driver
|
||||
title: ROHM BD79700, BD79701, BD79702 and BD79703 DACs
|
||||
|
||||
maintainers:
|
||||
- Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
|
||||
description: |
|
||||
The ROHM BD79703 is a 6 channel, 8-bit DAC.
|
||||
Datasheet can be found here:
|
||||
The ROHM BD7970[0,1,2,3] are 8-bit DACs. The BD79700 has 2 channels,
|
||||
BD79701 3 channels, BD79702 4 channels and BD79703 has 6 channels.
|
||||
Datasheets for BD79702 and BD79703 can be found from
|
||||
https://fscdn.rohm.com/en/products/databook/datasheet/ic/data_converter/dac/bd79702fv-lb_bd79703fv-lb-e.pdf
|
||||
and for the BD79700 and the BD79701 from
|
||||
https://fscdn.rohm.com/en/products/databook/datasheet/ic/data_converter/dac/bd79700fvm-lb_bd79701fvm-lb-e.pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: rohm,bd79703
|
||||
enum:
|
||||
- rohm,bd79700
|
||||
- rohm,bd79701
|
||||
- rohm,bd79702
|
||||
- rohm,bd79703
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -27,23 +34,35 @@ properties:
|
|||
|
||||
vfs-supply:
|
||||
description:
|
||||
The regulator to use as a full scale voltage. The voltage should be between 2.7V .. VCC
|
||||
The regulator to use as a full scale voltage. The voltage should be
|
||||
between 2.7V .. VCC. Not present on BD79700 and BD79701.
|
||||
|
||||
vcc-supply:
|
||||
description:
|
||||
The regulator supplying the operating voltage. Should be between 2.7V ... 5.5V
|
||||
The regulator supplying the operating voltage. Should be between
|
||||
2.7V ... 5.5V. Is used also as a Vfs on BD79700 and BD79701.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- spi-max-frequency
|
||||
- vfs-supply
|
||||
- vcc-supply
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- rohm,bd79702
|
||||
- rohm,bd79703
|
||||
then:
|
||||
required:
|
||||
- vfs-supply
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
@ -44,6 +44,24 @@ properties:
|
|||
'#clock-cells':
|
||||
const: 0
|
||||
|
||||
adi,lpf-margin-mhz:
|
||||
description:
|
||||
Sets the minimum distance between the fundamental frequency of `rf_in`
|
||||
and the corner frequency of the low-pass, output filter when operated in
|
||||
'auto' mode. The selected low-pass corner frequency will be greater than,
|
||||
or equal to, `rf_in` + `lpf-margin-hz`. If not setting is found that
|
||||
satisfies this relationship the filter will be put into 'bypass'.
|
||||
default: 0
|
||||
|
||||
adi,hpf-margin-mhz:
|
||||
description:
|
||||
Sets the minimum distance between the fundamental frequency of `rf_in`
|
||||
and the corner frequency of the high-pass, input filter when operated in
|
||||
'auto' mode. The selected high-pass corner frequency will be less than,
|
||||
or equal to, `rf_in` - `hpf-margin-hz`. If not setting is found that
|
||||
satisfies this relationship the filter will be put into 'bypass'.
|
||||
default: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -61,6 +79,8 @@ examples:
|
|||
spi-max-frequency = <10000000>;
|
||||
clocks = <&admv8818_rfin>;
|
||||
clock-names = "rf_in";
|
||||
adi,lpf-margin-mhz = <300>;
|
||||
adi,hpf-margin-mhz = <300>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
|
@ -53,7 +53,7 @@ required:
|
|||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
@ -39,7 +39,16 @@ properties:
|
|||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
interrupt-names:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
items:
|
||||
enum:
|
||||
- INT1
|
||||
- INT2
|
||||
|
||||
drive-open-drain:
|
||||
type: boolean
|
||||
|
@ -76,6 +85,7 @@ examples:
|
|||
reg = <0x68>;
|
||||
interrupt-parent = <&gpio2>;
|
||||
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
|
||||
interrupt-names = "INT1";
|
||||
vdd-supply = <&vdd>;
|
||||
vddio-supply = <&vddio>;
|
||||
};
|
||||
|
@ -95,6 +105,7 @@ examples:
|
|||
spi-cpol;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
|
||||
interrupt-names = "INT1";
|
||||
vdd-supply = <&vdd>;
|
||||
vddio-supply = <&vddio>;
|
||||
};
|
||||
|
|
|
@ -24,6 +24,10 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description: GPIO connected to the DVI reset pin (active low)
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -32,6 +36,7 @@ additionalProperties: false
|
|||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
@ -39,6 +44,7 @@ examples:
|
|||
light-sensor@23 {
|
||||
compatible = "rohm,bh1750";
|
||||
reg = <0x23>;
|
||||
reset-gpios = <&gpio2 17 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ required:
|
|||
allOf:
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
dependentSchemas:
|
||||
honeywell,pmin-pascal:
|
||||
|
|
|
@ -115,7 +115,7 @@ allOf:
|
|||
honeywell,pmin-pascal: false
|
||||
honeywell,pmax-pascal: false
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
|
|
|
@ -70,8 +70,8 @@ examples:
|
|||
reg = <0x00580000 0x14000>;
|
||||
#interconnect-cells = <1>;
|
||||
|
||||
snoc_mm: interconnect-snoc {
|
||||
compatible = "qcom,msm8939-snoc-mm";
|
||||
#interconnect-cells = <1>;
|
||||
};
|
||||
snoc_mm: interconnect-snoc {
|
||||
compatible = "qcom,msm8939-snoc-mm";
|
||||
#interconnect-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -84,17 +84,17 @@ additionalProperties: false
|
|||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,gcc-msm8953.h>
|
||||
#include <dt-bindings/clock/qcom,gcc-msm8953.h>
|
||||
|
||||
snoc: interconnect@580000 {
|
||||
compatible = "qcom,msm8953-snoc";
|
||||
reg = <0x580000 0x16080>;
|
||||
interconnect@580000 {
|
||||
compatible = "qcom,msm8953-snoc";
|
||||
reg = <0x580000 0x16080>;
|
||||
|
||||
#interconnect-cells = <2>;
|
||||
#interconnect-cells = <2>;
|
||||
|
||||
snoc_mm: interconnect-snoc {
|
||||
compatible = "qcom,msm8953-snoc-mm";
|
||||
interconnect-snoc {
|
||||
compatible = "qcom,msm8953-snoc-mm";
|
||||
|
||||
#interconnect-cells = <2>;
|
||||
};
|
||||
};
|
||||
#interconnect-cells = <2>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -50,13 +50,13 @@ additionalProperties: false
|
|||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,rpmcc.h>
|
||||
#include <dt-bindings/clock/qcom,rpmcc.h>
|
||||
|
||||
bimc: interconnect@fc380000 {
|
||||
reg = <0xfc380000 0x6a000>;
|
||||
compatible = "qcom,msm8974-bimc";
|
||||
#interconnect-cells = <1>;
|
||||
clock-names = "bus", "bus_a";
|
||||
clocks = <&rpmcc RPM_SMD_BIMC_CLK>,
|
||||
<&rpmcc RPM_SMD_BIMC_A_CLK>;
|
||||
};
|
||||
interconnect@fc380000 {
|
||||
reg = <0xfc380000 0x6a000>;
|
||||
compatible = "qcom,msm8974-bimc";
|
||||
#interconnect-cells = <1>;
|
||||
clock-names = "bus", "bus_a";
|
||||
clocks = <&rpmcc RPM_SMD_BIMC_CLK>,
|
||||
<&rpmcc RPM_SMD_BIMC_A_CLK>;
|
||||
};
|
||||
|
|
|
@ -28,6 +28,7 @@ properties:
|
|||
- const: qcom,osm-l3
|
||||
- items:
|
||||
- enum:
|
||||
- qcom,sa8775p-epss-l3
|
||||
- qcom,sc7280-epss-l3
|
||||
- qcom,sc8280xp-epss-l3
|
||||
- qcom,sm6375-cpucp-l3
|
||||
|
|
|
@ -41,10 +41,10 @@ unevaluatedProperties: false
|
|||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,rpmcc.h>
|
||||
#include <dt-bindings/clock/qcom,rpmcc.h>
|
||||
|
||||
bimc: interconnect@400000 {
|
||||
compatible = "qcom,msm8916-bimc";
|
||||
reg = <0x00400000 0x62000>;
|
||||
#interconnect-cells = <1>;
|
||||
};
|
||||
interconnect@400000 {
|
||||
compatible = "qcom,msm8916-bimc";
|
||||
reg = <0x00400000 0x62000>;
|
||||
#interconnect-cells = <1>;
|
||||
};
|
||||
|
|
|
@ -127,19 +127,19 @@ unevaluatedProperties: false
|
|||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interconnect/qcom,sdm845.h>
|
||||
#include <dt-bindings/interconnect/qcom,sdm845.h>
|
||||
|
||||
mem_noc: interconnect@1380000 {
|
||||
compatible = "qcom,sdm845-mem-noc";
|
||||
reg = <0x01380000 0x27200>;
|
||||
#interconnect-cells = <1>;
|
||||
qcom,bcm-voters = <&apps_bcm_voter>;
|
||||
};
|
||||
interconnect@1380000 {
|
||||
compatible = "qcom,sdm845-mem-noc";
|
||||
reg = <0x01380000 0x27200>;
|
||||
#interconnect-cells = <1>;
|
||||
qcom,bcm-voters = <&apps_bcm_voter>;
|
||||
};
|
||||
|
||||
mmss_noc: interconnect@1740000 {
|
||||
compatible = "qcom,sdm845-mmss-noc";
|
||||
reg = <0x01740000 0x1c1000>;
|
||||
#interconnect-cells = <1>;
|
||||
qcom,bcm-voter-names = "apps", "disp";
|
||||
qcom,bcm-voters = <&apps_bcm_voter>, <&disp_bcm_voter>;
|
||||
};
|
||||
interconnect@1740000 {
|
||||
compatible = "qcom,sdm845-mmss-noc";
|
||||
reg = <0x01740000 0x1c1000>;
|
||||
#interconnect-cells = <1>;
|
||||
qcom,bcm-voter-names = "apps", "disp";
|
||||
qcom,bcm-voters = <&apps_bcm_voter>, <&disp_bcm_voter>;
|
||||
};
|
||||
|
|
|
@ -78,15 +78,15 @@ examples:
|
|||
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||
|
||||
clk_virt: interconnect-0 {
|
||||
compatible = "qcom,sdx75-clk-virt";
|
||||
#interconnect-cells = <2>;
|
||||
qcom,bcm-voters = <&apps_bcm_voter>;
|
||||
clocks = <&rpmhcc RPMH_QPIC_CLK>;
|
||||
compatible = "qcom,sdx75-clk-virt";
|
||||
#interconnect-cells = <2>;
|
||||
qcom,bcm-voters = <&apps_bcm_voter>;
|
||||
clocks = <&rpmhcc RPMH_QPIC_CLK>;
|
||||
};
|
||||
|
||||
system_noc: interconnect@1640000 {
|
||||
compatible = "qcom,sdx75-system-noc";
|
||||
reg = <0x1640000 0x4b400>;
|
||||
#interconnect-cells = <2>;
|
||||
qcom,bcm-voters = <&apps_bcm_voter>;
|
||||
compatible = "qcom,sdx75-system-noc";
|
||||
reg = <0x1640000 0x4b400>;
|
||||
#interconnect-cells = <2>;
|
||||
qcom,bcm-voters = <&apps_bcm_voter>;
|
||||
};
|
||||
|
|
|
@ -25,6 +25,10 @@ properties:
|
|||
description:
|
||||
List of gpios used to control the multiplexer, least significant bit first.
|
||||
|
||||
mux-supply:
|
||||
description:
|
||||
Regulator to power on the multiplexer.
|
||||
|
||||
'#mux-control-cells':
|
||||
enum: [ 0, 1 ]
|
||||
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/nvmem/apple,spmi-nvmem.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Apple SPMI NVMEM
|
||||
|
||||
description: Exports a series of SPMI registers as NVMEM cells
|
||||
|
||||
maintainers:
|
||||
- Sasha Finkelstein <fnkl.kernel@gmail.com>
|
||||
|
||||
allOf:
|
||||
- $ref: nvmem.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- apple,maverick-pmic
|
||||
- apple,sera-pmic
|
||||
- apple,stowe-pmic
|
||||
- const: apple,spmi-nvmem
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/spmi/spmi.h>
|
||||
|
||||
pmic@f {
|
||||
compatible = "apple,maverick-pmic", "apple,spmi-nvmem";
|
||||
reg = <0xf SPMI_USID>;
|
||||
|
||||
nvmem-layout {
|
||||
compatible = "fixed-layout";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
boot_stage: boot-stage@6001 {
|
||||
reg = <0x6001 0x1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
49
Documentation/devicetree/bindings/spmi/apple,spmi.yaml
Normal file
49
Documentation/devicetree/bindings/spmi/apple,spmi.yaml
Normal file
|
@ -0,0 +1,49 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/spmi/apple,spmi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Apple SPMI controller
|
||||
|
||||
maintainers:
|
||||
- Sasha Finkelstein <fnkl.kernel@gmail.com>
|
||||
|
||||
description: A SPMI controller present on most Apple SoCs
|
||||
|
||||
allOf:
|
||||
- $ref: spmi.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- apple,t8103-spmi
|
||||
- apple,t6000-spmi
|
||||
- apple,t8112-spmi
|
||||
- const: apple,spmi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/spmi/spmi.h>
|
||||
|
||||
spmi@920a1300 {
|
||||
compatible = "apple,t6000-spmi", "apple,spmi";
|
||||
reg = <0x920a1300 0x100>;
|
||||
#address-cells = <2>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pmic@f {
|
||||
reg = <0xf SPMI_USID>;
|
||||
/* PMIC-specific properties */
|
||||
};
|
||||
};
|
|
@ -85,6 +85,8 @@ properties:
|
|||
- devantech,srf08
|
||||
# Devantech SRF10 ultrasonic ranger
|
||||
- devantech,srf10
|
||||
# DFRobot SEN0322 oxygen sensor
|
||||
- dfrobot,sen0322
|
||||
# DH electronics GmbH on-board CPLD trivial SPI device
|
||||
- dh,dhcom-board
|
||||
# DA9053: flexible system level PMIC with multicore support
|
||||
|
|
|
@ -1705,6 +1705,8 @@ patternProperties:
|
|||
description: Wingtech Technology Co., Ltd.
|
||||
"^winlink,.*":
|
||||
description: WinLink Co., Ltd
|
||||
"^winsen,.*":
|
||||
description: Winsen Corp.
|
||||
"^winstar,.*":
|
||||
description: Winstar Display Corp.
|
||||
"^wirelesstag,.*":
|
||||
|
|
|
@ -59,10 +59,10 @@ For example, a simple nvram case::
|
|||
devm_nvmem_register(&config);
|
||||
}
|
||||
|
||||
Users of board files can define and register nvmem cells using the
|
||||
nvmem_cell_table struct::
|
||||
Device drivers can define and register an nvmem cell using the nvmem_cell_info
|
||||
struct::
|
||||
|
||||
static struct nvmem_cell_info foo_nvmem_cells[] = {
|
||||
static const struct nvmem_cell_info foo_nvmem_cell = {
|
||||
{
|
||||
.name = "macaddr",
|
||||
.offset = 0x7f00,
|
||||
|
@ -70,13 +70,7 @@ nvmem_cell_table struct::
|
|||
}
|
||||
};
|
||||
|
||||
static struct nvmem_cell_table foo_nvmem_cell_table = {
|
||||
.nvmem_name = "i2c-eeprom",
|
||||
.cells = foo_nvmem_cells,
|
||||
.ncells = ARRAY_SIZE(foo_nvmem_cells),
|
||||
};
|
||||
|
||||
nvmem_add_cell_table(&foo_nvmem_cell_table);
|
||||
int nvmem_add_one_cell(nvmem, &foo_nvmem_cell);
|
||||
|
||||
Additionally it is possible to create nvmem cell lookup entries and register
|
||||
them with the nvmem framework from machine code as shown in the example below::
|
||||
|
|
72
Documentation/iio/ad3552r.rst
Normal file
72
Documentation/iio/ad3552r.rst
Normal file
|
@ -0,0 +1,72 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
==============
|
||||
AD3552R driver
|
||||
==============
|
||||
|
||||
Device driver for Analog Devices Inc. AD35XXR series of DACs. The module name
|
||||
is ``ad3552r``.
|
||||
With the same module name, two different driver variants are available, the
|
||||
``generic spi`` variant, to be used with any classic SPI controllers, and the
|
||||
``hs`` (high speed) variant, for an ADI ``axi-dac`` (IP core) based controller
|
||||
that allows to reach the maximum sample rate supported from the DACs, using the
|
||||
DMA transfer and all the SPI lines available (D/QDSPI)..
|
||||
The high speed driver variant is intended to be used with the ``adi-axi-dac``
|
||||
backend support enabled, that is enabled by default when the driver is selected.
|
||||
|
||||
Supported devices
|
||||
=================
|
||||
|
||||
* `AD3541R <https://www.analog.com/en/products/ad3541r.html>`_
|
||||
* `AD3542R <https://www.analog.com/en/products/ad3542r.html>`_
|
||||
* `AD3551R <https://www.analog.com/en/products/ad3551r.html>`_
|
||||
* `AD3552R <https://www.analog.com/en/products/ad3552r.html>`_
|
||||
|
||||
Wiring connections
|
||||
==================
|
||||
|
||||
Generic SPI
|
||||
-----------
|
||||
Use the classic SPI S_CLK/CS/SDO/SDI connection.
|
||||
|
||||
High speed (using axi-dac backend)
|
||||
----------------------------------
|
||||
|
||||
::
|
||||
|
||||
.-----------------. .-------.
|
||||
| |--- D/QSPI -----| |
|
||||
| DAC IP CORE |--- SPI S_CLK --| DAC |
|
||||
| |--- SPI CS -----| |
|
||||
| |--- LDAC -------| |
|
||||
| |--- RESET ------| |
|
||||
|_________________| |_______|
|
||||
|
||||
|
||||
High speed features
|
||||
===================
|
||||
|
||||
Device attributes
|
||||
-----------------
|
||||
|
||||
The following table shows the ad35xxr related device debug files, found in the
|
||||
specific debugfs path ``/sys/kernel/debug/iio/iio:deviceX``.
|
||||
|
||||
+-----------------------+------------------------------------------------------+
|
||||
| Debugfs device files | Description |
|
||||
+-----------------------+------------------------------------------------------+
|
||||
| data_source | The used data source, as |
|
||||
| | ``normal``, ``ramp-16bit``, etc. |
|
||||
+-----------------------+------------------------------------------------------+
|
||||
| data_source_available | The available data sources. |
|
||||
+-----------------------+------------------------------------------------------+
|
||||
|
||||
Usage examples
|
||||
--------------
|
||||
|
||||
. code-block:: bash
|
||||
root:/sys/bus/iio/devices/iio:device0# cat data_source
|
||||
normal
|
||||
root:/sys/bus/iio/devices/iio:device0# echo -n ramp-16bit > data_source
|
||||
root:/sys/bus/iio/devices/iio:device0# cat data_source
|
||||
ramp-16bit
|
|
@ -4,7 +4,7 @@
|
|||
AD4000 driver
|
||||
=============
|
||||
|
||||
Device driver for Analog Devices Inc. AD4000 series of ADCs.
|
||||
Device driver for Analog Devices Inc. AD4000 series of ADCs and similar devices.
|
||||
|
||||
Supported devices
|
||||
=================
|
||||
|
@ -25,6 +25,21 @@ Supported devices
|
|||
* `AD4022 <https://www.analog.com/AD4022>`_
|
||||
* `ADAQ4001 <https://www.analog.com/ADAQ4001>`_
|
||||
* `ADAQ4003 <https://www.analog.com/ADAQ4003>`_
|
||||
* `AD7685 <https://www.analog.com/AD7685>`_
|
||||
* `AD7686 <https://www.analog.com/AD7686>`_
|
||||
* `AD7687 <https://www.analog.com/AD7687>`_
|
||||
* `AD7688 <https://www.analog.com/AD7688>`_
|
||||
* `AD7690 <https://www.analog.com/AD7690>`_
|
||||
* `AD7691 <https://www.analog.com/AD7691>`_
|
||||
* `AD7693 <https://www.analog.com/AD7693>`_
|
||||
* `AD7942 <https://www.analog.com/AD7942>`_
|
||||
* `AD7946 <https://www.analog.com/AD7946>`_
|
||||
* `AD7980 <https://www.analog.com/AD7980>`_
|
||||
* `AD7982 <https://www.analog.com/AD7982>`_
|
||||
* `AD7983 <https://www.analog.com/AD7983>`_
|
||||
* `AD7984 <https://www.analog.com/AD7984>`_
|
||||
* `AD7988-1 <https://www.analog.com/AD7988-1>`_
|
||||
* `AD7988-5 <https://www.analog.com/AD7988-5>`_
|
||||
|
||||
Wiring connections
|
||||
------------------
|
||||
|
@ -129,3 +144,77 @@ Set ``adi,sdi-pin`` to ``"cs"`` to select this mode.
|
|||
^ | |
|
||||
+--------------------| SCLK |
|
||||
+-------------+
|
||||
|
||||
IIO Device characteristics
|
||||
==========================
|
||||
|
||||
The AD4000 series driver supports differential and pseudo-differential ADCs.
|
||||
|
||||
The span compression feature available in AD4000 series devices can be
|
||||
enabled/disabled by changing the ``_scale_available`` attribute of the voltage
|
||||
channel. Note that span compression configuration requires writing to AD4000
|
||||
configuration register, which is only possible when the ADC is wired in 3-wire
|
||||
turbo mode, and the SPI controller is ``SPI_MOSI_IDLE_HIGH`` capable. If those
|
||||
conditions are not met, no ``_scale_available`` attribute is provided.
|
||||
|
||||
Besides that, differential and pseudo-differential voltage channels present
|
||||
slightly different sysfs interfaces.
|
||||
|
||||
Pseudo-differential ADCs
|
||||
------------------------
|
||||
|
||||
Typical voltage channel attributes of a pseudo-differential AD4000 series device:
|
||||
|
||||
+-------------------------------------------+------------------------------------------+
|
||||
| Voltage Channel Attributes | Description |
|
||||
+===========================================+==========================================+
|
||||
| ``in_voltage0_raw`` | Raw ADC output code. |
|
||||
+-------------------------------------------+------------------------------------------+
|
||||
| ``in_voltage0_offset`` | Offset to convert raw value to mV. |
|
||||
+-------------------------------------------+------------------------------------------+
|
||||
| ``in_voltage0_scale`` | Scale factor to convert raw value to mV. |
|
||||
+-------------------------------------------+------------------------------------------+
|
||||
| ``in_voltage0_scale_available`` | Toggles input span compression |
|
||||
+-------------------------------------------+------------------------------------------+
|
||||
|
||||
Differential ADCs
|
||||
-----------------
|
||||
|
||||
Typical voltage channel attributes of a differential AD4000 series device:
|
||||
|
||||
+-------------------------------------------+------------------------------------------+
|
||||
| Voltage Channel Attributes | Description |
|
||||
+===========================================+==========================================+
|
||||
| ``in_voltage0-voltage1_raw`` | Raw ADC output code. |
|
||||
+-------------------------------------------+------------------------------------------+
|
||||
| ``in_voltage0-voltage1_scale`` | Scale factor to convert raw value to mV. |
|
||||
+-------------------------------------------+------------------------------------------+
|
||||
| ``in_voltage0-voltage1_scale_available`` | Toggles input span compression |
|
||||
+-------------------------------------------+------------------------------------------+
|
||||
|
||||
SPI offload support
|
||||
-------------------
|
||||
|
||||
To be able to achieve the maximum sample rate, the driver can be used with SPI
|
||||
offload engines such as the one usually present in `AXI SPI Engine`_, to provide
|
||||
SPI offload support.
|
||||
|
||||
.. _AXI SPI Engine: http://analogdevicesinc.github.io/hdl/projects/pulsar_adc/index.html
|
||||
|
||||
To keep up with SPI offloading transfer speeds, the ADC must be connected either
|
||||
in 3-wire turbo mode or in 3-wire without busy indicator mode and have SPI
|
||||
controller CS line connected to the CNV pin.
|
||||
|
||||
When set for SPI offload support, the IIO device will provide different
|
||||
interfaces.
|
||||
|
||||
* Either ``in_voltage0_sampling_frequency`` or
|
||||
``in_voltage0-voltage1_sampling_frequency`` file is provided to allow setting
|
||||
the sample rate.
|
||||
* IIO trigger device is not provided (no ``trigger`` directory).
|
||||
* ``timestamp`` channel is not provided.
|
||||
|
||||
Also, because the ADC output has a one sample latency (delay) when the device is
|
||||
wired in "3-wire" mode and only one transfer per sample is done when using SPI
|
||||
offloading, the first data sample in the buffer is not valid because it contains
|
||||
the output of an earlier conversion result.
|
||||
|
|
|
@ -27,6 +27,7 @@ The following chips are supported by this driver:
|
|||
* `AD7386-4 <https://www.analog.com/en/products/ad7386-4.html>`_
|
||||
* `AD7387-4 <https://www.analog.com/en/products/ad7387-4.html>`_
|
||||
* `AD7388-4 <https://www.analog.com/en/products/ad7388-4.html>`_
|
||||
* `AD7389-4 <https://www.analog.com/en/products/ad7389-4.html>`_
|
||||
* `ADAQ4370-4 <https://www.analog.com/en/products/adaq4370-4.html>`_
|
||||
* `ADAQ4380-4 <https://www.analog.com/en/products/adaq4380-4.html>`_
|
||||
* `ADAQ4381-4 <https://www.analog.com/en/products/adaq4381-4.html>`_
|
||||
|
@ -50,6 +51,12 @@ ad7380-4
|
|||
ad7380-4 supports only an external reference voltage (2.5V to 3.3V). It must be
|
||||
declared in the device tree as ``refin-supply``.
|
||||
|
||||
ad7389-4
|
||||
~~~~~~~~
|
||||
|
||||
ad7389-4 supports only an internal reference voltage. ``refin-supply`` and
|
||||
``refio-supply`` properties are both omitted in this case.
|
||||
|
||||
ADAQ devices
|
||||
~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -26,6 +26,35 @@ SPI wiring modes
|
|||
These ADCs can output data on several SDO lines (1/2/4/8). The driver
|
||||
currently supports only 1 SDO line.
|
||||
|
||||
SPI offload wiring
|
||||
------------------
|
||||
When used with a SPI offload, the supported wiring configuration is:
|
||||
|
||||
.. code-block::
|
||||
|
||||
+-------------+ +-------------+
|
||||
| BUSY |-------->| TRIGGER |
|
||||
| CS |<--------| CS |
|
||||
| | | |
|
||||
| ADC | | SPI |
|
||||
| | | |
|
||||
| SDI |<--------| SDO |
|
||||
| DOUTA |-------->| SDI |
|
||||
| SCLK |<--------| SCLK |
|
||||
| | | |
|
||||
| | +-------------+
|
||||
| CONVST |<--------| PWM |
|
||||
+-------------+ +-------------+
|
||||
|
||||
In this case, the ``pwms`` property is required.
|
||||
The ``#trigger-source-cells = <1>`` property is also required to connect back
|
||||
to the SPI offload. The SPI offload will have ``trigger-sources`` property
|
||||
with a cell to indicate the busy signal:
|
||||
``<&ad7606 AD4695_TRIGGER_EVENT_BUSY>``.
|
||||
|
||||
.. seealso:: `SPI offload support`_
|
||||
|
||||
|
||||
Parallel wiring mode
|
||||
--------------------
|
||||
|
||||
|
@ -123,6 +152,22 @@ Unimplemented features
|
|||
- CRC indication
|
||||
- Calibration
|
||||
|
||||
SPI offload support
|
||||
===================
|
||||
|
||||
To be able to achieve the maximum sample rate, the driver can be used with the
|
||||
`AXI SPI Engine`_ to provide SPI offload support.
|
||||
|
||||
.. _AXI SPI Engine: https://analogdevicesinc.github.io/hdl/library/spi_engine/index.html
|
||||
|
||||
When SPI offload is being used, some attributes will be different.
|
||||
|
||||
* ``trigger`` directory is removed.
|
||||
* ``sampling_frequency`` attribute is added for setting the sample rate.
|
||||
* ``timestamp`` channel is removed.
|
||||
* Buffer data format may be different compared to when offload is not used,
|
||||
e.g. the ``in_voltage0_type`` attribute.
|
||||
|
||||
Device buffers
|
||||
==============
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ Industrial I/O Kernel Drivers
|
|||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
ad3552r
|
||||
ad4000
|
||||
ad4030
|
||||
ad4695
|
||||
|
|
99
Documentation/misc-devices/amd-sbi.rst
Normal file
99
Documentation/misc-devices/amd-sbi.rst
Normal file
|
@ -0,0 +1,99 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=======================
|
||||
AMD SIDE BAND interface
|
||||
=======================
|
||||
|
||||
Some AMD Zen based processors supports system management
|
||||
functionality via side-band interface (SBI) called
|
||||
Advanced Platform Management Link (APML). APML is an I2C/I3C
|
||||
based 2-wire processor target interface. APML is used to
|
||||
communicate with the Remote Management Interface
|
||||
(SB Remote Management Interface (SB-RMI)
|
||||
and SB Temperature Sensor Interface (SB-TSI)).
|
||||
|
||||
More details on the interface can be found in chapter
|
||||
"5 Advanced Platform Management Link (APML)" of the family/model PPR [1]_.
|
||||
|
||||
.. [1] https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/programmer-references/55898_B1_pub_0_50.zip
|
||||
|
||||
|
||||
SBRMI device
|
||||
============
|
||||
|
||||
apml_sbrmi driver under the drivers/misc/amd-sbi creates miscdevice
|
||||
/dev/sbrmi-* to let user space programs run APML mailbox, CPUID,
|
||||
MCAMSR and register xfer commands.
|
||||
|
||||
Register sets is common across APML protocols. IOCTL is providing synchronization
|
||||
among protocols as transactions may create race condition.
|
||||
|
||||
$ ls -al /dev/sbrmi-3c
|
||||
crw------- 1 root root 10, 53 Jul 10 11:13 /dev/sbrmi-3c
|
||||
|
||||
apml_sbrmi driver registers hwmon sensors for monitoring power_cap_max,
|
||||
current power consumption and managing power_cap.
|
||||
|
||||
Characteristics of the dev node:
|
||||
* Differnet xfer protocols are defined:
|
||||
* Mailbox
|
||||
* CPUID
|
||||
* MCA_MSR
|
||||
* Register xfer
|
||||
|
||||
Access restrictions:
|
||||
* Only root user is allowed to open the file.
|
||||
* APML Mailbox messages and Register xfer access are read-write,
|
||||
* CPUID and MCA_MSR access is read-only.
|
||||
|
||||
Driver IOCTLs
|
||||
=============
|
||||
|
||||
.. c:macro:: SBRMI_IOCTL_MBOX_CMD
|
||||
.. kernel-doc:: include/uapi/misc/amd-apml.h
|
||||
:doc: SBRMI_IOCTL_MBOX_CMD
|
||||
.. c:macro:: SBRMI_IOCTL_CPUID_CMD
|
||||
.. kernel-doc:: include/uapi/misc/amd-apml.h
|
||||
:doc: SBRMI_IOCTL_CPUID_CMD
|
||||
.. c:macro:: SBRMI_IOCTL_MCAMSR_CMD
|
||||
.. kernel-doc:: include/uapi/misc/amd-apml.h
|
||||
:doc: SBRMI_IOCTL_MCAMSR_CMD
|
||||
.. c:macro:: SBRMI_IOCTL_REG_XFER_CMD
|
||||
.. kernel-doc:: include/uapi/misc/amd-apml.h
|
||||
:doc: SBRMI_IOCTL_REG_XFER_CMD
|
||||
|
||||
User-space usage
|
||||
================
|
||||
|
||||
To access side band interface from a C program.
|
||||
First, user need to include the headers::
|
||||
|
||||
#include <uapi/misc/amd-apml.h>
|
||||
|
||||
Which defines the supported IOCTL and data structure to be passed
|
||||
from the user space.
|
||||
|
||||
Next thing, open the device file, as follows::
|
||||
|
||||
int file;
|
||||
|
||||
file = open("/dev/sbrmi-*", O_RDWR);
|
||||
if (file < 0) {
|
||||
/* ERROR HANDLING */
|
||||
exit(1);
|
||||
}
|
||||
|
||||
The following IOCTLs are defined:
|
||||
|
||||
``#define SB_BASE_IOCTL_NR 0xF9``
|
||||
``#define SBRMI_IOCTL_MBOX_CMD _IOWR(SB_BASE_IOCTL_NR, 0, struct apml_mbox_msg)``
|
||||
``#define SBRMI_IOCTL_CPUID_CMD _IOWR(SB_BASE_IOCTL_NR, 1, struct apml_cpuid_msg)``
|
||||
``#define SBRMI_IOCTL_MCAMSR_CMD _IOWR(SB_BASE_IOCTL_NR, 2, struct apml_mcamsr_msg)``
|
||||
``#define SBRMI_IOCTL_REG_XFER_CMD _IOWR(SB_BASE_IOCTL_NR, 3, struct apml_reg_xfer_msg)``
|
||||
|
||||
|
||||
User space C-APIs are made available by esmi_oob_library, hosted at
|
||||
[2]_ which is provided by the E-SMS project [3]_.
|
||||
|
||||
.. [2] https://github.com/amd/esmi_oob_library
|
||||
.. [3] https://www.amd.com/en/developer/e-sms.html
|
|
@ -12,6 +12,7 @@ fit into other categories.
|
|||
:maxdepth: 2
|
||||
|
||||
ad525x_dpot
|
||||
amd-sbi
|
||||
apds990x
|
||||
bh1770glc
|
||||
c2port
|
||||
|
|
|
@ -22,10 +22,10 @@ sporting the feature officially called "HP Mobile Data Protection System 3D" or
|
|||
models (full list can be found in drivers/platform/x86/hp_accel.c) will have
|
||||
their axis automatically oriented on standard way (eg: you can directly play
|
||||
neverball). The accelerometer data is readable via
|
||||
/sys/devices/platform/lis3lv02d. Reported values are scaled
|
||||
/sys/devices/faux/lis3lv02d. Reported values are scaled
|
||||
to mg values (1/1000th of earth gravity).
|
||||
|
||||
Sysfs attributes under /sys/devices/platform/lis3lv02d/:
|
||||
Sysfs attributes under /sys/devices/faux/lis3lv02d/:
|
||||
|
||||
position
|
||||
- 3D position that the accelerometer reports. Format: "(x,y,z)"
|
||||
|
@ -85,7 +85,7 @@ the accelerometer are converted into a "standard" organisation of the axes
|
|||
If your laptop model is not recognized (cf "dmesg"), you can send an
|
||||
email to the maintainer to add it to the database. When reporting a new
|
||||
laptop, please include the output of "dmidecode" plus the value of
|
||||
/sys/devices/platform/lis3lv02d/position in these four cases.
|
||||
/sys/devices/faux/lis3lv02d/position in these four cases.
|
||||
|
||||
Q&A
|
||||
---
|
||||
|
|
|
@ -78,6 +78,37 @@ enabled like::
|
|||
|
||||
Please refer to the kernel configuration help for more information.
|
||||
|
||||
Fine-grained tracing with AUX pause and resume
|
||||
----------------------------------------------
|
||||
|
||||
Arm CoreSight may generate a large amount of hardware trace data, which
|
||||
will lead to overhead in recording and distract users when reviewing
|
||||
profiling result. To mitigate the issue of excessive trace data, Perf
|
||||
provides AUX pause and resume functionality for fine-grained tracing.
|
||||
|
||||
The AUX pause and resume can be triggered by associated events. These
|
||||
events can be ftrace tracepoints (including static and dynamic
|
||||
tracepoints) or PMU events (e.g. CPU PMU cycle event). To create a perf
|
||||
session with AUX pause / resume, three configuration terms are
|
||||
introduced:
|
||||
|
||||
- "aux-action=start-paused": it is specified for the cs_etm PMU event to
|
||||
launch in a paused state.
|
||||
- "aux-action=pause": an associated event is specified with this term
|
||||
to pause AUX trace.
|
||||
- "aux-action=resume": an associated event is specified with this term
|
||||
to resume AUX trace.
|
||||
|
||||
Example for triggering AUX pause and resume with ftrace tracepoints::
|
||||
|
||||
perf record -e cs_etm/aux-action=start-paused/k,syscalls:sys_enter_openat/aux-action=resume/,syscalls:sys_exit_openat/aux-action=pause/ ls
|
||||
|
||||
Example for triggering AUX pause and resume with PMU event::
|
||||
|
||||
perf record -a -e cs_etm/aux-action=start-paused/k \
|
||||
-e cycles/aux-action=pause,period=10000000/ \
|
||||
-e cycles/aux-action=resume,period=1050000/ -- sleep 1
|
||||
|
||||
Perf test - Verify kernel and userspace perf CoreSight work
|
||||
-----------------------------------------------------------
|
||||
|
||||
|
|
|
@ -402,6 +402,8 @@ Code Seq# Include File Comments
|
|||
<mailto:mathieu.desnoyers@efficios.com>
|
||||
0xF8 all arch/x86/include/uapi/asm/amd_hsmp.h AMD HSMP EPYC system management interface driver
|
||||
<mailto:nchatrad@amd.com>
|
||||
0xF9 00-0F uapi/misc/amd-apml.h AMD side band system management interface driver
|
||||
<mailto:naveenkrishna.chatradhi@amd.com>
|
||||
0xFD all linux/dm-ioctl.h
|
||||
0xFE all linux/isst_if.h
|
||||
==== ===== ======================================================= ================================================================
|
||||
|
|
70
MAINTAINERS
70
MAINTAINERS
|
@ -1338,12 +1338,21 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
|
|||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
|
||||
F: drivers/net/amt.c
|
||||
|
||||
ANALOG DEVICES INC AD3530R DRIVER
|
||||
M: Kim Seer Paller <kimseer.paller@analog.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
F: Documentation/devicetree/bindings/iio/dac/adi,ad3530r.yaml
|
||||
F: drivers/iio/dac/ad3530r.c
|
||||
|
||||
ANALOG DEVICES INC AD3552R DRIVER
|
||||
M: Nuno Sá <nuno.sa@analog.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
F: Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
|
||||
F: Documentation/iio/ad3552r.rst
|
||||
F: drivers/iio/dac/ad3552r.c
|
||||
|
||||
ANALOG DEVICES INC AD4000 DRIVER
|
||||
|
@ -1387,6 +1396,16 @@ F: Documentation/iio/ad4695.rst
|
|||
F: drivers/iio/adc/ad4695.c
|
||||
F: include/dt-bindings/iio/adc/adi,ad4695.h
|
||||
|
||||
ANALOG DEVICES INC AD4851 DRIVER
|
||||
M: Sergiu Cuciurean <sergiu.cuciurean@analog.com>
|
||||
M: Dragos Bogdan <dragos.bogdan@analog.com>
|
||||
R: Antoniu Miclaus <antoniu.miclaus@analog.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Supported
|
||||
W: https://ez.analog.com/linux-software-drivers
|
||||
F: Documentation/devicetree/bindings/iio/adc/adi,ad4851.yaml
|
||||
F: drivers/iio/adc/ad4851.c
|
||||
|
||||
ANALOG DEVICES INC AD7091R DRIVER
|
||||
M: Marcelo Schmitt <marcelo.schmitt@analog.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
|
@ -2322,11 +2341,13 @@ F: Documentation/devicetree/bindings/mailbox/apple,mailbox.yaml
|
|||
F: Documentation/devicetree/bindings/net/bluetooth/brcm,bcm4377-bluetooth.yaml
|
||||
F: Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml
|
||||
F: Documentation/devicetree/bindings/nvmem/apple,efuses.yaml
|
||||
F: Documentation/devicetree/bindings/nvmem/apple,spmi-nvmem.yaml
|
||||
F: Documentation/devicetree/bindings/pci/apple,pcie.yaml
|
||||
F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
|
||||
F: Documentation/devicetree/bindings/power/apple*
|
||||
F: Documentation/devicetree/bindings/pwm/apple,s5l-fpwm.yaml
|
||||
F: Documentation/devicetree/bindings/spi/apple,spi.yaml
|
||||
F: Documentation/devicetree/bindings/spmi/apple,spmi.yaml
|
||||
F: Documentation/devicetree/bindings/watchdog/apple,wdt.yaml
|
||||
F: arch/arm64/boot/dts/apple/
|
||||
F: drivers/bluetooth/hci_bcm4377.c
|
||||
|
@ -2342,10 +2363,12 @@ F: drivers/iommu/io-pgtable-dart.c
|
|||
F: drivers/irqchip/irq-apple-aic.c
|
||||
F: drivers/nvme/host/apple.c
|
||||
F: drivers/nvmem/apple-efuses.c
|
||||
F: drivers/nvmem/apple-spmi-nvmem.c
|
||||
F: drivers/pinctrl/pinctrl-apple-gpio.c
|
||||
F: drivers/pwm/pwm-apple.c
|
||||
F: drivers/soc/apple/*
|
||||
F: drivers/spi/spi-apple.c
|
||||
F: drivers/spmi/spmi-apple-controller.c
|
||||
F: drivers/video/backlight/apple_dwi_bl.c
|
||||
F: drivers/watchdog/apple_wdt.c
|
||||
F: include/dt-bindings/interrupt-controller/apple-aic.h
|
||||
|
@ -6938,6 +6961,12 @@ L: linux-rtc@vger.kernel.org
|
|||
S: Maintained
|
||||
F: drivers/rtc/rtc-sd2405al.c
|
||||
|
||||
DFROBOT SEN0322 DRIVER
|
||||
M: Tóth János <gomba007@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/iio/chemical/sen0322.c
|
||||
|
||||
DH ELECTRONICS DHSOM SOM AND BOARD SUPPORT
|
||||
M: Christoph Niedermaier <cniedermaier@dh-electronics.com>
|
||||
M: Marek Vasut <marex@denx.de>
|
||||
|
@ -11644,6 +11673,13 @@ L: linux-media@vger.kernel.org
|
|||
S: Maintained
|
||||
F: drivers/media/rc/iguanair.c
|
||||
|
||||
IIO ADC HELPERS
|
||||
M: Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/iio/adc/industrialio-adc.c
|
||||
F: include/linux/iio/adc-helpers.h
|
||||
|
||||
IIO BACKEND FRAMEWORK
|
||||
M: Nuno Sa <nuno.sa@analog.com>
|
||||
R: Olivier Moysan <olivier.moysan@foss.st.com>
|
||||
|
@ -11692,7 +11728,9 @@ F: drivers/iio/common/scmi_sensors/scmi_iio.c
|
|||
|
||||
IIO SUBSYSTEM AND DRIVERS
|
||||
M: Jonathan Cameron <jic23@kernel.org>
|
||||
R: Lars-Peter Clausen <lars@metafoo.de>
|
||||
R: David Lechner <dlechner@baylibre.com>
|
||||
R: Nuno Sá <nuno.sa@analog.com>
|
||||
R: Andy Shevchenko <andy@kernel.org>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git
|
||||
|
@ -12285,7 +12323,7 @@ F: drivers/mfd/intel-m10-bmc*
|
|||
F: include/linux/mfd/intel-m10-bmc.h
|
||||
|
||||
INTEL MAX10 BMC SECURE UPDATES
|
||||
M: Peter Colberg <peter.colberg@altera.com>
|
||||
M: Matthew Gerlach <matthew.gerlach@altera.com>
|
||||
L: linux-fpga@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
|
||||
|
@ -16938,7 +16976,7 @@ F: include/uapi/linux/mmc/
|
|||
|
||||
MULTIPLEXER SUBSYSTEM
|
||||
M: Peter Rosin <peda@axentia.se>
|
||||
S: Maintained
|
||||
S: Odd Fixes
|
||||
F: Documentation/ABI/testing/sysfs-class-mux*
|
||||
F: Documentation/devicetree/bindings/mux/
|
||||
F: drivers/mux/
|
||||
|
@ -17715,6 +17753,13 @@ F: drivers/nubus/
|
|||
F: include/linux/nubus.h
|
||||
F: include/uapi/linux/nubus.h
|
||||
|
||||
NUVOTON NCT7201 IIO DRIVER
|
||||
M: Eason Yang <j2anfernee@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/adc/nuvoton,nct7201.yaml
|
||||
F: drivers/iio/adc/nct7201.c
|
||||
|
||||
NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER
|
||||
M: Antonino Daplas <adaplas@gmail.com>
|
||||
L: linux-fbdev@vger.kernel.org
|
||||
|
@ -21445,6 +21490,11 @@ S: Supported
|
|||
F: drivers/power/supply/bd99954-charger.c
|
||||
F: drivers/power/supply/bd99954-charger.h
|
||||
|
||||
ROHM BD79124 ADC / GPO IC
|
||||
M: Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
S: Supported
|
||||
F: drivers/iio/adc/rohm-bd79124.c
|
||||
|
||||
ROHM BH1745 COLOUR SENSOR
|
||||
M: Mudit Sharma <muditsharma.info@gmail.com>
|
||||
L: linux-iio@vger.kernel.org
|
||||
|
@ -24646,6 +24696,12 @@ M: Robert Richter <rric@kernel.org>
|
|||
S: Odd Fixes
|
||||
F: drivers/gpio/gpio-thunderx.c
|
||||
|
||||
TI ADC12xs and ROHM BD79104 ADC driver
|
||||
M: Matti Vaittinen <mazziesaccount@gmail.com>
|
||||
S: Maintained
|
||||
F: drivers/iio/adc/ti-adc128s052.c
|
||||
L: linux-iio@vger.kernel.org
|
||||
|
||||
TI ADS1119 ADC DRIVER
|
||||
M: Francesco Dolcini <francesco@dolcini.it>
|
||||
M: João Paulo Gonçalves <jpaulo.silvagoncalves@gmail.com>
|
||||
|
@ -26595,6 +26651,12 @@ M: David Härdeman <david@hardeman.nu>
|
|||
S: Maintained
|
||||
F: drivers/media/rc/winbond-cir.c
|
||||
|
||||
WINSEN MHZ19B
|
||||
M: Gyeyoung Baek <gye976@gmail.com>
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/iio/chemical/winsen,mhz19b.yaml
|
||||
F: drivers/iio/chemical/mhz19b.c
|
||||
|
||||
WINSYSTEMS EBC-C384 WATCHDOG DRIVER
|
||||
L: linux-watchdog@vger.kernel.org
|
||||
S: Orphan
|
||||
|
@ -27092,8 +27154,6 @@ M: Dragan Cvetic <dragan.cvetic@amd.com>
|
|||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/misc/xlnx,sd-fec.yaml
|
||||
F: Documentation/misc-devices/xilinx_sdfec.rst
|
||||
F: drivers/misc/Kconfig
|
||||
F: drivers/misc/Makefile
|
||||
F: drivers/misc/xilinx_sdfec.c
|
||||
F: include/uapi/misc/xilinx_sdfec.h
|
||||
|
||||
|
|
|
@ -79,6 +79,8 @@ static HLIST_HEAD(binder_deferred_list);
|
|||
static DEFINE_MUTEX(binder_deferred_lock);
|
||||
|
||||
static HLIST_HEAD(binder_devices);
|
||||
static DEFINE_SPINLOCK(binder_devices_lock);
|
||||
|
||||
static HLIST_HEAD(binder_procs);
|
||||
static DEFINE_MUTEX(binder_procs_lock);
|
||||
|
||||
|
@ -3261,20 +3263,16 @@ static void binder_transaction(struct binder_proc *proc,
|
|||
|
||||
if (reply)
|
||||
binder_debug(BINDER_DEBUG_TRANSACTION,
|
||||
"%d:%d BC_REPLY %d -> %d:%d, data %016llx-%016llx size %lld-%lld-%lld\n",
|
||||
"%d:%d BC_REPLY %d -> %d:%d, data size %lld-%lld-%lld\n",
|
||||
proc->pid, thread->pid, t->debug_id,
|
||||
target_proc->pid, target_thread->pid,
|
||||
(u64)tr->data.ptr.buffer,
|
||||
(u64)tr->data.ptr.offsets,
|
||||
(u64)tr->data_size, (u64)tr->offsets_size,
|
||||
(u64)extra_buffers_size);
|
||||
else
|
||||
binder_debug(BINDER_DEBUG_TRANSACTION,
|
||||
"%d:%d BC_TRANSACTION %d -> %d - node %d, data %016llx-%016llx size %lld-%lld-%lld\n",
|
||||
"%d:%d BC_TRANSACTION %d -> %d - node %d, data size %lld-%lld-%lld\n",
|
||||
proc->pid, thread->pid, t->debug_id,
|
||||
target_proc->pid, target_node->debug_id,
|
||||
(u64)tr->data.ptr.buffer,
|
||||
(u64)tr->data.ptr.offsets,
|
||||
(u64)tr->data_size, (u64)tr->offsets_size,
|
||||
(u64)extra_buffers_size);
|
||||
|
||||
|
@ -4223,20 +4221,21 @@ static int binder_thread_write(struct binder_proc *proc,
|
|||
if (IS_ERR_OR_NULL(buffer)) {
|
||||
if (PTR_ERR(buffer) == -EPERM) {
|
||||
binder_user_error(
|
||||
"%d:%d BC_FREE_BUFFER u%016llx matched unreturned or currently freeing buffer\n",
|
||||
"%d:%d BC_FREE_BUFFER matched unreturned or currently freeing buffer at offset %lx\n",
|
||||
proc->pid, thread->pid,
|
||||
(u64)data_ptr);
|
||||
(unsigned long)data_ptr - proc->alloc.vm_start);
|
||||
} else {
|
||||
binder_user_error(
|
||||
"%d:%d BC_FREE_BUFFER u%016llx no match\n",
|
||||
"%d:%d BC_FREE_BUFFER no match for buffer at offset %lx\n",
|
||||
proc->pid, thread->pid,
|
||||
(u64)data_ptr);
|
||||
(unsigned long)data_ptr - proc->alloc.vm_start);
|
||||
}
|
||||
break;
|
||||
}
|
||||
binder_debug(BINDER_DEBUG_FREE_BUFFER,
|
||||
"%d:%d BC_FREE_BUFFER u%016llx found buffer %d for %s transaction\n",
|
||||
proc->pid, thread->pid, (u64)data_ptr,
|
||||
"%d:%d BC_FREE_BUFFER at offset %lx found buffer %d for %s transaction\n",
|
||||
proc->pid, thread->pid,
|
||||
(unsigned long)data_ptr - proc->alloc.vm_start,
|
||||
buffer->debug_id,
|
||||
buffer->transaction ? "active" : "finished");
|
||||
binder_free_buf(proc, thread, buffer, false);
|
||||
|
@ -5053,16 +5052,14 @@ retry:
|
|||
trace_binder_transaction_received(t);
|
||||
binder_stat_br(proc, thread, cmd);
|
||||
binder_debug(BINDER_DEBUG_TRANSACTION,
|
||||
"%d:%d %s %d %d:%d, cmd %u size %zd-%zd ptr %016llx-%016llx\n",
|
||||
"%d:%d %s %d %d:%d, cmd %u size %zd-%zd\n",
|
||||
proc->pid, thread->pid,
|
||||
(cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
|
||||
(cmd == BR_TRANSACTION_SEC_CTX) ?
|
||||
"BR_TRANSACTION_SEC_CTX" : "BR_REPLY",
|
||||
t->debug_id, t_from ? t_from->proc->pid : 0,
|
||||
t_from ? t_from->pid : 0, cmd,
|
||||
t->buffer->data_size, t->buffer->offsets_size,
|
||||
(u64)trd->data.ptr.buffer,
|
||||
(u64)trd->data.ptr.offsets);
|
||||
t->buffer->data_size, t->buffer->offsets_size);
|
||||
|
||||
if (t_from)
|
||||
binder_thread_dec_tmpref(t_from);
|
||||
|
@ -5244,6 +5241,7 @@ static void binder_free_proc(struct binder_proc *proc)
|
|||
__func__, proc->outstanding_txns);
|
||||
device = container_of(proc->context, struct binder_device, context);
|
||||
if (refcount_dec_and_test(&device->ref)) {
|
||||
binder_remove_device(device);
|
||||
kfree(proc->context->name);
|
||||
kfree(device);
|
||||
}
|
||||
|
@ -6377,10 +6375,10 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
|
|||
}
|
||||
|
||||
static void print_binder_work_ilocked(struct seq_file *m,
|
||||
struct binder_proc *proc,
|
||||
const char *prefix,
|
||||
const char *transaction_prefix,
|
||||
struct binder_work *w)
|
||||
struct binder_proc *proc,
|
||||
const char *prefix,
|
||||
const char *transaction_prefix,
|
||||
struct binder_work *w, bool hash_ptrs)
|
||||
{
|
||||
struct binder_node *node;
|
||||
struct binder_transaction *t;
|
||||
|
@ -6403,9 +6401,15 @@ static void print_binder_work_ilocked(struct seq_file *m,
|
|||
break;
|
||||
case BINDER_WORK_NODE:
|
||||
node = container_of(w, struct binder_node, work);
|
||||
seq_printf(m, "%snode work %d: u%016llx c%016llx\n",
|
||||
prefix, node->debug_id,
|
||||
(u64)node->ptr, (u64)node->cookie);
|
||||
if (hash_ptrs)
|
||||
seq_printf(m, "%snode work %d: u%p c%p\n",
|
||||
prefix, node->debug_id,
|
||||
(void *)(long)node->ptr,
|
||||
(void *)(long)node->cookie);
|
||||
else
|
||||
seq_printf(m, "%snode work %d: u%016llx c%016llx\n",
|
||||
prefix, node->debug_id,
|
||||
(u64)node->ptr, (u64)node->cookie);
|
||||
break;
|
||||
case BINDER_WORK_DEAD_BINDER:
|
||||
seq_printf(m, "%shas dead binder\n", prefix);
|
||||
|
@ -6430,7 +6434,7 @@ static void print_binder_work_ilocked(struct seq_file *m,
|
|||
|
||||
static void print_binder_thread_ilocked(struct seq_file *m,
|
||||
struct binder_thread *thread,
|
||||
int print_always)
|
||||
bool print_always, bool hash_ptrs)
|
||||
{
|
||||
struct binder_transaction *t;
|
||||
struct binder_work *w;
|
||||
|
@ -6460,14 +6464,16 @@ static void print_binder_thread_ilocked(struct seq_file *m,
|
|||
}
|
||||
list_for_each_entry(w, &thread->todo, entry) {
|
||||
print_binder_work_ilocked(m, thread->proc, " ",
|
||||
" pending transaction", w);
|
||||
" pending transaction",
|
||||
w, hash_ptrs);
|
||||
}
|
||||
if (!print_always && m->count == header_pos)
|
||||
m->count = start_pos;
|
||||
}
|
||||
|
||||
static void print_binder_node_nilocked(struct seq_file *m,
|
||||
struct binder_node *node)
|
||||
struct binder_node *node,
|
||||
bool hash_ptrs)
|
||||
{
|
||||
struct binder_ref *ref;
|
||||
struct binder_work *w;
|
||||
|
@ -6475,8 +6481,13 @@ static void print_binder_node_nilocked(struct seq_file *m,
|
|||
|
||||
count = hlist_count_nodes(&node->refs);
|
||||
|
||||
seq_printf(m, " node %d: u%016llx c%016llx hs %d hw %d ls %d lw %d is %d iw %d tr %d",
|
||||
node->debug_id, (u64)node->ptr, (u64)node->cookie,
|
||||
if (hash_ptrs)
|
||||
seq_printf(m, " node %d: u%p c%p", node->debug_id,
|
||||
(void *)(long)node->ptr, (void *)(long)node->cookie);
|
||||
else
|
||||
seq_printf(m, " node %d: u%016llx c%016llx", node->debug_id,
|
||||
(u64)node->ptr, (u64)node->cookie);
|
||||
seq_printf(m, " hs %d hw %d ls %d lw %d is %d iw %d tr %d",
|
||||
node->has_strong_ref, node->has_weak_ref,
|
||||
node->local_strong_refs, node->local_weak_refs,
|
||||
node->internal_strong_refs, count, node->tmp_refs);
|
||||
|
@ -6489,7 +6500,8 @@ static void print_binder_node_nilocked(struct seq_file *m,
|
|||
if (node->proc) {
|
||||
list_for_each_entry(w, &node->async_todo, entry)
|
||||
print_binder_work_ilocked(m, node->proc, " ",
|
||||
" pending async transaction", w);
|
||||
" pending async transaction",
|
||||
w, hash_ptrs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6505,8 +6517,54 @@ static void print_binder_ref_olocked(struct seq_file *m,
|
|||
binder_node_unlock(ref->node);
|
||||
}
|
||||
|
||||
static void print_binder_proc(struct seq_file *m,
|
||||
struct binder_proc *proc, int print_all)
|
||||
/**
|
||||
* print_next_binder_node_ilocked() - Print binder_node from a locked list
|
||||
* @m: struct seq_file for output via seq_printf()
|
||||
* @proc: struct binder_proc we hold the inner_proc_lock to (if any)
|
||||
* @node: struct binder_node to print fields of
|
||||
* @prev_node: struct binder_node we hold a temporary reference to (if any)
|
||||
* @hash_ptrs: whether to hash @node's binder_uintptr_t fields
|
||||
*
|
||||
* Helper function to handle synchronization around printing a struct
|
||||
* binder_node while iterating through @proc->nodes or the dead nodes list.
|
||||
* Caller must hold either @proc->inner_lock (for live nodes) or
|
||||
* binder_dead_nodes_lock. This lock will be released during the body of this
|
||||
* function, but it will be reacquired before returning to the caller.
|
||||
*
|
||||
* Return: pointer to the struct binder_node we hold a tmpref on
|
||||
*/
|
||||
static struct binder_node *
|
||||
print_next_binder_node_ilocked(struct seq_file *m, struct binder_proc *proc,
|
||||
struct binder_node *node,
|
||||
struct binder_node *prev_node, bool hash_ptrs)
|
||||
{
|
||||
/*
|
||||
* Take a temporary reference on the node so that isn't freed while
|
||||
* we print it.
|
||||
*/
|
||||
binder_inc_node_tmpref_ilocked(node);
|
||||
/*
|
||||
* Live nodes need to drop the inner proc lock and dead nodes need to
|
||||
* drop the binder_dead_nodes_lock before trying to take the node lock.
|
||||
*/
|
||||
if (proc)
|
||||
binder_inner_proc_unlock(proc);
|
||||
else
|
||||
spin_unlock(&binder_dead_nodes_lock);
|
||||
if (prev_node)
|
||||
binder_put_node(prev_node);
|
||||
binder_node_inner_lock(node);
|
||||
print_binder_node_nilocked(m, node, hash_ptrs);
|
||||
binder_node_inner_unlock(node);
|
||||
if (proc)
|
||||
binder_inner_proc_lock(proc);
|
||||
else
|
||||
spin_lock(&binder_dead_nodes_lock);
|
||||
return node;
|
||||
}
|
||||
|
||||
static void print_binder_proc(struct seq_file *m, struct binder_proc *proc,
|
||||
bool print_all, bool hash_ptrs)
|
||||
{
|
||||
struct binder_work *w;
|
||||
struct rb_node *n;
|
||||
|
@ -6519,31 +6577,19 @@ static void print_binder_proc(struct seq_file *m,
|
|||
header_pos = m->count;
|
||||
|
||||
binder_inner_proc_lock(proc);
|
||||
for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n))
|
||||
for (n = rb_first(&proc->threads); n; n = rb_next(n))
|
||||
print_binder_thread_ilocked(m, rb_entry(n, struct binder_thread,
|
||||
rb_node), print_all);
|
||||
rb_node), print_all, hash_ptrs);
|
||||
|
||||
for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) {
|
||||
for (n = rb_first(&proc->nodes); n; n = rb_next(n)) {
|
||||
struct binder_node *node = rb_entry(n, struct binder_node,
|
||||
rb_node);
|
||||
if (!print_all && !node->has_async_transaction)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* take a temporary reference on the node so it
|
||||
* survives and isn't removed from the tree
|
||||
* while we print it.
|
||||
*/
|
||||
binder_inc_node_tmpref_ilocked(node);
|
||||
/* Need to drop inner lock to take node lock */
|
||||
binder_inner_proc_unlock(proc);
|
||||
if (last_node)
|
||||
binder_put_node(last_node);
|
||||
binder_node_inner_lock(node);
|
||||
print_binder_node_nilocked(m, node);
|
||||
binder_node_inner_unlock(node);
|
||||
last_node = node;
|
||||
binder_inner_proc_lock(proc);
|
||||
last_node = print_next_binder_node_ilocked(m, proc, node,
|
||||
last_node,
|
||||
hash_ptrs);
|
||||
}
|
||||
binder_inner_proc_unlock(proc);
|
||||
if (last_node)
|
||||
|
@ -6551,19 +6597,18 @@ static void print_binder_proc(struct seq_file *m,
|
|||
|
||||
if (print_all) {
|
||||
binder_proc_lock(proc);
|
||||
for (n = rb_first(&proc->refs_by_desc);
|
||||
n != NULL;
|
||||
n = rb_next(n))
|
||||
for (n = rb_first(&proc->refs_by_desc); n; n = rb_next(n))
|
||||
print_binder_ref_olocked(m, rb_entry(n,
|
||||
struct binder_ref,
|
||||
rb_node_desc));
|
||||
struct binder_ref,
|
||||
rb_node_desc));
|
||||
binder_proc_unlock(proc);
|
||||
}
|
||||
binder_alloc_print_allocated(m, &proc->alloc);
|
||||
binder_inner_proc_lock(proc);
|
||||
list_for_each_entry(w, &proc->todo, entry)
|
||||
print_binder_work_ilocked(m, proc, " ",
|
||||
" pending transaction", w);
|
||||
" pending transaction", w,
|
||||
hash_ptrs);
|
||||
list_for_each_entry(w, &proc->delivered_death, entry) {
|
||||
seq_puts(m, " has delivered dead binder\n");
|
||||
break;
|
||||
|
@ -6696,7 +6741,7 @@ static void print_binder_proc_stats(struct seq_file *m,
|
|||
count = 0;
|
||||
ready_threads = 0;
|
||||
binder_inner_proc_lock(proc);
|
||||
for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n))
|
||||
for (n = rb_first(&proc->threads); n; n = rb_next(n))
|
||||
count++;
|
||||
|
||||
list_for_each_entry(thread, &proc->waiting_threads, waiting_thread_node)
|
||||
|
@ -6710,7 +6755,7 @@ static void print_binder_proc_stats(struct seq_file *m,
|
|||
ready_threads,
|
||||
free_async_space);
|
||||
count = 0;
|
||||
for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n))
|
||||
for (n = rb_first(&proc->nodes); n; n = rb_next(n))
|
||||
count++;
|
||||
binder_inner_proc_unlock(proc);
|
||||
seq_printf(m, " nodes: %d\n", count);
|
||||
|
@ -6718,7 +6763,7 @@ static void print_binder_proc_stats(struct seq_file *m,
|
|||
strong = 0;
|
||||
weak = 0;
|
||||
binder_proc_lock(proc);
|
||||
for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {
|
||||
for (n = rb_first(&proc->refs_by_desc); n; n = rb_next(n)) {
|
||||
struct binder_ref *ref = rb_entry(n, struct binder_ref,
|
||||
rb_node_desc);
|
||||
count++;
|
||||
|
@ -6745,7 +6790,7 @@ static void print_binder_proc_stats(struct seq_file *m,
|
|||
print_binder_stats(m, " ", &proc->stats);
|
||||
}
|
||||
|
||||
static int state_show(struct seq_file *m, void *unused)
|
||||
static void print_binder_state(struct seq_file *m, bool hash_ptrs)
|
||||
{
|
||||
struct binder_proc *proc;
|
||||
struct binder_node *node;
|
||||
|
@ -6756,31 +6801,40 @@ static int state_show(struct seq_file *m, void *unused)
|
|||
spin_lock(&binder_dead_nodes_lock);
|
||||
if (!hlist_empty(&binder_dead_nodes))
|
||||
seq_puts(m, "dead nodes:\n");
|
||||
hlist_for_each_entry(node, &binder_dead_nodes, dead_node) {
|
||||
/*
|
||||
* take a temporary reference on the node so it
|
||||
* survives and isn't removed from the list
|
||||
* while we print it.
|
||||
*/
|
||||
node->tmp_refs++;
|
||||
spin_unlock(&binder_dead_nodes_lock);
|
||||
if (last_node)
|
||||
binder_put_node(last_node);
|
||||
binder_node_lock(node);
|
||||
print_binder_node_nilocked(m, node);
|
||||
binder_node_unlock(node);
|
||||
last_node = node;
|
||||
spin_lock(&binder_dead_nodes_lock);
|
||||
}
|
||||
hlist_for_each_entry(node, &binder_dead_nodes, dead_node)
|
||||
last_node = print_next_binder_node_ilocked(m, NULL, node,
|
||||
last_node,
|
||||
hash_ptrs);
|
||||
spin_unlock(&binder_dead_nodes_lock);
|
||||
if (last_node)
|
||||
binder_put_node(last_node);
|
||||
|
||||
mutex_lock(&binder_procs_lock);
|
||||
hlist_for_each_entry(proc, &binder_procs, proc_node)
|
||||
print_binder_proc(m, proc, 1);
|
||||
print_binder_proc(m, proc, true, hash_ptrs);
|
||||
mutex_unlock(&binder_procs_lock);
|
||||
}
|
||||
|
||||
static void print_binder_transactions(struct seq_file *m, bool hash_ptrs)
|
||||
{
|
||||
struct binder_proc *proc;
|
||||
|
||||
seq_puts(m, "binder transactions:\n");
|
||||
mutex_lock(&binder_procs_lock);
|
||||
hlist_for_each_entry(proc, &binder_procs, proc_node)
|
||||
print_binder_proc(m, proc, false, hash_ptrs);
|
||||
mutex_unlock(&binder_procs_lock);
|
||||
}
|
||||
|
||||
static int state_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
print_binder_state(m, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int state_hashed_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
print_binder_state(m, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -6802,14 +6856,13 @@ static int stats_show(struct seq_file *m, void *unused)
|
|||
|
||||
static int transactions_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct binder_proc *proc;
|
||||
|
||||
seq_puts(m, "binder transactions:\n");
|
||||
mutex_lock(&binder_procs_lock);
|
||||
hlist_for_each_entry(proc, &binder_procs, proc_node)
|
||||
print_binder_proc(m, proc, 0);
|
||||
mutex_unlock(&binder_procs_lock);
|
||||
print_binder_transactions(m, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int transactions_hashed_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
print_binder_transactions(m, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -6822,7 +6875,7 @@ static int proc_show(struct seq_file *m, void *unused)
|
|||
hlist_for_each_entry(itr, &binder_procs, proc_node) {
|
||||
if (itr->pid == pid) {
|
||||
seq_puts(m, "binder proc state:\n");
|
||||
print_binder_proc(m, itr, 1);
|
||||
print_binder_proc(m, itr, true, false);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&binder_procs_lock);
|
||||
|
@ -6889,8 +6942,10 @@ const struct file_operations binder_fops = {
|
|||
};
|
||||
|
||||
DEFINE_SHOW_ATTRIBUTE(state);
|
||||
DEFINE_SHOW_ATTRIBUTE(state_hashed);
|
||||
DEFINE_SHOW_ATTRIBUTE(stats);
|
||||
DEFINE_SHOW_ATTRIBUTE(transactions);
|
||||
DEFINE_SHOW_ATTRIBUTE(transactions_hashed);
|
||||
DEFINE_SHOW_ATTRIBUTE(transaction_log);
|
||||
|
||||
const struct binder_debugfs_entry binder_debugfs_entries[] = {
|
||||
|
@ -6900,6 +6955,12 @@ const struct binder_debugfs_entry binder_debugfs_entries[] = {
|
|||
.fops = &state_fops,
|
||||
.data = NULL,
|
||||
},
|
||||
{
|
||||
.name = "state_hashed",
|
||||
.mode = 0444,
|
||||
.fops = &state_hashed_fops,
|
||||
.data = NULL,
|
||||
},
|
||||
{
|
||||
.name = "stats",
|
||||
.mode = 0444,
|
||||
|
@ -6912,6 +6973,12 @@ const struct binder_debugfs_entry binder_debugfs_entries[] = {
|
|||
.fops = &transactions_fops,
|
||||
.data = NULL,
|
||||
},
|
||||
{
|
||||
.name = "transactions_hashed",
|
||||
.mode = 0444,
|
||||
.fops = &transactions_hashed_fops,
|
||||
.data = NULL,
|
||||
},
|
||||
{
|
||||
.name = "transaction_log",
|
||||
.mode = 0444,
|
||||
|
@ -6929,7 +6996,16 @@ const struct binder_debugfs_entry binder_debugfs_entries[] = {
|
|||
|
||||
void binder_add_device(struct binder_device *device)
|
||||
{
|
||||
spin_lock(&binder_devices_lock);
|
||||
hlist_add_head(&device->hlist, &binder_devices);
|
||||
spin_unlock(&binder_devices_lock);
|
||||
}
|
||||
|
||||
void binder_remove_device(struct binder_device *device)
|
||||
{
|
||||
spin_lock(&binder_devices_lock);
|
||||
hlist_del_init(&device->hlist);
|
||||
spin_unlock(&binder_devices_lock);
|
||||
}
|
||||
|
||||
static int __init init_binder_device(const char *name)
|
||||
|
@ -6956,7 +7032,7 @@ static int __init init_binder_device(const char *name)
|
|||
return ret;
|
||||
}
|
||||
|
||||
hlist_add_head(&binder_device->hlist, &binder_devices);
|
||||
binder_add_device(binder_device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -7018,7 +7094,7 @@ static int __init binder_init(void)
|
|||
err_init_binder_device_failed:
|
||||
hlist_for_each_entry_safe(device, tmp, &binder_devices, hlist) {
|
||||
misc_deregister(&device->miscdev);
|
||||
hlist_del(&device->hlist);
|
||||
binder_remove_device(device);
|
||||
kfree(device);
|
||||
}
|
||||
|
||||
|
|
|
@ -583,9 +583,13 @@ struct binder_object {
|
|||
/**
|
||||
* Add a binder device to binder_devices
|
||||
* @device: the new binder device to add to the global list
|
||||
*
|
||||
* Not reentrant as the list is not protected by any locks
|
||||
*/
|
||||
void binder_add_device(struct binder_device *device);
|
||||
|
||||
/**
|
||||
* Remove a binder device to binder_devices
|
||||
* @device: the binder device to remove from the global list
|
||||
*/
|
||||
void binder_remove_device(struct binder_device *device);
|
||||
|
||||
#endif /* _LINUX_BINDER_INTERNAL_H */
|
||||
|
|
|
@ -274,7 +274,7 @@ static void binderfs_evict_inode(struct inode *inode)
|
|||
mutex_unlock(&binderfs_minors_mutex);
|
||||
|
||||
if (refcount_dec_and_test(&device->ref)) {
|
||||
hlist_del_init(&device->hlist);
|
||||
binder_remove_device(device);
|
||||
kfree(device->context.name);
|
||||
kfree(device);
|
||||
}
|
||||
|
|
|
@ -945,6 +945,33 @@ unsigned int fwnode_get_child_node_count(const struct fwnode_handle *fwnode)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(fwnode_get_child_node_count);
|
||||
|
||||
/**
|
||||
* fwnode_get_named_child_node_count - number of child nodes with given name
|
||||
* @fwnode: Node which child nodes are counted.
|
||||
* @name: String to match child node name against.
|
||||
*
|
||||
* Scan child nodes and count all the nodes with a specific name. Potential
|
||||
* 'number' -ending after the 'at sign' for scanned names is ignored.
|
||||
* E.g.::
|
||||
* fwnode_get_named_child_node_count(fwnode, "channel");
|
||||
* would match all the nodes::
|
||||
* channel { }, channel@0 {}, channel@0xabba {}...
|
||||
*
|
||||
* Return: the number of child nodes with a matching name for a given device.
|
||||
*/
|
||||
unsigned int fwnode_get_named_child_node_count(const struct fwnode_handle *fwnode,
|
||||
const char *name)
|
||||
{
|
||||
struct fwnode_handle *child;
|
||||
unsigned int count = 0;
|
||||
|
||||
fwnode_for_each_named_child_node(fwnode, child, name)
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fwnode_get_named_child_node_count);
|
||||
|
||||
bool device_dma_supported(const struct device *dev)
|
||||
{
|
||||
return fwnode_call_bool_op(dev_fwnode(dev), device_dma_supported);
|
||||
|
|
|
@ -131,19 +131,23 @@ int mhi_ep_ring_add_element(struct mhi_ep_ring *ring, struct mhi_ring_element *e
|
|||
}
|
||||
|
||||
old_offset = ring->rd_offset;
|
||||
mhi_ep_ring_inc_index(ring);
|
||||
|
||||
dev_dbg(dev, "Adding an element to ring at offset (%zu)\n", ring->rd_offset);
|
||||
buf_info.host_addr = ring->rbase + (old_offset * sizeof(*el));
|
||||
buf_info.dev_addr = el;
|
||||
buf_info.size = sizeof(*el);
|
||||
|
||||
ret = mhi_cntrl->write_sync(mhi_cntrl, &buf_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mhi_ep_ring_inc_index(ring);
|
||||
|
||||
/* Update rp in ring context */
|
||||
rp = cpu_to_le64(ring->rd_offset * sizeof(*el) + ring->rbase);
|
||||
memcpy_toio((void __iomem *) &ring->ring_ctx->generic.rp, &rp, sizeof(u64));
|
||||
|
||||
buf_info.host_addr = ring->rbase + (old_offset * sizeof(*el));
|
||||
buf_info.dev_addr = el;
|
||||
buf_info.size = sizeof(*el);
|
||||
|
||||
return mhi_cntrl->write_sync(mhi_cntrl, &buf_info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mhi_ep_ring_init(struct mhi_ep_ring *ring, enum mhi_ep_ring_type type, u32 id)
|
||||
|
|
|
@ -782,6 +782,42 @@ static const struct mhi_pci_dev_info mhi_telit_fe990a_info = {
|
|||
.mru_default = 32768,
|
||||
};
|
||||
|
||||
static const struct mhi_channel_config mhi_telit_fn920c04_channels[] = {
|
||||
MHI_CHANNEL_CONFIG_UL_SBL(2, "SAHARA", 32, 0),
|
||||
MHI_CHANNEL_CONFIG_DL_SBL(3, "SAHARA", 32, 0),
|
||||
MHI_CHANNEL_CONFIG_UL(4, "DIAG", 64, 1),
|
||||
MHI_CHANNEL_CONFIG_DL(5, "DIAG", 64, 1),
|
||||
MHI_CHANNEL_CONFIG_UL(14, "QMI", 32, 0),
|
||||
MHI_CHANNEL_CONFIG_DL(15, "QMI", 32, 0),
|
||||
MHI_CHANNEL_CONFIG_UL(32, "DUN", 32, 0),
|
||||
MHI_CHANNEL_CONFIG_DL(33, "DUN", 32, 0),
|
||||
MHI_CHANNEL_CONFIG_UL_FP(34, "FIREHOSE", 32, 0),
|
||||
MHI_CHANNEL_CONFIG_DL_FP(35, "FIREHOSE", 32, 0),
|
||||
MHI_CHANNEL_CONFIG_UL(92, "DUN2", 32, 1),
|
||||
MHI_CHANNEL_CONFIG_DL(93, "DUN2", 32, 1),
|
||||
MHI_CHANNEL_CONFIG_HW_UL(100, "IP_HW0", 128, 2),
|
||||
MHI_CHANNEL_CONFIG_HW_DL(101, "IP_HW0", 128, 3),
|
||||
};
|
||||
|
||||
static const struct mhi_controller_config modem_telit_fn920c04_config = {
|
||||
.max_channels = 128,
|
||||
.timeout_ms = 50000,
|
||||
.num_channels = ARRAY_SIZE(mhi_telit_fn920c04_channels),
|
||||
.ch_cfg = mhi_telit_fn920c04_channels,
|
||||
.num_events = ARRAY_SIZE(mhi_telit_fn990_events),
|
||||
.event_cfg = mhi_telit_fn990_events,
|
||||
};
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_telit_fn920c04_info = {
|
||||
.name = "telit-fn920c04",
|
||||
.config = &modem_telit_fn920c04_config,
|
||||
.bar_num = MHI_PCI_DEFAULT_BAR_NUM,
|
||||
.dma_data_width = 32,
|
||||
.sideband_wake = false,
|
||||
.mru_default = 32768,
|
||||
.edl_trigger = true,
|
||||
};
|
||||
|
||||
static const struct mhi_pci_dev_info mhi_netprisma_lcur57_info = {
|
||||
.name = "netprisma-lcur57",
|
||||
.edl = "qcom/prog_firehose_sdx24.mbn",
|
||||
|
@ -806,6 +842,9 @@ static const struct mhi_pci_dev_info mhi_netprisma_fcun69_info = {
|
|||
static const struct pci_device_id mhi_pci_id_table[] = {
|
||||
{PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0116),
|
||||
.driver_data = (kernel_ulong_t) &mhi_qcom_sa8775p_info },
|
||||
/* Telit FN920C04 (sdx35) */
|
||||
{PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x011a, 0x1c5d, 0x2020),
|
||||
.driver_data = (kernel_ulong_t) &mhi_telit_fn920c04_info },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0304),
|
||||
.driver_data = (kernel_ulong_t) &mhi_qcom_sdx24_info },
|
||||
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0306, PCI_VENDOR_ID_QCOM, 0x010c),
|
||||
|
@ -996,10 +1035,6 @@ static int mhi_pci_claim(struct mhi_controller *mhi_cntrl,
|
|||
struct pci_dev *pdev = to_pci_dev(mhi_cntrl->cntrl_dev);
|
||||
int err;
|
||||
|
||||
err = pci_assign_resource(pdev, bar_num);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = pcim_enable_device(pdev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to enable pci device: %d\n", err);
|
||||
|
|
|
@ -602,6 +602,7 @@ static void mhi_pm_sys_error_transition(struct mhi_controller *mhi_cntrl)
|
|||
struct mhi_cmd *mhi_cmd;
|
||||
struct mhi_event_ctxt *er_ctxt;
|
||||
struct device *dev = &mhi_cntrl->mhi_dev->dev;
|
||||
bool reset_device = false;
|
||||
int ret, i;
|
||||
|
||||
dev_dbg(dev, "Transitioning from PM state: %s to: %s\n",
|
||||
|
@ -630,8 +631,23 @@ static void mhi_pm_sys_error_transition(struct mhi_controller *mhi_cntrl)
|
|||
/* Wake up threads waiting for state transition */
|
||||
wake_up_all(&mhi_cntrl->state_event);
|
||||
|
||||
/* Trigger MHI RESET so that the device will not access host memory */
|
||||
if (MHI_REG_ACCESS_VALID(prev_state)) {
|
||||
/*
|
||||
* If the device is in PBL or SBL, it will only respond to
|
||||
* RESET if the device is in SYSERR state. SYSERR might
|
||||
* already be cleared at this point.
|
||||
*/
|
||||
enum mhi_state cur_state = mhi_get_mhi_state(mhi_cntrl);
|
||||
enum mhi_ee_type cur_ee = mhi_get_exec_env(mhi_cntrl);
|
||||
|
||||
if (cur_state == MHI_STATE_SYS_ERR)
|
||||
reset_device = true;
|
||||
else if (cur_ee != MHI_EE_PBL && cur_ee != MHI_EE_SBL)
|
||||
reset_device = true;
|
||||
}
|
||||
|
||||
/* Trigger MHI RESET so that the device will not access host memory */
|
||||
if (reset_device) {
|
||||
u32 in_reset = -1;
|
||||
unsigned long timeout = msecs_to_jiffies(mhi_cntrl->timeout_ms);
|
||||
|
||||
|
|
|
@ -165,7 +165,7 @@ struct irq_domain *cdx_msi_domain_init(struct device *dev)
|
|||
struct device_node *parent_node;
|
||||
struct irq_domain *parent;
|
||||
|
||||
fwnode_handle = of_node_to_fwnode(np);
|
||||
fwnode_handle = of_fwnode_handle(np);
|
||||
|
||||
parent_node = of_parse_phandle(np, "msi-map", 1);
|
||||
if (!parent_node) {
|
||||
|
@ -173,7 +173,7 @@ struct irq_domain *cdx_msi_domain_init(struct device *dev)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
parent = irq_find_matching_fwnode(of_node_to_fwnode(parent_node), DOMAIN_BUS_NEXUS);
|
||||
parent = irq_find_matching_fwnode(of_fwnode_handle(parent_node), DOMAIN_BUS_NEXUS);
|
||||
if (!parent || !msi_get_domain_info(parent)) {
|
||||
dev_err(dev, "unable to locate ITS domain\n");
|
||||
return NULL;
|
||||
|
|
|
@ -404,7 +404,7 @@ config TELCLOCK
|
|||
configuration of the telecom clock configuration settings. This
|
||||
device is used for hardware synchronization across the ATCA backplane
|
||||
fabric. Upon loading, the driver exports a sysfs directory,
|
||||
/sys/devices/platform/telco_clock, with a number of files for
|
||||
/sys/devices/faux/telco_clock, with a number of files for
|
||||
controlling the behavior of this hardware.
|
||||
|
||||
source "drivers/s390/char/Kconfig"
|
||||
|
|
|
@ -141,9 +141,6 @@ static struct apm_queue kapmd_queue;
|
|||
|
||||
static DEFINE_MUTEX(state_lock);
|
||||
|
||||
static const char driver_version[] = "1.13"; /* no spaces */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Compatibility cruft until the IPAQ people move over to the new
|
||||
|
@ -435,6 +432,8 @@ static struct miscdevice apm_device = {
|
|||
*/
|
||||
static int proc_apm_show(struct seq_file *m, void *v)
|
||||
{
|
||||
static const char driver_version[] = "1.13"; /* no spaces */
|
||||
|
||||
struct apm_power_info info;
|
||||
char *units;
|
||||
|
||||
|
|
|
@ -1023,8 +1023,7 @@ static int __init hpet_init(void)
|
|||
|
||||
result = acpi_bus_register_driver(&hpet_acpi_driver);
|
||||
if (result < 0) {
|
||||
if (sysctl_header)
|
||||
unregister_sysctl_table(sysctl_header);
|
||||
unregister_sysctl_table(sysctl_header);
|
||||
misc_deregister(&hpet_misc);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -58,9 +58,8 @@ static LIST_HEAD(misc_list);
|
|||
static DEFINE_MUTEX(misc_mtx);
|
||||
|
||||
/*
|
||||
* Assigned numbers, used for dynamic minors
|
||||
* Assigned numbers.
|
||||
*/
|
||||
#define DYNAMIC_MINORS 128 /* like dynamic majors */
|
||||
static DEFINE_IDA(misc_minors_ida);
|
||||
|
||||
static int misc_minor_alloc(int minor)
|
||||
|
@ -69,34 +68,17 @@ static int misc_minor_alloc(int minor)
|
|||
|
||||
if (minor == MISC_DYNAMIC_MINOR) {
|
||||
/* allocate free id */
|
||||
ret = ida_alloc_max(&misc_minors_ida, DYNAMIC_MINORS - 1, GFP_KERNEL);
|
||||
if (ret >= 0) {
|
||||
ret = DYNAMIC_MINORS - ret - 1;
|
||||
} else {
|
||||
ret = ida_alloc_range(&misc_minors_ida, MISC_DYNAMIC_MINOR + 1,
|
||||
MINORMASK, GFP_KERNEL);
|
||||
}
|
||||
ret = ida_alloc_range(&misc_minors_ida, MISC_DYNAMIC_MINOR + 1,
|
||||
MINORMASK, GFP_KERNEL);
|
||||
} else {
|
||||
/* specific minor, check if it is in dynamic or misc dynamic range */
|
||||
if (minor < DYNAMIC_MINORS) {
|
||||
minor = DYNAMIC_MINORS - minor - 1;
|
||||
ret = ida_alloc_range(&misc_minors_ida, minor, minor, GFP_KERNEL);
|
||||
} else if (minor > MISC_DYNAMIC_MINOR) {
|
||||
ret = ida_alloc_range(&misc_minors_ida, minor, minor, GFP_KERNEL);
|
||||
} else {
|
||||
/* case of non-dynamic minors, no need to allocate id */
|
||||
ret = 0;
|
||||
}
|
||||
ret = ida_alloc_range(&misc_minors_ida, minor, minor, GFP_KERNEL);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void misc_minor_free(int minor)
|
||||
{
|
||||
if (minor < DYNAMIC_MINORS)
|
||||
ida_free(&misc_minors_ida, DYNAMIC_MINORS - minor - 1);
|
||||
else if (minor > MISC_DYNAMIC_MINOR)
|
||||
ida_free(&misc_minors_ida, minor);
|
||||
ida_free(&misc_minors_ida, minor);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
|
|
@ -1184,8 +1184,7 @@ static int xillybus_flush(struct file *filp, fl_owner_t id)
|
|||
|
||||
static void xillybus_autoflush(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *workitem = container_of(
|
||||
work, struct delayed_work, work);
|
||||
struct delayed_work *workitem = to_delayed_work(work);
|
||||
struct xilly_channel *channel = container_of(
|
||||
workitem, struct xilly_channel, rd_workitem);
|
||||
int rc;
|
||||
|
|
|
@ -27,14 +27,12 @@ static void comedi_buf_map_kref_release(struct kref *kref)
|
|||
|
||||
if (bm->page_list) {
|
||||
if (bm->dma_dir != DMA_NONE) {
|
||||
/*
|
||||
* DMA buffer was allocated as a single block.
|
||||
* Address is in page_list[0].
|
||||
*/
|
||||
buf = &bm->page_list[0];
|
||||
dma_free_coherent(bm->dma_hw_dev,
|
||||
PAGE_SIZE * bm->n_pages,
|
||||
buf->virt_addr, buf->dma_addr);
|
||||
for (i = 0; i < bm->n_pages; i++) {
|
||||
buf = &bm->page_list[i];
|
||||
dma_free_coherent(bm->dma_hw_dev, PAGE_SIZE,
|
||||
buf->virt_addr,
|
||||
buf->dma_addr);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < bm->n_pages; i++) {
|
||||
buf = &bm->page_list[i];
|
||||
|
@ -56,13 +54,7 @@ static void __comedi_buf_free(struct comedi_device *dev,
|
|||
struct comedi_buf_map *bm;
|
||||
unsigned long flags;
|
||||
|
||||
if (async->prealloc_buf) {
|
||||
if (s->async_dma_dir == DMA_NONE)
|
||||
vunmap(async->prealloc_buf);
|
||||
async->prealloc_buf = NULL;
|
||||
async->prealloc_bufsz = 0;
|
||||
}
|
||||
|
||||
async->prealloc_bufsz = 0;
|
||||
spin_lock_irqsave(&s->spin_lock, flags);
|
||||
bm = async->buf_map;
|
||||
async->buf_map = NULL;
|
||||
|
@ -94,26 +86,14 @@ comedi_buf_map_alloc(struct comedi_device *dev, enum dma_data_direction dma_dir,
|
|||
goto err;
|
||||
|
||||
if (bm->dma_dir != DMA_NONE) {
|
||||
void *virt_addr;
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
/*
|
||||
* Currently, the DMA buffer needs to be allocated as a
|
||||
* single block so that it can be mmap()'ed.
|
||||
*/
|
||||
virt_addr = dma_alloc_coherent(bm->dma_hw_dev,
|
||||
PAGE_SIZE * n_pages, &dma_addr,
|
||||
GFP_KERNEL);
|
||||
if (!virt_addr)
|
||||
goto err;
|
||||
|
||||
for (i = 0; i < n_pages; i++) {
|
||||
buf = &bm->page_list[i];
|
||||
buf->virt_addr = virt_addr + (i << PAGE_SHIFT);
|
||||
buf->dma_addr = dma_addr + (i << PAGE_SHIFT);
|
||||
buf->virt_addr =
|
||||
dma_alloc_coherent(bm->dma_hw_dev, PAGE_SIZE,
|
||||
&buf->dma_addr, GFP_KERNEL);
|
||||
if (!buf->virt_addr)
|
||||
break;
|
||||
}
|
||||
|
||||
bm->n_pages = i;
|
||||
} else {
|
||||
for (i = 0; i < n_pages; i++) {
|
||||
buf = &bm->page_list[i];
|
||||
|
@ -123,11 +103,10 @@ comedi_buf_map_alloc(struct comedi_device *dev, enum dma_data_direction dma_dir,
|
|||
|
||||
SetPageReserved(virt_to_page(buf->virt_addr));
|
||||
}
|
||||
|
||||
bm->n_pages = i;
|
||||
if (i < n_pages)
|
||||
goto err;
|
||||
}
|
||||
bm->n_pages = i;
|
||||
if (i < n_pages)
|
||||
goto err;
|
||||
|
||||
return bm;
|
||||
|
||||
|
@ -141,11 +120,8 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
|
|||
unsigned int n_pages)
|
||||
{
|
||||
struct comedi_async *async = s->async;
|
||||
struct page **pages = NULL;
|
||||
struct comedi_buf_map *bm;
|
||||
struct comedi_buf_page *buf;
|
||||
unsigned long flags;
|
||||
unsigned int i;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_HAS_DMA) && s->async_dma_dir != DMA_NONE) {
|
||||
dev_err(dev->class_dev,
|
||||
|
@ -160,30 +136,7 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
|
|||
spin_lock_irqsave(&s->spin_lock, flags);
|
||||
async->buf_map = bm;
|
||||
spin_unlock_irqrestore(&s->spin_lock, flags);
|
||||
|
||||
if (bm->dma_dir != DMA_NONE) {
|
||||
/*
|
||||
* DMA buffer was allocated as a single block.
|
||||
* Address is in page_list[0].
|
||||
*/
|
||||
buf = &bm->page_list[0];
|
||||
async->prealloc_buf = buf->virt_addr;
|
||||
} else {
|
||||
pages = vmalloc(sizeof(struct page *) * n_pages);
|
||||
if (!pages)
|
||||
return;
|
||||
|
||||
for (i = 0; i < n_pages; i++) {
|
||||
buf = &bm->page_list[i];
|
||||
pages[i] = virt_to_page(buf->virt_addr);
|
||||
}
|
||||
|
||||
/* vmap the pages to prealloc_buf */
|
||||
async->prealloc_buf = vmap(pages, n_pages, VM_MAP,
|
||||
COMEDI_PAGE_PROTECTION);
|
||||
|
||||
vfree(pages);
|
||||
}
|
||||
async->prealloc_bufsz = n_pages << PAGE_SHIFT;
|
||||
}
|
||||
|
||||
void comedi_buf_map_get(struct comedi_buf_map *bm)
|
||||
|
@ -264,7 +217,7 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
|
|||
new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
|
||||
|
||||
/* if no change is required, do nothing */
|
||||
if (async->prealloc_buf && async->prealloc_bufsz == new_size)
|
||||
if (async->prealloc_bufsz == new_size)
|
||||
return 0;
|
||||
|
||||
/* deallocate old buffer */
|
||||
|
@ -275,14 +228,9 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
|
|||
unsigned int n_pages = new_size >> PAGE_SHIFT;
|
||||
|
||||
__comedi_buf_alloc(dev, s, n_pages);
|
||||
|
||||
if (!async->prealloc_buf) {
|
||||
/* allocation failed */
|
||||
__comedi_buf_free(dev, s);
|
||||
if (!async->prealloc_bufsz)
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
async->prealloc_bufsz = new_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -365,6 +313,7 @@ static unsigned int comedi_buf_munge(struct comedi_subdevice *s,
|
|||
unsigned int num_bytes)
|
||||
{
|
||||
struct comedi_async *async = s->async;
|
||||
struct comedi_buf_page *buf_page_list = async->buf_map->page_list;
|
||||
unsigned int count = 0;
|
||||
const unsigned int num_sample_bytes = comedi_bytes_per_sample(s);
|
||||
|
||||
|
@ -376,15 +325,16 @@ static unsigned int comedi_buf_munge(struct comedi_subdevice *s,
|
|||
/* don't munge partial samples */
|
||||
num_bytes -= num_bytes % num_sample_bytes;
|
||||
while (count < num_bytes) {
|
||||
int block_size = num_bytes - count;
|
||||
unsigned int buf_end;
|
||||
/*
|
||||
* Do not munge beyond page boundary.
|
||||
* Note: prealloc_bufsz is a multiple of PAGE_SIZE.
|
||||
*/
|
||||
unsigned int page = async->munge_ptr >> PAGE_SHIFT;
|
||||
unsigned int offset = offset_in_page(async->munge_ptr);
|
||||
unsigned int block_size =
|
||||
min(num_bytes - count, PAGE_SIZE - offset);
|
||||
|
||||
buf_end = async->prealloc_bufsz - async->munge_ptr;
|
||||
if (block_size > buf_end)
|
||||
block_size = buf_end;
|
||||
|
||||
s->munge(s->device, s,
|
||||
async->prealloc_buf + async->munge_ptr,
|
||||
s->munge(s->device, s, buf_page_list[page].virt_addr + offset,
|
||||
block_size, async->munge_chan);
|
||||
|
||||
/*
|
||||
|
@ -397,7 +347,8 @@ static unsigned int comedi_buf_munge(struct comedi_subdevice *s,
|
|||
async->munge_chan %= async->cmd.chanlist_len;
|
||||
async->munge_count += block_size;
|
||||
async->munge_ptr += block_size;
|
||||
async->munge_ptr %= async->prealloc_bufsz;
|
||||
if (async->munge_ptr == async->prealloc_bufsz)
|
||||
async->munge_ptr = 0;
|
||||
count += block_size;
|
||||
}
|
||||
|
||||
|
@ -558,46 +509,52 @@ static void comedi_buf_memcpy_to(struct comedi_subdevice *s,
|
|||
const void *data, unsigned int num_bytes)
|
||||
{
|
||||
struct comedi_async *async = s->async;
|
||||
struct comedi_buf_page *buf_page_list = async->buf_map->page_list;
|
||||
unsigned int write_ptr = async->buf_write_ptr;
|
||||
|
||||
while (num_bytes) {
|
||||
unsigned int block_size;
|
||||
/*
|
||||
* Do not copy beyond page boundary.
|
||||
* Note: prealloc_bufsz is a multiple of PAGE_SIZE.
|
||||
*/
|
||||
unsigned int page = write_ptr >> PAGE_SHIFT;
|
||||
unsigned int offset = offset_in_page(write_ptr);
|
||||
unsigned int block_size = min(num_bytes, PAGE_SIZE - offset);
|
||||
|
||||
if (write_ptr + num_bytes > async->prealloc_bufsz)
|
||||
block_size = async->prealloc_bufsz - write_ptr;
|
||||
else
|
||||
block_size = num_bytes;
|
||||
|
||||
memcpy(async->prealloc_buf + write_ptr, data, block_size);
|
||||
memcpy(buf_page_list[page].virt_addr + offset,
|
||||
data, block_size);
|
||||
|
||||
data += block_size;
|
||||
num_bytes -= block_size;
|
||||
|
||||
write_ptr = 0;
|
||||
write_ptr += block_size;
|
||||
if (write_ptr == async->prealloc_bufsz)
|
||||
write_ptr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void comedi_buf_memcpy_from(struct comedi_subdevice *s,
|
||||
void *dest, unsigned int nbytes)
|
||||
{
|
||||
void *src;
|
||||
struct comedi_async *async = s->async;
|
||||
struct comedi_buf_page *buf_page_list = async->buf_map->page_list;
|
||||
unsigned int read_ptr = async->buf_read_ptr;
|
||||
|
||||
while (nbytes) {
|
||||
unsigned int block_size;
|
||||
/*
|
||||
* Do not copy beyond page boundary.
|
||||
* Note: prealloc_bufsz is a multiple of PAGE_SIZE.
|
||||
*/
|
||||
unsigned int page = read_ptr >> PAGE_SHIFT;
|
||||
unsigned int offset = offset_in_page(read_ptr);
|
||||
unsigned int block_size = min(nbytes, PAGE_SIZE - offset);
|
||||
|
||||
src = async->prealloc_buf + read_ptr;
|
||||
|
||||
if (nbytes >= async->prealloc_bufsz - read_ptr)
|
||||
block_size = async->prealloc_bufsz - read_ptr;
|
||||
else
|
||||
block_size = nbytes;
|
||||
|
||||
memcpy(dest, src, block_size);
|
||||
memcpy(dest, buf_page_list[page].virt_addr + offset,
|
||||
block_size);
|
||||
nbytes -= block_size;
|
||||
dest += block_size;
|
||||
read_ptr = 0;
|
||||
read_ptr += block_size;
|
||||
if (read_ptr == async->prealloc_bufsz)
|
||||
read_ptr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2387,13 +2387,27 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
|
|||
goto done;
|
||||
}
|
||||
if (bm->dma_dir != DMA_NONE) {
|
||||
unsigned long vm_start = vma->vm_start;
|
||||
unsigned long vm_end = vma->vm_end;
|
||||
|
||||
/*
|
||||
* DMA buffer was allocated as a single block.
|
||||
* Address is in page_list[0].
|
||||
* Buffer pages are not contiguous, so temporarily modify VMA
|
||||
* start and end addresses for each buffer page.
|
||||
*/
|
||||
buf = &bm->page_list[0];
|
||||
retval = dma_mmap_coherent(bm->dma_hw_dev, vma, buf->virt_addr,
|
||||
buf->dma_addr, n_pages * PAGE_SIZE);
|
||||
for (i = 0; i < n_pages; ++i) {
|
||||
buf = &bm->page_list[i];
|
||||
vma->vm_start = start;
|
||||
vma->vm_end = start + PAGE_SIZE;
|
||||
retval = dma_mmap_coherent(bm->dma_hw_dev, vma,
|
||||
buf->virt_addr,
|
||||
buf->dma_addr, PAGE_SIZE);
|
||||
if (retval)
|
||||
break;
|
||||
|
||||
start += PAGE_SIZE;
|
||||
}
|
||||
vma->vm_start = vm_start;
|
||||
vma->vm_end = vm_end;
|
||||
} else {
|
||||
for (i = 0; i < n_pages; ++i) {
|
||||
unsigned long pfn;
|
||||
|
@ -2407,19 +2421,18 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
|
|||
|
||||
start += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
/*
|
||||
* Leaving behind a partial mapping of a buffer we're about to
|
||||
* drop is unsafe, see remap_pfn_range_notrack().
|
||||
* We need to zap the range here ourselves instead of relying
|
||||
* on the automatic zapping in remap_pfn_range() because we call
|
||||
* remap_pfn_range() in a loop.
|
||||
*/
|
||||
if (retval)
|
||||
zap_vma_ptes(vma, vma->vm_start, size);
|
||||
/*
|
||||
* Leaving behind a partial mapping of a buffer we're about to drop is
|
||||
* unsafe, see remap_pfn_range_notrack(). We need to zap the range
|
||||
* here ourselves instead of relying on the automatic zapping in
|
||||
* remap_pfn_range() because we call remap_pfn_range() in a loop.
|
||||
*/
|
||||
if (retval)
|
||||
zap_vma_ptes(vma, vma->vm_start, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (retval == 0) {
|
||||
vma->vm_ops = &comedi_vm_ops;
|
||||
|
@ -2475,6 +2488,62 @@ done:
|
|||
return mask;
|
||||
}
|
||||
|
||||
static unsigned int comedi_buf_copy_to_user(struct comedi_subdevice *s,
|
||||
void __user *dest, unsigned int src_offset, unsigned int n)
|
||||
{
|
||||
struct comedi_buf_map *bm = s->async->buf_map;
|
||||
struct comedi_buf_page *buf_page_list = bm->page_list;
|
||||
unsigned int page = src_offset >> PAGE_SHIFT;
|
||||
unsigned int offset = offset_in_page(src_offset);
|
||||
|
||||
while (n) {
|
||||
unsigned int copy_amount = min(n, PAGE_SIZE - offset);
|
||||
unsigned int uncopied;
|
||||
|
||||
uncopied = copy_to_user(dest, buf_page_list[page].virt_addr +
|
||||
offset, copy_amount);
|
||||
copy_amount -= uncopied;
|
||||
n -= copy_amount;
|
||||
if (uncopied)
|
||||
break;
|
||||
|
||||
dest += copy_amount;
|
||||
page++;
|
||||
if (page == bm->n_pages)
|
||||
page = 0; /* buffer wraparound */
|
||||
offset = 0;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static unsigned int comedi_buf_copy_from_user(struct comedi_subdevice *s,
|
||||
unsigned int dst_offset, const void __user *src, unsigned int n)
|
||||
{
|
||||
struct comedi_buf_map *bm = s->async->buf_map;
|
||||
struct comedi_buf_page *buf_page_list = bm->page_list;
|
||||
unsigned int page = dst_offset >> PAGE_SHIFT;
|
||||
unsigned int offset = offset_in_page(dst_offset);
|
||||
|
||||
while (n) {
|
||||
unsigned int copy_amount = min(n, PAGE_SIZE - offset);
|
||||
unsigned int uncopied;
|
||||
|
||||
uncopied = copy_from_user(buf_page_list[page].virt_addr +
|
||||
offset, src, copy_amount);
|
||||
copy_amount -= uncopied;
|
||||
n -= copy_amount;
|
||||
if (uncopied)
|
||||
break;
|
||||
|
||||
src += copy_amount;
|
||||
page++;
|
||||
if (page == bm->n_pages)
|
||||
page = 0; /* buffer wraparound */
|
||||
offset = 0;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static ssize_t comedi_write(struct file *file, const char __user *buf,
|
||||
size_t nbytes, loff_t *offset)
|
||||
{
|
||||
|
@ -2516,7 +2585,6 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
|
|||
add_wait_queue(&async->wait_head, &wait);
|
||||
while (count == 0 && !retval) {
|
||||
unsigned int runflags;
|
||||
unsigned int wp, n1, n2;
|
||||
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
|
@ -2555,14 +2623,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf,
|
|||
}
|
||||
|
||||
set_current_state(TASK_RUNNING);
|
||||
wp = async->buf_write_ptr;
|
||||
n1 = min(n, async->prealloc_bufsz - wp);
|
||||
n2 = n - n1;
|
||||
m = copy_from_user(async->prealloc_buf + wp, buf, n1);
|
||||
if (m)
|
||||
m += n2;
|
||||
else if (n2)
|
||||
m = copy_from_user(async->prealloc_buf, buf + n1, n2);
|
||||
m = comedi_buf_copy_from_user(s, async->buf_write_ptr, buf, n);
|
||||
if (m) {
|
||||
n -= m;
|
||||
retval = -EFAULT;
|
||||
|
@ -2651,8 +2712,6 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
|
|||
|
||||
add_wait_queue(&async->wait_head, &wait);
|
||||
while (count == 0 && !retval) {
|
||||
unsigned int rp, n1, n2;
|
||||
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
m = comedi_buf_read_n_available(s);
|
||||
|
@ -2689,14 +2748,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
|
|||
}
|
||||
|
||||
set_current_state(TASK_RUNNING);
|
||||
rp = async->buf_read_ptr;
|
||||
n1 = min(n, async->prealloc_bufsz - rp);
|
||||
n2 = n - n1;
|
||||
m = copy_to_user(buf, async->prealloc_buf + rp, n1);
|
||||
if (m)
|
||||
m += n2;
|
||||
else if (n2)
|
||||
m = copy_to_user(buf + n1, async->prealloc_buf, n2);
|
||||
m = comedi_buf_copy_to_user(s, buf, async->buf_read_ptr, n);
|
||||
if (m) {
|
||||
n -= m;
|
||||
retval = -EFAULT;
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
* ranges).
|
||||
*
|
||||
* There are some hardware limitations:
|
||||
* a) You cann't use mixture of unipolar/bipoar ranges or differencial/single
|
||||
* a) You can't use mixture of unipolar/bipolar ranges or differential/single
|
||||
* ended inputs.
|
||||
* b) DMA transfers must have the length aligned to two samples (32 bit),
|
||||
* so there is some problems if cmd->chanlist_len is odd. This driver tries
|
||||
|
@ -227,7 +227,7 @@ struct pci9118_private {
|
|||
struct pci9118_dmabuf dmabuf[2];
|
||||
int softsshdelay; /*
|
||||
* >0 use software S&H,
|
||||
* numer is requested delay in ns
|
||||
* number is requested delay in ns
|
||||
*/
|
||||
unsigned char softsshsample; /*
|
||||
* polarity of S&H signal
|
||||
|
|
|
@ -215,7 +215,7 @@ static const int ni_irqpin[] = {
|
|||
|
||||
#include "ni_mio_common.c"
|
||||
|
||||
static const struct pnp_device_id device_ids[] = {
|
||||
static const struct pnp_device_id __maybe_unused device_ids[] = {
|
||||
{.id = "NIC1900", .driver_data = 0},
|
||||
{.id = "NIC2400", .driver_data = 0},
|
||||
{.id = "NIC2500", .driver_data = 0},
|
||||
|
|
|
@ -747,8 +747,6 @@ static int ni_pcidio_change(struct comedi_device *dev,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
memset(s->async->prealloc_buf, 0xaa, s->async->prealloc_bufsz);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,22 +3,25 @@
|
|||
* Copyright (c) 2021 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
|
||||
*/
|
||||
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/counter.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define INTERRUPT_CNT_NAME "interrupt-cnt"
|
||||
|
||||
struct interrupt_cnt_priv {
|
||||
atomic_t count;
|
||||
atomic_long_t count;
|
||||
struct gpio_desc *gpio;
|
||||
int irq;
|
||||
bool enabled;
|
||||
struct mutex lock;
|
||||
struct counter_signal signals;
|
||||
struct counter_synapse synapses;
|
||||
struct counter_count cnts;
|
||||
|
@ -29,7 +32,7 @@ static irqreturn_t interrupt_cnt_isr(int irq, void *dev_id)
|
|||
struct counter_device *counter = dev_id;
|
||||
struct interrupt_cnt_priv *priv = counter_priv(counter);
|
||||
|
||||
atomic_inc(&priv->count);
|
||||
atomic_long_inc(&priv->count);
|
||||
|
||||
counter_push_event(counter, COUNTER_EVENT_CHANGE_OF_STATE, 0);
|
||||
|
||||
|
@ -41,6 +44,8 @@ static int interrupt_cnt_enable_read(struct counter_device *counter,
|
|||
{
|
||||
struct interrupt_cnt_priv *priv = counter_priv(counter);
|
||||
|
||||
guard(mutex)(&priv->lock);
|
||||
|
||||
*enable = priv->enabled;
|
||||
|
||||
return 0;
|
||||
|
@ -51,6 +56,8 @@ static int interrupt_cnt_enable_write(struct counter_device *counter,
|
|||
{
|
||||
struct interrupt_cnt_priv *priv = counter_priv(counter);
|
||||
|
||||
guard(mutex)(&priv->lock);
|
||||
|
||||
if (priv->enabled == enable)
|
||||
return 0;
|
||||
|
||||
|
@ -89,7 +96,7 @@ static int interrupt_cnt_read(struct counter_device *counter,
|
|||
{
|
||||
struct interrupt_cnt_priv *priv = counter_priv(counter);
|
||||
|
||||
*val = atomic_read(&priv->count);
|
||||
*val = atomic_long_read(&priv->count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -102,7 +109,7 @@ static int interrupt_cnt_write(struct counter_device *counter,
|
|||
if (val != (typeof(priv->count.counter))val)
|
||||
return -ERANGE;
|
||||
|
||||
atomic_set(&priv->count, val);
|
||||
atomic_long_set(&priv->count, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -227,6 +234,8 @@ static int interrupt_cnt_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_init(&priv->lock);
|
||||
|
||||
ret = devm_counter_add(dev, counter);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(dev, ret, "Failed to add counter\n");
|
||||
|
|
|
@ -337,6 +337,28 @@ static struct counter_comp mchp_tc_count_ext[] = {
|
|||
COUNTER_COMP_COMPARE(mchp_tc_count_compare_read, mchp_tc_count_compare_write),
|
||||
};
|
||||
|
||||
static int mchp_tc_watch_validate(struct counter_device *counter,
|
||||
const struct counter_watch *watch)
|
||||
{
|
||||
if (watch->channel == COUNTER_MCHP_EVCHN_CV || watch->channel == COUNTER_MCHP_EVCHN_RA)
|
||||
switch (watch->event) {
|
||||
case COUNTER_EVENT_CHANGE_OF_STATE:
|
||||
case COUNTER_EVENT_OVERFLOW:
|
||||
case COUNTER_EVENT_CAPTURE:
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (watch->channel == COUNTER_MCHP_EVCHN_RB && watch->event == COUNTER_EVENT_CAPTURE)
|
||||
return 0;
|
||||
|
||||
if (watch->channel == COUNTER_MCHP_EVCHN_RC && watch->event == COUNTER_EVENT_THRESHOLD)
|
||||
return 0;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct counter_count mchp_tc_counts[] = {
|
||||
{
|
||||
.id = 0,
|
||||
|
@ -356,7 +378,8 @@ static const struct counter_ops mchp_tc_ops = {
|
|||
.function_read = mchp_tc_count_function_read,
|
||||
.function_write = mchp_tc_count_function_write,
|
||||
.action_read = mchp_tc_count_action_read,
|
||||
.action_write = mchp_tc_count_action_write
|
||||
.action_write = mchp_tc_count_action_write,
|
||||
.watch_validate = mchp_tc_watch_validate,
|
||||
};
|
||||
|
||||
static const struct atmel_tcb_config tcb_rm9200_config = {
|
||||
|
|
|
@ -669,12 +669,14 @@ static void stm32_timer_cnt_detect_channels(struct device *dev,
|
|||
dev_dbg(dev, "has %d cc channels\n", priv->nchannels);
|
||||
}
|
||||
|
||||
/* encoder supported on TIM1 TIM2 TIM3 TIM4 TIM5 TIM8 */
|
||||
#define STM32_TIM_ENCODER_SUPPORTED (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(7))
|
||||
/* encoder supported on TIM1 TIM2 TIM3 TIM4 TIM5 TIM8 TIM20 */
|
||||
#define STM32_TIM_ENCODER_SUPPORTED (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(7) | \
|
||||
BIT(19))
|
||||
|
||||
static const char * const stm32_timer_trigger_compat[] = {
|
||||
"st,stm32-timer-trigger",
|
||||
"st,stm32h7-timer-trigger",
|
||||
"st,stm32mp25-timer-trigger",
|
||||
};
|
||||
|
||||
static int stm32_timer_cnt_probe_encoder(struct device *dev,
|
||||
|
@ -846,6 +848,7 @@ static SIMPLE_DEV_PM_OPS(stm32_timer_cnt_pm_ops, stm32_timer_cnt_suspend,
|
|||
|
||||
static const struct of_device_id stm32_timer_cnt_of_match[] = {
|
||||
{ .compatible = "st,stm32-timer-counter", },
|
||||
{ .compatible = "st,stm32mp25-timer-counter", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, stm32_timer_cnt_of_match);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Makefile for the Linux device tree
|
||||
|
||||
always-$(CONFIG_EISA) += devlist.h
|
||||
obj-$(CONFIG_EISA) += eisa-bus.o
|
||||
obj-${CONFIG_EISA_PCI_EISA} += pci_eisa.o
|
||||
|
||||
|
@ -9,14 +10,11 @@ obj-${CONFIG_EISA_PCI_EISA} += pci_eisa.o
|
|||
obj-${CONFIG_EISA_VIRTUAL_ROOT} += virtual_root.o
|
||||
|
||||
|
||||
# Ugly hack to get DEVICE_NAME_SIZE value...
|
||||
DEVICE_NAME_SIZE = 50
|
||||
|
||||
$(obj)/eisa-bus.o: $(obj)/devlist.h
|
||||
|
||||
quiet_cmd_eisaid = GEN $@
|
||||
cmd_eisaid = sed -e '/^\#/D' -e 's/^\([[:alnum:]]\{7\}\) \+"\([^"]\{1,$(DEVICE_NAME_SIZE)\}\).*"/EISA_DEVINFO ("\1", "\2"),/' $< > $@
|
||||
cmd_eisaid = sed -e '/^\#/D' -e 's/^\([[:alnum:]]\{7\}\) \+"\([^"]*\)"/EISA_DEVINFO ("\1", "\2"),/' $< > $@
|
||||
|
||||
clean-files := devlist.h
|
||||
$(obj)/devlist.h: $(src)/eisa.ids include/linux/device.h
|
||||
$(call cmd,eisaid)
|
||||
$(obj)/devlist.h: $(src)/eisa.ids include/linux/device.h FORCE
|
||||
$(call if_changed,eisaid)
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
struct eisa_device_info {
|
||||
struct eisa_device_id id;
|
||||
char name[50];
|
||||
char name[EISA_DEVICE_INFO_NAME_SIZE];
|
||||
};
|
||||
|
||||
#ifdef CONFIG_EISA_NAMES
|
||||
|
|
|
@ -263,6 +263,7 @@ static void fpga_mgr_test_img_load_sgt(struct kunit *test)
|
|||
img_buf = init_test_buffer(test, IMAGE_SIZE);
|
||||
|
||||
sgt = kunit_kzalloc(test, sizeof(*sgt), GFP_KERNEL);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sgt);
|
||||
ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
|
||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||
sg_init_one(sgt->sgl, img_buf, IMAGE_SIZE);
|
||||
|
|
|
@ -1905,16 +1905,6 @@ config SENSORS_SBTSI
|
|||
This driver can also be built as a module. If so, the module will
|
||||
be called sbtsi_temp.
|
||||
|
||||
config SENSORS_SBRMI
|
||||
tristate "Emulated SB-RMI sensor"
|
||||
depends on I2C
|
||||
help
|
||||
If you say yes here you get support for emulated RMI
|
||||
sensors on AMD SoCs with APML interface connected to a BMC device.
|
||||
|
||||
This driver can also be built as a module. If so, the module will
|
||||
be called sbrmi.
|
||||
|
||||
config SENSORS_SHT15
|
||||
tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
|
||||
depends on GPIOLIB || COMPILE_TEST
|
||||
|
|
|
@ -1,357 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* sbrmi.c - hwmon driver for a SB-RMI mailbox
|
||||
* compliant AMD SoC device.
|
||||
*
|
||||
* Copyright (C) 2020-2021 Advanced Micro Devices, Inc.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
/* Do not allow setting negative power limit */
|
||||
#define SBRMI_PWR_MIN 0
|
||||
/* Mask for Status Register bit[1] */
|
||||
#define SW_ALERT_MASK 0x2
|
||||
|
||||
/* Software Interrupt for triggering */
|
||||
#define START_CMD 0x80
|
||||
#define TRIGGER_MAILBOX 0x01
|
||||
|
||||
/*
|
||||
* SB-RMI supports soft mailbox service request to MP1 (power management
|
||||
* firmware) through SBRMI inbound/outbound message registers.
|
||||
* SB-RMI message IDs
|
||||
*/
|
||||
enum sbrmi_msg_id {
|
||||
SBRMI_READ_PKG_PWR_CONSUMPTION = 0x1,
|
||||
SBRMI_WRITE_PKG_PWR_LIMIT,
|
||||
SBRMI_READ_PKG_PWR_LIMIT,
|
||||
SBRMI_READ_PKG_MAX_PWR_LIMIT,
|
||||
};
|
||||
|
||||
/* SB-RMI registers */
|
||||
enum sbrmi_reg {
|
||||
SBRMI_CTRL = 0x01,
|
||||
SBRMI_STATUS,
|
||||
SBRMI_OUTBNDMSG0 = 0x30,
|
||||
SBRMI_OUTBNDMSG1,
|
||||
SBRMI_OUTBNDMSG2,
|
||||
SBRMI_OUTBNDMSG3,
|
||||
SBRMI_OUTBNDMSG4,
|
||||
SBRMI_OUTBNDMSG5,
|
||||
SBRMI_OUTBNDMSG6,
|
||||
SBRMI_OUTBNDMSG7,
|
||||
SBRMI_INBNDMSG0,
|
||||
SBRMI_INBNDMSG1,
|
||||
SBRMI_INBNDMSG2,
|
||||
SBRMI_INBNDMSG3,
|
||||
SBRMI_INBNDMSG4,
|
||||
SBRMI_INBNDMSG5,
|
||||
SBRMI_INBNDMSG6,
|
||||
SBRMI_INBNDMSG7,
|
||||
SBRMI_SW_INTERRUPT,
|
||||
};
|
||||
|
||||
/* Each client has this additional data */
|
||||
struct sbrmi_data {
|
||||
struct i2c_client *client;
|
||||
struct mutex lock;
|
||||
u32 pwr_limit_max;
|
||||
};
|
||||
|
||||
struct sbrmi_mailbox_msg {
|
||||
u8 cmd;
|
||||
bool read;
|
||||
u32 data_in;
|
||||
u32 data_out;
|
||||
};
|
||||
|
||||
static int sbrmi_enable_alert(struct i2c_client *client)
|
||||
{
|
||||
int ctrl;
|
||||
|
||||
/*
|
||||
* Enable the SB-RMI Software alert status
|
||||
* by writing 0 to bit 4 of Control register(0x1)
|
||||
*/
|
||||
ctrl = i2c_smbus_read_byte_data(client, SBRMI_CTRL);
|
||||
if (ctrl < 0)
|
||||
return ctrl;
|
||||
|
||||
if (ctrl & 0x10) {
|
||||
ctrl &= ~0x10;
|
||||
return i2c_smbus_write_byte_data(client,
|
||||
SBRMI_CTRL, ctrl);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rmi_mailbox_xfer(struct sbrmi_data *data,
|
||||
struct sbrmi_mailbox_msg *msg)
|
||||
{
|
||||
int i, ret, retry = 10;
|
||||
int sw_status;
|
||||
u8 byte;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
|
||||
/* Indicate firmware a command is to be serviced */
|
||||
ret = i2c_smbus_write_byte_data(data->client,
|
||||
SBRMI_INBNDMSG7, START_CMD);
|
||||
if (ret < 0)
|
||||
goto exit_unlock;
|
||||
|
||||
/* Write the command to SBRMI::InBndMsg_inst0 */
|
||||
ret = i2c_smbus_write_byte_data(data->client,
|
||||
SBRMI_INBNDMSG0, msg->cmd);
|
||||
if (ret < 0)
|
||||
goto exit_unlock;
|
||||
|
||||
/*
|
||||
* For both read and write the initiator (BMC) writes
|
||||
* Command Data In[31:0] to SBRMI::InBndMsg_inst[4:1]
|
||||
* SBRMI_x3C(MSB):SBRMI_x39(LSB)
|
||||
*/
|
||||
for (i = 0; i < 4; i++) {
|
||||
byte = (msg->data_in >> i * 8) & 0xff;
|
||||
ret = i2c_smbus_write_byte_data(data->client,
|
||||
SBRMI_INBNDMSG1 + i, byte);
|
||||
if (ret < 0)
|
||||
goto exit_unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write 0x01 to SBRMI::SoftwareInterrupt to notify firmware to
|
||||
* perform the requested read or write command
|
||||
*/
|
||||
ret = i2c_smbus_write_byte_data(data->client,
|
||||
SBRMI_SW_INTERRUPT, TRIGGER_MAILBOX);
|
||||
if (ret < 0)
|
||||
goto exit_unlock;
|
||||
|
||||
/*
|
||||
* Firmware will write SBRMI::Status[SwAlertSts]=1 to generate
|
||||
* an ALERT (if enabled) to initiator (BMC) to indicate completion
|
||||
* of the requested command
|
||||
*/
|
||||
do {
|
||||
sw_status = i2c_smbus_read_byte_data(data->client,
|
||||
SBRMI_STATUS);
|
||||
if (sw_status < 0) {
|
||||
ret = sw_status;
|
||||
goto exit_unlock;
|
||||
}
|
||||
if (sw_status & SW_ALERT_MASK)
|
||||
break;
|
||||
usleep_range(50, 100);
|
||||
} while (retry--);
|
||||
|
||||
if (retry < 0) {
|
||||
dev_err(&data->client->dev,
|
||||
"Firmware fail to indicate command completion\n");
|
||||
ret = -EIO;
|
||||
goto exit_unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* For a read operation, the initiator (BMC) reads the firmware
|
||||
* response Command Data Out[31:0] from SBRMI::OutBndMsg_inst[4:1]
|
||||
* {SBRMI_x34(MSB):SBRMI_x31(LSB)}.
|
||||
*/
|
||||
if (msg->read) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
ret = i2c_smbus_read_byte_data(data->client,
|
||||
SBRMI_OUTBNDMSG1 + i);
|
||||
if (ret < 0)
|
||||
goto exit_unlock;
|
||||
msg->data_out |= ret << i * 8;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* BMC must write 1'b1 to SBRMI::Status[SwAlertSts] to clear the
|
||||
* ALERT to initiator
|
||||
*/
|
||||
ret = i2c_smbus_write_byte_data(data->client, SBRMI_STATUS,
|
||||
sw_status | SW_ALERT_MASK);
|
||||
|
||||
exit_unlock:
|
||||
mutex_unlock(&data->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sbrmi_read(struct device *dev, enum hwmon_sensor_types type,
|
||||
u32 attr, int channel, long *val)
|
||||
{
|
||||
struct sbrmi_data *data = dev_get_drvdata(dev);
|
||||
struct sbrmi_mailbox_msg msg = { 0 };
|
||||
int ret;
|
||||
|
||||
if (type != hwmon_power)
|
||||
return -EINVAL;
|
||||
|
||||
msg.read = true;
|
||||
switch (attr) {
|
||||
case hwmon_power_input:
|
||||
msg.cmd = SBRMI_READ_PKG_PWR_CONSUMPTION;
|
||||
ret = rmi_mailbox_xfer(data, &msg);
|
||||
break;
|
||||
case hwmon_power_cap:
|
||||
msg.cmd = SBRMI_READ_PKG_PWR_LIMIT;
|
||||
ret = rmi_mailbox_xfer(data, &msg);
|
||||
break;
|
||||
case hwmon_power_cap_max:
|
||||
msg.data_out = data->pwr_limit_max;
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
/* hwmon power attributes are in microWatt */
|
||||
*val = (long)msg.data_out * 1000;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sbrmi_write(struct device *dev, enum hwmon_sensor_types type,
|
||||
u32 attr, int channel, long val)
|
||||
{
|
||||
struct sbrmi_data *data = dev_get_drvdata(dev);
|
||||
struct sbrmi_mailbox_msg msg = { 0 };
|
||||
|
||||
if (type != hwmon_power && attr != hwmon_power_cap)
|
||||
return -EINVAL;
|
||||
/*
|
||||
* hwmon power attributes are in microWatt
|
||||
* mailbox read/write is in mWatt
|
||||
*/
|
||||
val /= 1000;
|
||||
|
||||
val = clamp_val(val, SBRMI_PWR_MIN, data->pwr_limit_max);
|
||||
|
||||
msg.cmd = SBRMI_WRITE_PKG_PWR_LIMIT;
|
||||
msg.data_in = val;
|
||||
msg.read = false;
|
||||
|
||||
return rmi_mailbox_xfer(data, &msg);
|
||||
}
|
||||
|
||||
static umode_t sbrmi_is_visible(const void *data,
|
||||
enum hwmon_sensor_types type,
|
||||
u32 attr, int channel)
|
||||
{
|
||||
switch (type) {
|
||||
case hwmon_power:
|
||||
switch (attr) {
|
||||
case hwmon_power_input:
|
||||
case hwmon_power_cap_max:
|
||||
return 0444;
|
||||
case hwmon_power_cap:
|
||||
return 0644;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct hwmon_channel_info * const sbrmi_info[] = {
|
||||
HWMON_CHANNEL_INFO(power,
|
||||
HWMON_P_INPUT | HWMON_P_CAP | HWMON_P_CAP_MAX),
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct hwmon_ops sbrmi_hwmon_ops = {
|
||||
.is_visible = sbrmi_is_visible,
|
||||
.read = sbrmi_read,
|
||||
.write = sbrmi_write,
|
||||
};
|
||||
|
||||
static const struct hwmon_chip_info sbrmi_chip_info = {
|
||||
.ops = &sbrmi_hwmon_ops,
|
||||
.info = sbrmi_info,
|
||||
};
|
||||
|
||||
static int sbrmi_get_max_pwr_limit(struct sbrmi_data *data)
|
||||
{
|
||||
struct sbrmi_mailbox_msg msg = { 0 };
|
||||
int ret;
|
||||
|
||||
msg.cmd = SBRMI_READ_PKG_MAX_PWR_LIMIT;
|
||||
msg.read = true;
|
||||
ret = rmi_mailbox_xfer(data, &msg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
data->pwr_limit_max = msg.data_out;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sbrmi_probe(struct i2c_client *client)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device *hwmon_dev;
|
||||
struct sbrmi_data *data;
|
||||
int ret;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(struct sbrmi_data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->client = client;
|
||||
mutex_init(&data->lock);
|
||||
|
||||
/* Enable alert for SB-RMI sequence */
|
||||
ret = sbrmi_enable_alert(client);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Cache maximum power limit */
|
||||
ret = sbrmi_get_max_pwr_limit(data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data,
|
||||
&sbrmi_chip_info, NULL);
|
||||
|
||||
return PTR_ERR_OR_ZERO(hwmon_dev);
|
||||
}
|
||||
|
||||
static const struct i2c_device_id sbrmi_id[] = {
|
||||
{"sbrmi"},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, sbrmi_id);
|
||||
|
||||
static const struct of_device_id __maybe_unused sbrmi_of_match[] = {
|
||||
{
|
||||
.compatible = "amd,sbrmi",
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sbrmi_of_match);
|
||||
|
||||
static struct i2c_driver sbrmi_driver = {
|
||||
.driver = {
|
||||
.name = "sbrmi",
|
||||
.of_match_table = of_match_ptr(sbrmi_of_match),
|
||||
},
|
||||
.probe = sbrmi_probe,
|
||||
.id_table = sbrmi_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(sbrmi_driver);
|
||||
|
||||
MODULE_AUTHOR("Akshay Gupta <akshay.gupta@amd.com>");
|
||||
MODULE_DESCRIPTION("Hwmon driver for AMD SB-RMI emulated sensor");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -259,4 +259,13 @@ config CORESIGHT_DUMMY
|
|||
|
||||
To compile this driver as a module, choose M here: the module will be
|
||||
called coresight-dummy.
|
||||
|
||||
config CORESIGHT_KUNIT_TESTS
|
||||
tristate "Enable Coresight unit tests"
|
||||
depends on KUNIT
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
Enable Coresight unit tests. Only useful for development and not
|
||||
intended for production.
|
||||
|
||||
endif
|
||||
|
|
|
@ -22,6 +22,8 @@ condflags := \
|
|||
$(call cc-option, -Wstringop-truncation)
|
||||
subdir-ccflags-y += $(condflags)
|
||||
|
||||
CFLAGS_coresight-stm.o := -D__DISABLE_TRACE_MMIO__
|
||||
|
||||
obj-$(CONFIG_CORESIGHT) += coresight.o
|
||||
coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \
|
||||
coresight-sysfs.o coresight-syscfg.o coresight-config.o \
|
||||
|
@ -53,3 +55,4 @@ obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
|
|||
obj-$(CONFIG_CORESIGHT_DUMMY) += coresight-dummy.o
|
||||
obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
|
||||
coresight-ctcu-y := coresight-ctcu-core.o
|
||||
obj-$(CONFIG_CORESIGHT_KUNIT_TESTS) += coresight-kunit-tests.o
|
||||
|
|
|
@ -113,9 +113,8 @@ typedef u64 cate_t;
|
|||
* containing the data page pointer for @offset. If @daddrp is not NULL,
|
||||
* @daddrp points the DMA address of the beginning of the table.
|
||||
*/
|
||||
static inline cate_t *catu_get_table(struct tmc_sg_table *catu_table,
|
||||
unsigned long offset,
|
||||
dma_addr_t *daddrp)
|
||||
static cate_t *catu_get_table(struct tmc_sg_table *catu_table, unsigned long offset,
|
||||
dma_addr_t *daddrp)
|
||||
{
|
||||
unsigned long buf_size = tmc_sg_table_buf_size(catu_table);
|
||||
unsigned int table_nr, pg_idx, pg_offset;
|
||||
|
@ -165,12 +164,12 @@ static void catu_dump_table(struct tmc_sg_table *catu_table)
|
|||
}
|
||||
|
||||
#else
|
||||
static inline void catu_dump_table(struct tmc_sg_table *catu_table)
|
||||
static void catu_dump_table(struct tmc_sg_table *catu_table)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline cate_t catu_make_entry(dma_addr_t addr)
|
||||
static cate_t catu_make_entry(dma_addr_t addr)
|
||||
{
|
||||
return addr ? CATU_VALID_ENTRY(addr) : 0;
|
||||
}
|
||||
|
@ -390,7 +389,7 @@ static const struct attribute_group *catu_groups[] = {
|
|||
};
|
||||
|
||||
|
||||
static inline int catu_wait_for_ready(struct catu_drvdata *drvdata)
|
||||
static int catu_wait_for_ready(struct catu_drvdata *drvdata)
|
||||
{
|
||||
struct csdev_access *csa = &drvdata->csdev->access;
|
||||
|
||||
|
@ -458,12 +457,17 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, enum cs_mode cs_mode,
|
|||
static int catu_enable(struct coresight_device *csdev, enum cs_mode mode,
|
||||
void *data)
|
||||
{
|
||||
int rc;
|
||||
int rc = 0;
|
||||
struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
|
||||
|
||||
CS_UNLOCK(catu_drvdata->base);
|
||||
rc = catu_enable_hw(catu_drvdata, mode, data);
|
||||
CS_LOCK(catu_drvdata->base);
|
||||
guard(raw_spinlock_irqsave)(&catu_drvdata->spinlock);
|
||||
if (csdev->refcnt == 0) {
|
||||
CS_UNLOCK(catu_drvdata->base);
|
||||
rc = catu_enable_hw(catu_drvdata, mode, data);
|
||||
CS_LOCK(catu_drvdata->base);
|
||||
}
|
||||
if (!rc)
|
||||
csdev->refcnt++;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -486,12 +490,15 @@ static int catu_disable_hw(struct catu_drvdata *drvdata)
|
|||
|
||||
static int catu_disable(struct coresight_device *csdev, void *__unused)
|
||||
{
|
||||
int rc;
|
||||
int rc = 0;
|
||||
struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
|
||||
|
||||
CS_UNLOCK(catu_drvdata->base);
|
||||
rc = catu_disable_hw(catu_drvdata);
|
||||
CS_LOCK(catu_drvdata->base);
|
||||
guard(raw_spinlock_irqsave)(&catu_drvdata->spinlock);
|
||||
if (--csdev->refcnt == 0) {
|
||||
CS_UNLOCK(catu_drvdata->base);
|
||||
rc = catu_disable_hw(catu_drvdata);
|
||||
CS_LOCK(catu_drvdata->base);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -550,6 +557,7 @@ static int __catu_probe(struct device *dev, struct resource *res)
|
|||
dev->platform_data = pdata;
|
||||
|
||||
drvdata->base = base;
|
||||
raw_spin_lock_init(&drvdata->spinlock);
|
||||
catu_desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||
catu_desc.pdata = pdata;
|
||||
catu_desc.dev = dev;
|
||||
|
@ -558,6 +566,7 @@ static int __catu_probe(struct device *dev, struct resource *res)
|
|||
catu_desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CATU;
|
||||
catu_desc.ops = &catu_ops;
|
||||
|
||||
coresight_clear_self_claim_tag(&catu_desc.access);
|
||||
drvdata->csdev = coresight_register(&catu_desc);
|
||||
if (IS_ERR(drvdata->csdev))
|
||||
ret = PTR_ERR(drvdata->csdev);
|
||||
|
@ -702,7 +711,7 @@ static int __init catu_init(void)
|
|||
{
|
||||
int ret;
|
||||
|
||||
ret = coresight_init_driver("catu", &catu_driver, &catu_platform_driver);
|
||||
ret = coresight_init_driver("catu", &catu_driver, &catu_platform_driver, THIS_MODULE);
|
||||
tmc_etr_set_catu_ops(&etr_catu_buf_ops);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ struct catu_drvdata {
|
|||
void __iomem *base;
|
||||
struct coresight_device *csdev;
|
||||
int irq;
|
||||
raw_spinlock_t spinlock;
|
||||
};
|
||||
|
||||
#define CATU_REG32(name, offset) \
|
||||
|
|
|
@ -228,7 +228,7 @@ struct cscfg_feature_csdev {
|
|||
* @feats_csdev:references to the device features to enable.
|
||||
*/
|
||||
struct cscfg_config_csdev {
|
||||
const struct cscfg_config_desc *config_desc;
|
||||
struct cscfg_config_desc *config_desc;
|
||||
struct coresight_device *csdev;
|
||||
bool enabled;
|
||||
struct list_head node;
|
||||
|
|
|
@ -129,34 +129,36 @@ coresight_find_out_connection(struct coresight_device *csdev,
|
|||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static inline u32 coresight_read_claim_tags(struct coresight_device *csdev)
|
||||
static u32 coresight_read_claim_tags_unlocked(struct coresight_device *csdev)
|
||||
{
|
||||
return csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR);
|
||||
return FIELD_GET(CORESIGHT_CLAIM_MASK,
|
||||
csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR));
|
||||
}
|
||||
|
||||
static inline bool coresight_is_claimed_self_hosted(struct coresight_device *csdev)
|
||||
{
|
||||
return coresight_read_claim_tags(csdev) == CORESIGHT_CLAIM_SELF_HOSTED;
|
||||
}
|
||||
|
||||
static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
|
||||
{
|
||||
return coresight_read_claim_tags(csdev) != 0;
|
||||
}
|
||||
|
||||
static inline void coresight_set_claim_tags(struct coresight_device *csdev)
|
||||
static void coresight_set_self_claim_tag_unlocked(struct coresight_device *csdev)
|
||||
{
|
||||
csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
|
||||
CORESIGHT_CLAIMSET);
|
||||
isb();
|
||||
}
|
||||
|
||||
static inline void coresight_clear_claim_tags(struct coresight_device *csdev)
|
||||
void coresight_clear_self_claim_tag(struct csdev_access *csa)
|
||||
{
|
||||
csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
|
||||
if (csa->io_mem)
|
||||
CS_UNLOCK(csa->base);
|
||||
coresight_clear_self_claim_tag_unlocked(csa);
|
||||
if (csa->io_mem)
|
||||
CS_LOCK(csa->base);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag);
|
||||
|
||||
void coresight_clear_self_claim_tag_unlocked(struct csdev_access *csa)
|
||||
{
|
||||
csdev_access_relaxed_write32(csa, CORESIGHT_CLAIM_SELF_HOSTED,
|
||||
CORESIGHT_CLAIMCLR);
|
||||
isb();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag_unlocked);
|
||||
|
||||
/*
|
||||
* coresight_claim_device_unlocked : Claim the device for self-hosted usage
|
||||
|
@ -170,18 +172,41 @@ static inline void coresight_clear_claim_tags(struct coresight_device *csdev)
|
|||
*/
|
||||
int coresight_claim_device_unlocked(struct coresight_device *csdev)
|
||||
{
|
||||
int tag;
|
||||
struct csdev_access *csa;
|
||||
|
||||
if (WARN_ON(!csdev))
|
||||
return -EINVAL;
|
||||
|
||||
if (coresight_is_claimed_any(csdev))
|
||||
csa = &csdev->access;
|
||||
tag = coresight_read_claim_tags_unlocked(csdev);
|
||||
|
||||
switch (tag) {
|
||||
case CORESIGHT_CLAIM_FREE:
|
||||
coresight_set_self_claim_tag_unlocked(csdev);
|
||||
if (coresight_read_claim_tags_unlocked(csdev) == CORESIGHT_CLAIM_SELF_HOSTED)
|
||||
return 0;
|
||||
|
||||
/* There was a race setting the tag, clean up and fail */
|
||||
coresight_clear_self_claim_tag_unlocked(csa);
|
||||
dev_dbg(&csdev->dev, "Busy: Couldn't set self claim tag");
|
||||
return -EBUSY;
|
||||
|
||||
coresight_set_claim_tags(csdev);
|
||||
if (coresight_is_claimed_self_hosted(csdev))
|
||||
return 0;
|
||||
/* There was a race setting the tags, clean up and fail */
|
||||
coresight_clear_claim_tags(csdev);
|
||||
return -EBUSY;
|
||||
case CORESIGHT_CLAIM_EXTERNAL:
|
||||
/* External debug is an expected state, so log and report BUSY */
|
||||
dev_dbg(&csdev->dev, "Busy: Claimed by external debugger");
|
||||
return -EBUSY;
|
||||
|
||||
default:
|
||||
case CORESIGHT_CLAIM_SELF_HOSTED:
|
||||
case CORESIGHT_CLAIM_INVALID:
|
||||
/*
|
||||
* Warn here because we clear a lingering self hosted tag
|
||||
* on probe, so other tag combinations are impossible.
|
||||
*/
|
||||
dev_err_once(&csdev->dev, "Invalid claim tag state: %x", tag);
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked);
|
||||
|
||||
|
@ -201,7 +226,7 @@ int coresight_claim_device(struct coresight_device *csdev)
|
|||
EXPORT_SYMBOL_GPL(coresight_claim_device);
|
||||
|
||||
/*
|
||||
* coresight_disclaim_device_unlocked : Clear the claim tags for the device.
|
||||
* coresight_disclaim_device_unlocked : Clear the claim tag for the device.
|
||||
* Called with CS_UNLOCKed for the component.
|
||||
*/
|
||||
void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
|
||||
|
@ -210,15 +235,15 @@ void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
|
|||
if (WARN_ON(!csdev))
|
||||
return;
|
||||
|
||||
if (coresight_is_claimed_self_hosted(csdev))
|
||||
coresight_clear_claim_tags(csdev);
|
||||
if (coresight_read_claim_tags_unlocked(csdev) == CORESIGHT_CLAIM_SELF_HOSTED)
|
||||
coresight_clear_self_claim_tag_unlocked(&csdev->access);
|
||||
else
|
||||
/*
|
||||
* The external agent may have not honoured our claim
|
||||
* and has manipulated it. Or something else has seriously
|
||||
* gone wrong in our driver.
|
||||
*/
|
||||
WARN_ON_ONCE(1);
|
||||
dev_WARN_ONCE(&csdev->dev, 1, "External agent took claim tag");
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_disclaim_device_unlocked);
|
||||
|
||||
|
@ -367,6 +392,28 @@ void coresight_disable_source(struct coresight_device *csdev, void *data)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_disable_source);
|
||||
|
||||
void coresight_pause_source(struct coresight_device *csdev)
|
||||
{
|
||||
if (!coresight_is_percpu_source(csdev))
|
||||
return;
|
||||
|
||||
if (source_ops(csdev)->pause_perf)
|
||||
source_ops(csdev)->pause_perf(csdev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_pause_source);
|
||||
|
||||
int coresight_resume_source(struct coresight_device *csdev)
|
||||
{
|
||||
if (!coresight_is_percpu_source(csdev))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!source_ops(csdev)->resume_perf)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return source_ops(csdev)->resume_perf(csdev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_resume_source);
|
||||
|
||||
/*
|
||||
* coresight_disable_path_from : Disable components in the given path beyond
|
||||
* @nd in the list. If @nd is NULL, all the components, except the SOURCE are
|
||||
|
@ -465,7 +512,7 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
|
|||
/* Enable all helpers adjacent to the path first */
|
||||
ret = coresight_enable_helpers(csdev, mode, path);
|
||||
if (ret)
|
||||
goto err;
|
||||
goto err_disable_path;
|
||||
/*
|
||||
* ETF devices are tricky... They can be a link or a sink,
|
||||
* depending on how they are configured. If an ETF has been
|
||||
|
@ -486,8 +533,10 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
|
|||
* that need disabling. Disabling the path here
|
||||
* would mean we could disrupt an existing session.
|
||||
*/
|
||||
if (ret)
|
||||
if (ret) {
|
||||
coresight_disable_helpers(csdev, path);
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
case CORESIGHT_DEV_TYPE_SOURCE:
|
||||
/* sources are enabled from either sysFS or Perf */
|
||||
|
@ -497,16 +546,19 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
|
|||
child = list_next_entry(nd, link)->csdev;
|
||||
ret = coresight_enable_link(csdev, parent, child, source);
|
||||
if (ret)
|
||||
goto err;
|
||||
goto err_disable_helpers;
|
||||
break;
|
||||
default:
|
||||
goto err;
|
||||
ret = -EINVAL;
|
||||
goto err_disable_helpers;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
err:
|
||||
err_disable_helpers:
|
||||
coresight_disable_helpers(csdev, path);
|
||||
err_disable_path:
|
||||
coresight_disable_path_from(path, nd);
|
||||
goto out;
|
||||
}
|
||||
|
@ -579,7 +631,7 @@ struct coresight_device *coresight_get_sink_by_id(u32 id)
|
|||
* Return true in successful case and power up the device.
|
||||
* Return false when failed to get reference of module.
|
||||
*/
|
||||
static inline bool coresight_get_ref(struct coresight_device *csdev)
|
||||
static bool coresight_get_ref(struct coresight_device *csdev)
|
||||
{
|
||||
struct device *dev = csdev->dev.parent;
|
||||
|
||||
|
@ -598,7 +650,7 @@ static inline bool coresight_get_ref(struct coresight_device *csdev)
|
|||
*
|
||||
* @csdev: The coresight device to decrement a reference from.
|
||||
*/
|
||||
static inline void coresight_put_ref(struct coresight_device *csdev)
|
||||
static void coresight_put_ref(struct coresight_device *csdev)
|
||||
{
|
||||
struct device *dev = csdev->dev.parent;
|
||||
|
||||
|
@ -821,7 +873,7 @@ void coresight_release_path(struct coresight_path *path)
|
|||
}
|
||||
|
||||
/* return true if the device is a suitable type for a default sink */
|
||||
static inline bool coresight_is_def_sink_type(struct coresight_device *csdev)
|
||||
static bool coresight_is_def_sink_type(struct coresight_device *csdev)
|
||||
{
|
||||
/* sink & correct subtype */
|
||||
if (((csdev->type == CORESIGHT_DEV_TYPE_SINK) ||
|
||||
|
@ -959,6 +1011,7 @@ coresight_find_default_sink(struct coresight_device *csdev)
|
|||
}
|
||||
return csdev->def_sink;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(coresight_find_default_sink);
|
||||
|
||||
static int coresight_remove_sink_ref(struct device *dev, void *data)
|
||||
{
|
||||
|
@ -1385,8 +1438,8 @@ EXPORT_SYMBOL_GPL(coresight_unregister);
|
|||
*
|
||||
* Returns the index of the entry, when found. Otherwise, -ENOENT.
|
||||
*/
|
||||
static inline int coresight_search_device_idx(struct coresight_dev_list *dict,
|
||||
struct fwnode_handle *fwnode)
|
||||
static int coresight_search_device_idx(struct coresight_dev_list *dict,
|
||||
struct fwnode_handle *fwnode)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -1585,17 +1638,17 @@ module_init(coresight_init);
|
|||
module_exit(coresight_exit);
|
||||
|
||||
int coresight_init_driver(const char *drv, struct amba_driver *amba_drv,
|
||||
struct platform_driver *pdev_drv)
|
||||
struct platform_driver *pdev_drv, struct module *owner)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = amba_driver_register(amba_drv);
|
||||
ret = __amba_driver_register(amba_drv, owner);
|
||||
if (ret) {
|
||||
pr_err("%s: error registering AMBA driver\n", drv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = platform_driver_register(pdev_drv);
|
||||
ret = __platform_driver_register(pdev_drv, owner);
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -774,7 +774,8 @@ static struct platform_driver debug_platform_driver = {
|
|||
|
||||
static int __init debug_init(void)
|
||||
{
|
||||
return coresight_init_driver("debug", &debug_driver, &debug_platform_driver);
|
||||
return coresight_init_driver("debug", &debug_driver, &debug_platform_driver,
|
||||
THIS_MODULE);
|
||||
}
|
||||
|
||||
static void __exit debug_exit(void)
|
||||
|
|
|
@ -931,6 +931,8 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
cti_desc.ops = &cti_ops;
|
||||
cti_desc.groups = drvdata->ctidev.con_groups;
|
||||
cti_desc.dev = dev;
|
||||
|
||||
coresight_clear_self_claim_tag(&cti_desc.access);
|
||||
drvdata->csdev = coresight_register(&cti_desc);
|
||||
if (IS_ERR(drvdata->csdev)) {
|
||||
ret = PTR_ERR(drvdata->csdev);
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include <linux/coresight.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/fwnode.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
@ -17,6 +16,8 @@
|
|||
|
||||
#include "coresight-priv.h"
|
||||
|
||||
struct fwnode_handle;
|
||||
|
||||
/*
|
||||
* Device registers
|
||||
* 0x000 - 0x144: CTI programming and status
|
||||
|
|
|
@ -95,7 +95,7 @@ struct etb_drvdata {
|
|||
static int etb_set_buffer(struct coresight_device *csdev,
|
||||
struct perf_output_handle *handle);
|
||||
|
||||
static inline unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
|
||||
static unsigned int etb_get_buffer_depth(struct etb_drvdata *drvdata)
|
||||
{
|
||||
return readl_relaxed(drvdata->base + ETB_RAM_DEPTH_REG);
|
||||
}
|
||||
|
@ -772,6 +772,8 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
desc.pdata = pdata;
|
||||
desc.dev = dev;
|
||||
desc.groups = coresight_etb_groups;
|
||||
|
||||
coresight_clear_self_claim_tag(&desc.access);
|
||||
drvdata->csdev = coresight_register(&desc);
|
||||
if (IS_ERR(drvdata->csdev))
|
||||
return PTR_ERR(drvdata->csdev);
|
||||
|
|
|
@ -365,6 +365,18 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
|
|||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If AUX pause feature is enabled but the ETM driver does not
|
||||
* support the operations, clear this CPU from the mask and
|
||||
* continue to next one.
|
||||
*/
|
||||
if (event->attr.aux_start_paused &&
|
||||
(!source_ops(csdev)->pause_perf || !source_ops(csdev)->resume_perf)) {
|
||||
dev_err_once(&csdev->dev, "AUX pause is not supported.\n");
|
||||
cpumask_clear_cpu(cpu, mask);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* No sink provided - look for a default sink for all the ETMs,
|
||||
* where this event can be scheduled.
|
||||
|
@ -450,6 +462,15 @@ err:
|
|||
goto out;
|
||||
}
|
||||
|
||||
static int etm_event_resume(struct coresight_device *csdev,
|
||||
struct etm_ctxt *ctxt)
|
||||
{
|
||||
if (!ctxt->event_data)
|
||||
return 0;
|
||||
|
||||
return coresight_resume_source(csdev);
|
||||
}
|
||||
|
||||
static void etm_event_start(struct perf_event *event, int flags)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
|
@ -463,6 +484,14 @@ static void etm_event_start(struct perf_event *event, int flags)
|
|||
if (!csdev)
|
||||
goto fail;
|
||||
|
||||
if (flags & PERF_EF_RESUME) {
|
||||
if (etm_event_resume(csdev, ctxt) < 0) {
|
||||
dev_err(&csdev->dev, "Failed to resume ETM event.\n");
|
||||
goto fail;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Have we messed up our tracking ? */
|
||||
if (WARN_ON(ctxt->event_data))
|
||||
goto fail;
|
||||
|
@ -545,6 +574,55 @@ fail:
|
|||
return;
|
||||
}
|
||||
|
||||
static void etm_event_pause(struct perf_event *event,
|
||||
struct coresight_device *csdev,
|
||||
struct etm_ctxt *ctxt)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
struct coresight_device *sink;
|
||||
struct perf_output_handle *handle = &ctxt->handle;
|
||||
struct coresight_path *path;
|
||||
unsigned long size;
|
||||
|
||||
if (!ctxt->event_data)
|
||||
return;
|
||||
|
||||
/* Stop tracer */
|
||||
coresight_pause_source(csdev);
|
||||
|
||||
path = etm_event_cpu_path(ctxt->event_data, cpu);
|
||||
sink = coresight_get_sink(path);
|
||||
if (WARN_ON_ONCE(!sink))
|
||||
return;
|
||||
|
||||
/*
|
||||
* The per CPU sink has own interrupt handling, it might have
|
||||
* race condition with updating buffer on AUX trace pause if
|
||||
* it is invoked from NMI. To avoid the race condition,
|
||||
* disallows updating buffer for the per CPU sink case.
|
||||
*/
|
||||
if (coresight_is_percpu_sink(sink))
|
||||
return;
|
||||
|
||||
if (WARN_ON_ONCE(handle->event != event))
|
||||
return;
|
||||
|
||||
if (!sink_ops(sink)->update_buffer)
|
||||
return;
|
||||
|
||||
size = sink_ops(sink)->update_buffer(sink, handle,
|
||||
ctxt->event_data->snk_config);
|
||||
if (READ_ONCE(handle->event)) {
|
||||
if (!size)
|
||||
return;
|
||||
|
||||
perf_aux_output_end(handle, size);
|
||||
perf_aux_output_begin(handle, event);
|
||||
} else {
|
||||
WARN_ON_ONCE(size);
|
||||
}
|
||||
}
|
||||
|
||||
static void etm_event_stop(struct perf_event *event, int mode)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
|
@ -555,6 +633,9 @@ static void etm_event_stop(struct perf_event *event, int mode)
|
|||
struct etm_event_data *event_data;
|
||||
struct coresight_path *path;
|
||||
|
||||
if (mode & PERF_EF_PAUSE)
|
||||
return etm_event_pause(event, csdev, ctxt);
|
||||
|
||||
/*
|
||||
* If we still have access to the event_data via handle,
|
||||
* confirm that we haven't messed up the tracking.
|
||||
|
@ -899,7 +980,8 @@ int __init etm_perf_init(void)
|
|||
int ret;
|
||||
|
||||
etm_pmu.capabilities = (PERF_PMU_CAP_EXCLUSIVE |
|
||||
PERF_PMU_CAP_ITRACE);
|
||||
PERF_PMU_CAP_ITRACE |
|
||||
PERF_PMU_CAP_AUX_PAUSE);
|
||||
|
||||
etm_pmu.attr_groups = etm_pmu_attr_groups;
|
||||
etm_pmu.task_ctx_nr = perf_sw_context;
|
||||
|
|
|
@ -229,7 +229,7 @@ struct etm_config {
|
|||
* @config: structure holding configuration parameters.
|
||||
*/
|
||||
struct etm_drvdata {
|
||||
void __iomem *base;
|
||||
struct csdev_access csa;
|
||||
struct clk *atclk;
|
||||
struct coresight_device *csdev;
|
||||
spinlock_t spinlock;
|
||||
|
@ -260,7 +260,7 @@ static inline void etm_writel(struct etm_drvdata *drvdata,
|
|||
"invalid CP14 access to ETM reg: %#x", off);
|
||||
}
|
||||
} else {
|
||||
writel_relaxed(val, drvdata->base + off);
|
||||
writel_relaxed(val, drvdata->csa.base + off);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,7 +274,7 @@ static inline unsigned int etm_readl(struct etm_drvdata *drvdata, u32 off)
|
|||
"invalid CP14 access to ETM reg: %#x", off);
|
||||
}
|
||||
} else {
|
||||
val = readl_relaxed(drvdata->base + off);
|
||||
val = readl_relaxed(drvdata->csa.base + off);
|
||||
}
|
||||
|
||||
return val;
|
||||
|
|
|
@ -86,9 +86,9 @@ static void etm_set_pwrup(struct etm_drvdata *drvdata)
|
|||
{
|
||||
u32 etmpdcr;
|
||||
|
||||
etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);
|
||||
etmpdcr = readl_relaxed(drvdata->csa.base + ETMPDCR);
|
||||
etmpdcr |= ETMPDCR_PWD_UP;
|
||||
writel_relaxed(etmpdcr, drvdata->base + ETMPDCR);
|
||||
writel_relaxed(etmpdcr, drvdata->csa.base + ETMPDCR);
|
||||
/* Ensure pwrup completes before subsequent cp14 accesses */
|
||||
mb();
|
||||
isb();
|
||||
|
@ -101,9 +101,9 @@ static void etm_clr_pwrup(struct etm_drvdata *drvdata)
|
|||
/* Ensure pending cp14 accesses complete before clearing pwrup */
|
||||
mb();
|
||||
isb();
|
||||
etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);
|
||||
etmpdcr = readl_relaxed(drvdata->csa.base + ETMPDCR);
|
||||
etmpdcr &= ~ETMPDCR_PWD_UP;
|
||||
writel_relaxed(etmpdcr, drvdata->base + ETMPDCR);
|
||||
writel_relaxed(etmpdcr, drvdata->csa.base + ETMPDCR);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -365,7 +365,7 @@ static int etm_enable_hw(struct etm_drvdata *drvdata)
|
|||
struct etm_config *config = &drvdata->config;
|
||||
struct coresight_device *csdev = drvdata->csdev;
|
||||
|
||||
CS_UNLOCK(drvdata->base);
|
||||
CS_UNLOCK(drvdata->csa.base);
|
||||
|
||||
rc = coresight_claim_device_unlocked(csdev);
|
||||
if (rc)
|
||||
|
@ -427,7 +427,7 @@ static int etm_enable_hw(struct etm_drvdata *drvdata)
|
|||
etm_clr_prog(drvdata);
|
||||
|
||||
done:
|
||||
CS_LOCK(drvdata->base);
|
||||
CS_LOCK(drvdata->csa.base);
|
||||
|
||||
dev_dbg(&drvdata->csdev->dev, "cpu: %d enable smp call done: %d\n",
|
||||
drvdata->cpu, rc);
|
||||
|
@ -549,7 +549,7 @@ static void etm_disable_hw(void *info)
|
|||
struct etm_config *config = &drvdata->config;
|
||||
struct coresight_device *csdev = drvdata->csdev;
|
||||
|
||||
CS_UNLOCK(drvdata->base);
|
||||
CS_UNLOCK(drvdata->csa.base);
|
||||
etm_set_prog(drvdata);
|
||||
|
||||
/* Read back sequencer and counters for post trace analysis */
|
||||
|
@ -561,7 +561,7 @@ static void etm_disable_hw(void *info)
|
|||
etm_set_pwrdwn(drvdata);
|
||||
coresight_disclaim_device_unlocked(csdev);
|
||||
|
||||
CS_LOCK(drvdata->base);
|
||||
CS_LOCK(drvdata->csa.base);
|
||||
|
||||
dev_dbg(&drvdata->csdev->dev,
|
||||
"cpu: %d disable smp call done\n", drvdata->cpu);
|
||||
|
@ -574,7 +574,7 @@ static void etm_disable_perf(struct coresight_device *csdev)
|
|||
if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id()))
|
||||
return;
|
||||
|
||||
CS_UNLOCK(drvdata->base);
|
||||
CS_UNLOCK(drvdata->csa.base);
|
||||
|
||||
/* Setting the prog bit disables tracing immediately */
|
||||
etm_set_prog(drvdata);
|
||||
|
@ -586,7 +586,7 @@ static void etm_disable_perf(struct coresight_device *csdev)
|
|||
etm_set_pwrdwn(drvdata);
|
||||
coresight_disclaim_device_unlocked(csdev);
|
||||
|
||||
CS_LOCK(drvdata->base);
|
||||
CS_LOCK(drvdata->csa.base);
|
||||
|
||||
/*
|
||||
* perf will release trace ids when _free_aux()
|
||||
|
@ -733,7 +733,7 @@ static void etm_init_arch_data(void *info)
|
|||
/* Make sure all registers are accessible */
|
||||
etm_os_unlock(drvdata);
|
||||
|
||||
CS_UNLOCK(drvdata->base);
|
||||
CS_UNLOCK(drvdata->csa.base);
|
||||
|
||||
/* First dummy read */
|
||||
(void)etm_readl(drvdata, ETMPDSR);
|
||||
|
@ -764,9 +764,10 @@ static void etm_init_arch_data(void *info)
|
|||
drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
|
||||
drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
|
||||
|
||||
coresight_clear_self_claim_tag_unlocked(&drvdata->csa);
|
||||
etm_set_pwrdwn(drvdata);
|
||||
etm_clr_pwrup(drvdata);
|
||||
CS_LOCK(drvdata->base);
|
||||
CS_LOCK(drvdata->csa.base);
|
||||
}
|
||||
|
||||
static int __init etm_hp_setup(void)
|
||||
|
@ -827,8 +828,7 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id)
|
|||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
drvdata->base = base;
|
||||
desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||
desc.access = drvdata->csa = CSDEV_ACCESS_IOMEM(base);
|
||||
|
||||
spin_lock_init(&drvdata->spinlock);
|
||||
|
||||
|
|
|
@ -50,11 +50,11 @@ static ssize_t etmsr_show(struct device *dev,
|
|||
|
||||
pm_runtime_get_sync(dev->parent);
|
||||
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||
CS_UNLOCK(drvdata->base);
|
||||
CS_UNLOCK(drvdata->csa.base);
|
||||
|
||||
val = etm_readl(drvdata, ETMSR);
|
||||
|
||||
CS_LOCK(drvdata->base);
|
||||
CS_LOCK(drvdata->csa.base);
|
||||
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||
pm_runtime_put(dev->parent);
|
||||
|
||||
|
@ -949,9 +949,9 @@ static ssize_t seq_curr_state_show(struct device *dev,
|
|||
pm_runtime_get_sync(dev->parent);
|
||||
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||
|
||||
CS_UNLOCK(drvdata->base);
|
||||
CS_UNLOCK(drvdata->csa.base);
|
||||
val = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK);
|
||||
CS_LOCK(drvdata->base);
|
||||
CS_LOCK(drvdata->csa.base);
|
||||
|
||||
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||
pm_runtime_put(dev->parent);
|
||||
|
|
|
@ -84,7 +84,7 @@ static int etm4_probe_cpu(unsigned int cpu);
|
|||
* TRCIDR4.NUMPC > 0b0000 .
|
||||
* TRCSSCSR<n>.PC == 0b1
|
||||
*/
|
||||
static inline bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
|
||||
static bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
|
||||
{
|
||||
return (n < drvdata->nr_ss_cmp) &&
|
||||
drvdata->nr_pe &&
|
||||
|
@ -185,7 +185,7 @@ static void etm_write_os_lock(struct etmv4_drvdata *drvdata,
|
|||
isb();
|
||||
}
|
||||
|
||||
static inline void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata,
|
||||
static void etm4_os_unlock_csa(struct etmv4_drvdata *drvdata,
|
||||
struct csdev_access *csa)
|
||||
{
|
||||
WARN_ON(drvdata->cpu != smp_processor_id());
|
||||
|
@ -431,6 +431,44 @@ static int etm4x_wait_status(struct csdev_access *csa, int pos, int val)
|
|||
return coresight_timeout(csa, TRCSTATR, pos, val);
|
||||
}
|
||||
|
||||
static int etm4_enable_trace_unit(struct etmv4_drvdata *drvdata)
|
||||
{
|
||||
struct coresight_device *csdev = drvdata->csdev;
|
||||
struct device *etm_dev = &csdev->dev;
|
||||
struct csdev_access *csa = &csdev->access;
|
||||
|
||||
/*
|
||||
* ETE mandates that the TRCRSR is written to before
|
||||
* enabling it.
|
||||
*/
|
||||
if (etm4x_is_ete(drvdata))
|
||||
etm4x_relaxed_write32(csa, TRCRSR_TA, TRCRSR);
|
||||
|
||||
etm4x_allow_trace(drvdata);
|
||||
/* Enable the trace unit */
|
||||
etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);
|
||||
|
||||
/* Synchronize the register updates for sysreg access */
|
||||
if (!csa->io_mem)
|
||||
isb();
|
||||
|
||||
/* wait for TRCSTATR.IDLE to go back down to '0' */
|
||||
if (etm4x_wait_status(csa, TRCSTATR_IDLE_BIT, 0)) {
|
||||
dev_err(etm_dev,
|
||||
"timeout while waiting for Idle Trace Status\n");
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
/*
|
||||
* As recommended by section 4.3.7 ("Synchronization when using the
|
||||
* memory-mapped interface") of ARM IHI 0064D
|
||||
*/
|
||||
dsb(sy);
|
||||
isb();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
|
||||
{
|
||||
int i, rc;
|
||||
|
@ -539,33 +577,8 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
|
|||
etm4x_relaxed_write32(csa, trcpdcr | TRCPDCR_PU, TRCPDCR);
|
||||
}
|
||||
|
||||
/*
|
||||
* ETE mandates that the TRCRSR is written to before
|
||||
* enabling it.
|
||||
*/
|
||||
if (etm4x_is_ete(drvdata))
|
||||
etm4x_relaxed_write32(csa, TRCRSR_TA, TRCRSR);
|
||||
|
||||
etm4x_allow_trace(drvdata);
|
||||
/* Enable the trace unit */
|
||||
etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);
|
||||
|
||||
/* Synchronize the register updates for sysreg access */
|
||||
if (!csa->io_mem)
|
||||
isb();
|
||||
|
||||
/* wait for TRCSTATR.IDLE to go back down to '0' */
|
||||
if (etm4x_wait_status(csa, TRCSTATR_IDLE_BIT, 0))
|
||||
dev_err(etm_dev,
|
||||
"timeout while waiting for Idle Trace Status\n");
|
||||
|
||||
/*
|
||||
* As recommended by section 4.3.7 ("Synchronization when using the
|
||||
* memory-mapped interface") of ARM IHI 0064D
|
||||
*/
|
||||
dsb(sy);
|
||||
isb();
|
||||
|
||||
if (!drvdata->paused)
|
||||
rc = etm4_enable_trace_unit(drvdata);
|
||||
done:
|
||||
etm4_cs_lock(drvdata, csa);
|
||||
|
||||
|
@ -808,6 +821,9 @@ static int etm4_enable_perf(struct coresight_device *csdev,
|
|||
|
||||
drvdata->trcid = path->trace_id;
|
||||
|
||||
/* Populate pause state */
|
||||
drvdata->paused = !!READ_ONCE(event->hw.aux_paused);
|
||||
|
||||
/* And enable it */
|
||||
ret = etm4_enable_hw(drvdata);
|
||||
|
||||
|
@ -834,6 +850,9 @@ static int etm4_enable_sysfs(struct coresight_device *csdev, struct coresight_pa
|
|||
|
||||
drvdata->trcid = path->trace_id;
|
||||
|
||||
/* Tracer will never be paused in sysfs mode */
|
||||
drvdata->paused = false;
|
||||
|
||||
/*
|
||||
* Executing etm4_enable_hw on the cpu whose ETM is being enabled
|
||||
* ensures that register writes occur when cpu is powered.
|
||||
|
@ -884,25 +903,12 @@ static int etm4_enable(struct coresight_device *csdev, struct perf_event *event,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void etm4_disable_hw(void *info)
|
||||
static void etm4_disable_trace_unit(struct etmv4_drvdata *drvdata)
|
||||
{
|
||||
u32 control;
|
||||
struct etmv4_drvdata *drvdata = info;
|
||||
struct etmv4_config *config = &drvdata->config;
|
||||
struct coresight_device *csdev = drvdata->csdev;
|
||||
struct device *etm_dev = &csdev->dev;
|
||||
struct csdev_access *csa = &csdev->access;
|
||||
int i;
|
||||
|
||||
etm4_cs_unlock(drvdata, csa);
|
||||
etm4_disable_arch_specific(drvdata);
|
||||
|
||||
if (!drvdata->skip_power_up) {
|
||||
/* power can be removed from the trace unit now */
|
||||
control = etm4x_relaxed_read32(csa, TRCPDCR);
|
||||
control &= ~TRCPDCR_PU;
|
||||
etm4x_relaxed_write32(csa, control, TRCPDCR);
|
||||
}
|
||||
|
||||
control = etm4x_relaxed_read32(csa, TRCPRGCTLR);
|
||||
|
||||
|
@ -943,6 +949,28 @@ static void etm4_disable_hw(void *info)
|
|||
* of ARM IHI 0064H.b.
|
||||
*/
|
||||
isb();
|
||||
}
|
||||
|
||||
static void etm4_disable_hw(void *info)
|
||||
{
|
||||
u32 control;
|
||||
struct etmv4_drvdata *drvdata = info;
|
||||
struct etmv4_config *config = &drvdata->config;
|
||||
struct coresight_device *csdev = drvdata->csdev;
|
||||
struct csdev_access *csa = &csdev->access;
|
||||
int i;
|
||||
|
||||
etm4_cs_unlock(drvdata, csa);
|
||||
etm4_disable_arch_specific(drvdata);
|
||||
|
||||
if (!drvdata->skip_power_up) {
|
||||
/* power can be removed from the trace unit now */
|
||||
control = etm4x_relaxed_read32(csa, TRCPDCR);
|
||||
control &= ~TRCPDCR_PU;
|
||||
etm4x_relaxed_write32(csa, control, TRCPDCR);
|
||||
}
|
||||
|
||||
etm4_disable_trace_unit(drvdata);
|
||||
|
||||
/* read the status of the single shot comparators */
|
||||
for (i = 0; i < drvdata->nr_ss_cmp; i++) {
|
||||
|
@ -1020,6 +1048,9 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
|
|||
smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);
|
||||
|
||||
raw_spin_unlock(&drvdata->spinlock);
|
||||
|
||||
cscfg_csdev_disable_active_config(csdev);
|
||||
|
||||
cpus_read_unlock();
|
||||
|
||||
/*
|
||||
|
@ -1059,10 +1090,43 @@ static void etm4_disable(struct coresight_device *csdev,
|
|||
coresight_set_mode(csdev, CS_MODE_DISABLED);
|
||||
}
|
||||
|
||||
static int etm4_resume_perf(struct coresight_device *csdev)
|
||||
{
|
||||
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
struct csdev_access *csa = &csdev->access;
|
||||
|
||||
if (coresight_get_mode(csdev) != CS_MODE_PERF)
|
||||
return -EINVAL;
|
||||
|
||||
etm4_cs_unlock(drvdata, csa);
|
||||
etm4_enable_trace_unit(drvdata);
|
||||
etm4_cs_lock(drvdata, csa);
|
||||
|
||||
drvdata->paused = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void etm4_pause_perf(struct coresight_device *csdev)
|
||||
{
|
||||
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
struct csdev_access *csa = &csdev->access;
|
||||
|
||||
if (coresight_get_mode(csdev) != CS_MODE_PERF)
|
||||
return;
|
||||
|
||||
etm4_cs_unlock(drvdata, csa);
|
||||
etm4_disable_trace_unit(drvdata);
|
||||
etm4_cs_lock(drvdata, csa);
|
||||
|
||||
drvdata->paused = true;
|
||||
}
|
||||
|
||||
static const struct coresight_ops_source etm4_source_ops = {
|
||||
.cpu_id = etm4_cpu_id,
|
||||
.enable = etm4_enable,
|
||||
.disable = etm4_disable,
|
||||
.resume_perf = etm4_resume_perf,
|
||||
.pause_perf = etm4_pause_perf,
|
||||
};
|
||||
|
||||
static const struct coresight_ops etm4_cs_ops = {
|
||||
|
@ -1070,7 +1134,7 @@ static const struct coresight_ops etm4_cs_ops = {
|
|||
.source_ops = &etm4_source_ops,
|
||||
};
|
||||
|
||||
static inline bool cpu_supports_sysreg_trace(void)
|
||||
static bool cpu_supports_sysreg_trace(void)
|
||||
{
|
||||
u64 dfr0 = read_sysreg_s(SYS_ID_AA64DFR0_EL1);
|
||||
|
||||
|
@ -1176,7 +1240,7 @@ static void cpu_detect_trace_filtering(struct etmv4_drvdata *drvdata)
|
|||
* tracing at the kernel EL and EL0, forcing to use the
|
||||
* virtual time as the timestamp.
|
||||
*/
|
||||
trfcr = (TRFCR_EL1_TS_VIRTUAL |
|
||||
trfcr = (FIELD_PREP(TRFCR_EL1_TS_MASK, TRFCR_EL1_TS_VIRTUAL) |
|
||||
TRFCR_EL1_ExTRE |
|
||||
TRFCR_EL1_E0TRE);
|
||||
|
||||
|
@ -1372,11 +1436,13 @@ static void etm4_init_arch_data(void *info)
|
|||
drvdata->nrseqstate = FIELD_GET(TRCIDR5_NUMSEQSTATE_MASK, etmidr5);
|
||||
/* NUMCNTR, bits[30:28] number of counters available for tracing */
|
||||
drvdata->nr_cntr = FIELD_GET(TRCIDR5_NUMCNTR_MASK, etmidr5);
|
||||
|
||||
coresight_clear_self_claim_tag_unlocked(csa);
|
||||
etm4_cs_lock(drvdata, csa);
|
||||
cpu_detect_trace_filtering(drvdata);
|
||||
}
|
||||
|
||||
static inline u32 etm4_get_victlr_access_type(struct etmv4_config *config)
|
||||
static u32 etm4_get_victlr_access_type(struct etmv4_config *config)
|
||||
{
|
||||
return etm4_get_access_type(config) << __bf_shf(TRCVICTLR_EXLEVEL_MASK);
|
||||
}
|
||||
|
|
|
@ -2320,11 +2320,11 @@ static ssize_t ts_source_show(struct device *dev,
|
|||
goto out;
|
||||
}
|
||||
|
||||
switch (drvdata->trfcr & TRFCR_EL1_TS_MASK) {
|
||||
val = FIELD_GET(TRFCR_EL1_TS_MASK, drvdata->trfcr);
|
||||
switch (val) {
|
||||
case TRFCR_EL1_TS_VIRTUAL:
|
||||
case TRFCR_EL1_TS_GUEST_PHYSICAL:
|
||||
case TRFCR_EL1_TS_PHYSICAL:
|
||||
val = FIELD_GET(TRFCR_EL1_TS_MASK, drvdata->trfcr);
|
||||
break;
|
||||
default:
|
||||
val = -1;
|
||||
|
@ -2440,7 +2440,7 @@ static u32 etmv4_cross_read(const struct etmv4_drvdata *drvdata, u32 offset)
|
|||
return reg.data;
|
||||
}
|
||||
|
||||
static inline u32 coresight_etm4x_attr_to_offset(struct device_attribute *attr)
|
||||
static u32 coresight_etm4x_attr_to_offset(struct device_attribute *attr)
|
||||
{
|
||||
struct dev_ext_attribute *eattr;
|
||||
|
||||
|
@ -2464,7 +2464,7 @@ static ssize_t coresight_etm4x_reg_show(struct device *dev,
|
|||
return scnprintf(buf, PAGE_SIZE, "0x%x\n", val);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
static bool
|
||||
etm4x_register_implemented(struct etmv4_drvdata *drvdata, u32 offset)
|
||||
{
|
||||
switch (offset) {
|
||||
|
|
|
@ -983,6 +983,7 @@ struct etmv4_save_state {
|
|||
* @state_needs_restore: True when there is context to restore after PM exit
|
||||
* @skip_power_up: Indicates if an implementation can skip powering up
|
||||
* the trace unit.
|
||||
* @paused: Indicates if the trace unit is paused.
|
||||
* @arch_features: Bitmap of arch features of etmv4 devices.
|
||||
*/
|
||||
struct etmv4_drvdata {
|
||||
|
@ -1036,6 +1037,7 @@ struct etmv4_drvdata {
|
|||
struct etmv4_save_state *save_state;
|
||||
bool state_needs_restore;
|
||||
bool skip_power_up;
|
||||
bool paused;
|
||||
DECLARE_BITMAP(arch_features, ETM4_IMPDEF_FEATURE_MAX);
|
||||
};
|
||||
|
||||
|
|
|
@ -255,6 +255,7 @@ static int funnel_probe(struct device *dev, struct resource *res)
|
|||
drvdata->base = base;
|
||||
desc.groups = coresight_funnel_groups;
|
||||
desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||
coresight_clear_self_claim_tag(&desc.access);
|
||||
}
|
||||
|
||||
dev_set_drvdata(dev, drvdata);
|
||||
|
@ -433,7 +434,8 @@ static struct amba_driver dynamic_funnel_driver = {
|
|||
|
||||
static int __init funnel_init(void)
|
||||
{
|
||||
return coresight_init_driver("funnel", &dynamic_funnel_driver, &funnel_driver);
|
||||
return coresight_init_driver("funnel", &dynamic_funnel_driver, &funnel_driver,
|
||||
THIS_MODULE);
|
||||
}
|
||||
|
||||
static void __exit funnel_exit(void)
|
||||
|
|
74
drivers/hwtracing/coresight/coresight-kunit-tests.c
Normal file
74
drivers/hwtracing/coresight/coresight-kunit-tests.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <kunit/test.h>
|
||||
#include <kunit/device.h>
|
||||
#include <linux/coresight.h>
|
||||
|
||||
#include "coresight-priv.h"
|
||||
|
||||
static struct coresight_device *coresight_test_device(struct device *dev)
|
||||
{
|
||||
struct coresight_device *csdev = devm_kcalloc(dev, 1,
|
||||
sizeof(struct coresight_device),
|
||||
GFP_KERNEL);
|
||||
csdev->pdata = devm_kcalloc(dev, 1,
|
||||
sizeof(struct coresight_platform_data),
|
||||
GFP_KERNEL);
|
||||
return csdev;
|
||||
}
|
||||
|
||||
static void test_default_sink(struct kunit *test)
|
||||
{
|
||||
/*
|
||||
* Source -> ETF -> ETR -> CATU
|
||||
* ^
|
||||
* | default
|
||||
*/
|
||||
struct device *dev = kunit_device_register(test, "coresight_kunit");
|
||||
struct coresight_device *src = coresight_test_device(dev),
|
||||
*etf = coresight_test_device(dev),
|
||||
*etr = coresight_test_device(dev),
|
||||
*catu = coresight_test_device(dev);
|
||||
struct coresight_connection conn = {};
|
||||
|
||||
src->type = CORESIGHT_DEV_TYPE_SOURCE;
|
||||
/*
|
||||
* Don't use CORESIGHT_DEV_SUBTYPE_SOURCE_PROC, that would always return
|
||||
* a TRBE sink if one is registered.
|
||||
*/
|
||||
src->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_BUS;
|
||||
etf->type = CORESIGHT_DEV_TYPE_LINKSINK;
|
||||
etf->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
|
||||
etr->type = CORESIGHT_DEV_TYPE_SINK;
|
||||
etr->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_SYSMEM;
|
||||
catu->type = CORESIGHT_DEV_TYPE_HELPER;
|
||||
|
||||
conn.src_dev = src;
|
||||
conn.dest_dev = etf;
|
||||
coresight_add_out_conn(dev, src->pdata, &conn);
|
||||
|
||||
conn.src_dev = etf;
|
||||
conn.dest_dev = etr;
|
||||
coresight_add_out_conn(dev, etf->pdata, &conn);
|
||||
|
||||
conn.src_dev = etr;
|
||||
conn.dest_dev = catu;
|
||||
coresight_add_out_conn(dev, etr->pdata, &conn);
|
||||
|
||||
KUNIT_ASSERT_PTR_EQ(test, coresight_find_default_sink(src), etr);
|
||||
}
|
||||
|
||||
static struct kunit_case coresight_testcases[] = {
|
||||
KUNIT_CASE(test_default_sink),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite coresight_test_suite = {
|
||||
.name = "coresight_test_suite",
|
||||
.test_cases = coresight_testcases,
|
||||
};
|
||||
|
||||
kunit_test_suites(&coresight_test_suite);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("James Clark <james.clark@linaro.org>");
|
||||
MODULE_DESCRIPTION("Arm CoreSight KUnit tests");
|
|
@ -139,7 +139,7 @@ coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode)
|
|||
EXPORT_SYMBOL_GPL(coresight_find_csdev_by_fwnode);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static inline bool of_coresight_legacy_ep_is_input(struct device_node *ep)
|
||||
static bool of_coresight_legacy_ep_is_input(struct device_node *ep)
|
||||
{
|
||||
return of_property_read_bool(ep, "slave-mode");
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ static struct device_node *of_coresight_get_port_parent(struct device_node *ep)
|
|||
return parent;
|
||||
}
|
||||
|
||||
static inline struct device_node *
|
||||
static struct device_node *
|
||||
of_coresight_get_output_ports_node(const struct device_node *node)
|
||||
{
|
||||
return of_get_child_by_name(node, "out-ports");
|
||||
|
@ -327,14 +327,14 @@ static int of_get_coresight_platform_data(struct device *dev,
|
|||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline int
|
||||
static int
|
||||
of_get_coresight_platform_data(struct device *dev,
|
||||
struct coresight_platform_data *pdata)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int of_coresight_get_cpu(struct device *dev)
|
||||
static int of_coresight_get_cpu(struct device *dev)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -356,7 +356,7 @@ static const guid_t coresight_graph_uuid = GUID_INIT(0x3ecbc8b6, 0x1d0e, 0x4fb3,
|
|||
#define ACPI_CORESIGHT_LINK_SLAVE 0
|
||||
#define ACPI_CORESIGHT_LINK_MASTER 1
|
||||
|
||||
static inline bool is_acpi_guid(const union acpi_object *obj)
|
||||
static bool is_acpi_guid(const union acpi_object *obj)
|
||||
{
|
||||
return (obj->type == ACPI_TYPE_BUFFER) && (obj->buffer.length == 16);
|
||||
}
|
||||
|
@ -365,24 +365,24 @@ static inline bool is_acpi_guid(const union acpi_object *obj)
|
|||
* acpi_guid_matches - Checks if the given object is a GUID object and
|
||||
* that it matches the supplied the GUID.
|
||||
*/
|
||||
static inline bool acpi_guid_matches(const union acpi_object *obj,
|
||||
static bool acpi_guid_matches(const union acpi_object *obj,
|
||||
const guid_t *guid)
|
||||
{
|
||||
return is_acpi_guid(obj) &&
|
||||
guid_equal((guid_t *)obj->buffer.pointer, guid);
|
||||
}
|
||||
|
||||
static inline bool is_acpi_dsd_graph_guid(const union acpi_object *obj)
|
||||
static bool is_acpi_dsd_graph_guid(const union acpi_object *obj)
|
||||
{
|
||||
return acpi_guid_matches(obj, &acpi_graph_uuid);
|
||||
}
|
||||
|
||||
static inline bool is_acpi_coresight_graph_guid(const union acpi_object *obj)
|
||||
static bool is_acpi_coresight_graph_guid(const union acpi_object *obj)
|
||||
{
|
||||
return acpi_guid_matches(obj, &coresight_graph_uuid);
|
||||
}
|
||||
|
||||
static inline bool is_acpi_coresight_graph(const union acpi_object *obj)
|
||||
static bool is_acpi_coresight_graph(const union acpi_object *obj)
|
||||
{
|
||||
const union acpi_object *graphid, *guid, *links;
|
||||
|
||||
|
@ -469,7 +469,7 @@ static inline bool is_acpi_coresight_graph(const union acpi_object *obj)
|
|||
* }, // End of ACPI Graph Property
|
||||
* })
|
||||
*/
|
||||
static inline bool acpi_validate_dsd_graph(const union acpi_object *graph)
|
||||
static bool acpi_validate_dsd_graph(const union acpi_object *graph)
|
||||
{
|
||||
int i, n;
|
||||
const union acpi_object *rev, *nr_graphs;
|
||||
|
@ -553,7 +553,7 @@ acpi_get_dsd_graph(struct acpi_device *adev, struct acpi_buffer *buf)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
static bool
|
||||
acpi_validate_coresight_graph(const union acpi_object *cs_graph)
|
||||
{
|
||||
int nlinks;
|
||||
|
@ -794,14 +794,14 @@ acpi_get_coresight_platform_data(struct device *dev,
|
|||
|
||||
#else
|
||||
|
||||
static inline int
|
||||
static int
|
||||
acpi_get_coresight_platform_data(struct device *dev,
|
||||
struct coresight_platform_data *pdata)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static inline int acpi_coresight_get_cpu(struct device *dev)
|
||||
static int acpi_coresight_get_cpu(struct device *dev)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,11 @@ extern const struct device_type coresight_dev_type[];
|
|||
* Coresight device CLAIM protocol.
|
||||
* See PSCI - ARM DEN 0022D, Section: 6.8.1 Debug and Trace save and restore.
|
||||
*/
|
||||
#define CORESIGHT_CLAIM_SELF_HOSTED BIT(1)
|
||||
#define CORESIGHT_CLAIM_MASK GENMASK(1, 0)
|
||||
#define CORESIGHT_CLAIM_FREE 0
|
||||
#define CORESIGHT_CLAIM_EXTERNAL 1
|
||||
#define CORESIGHT_CLAIM_SELF_HOSTED 2
|
||||
#define CORESIGHT_CLAIM_INVALID 3
|
||||
|
||||
#define TIMEOUT_US 100
|
||||
#define BMVAL(val, lsb, msb) ((val & GENMASK(msb, lsb)) >> lsb)
|
||||
|
@ -56,10 +60,8 @@ struct cs_off_attribute {
|
|||
u32 off;
|
||||
};
|
||||
|
||||
extern ssize_t coresight_simple_show32(struct device *_dev,
|
||||
struct device_attribute *attr, char *buf);
|
||||
extern ssize_t coresight_simple_show_pair(struct device *_dev,
|
||||
struct device_attribute *attr, char *buf);
|
||||
ssize_t coresight_simple_show32(struct device *_dev, struct device_attribute *attr, char *buf);
|
||||
ssize_t coresight_simple_show_pair(struct device *_dev, struct device_attribute *attr, char *buf);
|
||||
|
||||
#define coresight_simple_reg32(name, offset) \
|
||||
(&((struct cs_off_attribute[]) { \
|
||||
|
@ -156,8 +158,8 @@ void coresight_path_assign_trace_id(struct coresight_path *path,
|
|||
enum cs_mode mode);
|
||||
|
||||
#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X)
|
||||
extern int etm_readl_cp14(u32 off, unsigned int *val);
|
||||
extern int etm_writel_cp14(u32 off, u32 val);
|
||||
int etm_readl_cp14(u32 off, unsigned int *val);
|
||||
int etm_writel_cp14(u32 off, u32 val);
|
||||
#else
|
||||
static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; }
|
||||
static inline int etm_writel_cp14(u32 off, u32 val) { return 0; }
|
||||
|
@ -168,8 +170,8 @@ struct cti_assoc_op {
|
|||
void (*remove)(struct coresight_device *csdev);
|
||||
};
|
||||
|
||||
extern void coresight_set_cti_ops(const struct cti_assoc_op *cti_op);
|
||||
extern void coresight_remove_cti_ops(void);
|
||||
void coresight_set_cti_ops(const struct cti_assoc_op *cti_op);
|
||||
void coresight_remove_cti_ops(void);
|
||||
|
||||
/*
|
||||
* Macros and inline functions to handle CoreSight UCI data and driver
|
||||
|
@ -249,5 +251,7 @@ void coresight_add_helper(struct coresight_device *csdev,
|
|||
void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev);
|
||||
struct coresight_device *coresight_get_percpu_sink(int cpu);
|
||||
void coresight_disable_source(struct coresight_device *csdev, void *data);
|
||||
void coresight_pause_source(struct coresight_device *csdev);
|
||||
int coresight_resume_source(struct coresight_device *csdev);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -63,7 +63,7 @@ static void dynamic_replicator_reset(struct replicator_drvdata *drvdata)
|
|||
/*
|
||||
* replicator_reset : Reset the replicator configuration to sane values.
|
||||
*/
|
||||
static inline void replicator_reset(struct replicator_drvdata *drvdata)
|
||||
static void replicator_reset(struct replicator_drvdata *drvdata)
|
||||
{
|
||||
if (drvdata->base)
|
||||
dynamic_replicator_reset(drvdata);
|
||||
|
@ -262,6 +262,7 @@ static int replicator_probe(struct device *dev, struct resource *res)
|
|||
drvdata->base = base;
|
||||
desc.groups = replicator_groups;
|
||||
desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||
coresight_clear_self_claim_tag(&desc.access);
|
||||
}
|
||||
|
||||
if (fwnode_property_present(dev_fwnode(dev),
|
||||
|
@ -438,7 +439,8 @@ static struct amba_driver dynamic_replicator_driver = {
|
|||
|
||||
static int __init replicator_init(void)
|
||||
{
|
||||
return coresight_init_driver("replicator", &dynamic_replicator_driver, &replicator_driver);
|
||||
return coresight_init_driver("replicator", &dynamic_replicator_driver, &replicator_driver,
|
||||
THIS_MODULE);
|
||||
}
|
||||
|
||||
static void __exit replicator_exit(void)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue