mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-06-08 00:07:34 +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/sampling_frequency
|
||||||
What: /sys/bus/iio/devices/iio:deviceX/in_intensity_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/buffer/sampling_frequency
|
||||||
|
What: /sys/bus/iio/devices/iio:deviceX/events/sampling_frequency
|
||||||
What: /sys/bus/iio/devices/triggerX/sampling_frequency
|
What: /sys/bus/iio/devices/triggerX/sampling_frequency
|
||||||
KernelVersion: 2.6.35
|
KernelVersion: 2.6.35
|
||||||
Contact: linux-iio@vger.kernel.org
|
Contact: linux-iio@vger.kernel.org
|
||||||
|
@ -740,7 +741,9 @@ Description:
|
||||||
1kohm_to_gnd: connected to ground via an 1kOhm resistor,
|
1kohm_to_gnd: connected to ground via an 1kOhm resistor,
|
||||||
2.5kohm_to_gnd: connected to ground via a 2.5kOhm resistor,
|
2.5kohm_to_gnd: connected to ground via a 2.5kOhm resistor,
|
||||||
6kohm_to_gnd: connected to ground via a 6kOhm 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,
|
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,
|
42kohm_to_gnd: connected to ground via a 42kOhm resistor,
|
||||||
90kohm_to_gnd: connected to ground via a 90kOhm resistor,
|
90kohm_to_gnd: connected to ground via a 90kOhm resistor,
|
||||||
100kohm_to_gnd: connected to ground via an 100kOhm 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
|
What: /sys/bus/.../drivers/intel-m10-bmc/.../mac_address
|
||||||
Date: January 2021
|
Date: January 2021
|
||||||
KernelVersion: 5.12
|
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
|
Description: Read only. Returns the first MAC address in a block
|
||||||
of sequential MAC addresses assigned to the board
|
of sequential MAC addresses assigned to the board
|
||||||
that is managed by the Intel MAX10 BMC. It is stored in
|
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
|
What: /sys/bus/.../drivers/intel-m10-bmc/.../mac_count
|
||||||
Date: January 2021
|
Date: January 2021
|
||||||
KernelVersion: 5.12
|
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
|
Description: Read only. Returns the number of sequential MAC
|
||||||
addresses assigned to the board managed by the Intel
|
addresses assigned to the board managed by the Intel
|
||||||
MAX10 BMC. This value is stored in FLASH and is mirrored
|
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
|
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/sr_root_entry_hash
|
||||||
Date: Sep 2022
|
Date: Sep 2022
|
||||||
KernelVersion: 5.20
|
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
|
Description: Read only. Returns the root entry hash for the static
|
||||||
region if one is programmed, else it returns the
|
region if one is programmed, else it returns the
|
||||||
string: "hash not programmed". This file is only
|
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
|
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/pr_root_entry_hash
|
||||||
Date: Sep 2022
|
Date: Sep 2022
|
||||||
KernelVersion: 5.20
|
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
|
Description: Read only. Returns the root entry hash for the partial
|
||||||
reconfiguration region if one is programmed, else it
|
reconfiguration region if one is programmed, else it
|
||||||
returns the string: "hash not programmed". This file
|
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
|
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/bmc_root_entry_hash
|
||||||
Date: Sep 2022
|
Date: Sep 2022
|
||||||
KernelVersion: 5.20
|
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
|
Description: Read only. Returns the root entry hash for the BMC image
|
||||||
if one is programmed, else it returns the string:
|
if one is programmed, else it returns the string:
|
||||||
"hash not programmed". This file is only visible if the
|
"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
|
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/sr_canceled_csks
|
||||||
Date: Sep 2022
|
Date: Sep 2022
|
||||||
KernelVersion: 5.20
|
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
|
Description: Read only. Returns a list of indices for canceled code
|
||||||
signing keys for the static region. The standard bitmap
|
signing keys for the static region. The standard bitmap
|
||||||
list format is used (e.g. "1,2-6,9").
|
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
|
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/pr_canceled_csks
|
||||||
Date: Sep 2022
|
Date: Sep 2022
|
||||||
KernelVersion: 5.20
|
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
|
Description: Read only. Returns a list of indices for canceled code
|
||||||
signing keys for the partial reconfiguration region. The
|
signing keys for the partial reconfiguration region. The
|
||||||
standard bitmap list format is used (e.g. "1,2-6,9").
|
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
|
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/bmc_canceled_csks
|
||||||
Date: Sep 2022
|
Date: Sep 2022
|
||||||
KernelVersion: 5.20
|
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
|
Description: Read only. Returns a list of indices for canceled code
|
||||||
signing keys for the BMC. The standard bitmap list format
|
signing keys for the BMC. The standard bitmap list format
|
||||||
is used (e.g. "1,2-6,9").
|
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
|
What: /sys/bus/platform/drivers/intel-m10bmc-sec-update/.../security/flash_count
|
||||||
Date: Sep 2022
|
Date: Sep 2022
|
||||||
KernelVersion: 5.20
|
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
|
Description: Read only. Returns number of times the secure update
|
||||||
staging area has been flashed.
|
staging area has been flashed.
|
||||||
Format: "%u".
|
Format: "%u".
|
||||||
|
|
|
@ -30,6 +30,19 @@ properties:
|
||||||
power-domains:
|
power-domains:
|
||||||
maxItems: 1
|
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:
|
in-ports:
|
||||||
$ref: /schemas/graph.yaml#/properties/ports
|
$ref: /schemas/graph.yaml#/properties/ports
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
|
|
@ -25,6 +25,7 @@ description: |
|
||||||
* https://www.analog.com/en/products/ad7386-4.html
|
* https://www.analog.com/en/products/ad7386-4.html
|
||||||
* https://www.analog.com/en/products/ad7387-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/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/adaq4370-4.html
|
||||||
* https://www.analog.com/en/products/adaq4380-4.html
|
* https://www.analog.com/en/products/adaq4380-4.html
|
||||||
* https://www.analog.com/en/products/adaq4381-4.html
|
* https://www.analog.com/en/products/adaq4381-4.html
|
||||||
|
@ -49,6 +50,7 @@ properties:
|
||||||
- adi,ad7386-4
|
- adi,ad7386-4
|
||||||
- adi,ad7387-4
|
- adi,ad7387-4
|
||||||
- adi,ad7388-4
|
- adi,ad7388-4
|
||||||
|
- adi,ad7389-4
|
||||||
- adi,adaq4370-4
|
- adi,adaq4370-4
|
||||||
- adi,adaq4380-4
|
- adi,adaq4380-4
|
||||||
- adi,adaq4381-4
|
- adi,adaq4381-4
|
||||||
|
@ -213,6 +215,15 @@ allOf:
|
||||||
properties:
|
properties:
|
||||||
refin-supply: false
|
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
|
# adaq devices need more supplies and using channel to declare gain property
|
||||||
# only applies to adaq devices
|
# only applies to adaq devices
|
||||||
- if:
|
- if:
|
||||||
|
|
|
@ -17,35 +17,40 @@ description: |
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
enum:
|
oneOf:
|
||||||
- adi,ad7091
|
- items:
|
||||||
- adi,ad7091r
|
- enum:
|
||||||
- adi,ad7273
|
- adi,ad7091
|
||||||
- adi,ad7274
|
- adi,ad7091r
|
||||||
- adi,ad7276
|
- adi,ad7273
|
||||||
- adi,ad7277
|
- adi,ad7274
|
||||||
- adi,ad7278
|
- adi,ad7276
|
||||||
- adi,ad7466
|
- adi,ad7277
|
||||||
- adi,ad7467
|
- adi,ad7278
|
||||||
- adi,ad7468
|
- adi,ad7466
|
||||||
- adi,ad7475
|
- adi,ad7467
|
||||||
- adi,ad7476
|
- adi,ad7468
|
||||||
- adi,ad7476a
|
- adi,ad7475
|
||||||
- adi,ad7477
|
- adi,ad7476
|
||||||
- adi,ad7477a
|
- adi,ad7476a
|
||||||
- adi,ad7478
|
- adi,ad7477
|
||||||
- adi,ad7478a
|
- adi,ad7477a
|
||||||
- adi,ad7495
|
- adi,ad7478
|
||||||
- adi,ad7910
|
- adi,ad7478a
|
||||||
- adi,ad7920
|
- adi,ad7495
|
||||||
- adi,ad7940
|
- adi,ad7910
|
||||||
- ti,adc081s
|
- adi,ad7920
|
||||||
- ti,adc101s
|
- adi,ad7940
|
||||||
- ti,adc121s
|
- ti,adc081s
|
||||||
- ti,ads7866
|
- ti,adc101s
|
||||||
- ti,ads7867
|
- ti,adc121s
|
||||||
- ti,ads7868
|
- ti,ads7866
|
||||||
- lltc,ltc2314-14
|
- ti,ads7867
|
||||||
|
- ti,ads7868
|
||||||
|
- lltc,ltc2314-14
|
||||||
|
- items:
|
||||||
|
- const: rohm,bu79100g
|
||||||
|
- const: ti,ads7866
|
||||||
|
|
||||||
reg:
|
reg:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
|
@ -45,6 +45,14 @@ properties:
|
||||||
"#size-cells":
|
"#size-cells":
|
||||||
const: 0
|
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
|
# 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
|
# 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
|
# SCLK". Also, even if not stated textually in the datasheet, it is made
|
||||||
|
|
|
@ -23,6 +23,7 @@ properties:
|
||||||
- amlogic,meson8m2-saradc
|
- amlogic,meson8m2-saradc
|
||||||
- amlogic,meson-gxbb-saradc
|
- amlogic,meson-gxbb-saradc
|
||||||
- amlogic,meson-gxl-saradc
|
- amlogic,meson-gxl-saradc
|
||||||
|
- amlogic,meson-gxlx-saradc
|
||||||
- amlogic,meson-gxm-saradc
|
- amlogic,meson-gxm-saradc
|
||||||
- amlogic,meson-axg-saradc
|
- amlogic,meson-axg-saradc
|
||||||
- amlogic,meson-g12a-saradc
|
- amlogic,meson-g12a-saradc
|
||||||
|
|
|
@ -34,6 +34,7 @@ properties:
|
||||||
- const: mediatek,mt2701-auxadc
|
- const: mediatek,mt2701-auxadc
|
||||||
- items:
|
- items:
|
||||||
- enum:
|
- enum:
|
||||||
|
- mediatek,mt6893-auxadc
|
||||||
- mediatek,mt8183-auxadc
|
- mediatek,mt8183-auxadc
|
||||||
- mediatek,mt8186-auxadc
|
- mediatek,mt8186-auxadc
|
||||||
- mediatek,mt8188-auxadc
|
- mediatek,mt8188-auxadc
|
||||||
|
|
|
@ -32,6 +32,9 @@ properties:
|
||||||
spi-max-frequency:
|
spi-max-frequency:
|
||||||
maximum: 20000000
|
maximum: 20000000
|
||||||
|
|
||||||
|
reset-gpios:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
clocks:
|
clocks:
|
||||||
description: |
|
description: |
|
||||||
Phandle and clock identifier for external sampling clock.
|
Phandle and clock identifier for external sampling clock.
|
||||||
|
@ -71,6 +74,7 @@ unevaluatedProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
spi {
|
spi {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
@ -80,6 +84,7 @@ examples:
|
||||||
reg = <0>;
|
reg = <0>;
|
||||||
interrupt-parent = <&gpio5>;
|
interrupt-parent = <&gpio5>;
|
||||||
interrupts = <15 2>;
|
interrupts = <15 2>;
|
||||||
|
reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
|
||||||
spi-max-frequency = <20000000>;
|
spi-max-frequency = <20000000>;
|
||||||
microchip,device-addr = <0>;
|
microchip,device-addr = <0>;
|
||||||
vref-supply = <&vref_reg>;
|
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:
|
examples:
|
||||||
- |
|
- |
|
||||||
// Example 1: with stm32f429, ADC1, single-ended channel 8
|
// Example 1: with stm32f429, ADC1, single-ended channel 8
|
||||||
adc123: adc@40012000 {
|
adc123: adc@40012000 {
|
||||||
compatible = "st,stm32f4-adc-core";
|
compatible = "st,stm32f4-adc-core";
|
||||||
reg = <0x40012000 0x400>;
|
reg = <0x40012000 0x400>;
|
||||||
interrupts = <18>;
|
interrupts = <18>;
|
||||||
|
@ -512,28 +512,28 @@ examples:
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
adc@0 {
|
adc@0 {
|
||||||
compatible = "st,stm32f4-adc";
|
compatible = "st,stm32f4-adc";
|
||||||
#io-channel-cells = <1>;
|
#io-channel-cells = <1>;
|
||||||
reg = <0x0>;
|
reg = <0x0>;
|
||||||
clocks = <&rcc 0 168>;
|
clocks = <&rcc 0 168>;
|
||||||
interrupt-parent = <&adc123>;
|
interrupt-parent = <&adc123>;
|
||||||
interrupts = <0>;
|
interrupts = <0>;
|
||||||
st,adc-channels = <8>;
|
st,adc-channels = <8>;
|
||||||
dmas = <&dma2 0 0 0x400 0x0>;
|
dmas = <&dma2 0 0 0x400 0x0>;
|
||||||
dma-names = "rx";
|
dma-names = "rx";
|
||||||
assigned-resolution-bits = <8>;
|
assigned-resolution-bits = <8>;
|
||||||
};
|
};
|
||||||
// ...
|
// ...
|
||||||
// other adc child nodes follow...
|
// other adc child nodes follow...
|
||||||
};
|
};
|
||||||
|
|
||||||
- |
|
- |
|
||||||
// Example 2: with stm32mp157c to setup ADC1 with:
|
// Example 2: with stm32mp157c to setup ADC1 with:
|
||||||
// - channels 0 & 1 as single-ended
|
// - channels 0 & 1 as single-ended
|
||||||
// - channels 2 & 3 as differential (with resp. 6 & 7 negative inputs)
|
// - channels 2 & 3 as differential (with resp. 6 & 7 negative inputs)
|
||||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
#include <dt-bindings/clock/stm32mp1-clks.h>
|
#include <dt-bindings/clock/stm32mp1-clks.h>
|
||||||
adc12: adc@48003000 {
|
adc12: adc@48003000 {
|
||||||
compatible = "st,stm32mp1-adc-core";
|
compatible = "st,stm32mp1-adc-core";
|
||||||
reg = <0x48003000 0x400>;
|
reg = <0x48003000 0x400>;
|
||||||
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
|
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
|
||||||
|
@ -550,27 +550,27 @@ examples:
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
adc@0 {
|
adc@0 {
|
||||||
compatible = "st,stm32mp1-adc";
|
compatible = "st,stm32mp1-adc";
|
||||||
#io-channel-cells = <1>;
|
#io-channel-cells = <1>;
|
||||||
reg = <0x0>;
|
reg = <0x0>;
|
||||||
interrupt-parent = <&adc12>;
|
interrupt-parent = <&adc12>;
|
||||||
interrupts = <0>;
|
interrupts = <0>;
|
||||||
st,adc-channels = <0 1>;
|
st,adc-channels = <0 1>;
|
||||||
st,adc-diff-channels = <2 6>, <3 7>;
|
st,adc-diff-channels = <2 6>, <3 7>;
|
||||||
st,min-sample-time-nsecs = <5000>;
|
st,min-sample-time-nsecs = <5000>;
|
||||||
dmas = <&dmamux1 9 0x400 0x05>;
|
dmas = <&dmamux1 9 0x400 0x05>;
|
||||||
dma-names = "rx";
|
dma-names = "rx";
|
||||||
};
|
};
|
||||||
// ...
|
// ...
|
||||||
// other adc child node follow...
|
// other adc child node follow...
|
||||||
};
|
};
|
||||||
|
|
||||||
- |
|
- |
|
||||||
// Example 3: with stm32mp157c to setup ADC2 with:
|
// Example 3: with stm32mp157c to setup ADC2 with:
|
||||||
// - internal channels 13, 14, 15.
|
// - internal channels 13, 14, 15.
|
||||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
#include <dt-bindings/clock/stm32mp1-clks.h>
|
#include <dt-bindings/clock/stm32mp1-clks.h>
|
||||||
adc122: adc@48003000 {
|
adc122: adc@48003000 {
|
||||||
compatible = "st,stm32mp1-adc-core";
|
compatible = "st,stm32mp1-adc-core";
|
||||||
reg = <0x48003000 0x400>;
|
reg = <0x48003000 0x400>;
|
||||||
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
|
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
|
||||||
|
@ -587,28 +587,28 @@ examples:
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
adc@100 {
|
adc@100 {
|
||||||
compatible = "st,stm32mp1-adc";
|
compatible = "st,stm32mp1-adc";
|
||||||
#io-channel-cells = <1>;
|
#io-channel-cells = <1>;
|
||||||
reg = <0x100>;
|
reg = <0x100>;
|
||||||
interrupts = <1>;
|
interrupts = <1>;
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
channel@13 {
|
channel@13 {
|
||||||
reg = <13>;
|
reg = <13>;
|
||||||
label = "vrefint";
|
label = "vrefint";
|
||||||
st,min-sample-time-ns = <9000>;
|
st,min-sample-time-ns = <9000>;
|
||||||
};
|
};
|
||||||
channel@14 {
|
channel@14 {
|
||||||
reg = <14>;
|
reg = <14>;
|
||||||
label = "vddcore";
|
label = "vddcore";
|
||||||
st,min-sample-time-ns = <9000>;
|
st,min-sample-time-ns = <9000>;
|
||||||
};
|
};
|
||||||
channel@15 {
|
channel@15 {
|
||||||
reg = <15>;
|
reg = <15>;
|
||||||
label = "vbat";
|
label = "vbat";
|
||||||
st,min-sample-time-ns = <9000>;
|
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
|
- reg
|
||||||
- spi-max-frequency
|
- spi-max-frequency
|
||||||
|
|
||||||
additionalProperties: false
|
unevaluatedProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
|
|
|
@ -27,6 +27,8 @@ properties:
|
||||||
|
|
||||||
vdrive-supply: true
|
vdrive-supply: true
|
||||||
|
|
||||||
|
vrefin-supply: true
|
||||||
|
|
||||||
reset-gpios:
|
reset-gpios:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,7 @@ required:
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||||
|
|
||||||
additionalProperties: false
|
unevaluatedProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
|
|
|
@ -124,7 +124,7 @@ required:
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||||
|
|
||||||
additionalProperties: false
|
unevaluatedProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
|
|
|
@ -64,7 +64,7 @@ required:
|
||||||
- reg
|
- reg
|
||||||
- vdd-supply
|
- vdd-supply
|
||||||
|
|
||||||
additionalProperties: false
|
unevaluatedProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
|
|
|
@ -5,19 +5,26 @@
|
||||||
$id: http://devicetree.org/schemas/iio/dac/rohm,bd79703.yaml#
|
$id: http://devicetree.org/schemas/iio/dac/rohm,bd79703.yaml#
|
||||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
title: ROHM BD79703 DAC device driver
|
title: ROHM BD79700, BD79701, BD79702 and BD79703 DACs
|
||||||
|
|
||||||
maintainers:
|
maintainers:
|
||||||
- Matti Vaittinen <mazziesaccount@gmail.com>
|
- Matti Vaittinen <mazziesaccount@gmail.com>
|
||||||
|
|
||||||
description: |
|
description: |
|
||||||
The ROHM BD79703 is a 6 channel, 8-bit DAC.
|
The ROHM BD7970[0,1,2,3] are 8-bit DACs. The BD79700 has 2 channels,
|
||||||
Datasheet can be found here:
|
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
|
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:
|
properties:
|
||||||
compatible:
|
compatible:
|
||||||
const: rohm,bd79703
|
enum:
|
||||||
|
- rohm,bd79700
|
||||||
|
- rohm,bd79701
|
||||||
|
- rohm,bd79702
|
||||||
|
- rohm,bd79703
|
||||||
|
|
||||||
reg:
|
reg:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
@ -27,23 +34,35 @@ properties:
|
||||||
|
|
||||||
vfs-supply:
|
vfs-supply:
|
||||||
description:
|
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:
|
vcc-supply:
|
||||||
description:
|
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:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
- reg
|
- reg
|
||||||
- spi-max-frequency
|
- spi-max-frequency
|
||||||
- vfs-supply
|
|
||||||
- vcc-supply
|
- vcc-supply
|
||||||
|
|
||||||
|
if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
enum:
|
||||||
|
- rohm,bd79702
|
||||||
|
- rohm,bd79703
|
||||||
|
then:
|
||||||
|
required:
|
||||||
|
- vfs-supply
|
||||||
|
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||||
|
|
||||||
additionalProperties: false
|
unevaluatedProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
|
|
|
@ -44,6 +44,24 @@ properties:
|
||||||
'#clock-cells':
|
'#clock-cells':
|
||||||
const: 0
|
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:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
- reg
|
- reg
|
||||||
|
@ -61,6 +79,8 @@ examples:
|
||||||
spi-max-frequency = <10000000>;
|
spi-max-frequency = <10000000>;
|
||||||
clocks = <&admv8818_rfin>;
|
clocks = <&admv8818_rfin>;
|
||||||
clock-names = "rf_in";
|
clock-names = "rf_in";
|
||||||
|
adi,lpf-margin-mhz = <300>;
|
||||||
|
adi,hpf-margin-mhz = <300>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
...
|
...
|
||||||
|
|
|
@ -53,7 +53,7 @@ required:
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||||
|
|
||||||
additionalProperties: false
|
unevaluatedProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
|
|
|
@ -39,7 +39,16 @@ properties:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
||||||
interrupts:
|
interrupts:
|
||||||
maxItems: 1
|
minItems: 1
|
||||||
|
maxItems: 2
|
||||||
|
|
||||||
|
interrupt-names:
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 2
|
||||||
|
items:
|
||||||
|
enum:
|
||||||
|
- INT1
|
||||||
|
- INT2
|
||||||
|
|
||||||
drive-open-drain:
|
drive-open-drain:
|
||||||
type: boolean
|
type: boolean
|
||||||
|
@ -76,6 +85,7 @@ examples:
|
||||||
reg = <0x68>;
|
reg = <0x68>;
|
||||||
interrupt-parent = <&gpio2>;
|
interrupt-parent = <&gpio2>;
|
||||||
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
|
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
|
||||||
|
interrupt-names = "INT1";
|
||||||
vdd-supply = <&vdd>;
|
vdd-supply = <&vdd>;
|
||||||
vddio-supply = <&vddio>;
|
vddio-supply = <&vddio>;
|
||||||
};
|
};
|
||||||
|
@ -95,6 +105,7 @@ examples:
|
||||||
spi-cpol;
|
spi-cpol;
|
||||||
interrupt-parent = <&gpio1>;
|
interrupt-parent = <&gpio1>;
|
||||||
interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
|
interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
|
||||||
|
interrupt-names = "INT1";
|
||||||
vdd-supply = <&vdd>;
|
vdd-supply = <&vdd>;
|
||||||
vddio-supply = <&vddio>;
|
vddio-supply = <&vddio>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,6 +24,10 @@ properties:
|
||||||
reg:
|
reg:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
||||||
|
reset-gpios:
|
||||||
|
description: GPIO connected to the DVI reset pin (active low)
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
- reg
|
- reg
|
||||||
|
@ -32,6 +36,7 @@ additionalProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
|
#include <dt-bindings/gpio/gpio.h>
|
||||||
i2c {
|
i2c {
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
|
@ -39,6 +44,7 @@ examples:
|
||||||
light-sensor@23 {
|
light-sensor@23 {
|
||||||
compatible = "rohm,bh1750";
|
compatible = "rohm,bh1750";
|
||||||
reg = <0x23>;
|
reg = <0x23>;
|
||||||
|
reset-gpios = <&gpio2 17 GPIO_ACTIVE_LOW>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,7 @@ required:
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: /schemas/spi/spi-peripheral-props.yaml
|
- $ref: /schemas/spi/spi-peripheral-props.yaml
|
||||||
|
|
||||||
additionalProperties: false
|
unevaluatedProperties: false
|
||||||
|
|
||||||
dependentSchemas:
|
dependentSchemas:
|
||||||
honeywell,pmin-pascal:
|
honeywell,pmin-pascal:
|
||||||
|
|
|
@ -115,7 +115,7 @@ allOf:
|
||||||
honeywell,pmin-pascal: false
|
honeywell,pmin-pascal: false
|
||||||
honeywell,pmax-pascal: false
|
honeywell,pmax-pascal: false
|
||||||
|
|
||||||
additionalProperties: false
|
unevaluatedProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
|
|
|
@ -70,8 +70,8 @@ examples:
|
||||||
reg = <0x00580000 0x14000>;
|
reg = <0x00580000 0x14000>;
|
||||||
#interconnect-cells = <1>;
|
#interconnect-cells = <1>;
|
||||||
|
|
||||||
snoc_mm: interconnect-snoc {
|
snoc_mm: interconnect-snoc {
|
||||||
compatible = "qcom,msm8939-snoc-mm";
|
compatible = "qcom,msm8939-snoc-mm";
|
||||||
#interconnect-cells = <1>;
|
#interconnect-cells = <1>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -84,17 +84,17 @@ additionalProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
#include <dt-bindings/clock/qcom,gcc-msm8953.h>
|
#include <dt-bindings/clock/qcom,gcc-msm8953.h>
|
||||||
|
|
||||||
snoc: interconnect@580000 {
|
interconnect@580000 {
|
||||||
compatible = "qcom,msm8953-snoc";
|
compatible = "qcom,msm8953-snoc";
|
||||||
reg = <0x580000 0x16080>;
|
reg = <0x580000 0x16080>;
|
||||||
|
|
||||||
#interconnect-cells = <2>;
|
#interconnect-cells = <2>;
|
||||||
|
|
||||||
snoc_mm: interconnect-snoc {
|
interconnect-snoc {
|
||||||
compatible = "qcom,msm8953-snoc-mm";
|
compatible = "qcom,msm8953-snoc-mm";
|
||||||
|
|
||||||
#interconnect-cells = <2>;
|
#interconnect-cells = <2>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -50,13 +50,13 @@ additionalProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
#include <dt-bindings/clock/qcom,rpmcc.h>
|
#include <dt-bindings/clock/qcom,rpmcc.h>
|
||||||
|
|
||||||
bimc: interconnect@fc380000 {
|
interconnect@fc380000 {
|
||||||
reg = <0xfc380000 0x6a000>;
|
reg = <0xfc380000 0x6a000>;
|
||||||
compatible = "qcom,msm8974-bimc";
|
compatible = "qcom,msm8974-bimc";
|
||||||
#interconnect-cells = <1>;
|
#interconnect-cells = <1>;
|
||||||
clock-names = "bus", "bus_a";
|
clock-names = "bus", "bus_a";
|
||||||
clocks = <&rpmcc RPM_SMD_BIMC_CLK>,
|
clocks = <&rpmcc RPM_SMD_BIMC_CLK>,
|
||||||
<&rpmcc RPM_SMD_BIMC_A_CLK>;
|
<&rpmcc RPM_SMD_BIMC_A_CLK>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,6 +28,7 @@ properties:
|
||||||
- const: qcom,osm-l3
|
- const: qcom,osm-l3
|
||||||
- items:
|
- items:
|
||||||
- enum:
|
- enum:
|
||||||
|
- qcom,sa8775p-epss-l3
|
||||||
- qcom,sc7280-epss-l3
|
- qcom,sc7280-epss-l3
|
||||||
- qcom,sc8280xp-epss-l3
|
- qcom,sc8280xp-epss-l3
|
||||||
- qcom,sm6375-cpucp-l3
|
- qcom,sm6375-cpucp-l3
|
||||||
|
|
|
@ -41,10 +41,10 @@ unevaluatedProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
#include <dt-bindings/clock/qcom,rpmcc.h>
|
#include <dt-bindings/clock/qcom,rpmcc.h>
|
||||||
|
|
||||||
bimc: interconnect@400000 {
|
interconnect@400000 {
|
||||||
compatible = "qcom,msm8916-bimc";
|
compatible = "qcom,msm8916-bimc";
|
||||||
reg = <0x00400000 0x62000>;
|
reg = <0x00400000 0x62000>;
|
||||||
#interconnect-cells = <1>;
|
#interconnect-cells = <1>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -127,19 +127,19 @@ unevaluatedProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
#include <dt-bindings/interconnect/qcom,sdm845.h>
|
#include <dt-bindings/interconnect/qcom,sdm845.h>
|
||||||
|
|
||||||
mem_noc: interconnect@1380000 {
|
interconnect@1380000 {
|
||||||
compatible = "qcom,sdm845-mem-noc";
|
compatible = "qcom,sdm845-mem-noc";
|
||||||
reg = <0x01380000 0x27200>;
|
reg = <0x01380000 0x27200>;
|
||||||
#interconnect-cells = <1>;
|
#interconnect-cells = <1>;
|
||||||
qcom,bcm-voters = <&apps_bcm_voter>;
|
qcom,bcm-voters = <&apps_bcm_voter>;
|
||||||
};
|
};
|
||||||
|
|
||||||
mmss_noc: interconnect@1740000 {
|
interconnect@1740000 {
|
||||||
compatible = "qcom,sdm845-mmss-noc";
|
compatible = "qcom,sdm845-mmss-noc";
|
||||||
reg = <0x01740000 0x1c1000>;
|
reg = <0x01740000 0x1c1000>;
|
||||||
#interconnect-cells = <1>;
|
#interconnect-cells = <1>;
|
||||||
qcom,bcm-voter-names = "apps", "disp";
|
qcom,bcm-voter-names = "apps", "disp";
|
||||||
qcom,bcm-voters = <&apps_bcm_voter>, <&disp_bcm_voter>;
|
qcom,bcm-voters = <&apps_bcm_voter>, <&disp_bcm_voter>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -78,15 +78,15 @@ examples:
|
||||||
#include <dt-bindings/clock/qcom,rpmh.h>
|
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||||
|
|
||||||
clk_virt: interconnect-0 {
|
clk_virt: interconnect-0 {
|
||||||
compatible = "qcom,sdx75-clk-virt";
|
compatible = "qcom,sdx75-clk-virt";
|
||||||
#interconnect-cells = <2>;
|
#interconnect-cells = <2>;
|
||||||
qcom,bcm-voters = <&apps_bcm_voter>;
|
qcom,bcm-voters = <&apps_bcm_voter>;
|
||||||
clocks = <&rpmhcc RPMH_QPIC_CLK>;
|
clocks = <&rpmhcc RPMH_QPIC_CLK>;
|
||||||
};
|
};
|
||||||
|
|
||||||
system_noc: interconnect@1640000 {
|
system_noc: interconnect@1640000 {
|
||||||
compatible = "qcom,sdx75-system-noc";
|
compatible = "qcom,sdx75-system-noc";
|
||||||
reg = <0x1640000 0x4b400>;
|
reg = <0x1640000 0x4b400>;
|
||||||
#interconnect-cells = <2>;
|
#interconnect-cells = <2>;
|
||||||
qcom,bcm-voters = <&apps_bcm_voter>;
|
qcom,bcm-voters = <&apps_bcm_voter>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,6 +25,10 @@ properties:
|
||||||
description:
|
description:
|
||||||
List of gpios used to control the multiplexer, least significant bit first.
|
List of gpios used to control the multiplexer, least significant bit first.
|
||||||
|
|
||||||
|
mux-supply:
|
||||||
|
description:
|
||||||
|
Regulator to power on the multiplexer.
|
||||||
|
|
||||||
'#mux-control-cells':
|
'#mux-control-cells':
|
||||||
enum: [ 0, 1 ]
|
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,srf08
|
||||||
# Devantech SRF10 ultrasonic ranger
|
# Devantech SRF10 ultrasonic ranger
|
||||||
- devantech,srf10
|
- devantech,srf10
|
||||||
|
# DFRobot SEN0322 oxygen sensor
|
||||||
|
- dfrobot,sen0322
|
||||||
# DH electronics GmbH on-board CPLD trivial SPI device
|
# DH electronics GmbH on-board CPLD trivial SPI device
|
||||||
- dh,dhcom-board
|
- dh,dhcom-board
|
||||||
# DA9053: flexible system level PMIC with multicore support
|
# DA9053: flexible system level PMIC with multicore support
|
||||||
|
|
|
@ -1705,6 +1705,8 @@ patternProperties:
|
||||||
description: Wingtech Technology Co., Ltd.
|
description: Wingtech Technology Co., Ltd.
|
||||||
"^winlink,.*":
|
"^winlink,.*":
|
||||||
description: WinLink Co., Ltd
|
description: WinLink Co., Ltd
|
||||||
|
"^winsen,.*":
|
||||||
|
description: Winsen Corp.
|
||||||
"^winstar,.*":
|
"^winstar,.*":
|
||||||
description: Winstar Display Corp.
|
description: Winstar Display Corp.
|
||||||
"^wirelesstag,.*":
|
"^wirelesstag,.*":
|
||||||
|
|
|
@ -59,10 +59,10 @@ For example, a simple nvram case::
|
||||||
devm_nvmem_register(&config);
|
devm_nvmem_register(&config);
|
||||||
}
|
}
|
||||||
|
|
||||||
Users of board files can define and register nvmem cells using the
|
Device drivers can define and register an nvmem cell using the nvmem_cell_info
|
||||||
nvmem_cell_table struct::
|
struct::
|
||||||
|
|
||||||
static struct nvmem_cell_info foo_nvmem_cells[] = {
|
static const struct nvmem_cell_info foo_nvmem_cell = {
|
||||||
{
|
{
|
||||||
.name = "macaddr",
|
.name = "macaddr",
|
||||||
.offset = 0x7f00,
|
.offset = 0x7f00,
|
||||||
|
@ -70,13 +70,7 @@ nvmem_cell_table struct::
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct nvmem_cell_table foo_nvmem_cell_table = {
|
int nvmem_add_one_cell(nvmem, &foo_nvmem_cell);
|
||||||
.nvmem_name = "i2c-eeprom",
|
|
||||||
.cells = foo_nvmem_cells,
|
|
||||||
.ncells = ARRAY_SIZE(foo_nvmem_cells),
|
|
||||||
};
|
|
||||||
|
|
||||||
nvmem_add_cell_table(&foo_nvmem_cell_table);
|
|
||||||
|
|
||||||
Additionally it is possible to create nvmem cell lookup entries and register
|
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::
|
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
|
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
|
Supported devices
|
||||||
=================
|
=================
|
||||||
|
@ -25,6 +25,21 @@ Supported devices
|
||||||
* `AD4022 <https://www.analog.com/AD4022>`_
|
* `AD4022 <https://www.analog.com/AD4022>`_
|
||||||
* `ADAQ4001 <https://www.analog.com/ADAQ4001>`_
|
* `ADAQ4001 <https://www.analog.com/ADAQ4001>`_
|
||||||
* `ADAQ4003 <https://www.analog.com/ADAQ4003>`_
|
* `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
|
Wiring connections
|
||||||
------------------
|
------------------
|
||||||
|
@ -129,3 +144,77 @@ Set ``adi,sdi-pin`` to ``"cs"`` to select this mode.
|
||||||
^ | |
|
^ | |
|
||||||
+--------------------| SCLK |
|
+--------------------| 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>`_
|
* `AD7386-4 <https://www.analog.com/en/products/ad7386-4.html>`_
|
||||||
* `AD7387-4 <https://www.analog.com/en/products/ad7387-4.html>`_
|
* `AD7387-4 <https://www.analog.com/en/products/ad7387-4.html>`_
|
||||||
* `AD7388-4 <https://www.analog.com/en/products/ad7388-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>`_
|
* `ADAQ4370-4 <https://www.analog.com/en/products/adaq4370-4.html>`_
|
||||||
* `ADAQ4380-4 <https://www.analog.com/en/products/adaq4380-4.html>`_
|
* `ADAQ4380-4 <https://www.analog.com/en/products/adaq4380-4.html>`_
|
||||||
* `ADAQ4381-4 <https://www.analog.com/en/products/adaq4381-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
|
ad7380-4 supports only an external reference voltage (2.5V to 3.3V). It must be
|
||||||
declared in the device tree as ``refin-supply``.
|
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
|
ADAQ devices
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,35 @@ SPI wiring modes
|
||||||
These ADCs can output data on several SDO lines (1/2/4/8). The driver
|
These ADCs can output data on several SDO lines (1/2/4/8). The driver
|
||||||
currently supports only 1 SDO line.
|
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
|
Parallel wiring mode
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
|
@ -123,6 +152,22 @@ Unimplemented features
|
||||||
- CRC indication
|
- CRC indication
|
||||||
- Calibration
|
- 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
|
Device buffers
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ Industrial I/O Kernel Drivers
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
|
ad3552r
|
||||||
ad4000
|
ad4000
|
||||||
ad4030
|
ad4030
|
||||||
ad4695
|
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
|
:maxdepth: 2
|
||||||
|
|
||||||
ad525x_dpot
|
ad525x_dpot
|
||||||
|
amd-sbi
|
||||||
apds990x
|
apds990x
|
||||||
bh1770glc
|
bh1770glc
|
||||||
c2port
|
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
|
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
|
their axis automatically oriented on standard way (eg: you can directly play
|
||||||
neverball). The accelerometer data is readable via
|
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).
|
to mg values (1/1000th of earth gravity).
|
||||||
|
|
||||||
Sysfs attributes under /sys/devices/platform/lis3lv02d/:
|
Sysfs attributes under /sys/devices/faux/lis3lv02d/:
|
||||||
|
|
||||||
position
|
position
|
||||||
- 3D position that the accelerometer reports. Format: "(x,y,z)"
|
- 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
|
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
|
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
|
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
|
Q&A
|
||||||
---
|
---
|
||||||
|
|
|
@ -78,6 +78,37 @@ enabled like::
|
||||||
|
|
||||||
Please refer to the kernel configuration help for more information.
|
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
|
Perf test - Verify kernel and userspace perf CoreSight work
|
||||||
-----------------------------------------------------------
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -402,6 +402,8 @@ Code Seq# Include File Comments
|
||||||
<mailto:mathieu.desnoyers@efficios.com>
|
<mailto:mathieu.desnoyers@efficios.com>
|
||||||
0xF8 all arch/x86/include/uapi/asm/amd_hsmp.h AMD HSMP EPYC system management interface driver
|
0xF8 all arch/x86/include/uapi/asm/amd_hsmp.h AMD HSMP EPYC system management interface driver
|
||||||
<mailto:nchatrad@amd.com>
|
<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
|
0xFD all linux/dm-ioctl.h
|
||||||
0xFE all linux/isst_if.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
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
|
||||||
F: drivers/net/amt.c
|
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
|
ANALOG DEVICES INC AD3552R DRIVER
|
||||||
M: Nuno Sá <nuno.sa@analog.com>
|
M: Nuno Sá <nuno.sa@analog.com>
|
||||||
L: linux-iio@vger.kernel.org
|
L: linux-iio@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
W: https://ez.analog.com/linux-software-drivers
|
W: https://ez.analog.com/linux-software-drivers
|
||||||
F: Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
|
F: Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
|
||||||
|
F: Documentation/iio/ad3552r.rst
|
||||||
F: drivers/iio/dac/ad3552r.c
|
F: drivers/iio/dac/ad3552r.c
|
||||||
|
|
||||||
ANALOG DEVICES INC AD4000 DRIVER
|
ANALOG DEVICES INC AD4000 DRIVER
|
||||||
|
@ -1387,6 +1396,16 @@ F: Documentation/iio/ad4695.rst
|
||||||
F: drivers/iio/adc/ad4695.c
|
F: drivers/iio/adc/ad4695.c
|
||||||
F: include/dt-bindings/iio/adc/adi,ad4695.h
|
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
|
ANALOG DEVICES INC AD7091R DRIVER
|
||||||
M: Marcelo Schmitt <marcelo.schmitt@analog.com>
|
M: Marcelo Schmitt <marcelo.schmitt@analog.com>
|
||||||
L: linux-iio@vger.kernel.org
|
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/net/bluetooth/brcm,bcm4377-bluetooth.yaml
|
||||||
F: Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml
|
F: Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml
|
||||||
F: Documentation/devicetree/bindings/nvmem/apple,efuses.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/pci/apple,pcie.yaml
|
||||||
F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
|
F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml
|
||||||
F: Documentation/devicetree/bindings/power/apple*
|
F: Documentation/devicetree/bindings/power/apple*
|
||||||
F: Documentation/devicetree/bindings/pwm/apple,s5l-fpwm.yaml
|
F: Documentation/devicetree/bindings/pwm/apple,s5l-fpwm.yaml
|
||||||
F: Documentation/devicetree/bindings/spi/apple,spi.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: Documentation/devicetree/bindings/watchdog/apple,wdt.yaml
|
||||||
F: arch/arm64/boot/dts/apple/
|
F: arch/arm64/boot/dts/apple/
|
||||||
F: drivers/bluetooth/hci_bcm4377.c
|
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/irqchip/irq-apple-aic.c
|
||||||
F: drivers/nvme/host/apple.c
|
F: drivers/nvme/host/apple.c
|
||||||
F: drivers/nvmem/apple-efuses.c
|
F: drivers/nvmem/apple-efuses.c
|
||||||
|
F: drivers/nvmem/apple-spmi-nvmem.c
|
||||||
F: drivers/pinctrl/pinctrl-apple-gpio.c
|
F: drivers/pinctrl/pinctrl-apple-gpio.c
|
||||||
F: drivers/pwm/pwm-apple.c
|
F: drivers/pwm/pwm-apple.c
|
||||||
F: drivers/soc/apple/*
|
F: drivers/soc/apple/*
|
||||||
F: drivers/spi/spi-apple.c
|
F: drivers/spi/spi-apple.c
|
||||||
|
F: drivers/spmi/spmi-apple-controller.c
|
||||||
F: drivers/video/backlight/apple_dwi_bl.c
|
F: drivers/video/backlight/apple_dwi_bl.c
|
||||||
F: drivers/watchdog/apple_wdt.c
|
F: drivers/watchdog/apple_wdt.c
|
||||||
F: include/dt-bindings/interrupt-controller/apple-aic.h
|
F: include/dt-bindings/interrupt-controller/apple-aic.h
|
||||||
|
@ -6938,6 +6961,12 @@ L: linux-rtc@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/rtc/rtc-sd2405al.c
|
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
|
DH ELECTRONICS DHSOM SOM AND BOARD SUPPORT
|
||||||
M: Christoph Niedermaier <cniedermaier@dh-electronics.com>
|
M: Christoph Niedermaier <cniedermaier@dh-electronics.com>
|
||||||
M: Marek Vasut <marex@denx.de>
|
M: Marek Vasut <marex@denx.de>
|
||||||
|
@ -11644,6 +11673,13 @@ L: linux-media@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/media/rc/iguanair.c
|
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
|
IIO BACKEND FRAMEWORK
|
||||||
M: Nuno Sa <nuno.sa@analog.com>
|
M: Nuno Sa <nuno.sa@analog.com>
|
||||||
R: Olivier Moysan <olivier.moysan@foss.st.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
|
IIO SUBSYSTEM AND DRIVERS
|
||||||
M: Jonathan Cameron <jic23@kernel.org>
|
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
|
L: linux-iio@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git
|
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
|
F: include/linux/mfd/intel-m10-bmc.h
|
||||||
|
|
||||||
INTEL MAX10 BMC SECURE UPDATES
|
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
|
L: linux-fpga@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
|
F: Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-sec-update
|
||||||
|
@ -16938,7 +16976,7 @@ F: include/uapi/linux/mmc/
|
||||||
|
|
||||||
MULTIPLEXER SUBSYSTEM
|
MULTIPLEXER SUBSYSTEM
|
||||||
M: Peter Rosin <peda@axentia.se>
|
M: Peter Rosin <peda@axentia.se>
|
||||||
S: Maintained
|
S: Odd Fixes
|
||||||
F: Documentation/ABI/testing/sysfs-class-mux*
|
F: Documentation/ABI/testing/sysfs-class-mux*
|
||||||
F: Documentation/devicetree/bindings/mux/
|
F: Documentation/devicetree/bindings/mux/
|
||||||
F: drivers/mux/
|
F: drivers/mux/
|
||||||
|
@ -17715,6 +17753,13 @@ F: drivers/nubus/
|
||||||
F: include/linux/nubus.h
|
F: include/linux/nubus.h
|
||||||
F: include/uapi/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
|
NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER
|
||||||
M: Antonino Daplas <adaplas@gmail.com>
|
M: Antonino Daplas <adaplas@gmail.com>
|
||||||
L: linux-fbdev@vger.kernel.org
|
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.c
|
||||||
F: drivers/power/supply/bd99954-charger.h
|
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
|
ROHM BH1745 COLOUR SENSOR
|
||||||
M: Mudit Sharma <muditsharma.info@gmail.com>
|
M: Mudit Sharma <muditsharma.info@gmail.com>
|
||||||
L: linux-iio@vger.kernel.org
|
L: linux-iio@vger.kernel.org
|
||||||
|
@ -24646,6 +24696,12 @@ M: Robert Richter <rric@kernel.org>
|
||||||
S: Odd Fixes
|
S: Odd Fixes
|
||||||
F: drivers/gpio/gpio-thunderx.c
|
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
|
TI ADS1119 ADC DRIVER
|
||||||
M: Francesco Dolcini <francesco@dolcini.it>
|
M: Francesco Dolcini <francesco@dolcini.it>
|
||||||
M: João Paulo Gonçalves <jpaulo.silvagoncalves@gmail.com>
|
M: João Paulo Gonçalves <jpaulo.silvagoncalves@gmail.com>
|
||||||
|
@ -26595,6 +26651,12 @@ M: David Härdeman <david@hardeman.nu>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/media/rc/winbond-cir.c
|
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
|
WINSYSTEMS EBC-C384 WATCHDOG DRIVER
|
||||||
L: linux-watchdog@vger.kernel.org
|
L: linux-watchdog@vger.kernel.org
|
||||||
S: Orphan
|
S: Orphan
|
||||||
|
@ -27092,8 +27154,6 @@ M: Dragan Cvetic <dragan.cvetic@amd.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: Documentation/devicetree/bindings/misc/xlnx,sd-fec.yaml
|
F: Documentation/devicetree/bindings/misc/xlnx,sd-fec.yaml
|
||||||
F: Documentation/misc-devices/xilinx_sdfec.rst
|
F: Documentation/misc-devices/xilinx_sdfec.rst
|
||||||
F: drivers/misc/Kconfig
|
|
||||||
F: drivers/misc/Makefile
|
|
||||||
F: drivers/misc/xilinx_sdfec.c
|
F: drivers/misc/xilinx_sdfec.c
|
||||||
F: include/uapi/misc/xilinx_sdfec.h
|
F: include/uapi/misc/xilinx_sdfec.h
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,8 @@ static HLIST_HEAD(binder_deferred_list);
|
||||||
static DEFINE_MUTEX(binder_deferred_lock);
|
static DEFINE_MUTEX(binder_deferred_lock);
|
||||||
|
|
||||||
static HLIST_HEAD(binder_devices);
|
static HLIST_HEAD(binder_devices);
|
||||||
|
static DEFINE_SPINLOCK(binder_devices_lock);
|
||||||
|
|
||||||
static HLIST_HEAD(binder_procs);
|
static HLIST_HEAD(binder_procs);
|
||||||
static DEFINE_MUTEX(binder_procs_lock);
|
static DEFINE_MUTEX(binder_procs_lock);
|
||||||
|
|
||||||
|
@ -3261,20 +3263,16 @@ static void binder_transaction(struct binder_proc *proc,
|
||||||
|
|
||||||
if (reply)
|
if (reply)
|
||||||
binder_debug(BINDER_DEBUG_TRANSACTION,
|
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,
|
proc->pid, thread->pid, t->debug_id,
|
||||||
target_proc->pid, target_thread->pid,
|
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)tr->data_size, (u64)tr->offsets_size,
|
||||||
(u64)extra_buffers_size);
|
(u64)extra_buffers_size);
|
||||||
else
|
else
|
||||||
binder_debug(BINDER_DEBUG_TRANSACTION,
|
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,
|
proc->pid, thread->pid, t->debug_id,
|
||||||
target_proc->pid, target_node->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)tr->data_size, (u64)tr->offsets_size,
|
||||||
(u64)extra_buffers_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 (IS_ERR_OR_NULL(buffer)) {
|
||||||
if (PTR_ERR(buffer) == -EPERM) {
|
if (PTR_ERR(buffer) == -EPERM) {
|
||||||
binder_user_error(
|
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,
|
proc->pid, thread->pid,
|
||||||
(u64)data_ptr);
|
(unsigned long)data_ptr - proc->alloc.vm_start);
|
||||||
} else {
|
} else {
|
||||||
binder_user_error(
|
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,
|
proc->pid, thread->pid,
|
||||||
(u64)data_ptr);
|
(unsigned long)data_ptr - proc->alloc.vm_start);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
binder_debug(BINDER_DEBUG_FREE_BUFFER,
|
binder_debug(BINDER_DEBUG_FREE_BUFFER,
|
||||||
"%d:%d BC_FREE_BUFFER u%016llx found buffer %d for %s transaction\n",
|
"%d:%d BC_FREE_BUFFER at offset %lx found buffer %d for %s transaction\n",
|
||||||
proc->pid, thread->pid, (u64)data_ptr,
|
proc->pid, thread->pid,
|
||||||
|
(unsigned long)data_ptr - proc->alloc.vm_start,
|
||||||
buffer->debug_id,
|
buffer->debug_id,
|
||||||
buffer->transaction ? "active" : "finished");
|
buffer->transaction ? "active" : "finished");
|
||||||
binder_free_buf(proc, thread, buffer, false);
|
binder_free_buf(proc, thread, buffer, false);
|
||||||
|
@ -5053,16 +5052,14 @@ retry:
|
||||||
trace_binder_transaction_received(t);
|
trace_binder_transaction_received(t);
|
||||||
binder_stat_br(proc, thread, cmd);
|
binder_stat_br(proc, thread, cmd);
|
||||||
binder_debug(BINDER_DEBUG_TRANSACTION,
|
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,
|
proc->pid, thread->pid,
|
||||||
(cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
|
(cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
|
||||||
(cmd == BR_TRANSACTION_SEC_CTX) ?
|
(cmd == BR_TRANSACTION_SEC_CTX) ?
|
||||||
"BR_TRANSACTION_SEC_CTX" : "BR_REPLY",
|
"BR_TRANSACTION_SEC_CTX" : "BR_REPLY",
|
||||||
t->debug_id, t_from ? t_from->proc->pid : 0,
|
t->debug_id, t_from ? t_from->proc->pid : 0,
|
||||||
t_from ? t_from->pid : 0, cmd,
|
t_from ? t_from->pid : 0, cmd,
|
||||||
t->buffer->data_size, t->buffer->offsets_size,
|
t->buffer->data_size, t->buffer->offsets_size);
|
||||||
(u64)trd->data.ptr.buffer,
|
|
||||||
(u64)trd->data.ptr.offsets);
|
|
||||||
|
|
||||||
if (t_from)
|
if (t_from)
|
||||||
binder_thread_dec_tmpref(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);
|
__func__, proc->outstanding_txns);
|
||||||
device = container_of(proc->context, struct binder_device, context);
|
device = container_of(proc->context, struct binder_device, context);
|
||||||
if (refcount_dec_and_test(&device->ref)) {
|
if (refcount_dec_and_test(&device->ref)) {
|
||||||
|
binder_remove_device(device);
|
||||||
kfree(proc->context->name);
|
kfree(proc->context->name);
|
||||||
kfree(device);
|
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,
|
static void print_binder_work_ilocked(struct seq_file *m,
|
||||||
struct binder_proc *proc,
|
struct binder_proc *proc,
|
||||||
const char *prefix,
|
const char *prefix,
|
||||||
const char *transaction_prefix,
|
const char *transaction_prefix,
|
||||||
struct binder_work *w)
|
struct binder_work *w, bool hash_ptrs)
|
||||||
{
|
{
|
||||||
struct binder_node *node;
|
struct binder_node *node;
|
||||||
struct binder_transaction *t;
|
struct binder_transaction *t;
|
||||||
|
@ -6403,9 +6401,15 @@ static void print_binder_work_ilocked(struct seq_file *m,
|
||||||
break;
|
break;
|
||||||
case BINDER_WORK_NODE:
|
case BINDER_WORK_NODE:
|
||||||
node = container_of(w, struct binder_node, work);
|
node = container_of(w, struct binder_node, work);
|
||||||
seq_printf(m, "%snode work %d: u%016llx c%016llx\n",
|
if (hash_ptrs)
|
||||||
prefix, node->debug_id,
|
seq_printf(m, "%snode work %d: u%p c%p\n",
|
||||||
(u64)node->ptr, (u64)node->cookie);
|
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;
|
break;
|
||||||
case BINDER_WORK_DEAD_BINDER:
|
case BINDER_WORK_DEAD_BINDER:
|
||||||
seq_printf(m, "%shas dead binder\n", prefix);
|
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,
|
static void print_binder_thread_ilocked(struct seq_file *m,
|
||||||
struct binder_thread *thread,
|
struct binder_thread *thread,
|
||||||
int print_always)
|
bool print_always, bool hash_ptrs)
|
||||||
{
|
{
|
||||||
struct binder_transaction *t;
|
struct binder_transaction *t;
|
||||||
struct binder_work *w;
|
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) {
|
list_for_each_entry(w, &thread->todo, entry) {
|
||||||
print_binder_work_ilocked(m, thread->proc, " ",
|
print_binder_work_ilocked(m, thread->proc, " ",
|
||||||
" pending transaction", w);
|
" pending transaction",
|
||||||
|
w, hash_ptrs);
|
||||||
}
|
}
|
||||||
if (!print_always && m->count == header_pos)
|
if (!print_always && m->count == header_pos)
|
||||||
m->count = start_pos;
|
m->count = start_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_binder_node_nilocked(struct seq_file *m,
|
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_ref *ref;
|
||||||
struct binder_work *w;
|
struct binder_work *w;
|
||||||
|
@ -6475,8 +6481,13 @@ static void print_binder_node_nilocked(struct seq_file *m,
|
||||||
|
|
||||||
count = hlist_count_nodes(&node->refs);
|
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",
|
if (hash_ptrs)
|
||||||
node->debug_id, (u64)node->ptr, (u64)node->cookie,
|
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->has_strong_ref, node->has_weak_ref,
|
||||||
node->local_strong_refs, node->local_weak_refs,
|
node->local_strong_refs, node->local_weak_refs,
|
||||||
node->internal_strong_refs, count, node->tmp_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) {
|
if (node->proc) {
|
||||||
list_for_each_entry(w, &node->async_todo, entry)
|
list_for_each_entry(w, &node->async_todo, entry)
|
||||||
print_binder_work_ilocked(m, node->proc, " ",
|
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);
|
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 binder_work *w;
|
||||||
struct rb_node *n;
|
struct rb_node *n;
|
||||||
|
@ -6519,31 +6577,19 @@ static void print_binder_proc(struct seq_file *m,
|
||||||
header_pos = m->count;
|
header_pos = m->count;
|
||||||
|
|
||||||
binder_inner_proc_lock(proc);
|
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,
|
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,
|
struct binder_node *node = rb_entry(n, struct binder_node,
|
||||||
rb_node);
|
rb_node);
|
||||||
if (!print_all && !node->has_async_transaction)
|
if (!print_all && !node->has_async_transaction)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
last_node = print_next_binder_node_ilocked(m, proc, node,
|
||||||
* take a temporary reference on the node so it
|
last_node,
|
||||||
* survives and isn't removed from the tree
|
hash_ptrs);
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
binder_inner_proc_unlock(proc);
|
binder_inner_proc_unlock(proc);
|
||||||
if (last_node)
|
if (last_node)
|
||||||
|
@ -6551,19 +6597,18 @@ static void print_binder_proc(struct seq_file *m,
|
||||||
|
|
||||||
if (print_all) {
|
if (print_all) {
|
||||||
binder_proc_lock(proc);
|
binder_proc_lock(proc);
|
||||||
for (n = rb_first(&proc->refs_by_desc);
|
for (n = rb_first(&proc->refs_by_desc); n; n = rb_next(n))
|
||||||
n != NULL;
|
|
||||||
n = rb_next(n))
|
|
||||||
print_binder_ref_olocked(m, rb_entry(n,
|
print_binder_ref_olocked(m, rb_entry(n,
|
||||||
struct binder_ref,
|
struct binder_ref,
|
||||||
rb_node_desc));
|
rb_node_desc));
|
||||||
binder_proc_unlock(proc);
|
binder_proc_unlock(proc);
|
||||||
}
|
}
|
||||||
binder_alloc_print_allocated(m, &proc->alloc);
|
binder_alloc_print_allocated(m, &proc->alloc);
|
||||||
binder_inner_proc_lock(proc);
|
binder_inner_proc_lock(proc);
|
||||||
list_for_each_entry(w, &proc->todo, entry)
|
list_for_each_entry(w, &proc->todo, entry)
|
||||||
print_binder_work_ilocked(m, proc, " ",
|
print_binder_work_ilocked(m, proc, " ",
|
||||||
" pending transaction", w);
|
" pending transaction", w,
|
||||||
|
hash_ptrs);
|
||||||
list_for_each_entry(w, &proc->delivered_death, entry) {
|
list_for_each_entry(w, &proc->delivered_death, entry) {
|
||||||
seq_puts(m, " has delivered dead binder\n");
|
seq_puts(m, " has delivered dead binder\n");
|
||||||
break;
|
break;
|
||||||
|
@ -6696,7 +6741,7 @@ static void print_binder_proc_stats(struct seq_file *m,
|
||||||
count = 0;
|
count = 0;
|
||||||
ready_threads = 0;
|
ready_threads = 0;
|
||||||
binder_inner_proc_lock(proc);
|
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++;
|
count++;
|
||||||
|
|
||||||
list_for_each_entry(thread, &proc->waiting_threads, waiting_thread_node)
|
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,
|
ready_threads,
|
||||||
free_async_space);
|
free_async_space);
|
||||||
count = 0;
|
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++;
|
count++;
|
||||||
binder_inner_proc_unlock(proc);
|
binder_inner_proc_unlock(proc);
|
||||||
seq_printf(m, " nodes: %d\n", count);
|
seq_printf(m, " nodes: %d\n", count);
|
||||||
|
@ -6718,7 +6763,7 @@ static void print_binder_proc_stats(struct seq_file *m,
|
||||||
strong = 0;
|
strong = 0;
|
||||||
weak = 0;
|
weak = 0;
|
||||||
binder_proc_lock(proc);
|
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,
|
struct binder_ref *ref = rb_entry(n, struct binder_ref,
|
||||||
rb_node_desc);
|
rb_node_desc);
|
||||||
count++;
|
count++;
|
||||||
|
@ -6745,7 +6790,7 @@ static void print_binder_proc_stats(struct seq_file *m,
|
||||||
print_binder_stats(m, " ", &proc->stats);
|
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_proc *proc;
|
||||||
struct binder_node *node;
|
struct binder_node *node;
|
||||||
|
@ -6756,31 +6801,40 @@ static int state_show(struct seq_file *m, void *unused)
|
||||||
spin_lock(&binder_dead_nodes_lock);
|
spin_lock(&binder_dead_nodes_lock);
|
||||||
if (!hlist_empty(&binder_dead_nodes))
|
if (!hlist_empty(&binder_dead_nodes))
|
||||||
seq_puts(m, "dead nodes:\n");
|
seq_puts(m, "dead nodes:\n");
|
||||||
hlist_for_each_entry(node, &binder_dead_nodes, dead_node) {
|
hlist_for_each_entry(node, &binder_dead_nodes, dead_node)
|
||||||
/*
|
last_node = print_next_binder_node_ilocked(m, NULL, node,
|
||||||
* take a temporary reference on the node so it
|
last_node,
|
||||||
* survives and isn't removed from the list
|
hash_ptrs);
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
spin_unlock(&binder_dead_nodes_lock);
|
spin_unlock(&binder_dead_nodes_lock);
|
||||||
if (last_node)
|
if (last_node)
|
||||||
binder_put_node(last_node);
|
binder_put_node(last_node);
|
||||||
|
|
||||||
mutex_lock(&binder_procs_lock);
|
mutex_lock(&binder_procs_lock);
|
||||||
hlist_for_each_entry(proc, &binder_procs, proc_node)
|
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);
|
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;
|
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)
|
static int transactions_show(struct seq_file *m, void *unused)
|
||||||
{
|
{
|
||||||
struct binder_proc *proc;
|
print_binder_transactions(m, false);
|
||||||
|
return 0;
|
||||||
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);
|
|
||||||
|
|
||||||
|
static int transactions_hashed_show(struct seq_file *m, void *unused)
|
||||||
|
{
|
||||||
|
print_binder_transactions(m, true);
|
||||||
return 0;
|
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) {
|
hlist_for_each_entry(itr, &binder_procs, proc_node) {
|
||||||
if (itr->pid == pid) {
|
if (itr->pid == pid) {
|
||||||
seq_puts(m, "binder proc state:\n");
|
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);
|
mutex_unlock(&binder_procs_lock);
|
||||||
|
@ -6889,8 +6942,10 @@ const struct file_operations binder_fops = {
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_SHOW_ATTRIBUTE(state);
|
DEFINE_SHOW_ATTRIBUTE(state);
|
||||||
|
DEFINE_SHOW_ATTRIBUTE(state_hashed);
|
||||||
DEFINE_SHOW_ATTRIBUTE(stats);
|
DEFINE_SHOW_ATTRIBUTE(stats);
|
||||||
DEFINE_SHOW_ATTRIBUTE(transactions);
|
DEFINE_SHOW_ATTRIBUTE(transactions);
|
||||||
|
DEFINE_SHOW_ATTRIBUTE(transactions_hashed);
|
||||||
DEFINE_SHOW_ATTRIBUTE(transaction_log);
|
DEFINE_SHOW_ATTRIBUTE(transaction_log);
|
||||||
|
|
||||||
const struct binder_debugfs_entry binder_debugfs_entries[] = {
|
const struct binder_debugfs_entry binder_debugfs_entries[] = {
|
||||||
|
@ -6900,6 +6955,12 @@ const struct binder_debugfs_entry binder_debugfs_entries[] = {
|
||||||
.fops = &state_fops,
|
.fops = &state_fops,
|
||||||
.data = NULL,
|
.data = NULL,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "state_hashed",
|
||||||
|
.mode = 0444,
|
||||||
|
.fops = &state_hashed_fops,
|
||||||
|
.data = NULL,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.name = "stats",
|
.name = "stats",
|
||||||
.mode = 0444,
|
.mode = 0444,
|
||||||
|
@ -6912,6 +6973,12 @@ const struct binder_debugfs_entry binder_debugfs_entries[] = {
|
||||||
.fops = &transactions_fops,
|
.fops = &transactions_fops,
|
||||||
.data = NULL,
|
.data = NULL,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "transactions_hashed",
|
||||||
|
.mode = 0444,
|
||||||
|
.fops = &transactions_hashed_fops,
|
||||||
|
.data = NULL,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.name = "transaction_log",
|
.name = "transaction_log",
|
||||||
.mode = 0444,
|
.mode = 0444,
|
||||||
|
@ -6929,7 +6996,16 @@ const struct binder_debugfs_entry binder_debugfs_entries[] = {
|
||||||
|
|
||||||
void binder_add_device(struct binder_device *device)
|
void binder_add_device(struct binder_device *device)
|
||||||
{
|
{
|
||||||
|
spin_lock(&binder_devices_lock);
|
||||||
hlist_add_head(&device->hlist, &binder_devices);
|
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)
|
static int __init init_binder_device(const char *name)
|
||||||
|
@ -6956,7 +7032,7 @@ static int __init init_binder_device(const char *name)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
hlist_add_head(&binder_device->hlist, &binder_devices);
|
binder_add_device(binder_device);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -7018,7 +7094,7 @@ static int __init binder_init(void)
|
||||||
err_init_binder_device_failed:
|
err_init_binder_device_failed:
|
||||||
hlist_for_each_entry_safe(device, tmp, &binder_devices, hlist) {
|
hlist_for_each_entry_safe(device, tmp, &binder_devices, hlist) {
|
||||||
misc_deregister(&device->miscdev);
|
misc_deregister(&device->miscdev);
|
||||||
hlist_del(&device->hlist);
|
binder_remove_device(device);
|
||||||
kfree(device);
|
kfree(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -583,9 +583,13 @@ struct binder_object {
|
||||||
/**
|
/**
|
||||||
* Add a binder device to binder_devices
|
* Add a binder device to binder_devices
|
||||||
* @device: the new binder device to add to the global list
|
* @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);
|
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 */
|
#endif /* _LINUX_BINDER_INTERNAL_H */
|
||||||
|
|
|
@ -274,7 +274,7 @@ static void binderfs_evict_inode(struct inode *inode)
|
||||||
mutex_unlock(&binderfs_minors_mutex);
|
mutex_unlock(&binderfs_minors_mutex);
|
||||||
|
|
||||||
if (refcount_dec_and_test(&device->ref)) {
|
if (refcount_dec_and_test(&device->ref)) {
|
||||||
hlist_del_init(&device->hlist);
|
binder_remove_device(device);
|
||||||
kfree(device->context.name);
|
kfree(device->context.name);
|
||||||
kfree(device);
|
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);
|
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)
|
bool device_dma_supported(const struct device *dev)
|
||||||
{
|
{
|
||||||
return fwnode_call_bool_op(dev_fwnode(dev), device_dma_supported);
|
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;
|
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);
|
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 */
|
/* Update rp in ring context */
|
||||||
rp = cpu_to_le64(ring->rd_offset * sizeof(*el) + ring->rbase);
|
rp = cpu_to_le64(ring->rd_offset * sizeof(*el) + ring->rbase);
|
||||||
memcpy_toio((void __iomem *) &ring->ring_ctx->generic.rp, &rp, sizeof(u64));
|
memcpy_toio((void __iomem *) &ring->ring_ctx->generic.rp, &rp, sizeof(u64));
|
||||||
|
|
||||||
buf_info.host_addr = ring->rbase + (old_offset * sizeof(*el));
|
return ret;
|
||||||
buf_info.dev_addr = el;
|
|
||||||
buf_info.size = sizeof(*el);
|
|
||||||
|
|
||||||
return mhi_cntrl->write_sync(mhi_cntrl, &buf_info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mhi_ep_ring_init(struct mhi_ep_ring *ring, enum mhi_ep_ring_type type, u32 id)
|
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,
|
.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 = {
|
static const struct mhi_pci_dev_info mhi_netprisma_lcur57_info = {
|
||||||
.name = "netprisma-lcur57",
|
.name = "netprisma-lcur57",
|
||||||
.edl = "qcom/prog_firehose_sdx24.mbn",
|
.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[] = {
|
static const struct pci_device_id mhi_pci_id_table[] = {
|
||||||
{PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0116),
|
{PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0116),
|
||||||
.driver_data = (kernel_ulong_t) &mhi_qcom_sa8775p_info },
|
.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),
|
{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0304),
|
||||||
.driver_data = (kernel_ulong_t) &mhi_qcom_sdx24_info },
|
.driver_data = (kernel_ulong_t) &mhi_qcom_sdx24_info },
|
||||||
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0306, PCI_VENDOR_ID_QCOM, 0x010c),
|
{ 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);
|
struct pci_dev *pdev = to_pci_dev(mhi_cntrl->cntrl_dev);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = pci_assign_resource(pdev, bar_num);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err = pcim_enable_device(pdev);
|
err = pcim_enable_device(pdev);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&pdev->dev, "failed to enable pci device: %d\n", 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_cmd *mhi_cmd;
|
||||||
struct mhi_event_ctxt *er_ctxt;
|
struct mhi_event_ctxt *er_ctxt;
|
||||||
struct device *dev = &mhi_cntrl->mhi_dev->dev;
|
struct device *dev = &mhi_cntrl->mhi_dev->dev;
|
||||||
|
bool reset_device = false;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
|
||||||
dev_dbg(dev, "Transitioning from PM state: %s to: %s\n",
|
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 threads waiting for state transition */
|
||||||
wake_up_all(&mhi_cntrl->state_event);
|
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 (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;
|
u32 in_reset = -1;
|
||||||
unsigned long timeout = msecs_to_jiffies(mhi_cntrl->timeout_ms);
|
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 device_node *parent_node;
|
||||||
struct irq_domain *parent;
|
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);
|
parent_node = of_parse_phandle(np, "msi-map", 1);
|
||||||
if (!parent_node) {
|
if (!parent_node) {
|
||||||
|
@ -173,7 +173,7 @@ struct irq_domain *cdx_msi_domain_init(struct device *dev)
|
||||||
return NULL;
|
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)) {
|
if (!parent || !msi_get_domain_info(parent)) {
|
||||||
dev_err(dev, "unable to locate ITS domain\n");
|
dev_err(dev, "unable to locate ITS domain\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -404,7 +404,7 @@ config TELCLOCK
|
||||||
configuration of the telecom clock configuration settings. This
|
configuration of the telecom clock configuration settings. This
|
||||||
device is used for hardware synchronization across the ATCA backplane
|
device is used for hardware synchronization across the ATCA backplane
|
||||||
fabric. Upon loading, the driver exports a sysfs directory,
|
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.
|
controlling the behavior of this hardware.
|
||||||
|
|
||||||
source "drivers/s390/char/Kconfig"
|
source "drivers/s390/char/Kconfig"
|
||||||
|
|
|
@ -141,9 +141,6 @@ static struct apm_queue kapmd_queue;
|
||||||
|
|
||||||
static DEFINE_MUTEX(state_lock);
|
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
|
* 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 int proc_apm_show(struct seq_file *m, void *v)
|
||||||
{
|
{
|
||||||
|
static const char driver_version[] = "1.13"; /* no spaces */
|
||||||
|
|
||||||
struct apm_power_info info;
|
struct apm_power_info info;
|
||||||
char *units;
|
char *units;
|
||||||
|
|
||||||
|
|
|
@ -1023,8 +1023,7 @@ static int __init hpet_init(void)
|
||||||
|
|
||||||
result = acpi_bus_register_driver(&hpet_acpi_driver);
|
result = acpi_bus_register_driver(&hpet_acpi_driver);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
if (sysctl_header)
|
unregister_sysctl_table(sysctl_header);
|
||||||
unregister_sysctl_table(sysctl_header);
|
|
||||||
misc_deregister(&hpet_misc);
|
misc_deregister(&hpet_misc);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,9 +58,8 @@ static LIST_HEAD(misc_list);
|
||||||
static DEFINE_MUTEX(misc_mtx);
|
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 DEFINE_IDA(misc_minors_ida);
|
||||||
|
|
||||||
static int misc_minor_alloc(int minor)
|
static int misc_minor_alloc(int minor)
|
||||||
|
@ -69,34 +68,17 @@ static int misc_minor_alloc(int minor)
|
||||||
|
|
||||||
if (minor == MISC_DYNAMIC_MINOR) {
|
if (minor == MISC_DYNAMIC_MINOR) {
|
||||||
/* allocate free id */
|
/* allocate free id */
|
||||||
ret = ida_alloc_max(&misc_minors_ida, DYNAMIC_MINORS - 1, GFP_KERNEL);
|
ret = ida_alloc_range(&misc_minors_ida, MISC_DYNAMIC_MINOR + 1,
|
||||||
if (ret >= 0) {
|
MINORMASK, GFP_KERNEL);
|
||||||
ret = DYNAMIC_MINORS - ret - 1;
|
|
||||||
} else {
|
|
||||||
ret = ida_alloc_range(&misc_minors_ida, MISC_DYNAMIC_MINOR + 1,
|
|
||||||
MINORMASK, GFP_KERNEL);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* specific minor, check if it is in dynamic or misc dynamic range */
|
ret = ida_alloc_range(&misc_minors_ida, minor, minor, GFP_KERNEL);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void misc_minor_free(int minor)
|
static void misc_minor_free(int minor)
|
||||||
{
|
{
|
||||||
if (minor < DYNAMIC_MINORS)
|
ida_free(&misc_minors_ida, minor);
|
||||||
ida_free(&misc_minors_ida, DYNAMIC_MINORS - minor - 1);
|
|
||||||
else if (minor > MISC_DYNAMIC_MINOR)
|
|
||||||
ida_free(&misc_minors_ida, minor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#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)
|
static void xillybus_autoflush(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct delayed_work *workitem = container_of(
|
struct delayed_work *workitem = to_delayed_work(work);
|
||||||
work, struct delayed_work, work);
|
|
||||||
struct xilly_channel *channel = container_of(
|
struct xilly_channel *channel = container_of(
|
||||||
workitem, struct xilly_channel, rd_workitem);
|
workitem, struct xilly_channel, rd_workitem);
|
||||||
int rc;
|
int rc;
|
||||||
|
|
|
@ -27,14 +27,12 @@ static void comedi_buf_map_kref_release(struct kref *kref)
|
||||||
|
|
||||||
if (bm->page_list) {
|
if (bm->page_list) {
|
||||||
if (bm->dma_dir != DMA_NONE) {
|
if (bm->dma_dir != DMA_NONE) {
|
||||||
/*
|
for (i = 0; i < bm->n_pages; i++) {
|
||||||
* DMA buffer was allocated as a single block.
|
buf = &bm->page_list[i];
|
||||||
* Address is in page_list[0].
|
dma_free_coherent(bm->dma_hw_dev, PAGE_SIZE,
|
||||||
*/
|
buf->virt_addr,
|
||||||
buf = &bm->page_list[0];
|
buf->dma_addr);
|
||||||
dma_free_coherent(bm->dma_hw_dev,
|
}
|
||||||
PAGE_SIZE * bm->n_pages,
|
|
||||||
buf->virt_addr, buf->dma_addr);
|
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < bm->n_pages; i++) {
|
for (i = 0; i < bm->n_pages; i++) {
|
||||||
buf = &bm->page_list[i];
|
buf = &bm->page_list[i];
|
||||||
|
@ -56,13 +54,7 @@ static void __comedi_buf_free(struct comedi_device *dev,
|
||||||
struct comedi_buf_map *bm;
|
struct comedi_buf_map *bm;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (async->prealloc_buf) {
|
async->prealloc_bufsz = 0;
|
||||||
if (s->async_dma_dir == DMA_NONE)
|
|
||||||
vunmap(async->prealloc_buf);
|
|
||||||
async->prealloc_buf = NULL;
|
|
||||||
async->prealloc_bufsz = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_lock_irqsave(&s->spin_lock, flags);
|
spin_lock_irqsave(&s->spin_lock, flags);
|
||||||
bm = async->buf_map;
|
bm = async->buf_map;
|
||||||
async->buf_map = NULL;
|
async->buf_map = NULL;
|
||||||
|
@ -94,26 +86,14 @@ comedi_buf_map_alloc(struct comedi_device *dev, enum dma_data_direction dma_dir,
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (bm->dma_dir != DMA_NONE) {
|
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++) {
|
for (i = 0; i < n_pages; i++) {
|
||||||
buf = &bm->page_list[i];
|
buf = &bm->page_list[i];
|
||||||
buf->virt_addr = virt_addr + (i << PAGE_SHIFT);
|
buf->virt_addr =
|
||||||
buf->dma_addr = dma_addr + (i << PAGE_SHIFT);
|
dma_alloc_coherent(bm->dma_hw_dev, PAGE_SIZE,
|
||||||
|
&buf->dma_addr, GFP_KERNEL);
|
||||||
|
if (!buf->virt_addr)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bm->n_pages = i;
|
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < n_pages; i++) {
|
for (i = 0; i < n_pages; i++) {
|
||||||
buf = &bm->page_list[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));
|
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;
|
return bm;
|
||||||
|
|
||||||
|
@ -141,11 +120,8 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
|
||||||
unsigned int n_pages)
|
unsigned int n_pages)
|
||||||
{
|
{
|
||||||
struct comedi_async *async = s->async;
|
struct comedi_async *async = s->async;
|
||||||
struct page **pages = NULL;
|
|
||||||
struct comedi_buf_map *bm;
|
struct comedi_buf_map *bm;
|
||||||
struct comedi_buf_page *buf;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
if (!IS_ENABLED(CONFIG_HAS_DMA) && s->async_dma_dir != DMA_NONE) {
|
if (!IS_ENABLED(CONFIG_HAS_DMA) && s->async_dma_dir != DMA_NONE) {
|
||||||
dev_err(dev->class_dev,
|
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);
|
spin_lock_irqsave(&s->spin_lock, flags);
|
||||||
async->buf_map = bm;
|
async->buf_map = bm;
|
||||||
spin_unlock_irqrestore(&s->spin_lock, flags);
|
spin_unlock_irqrestore(&s->spin_lock, flags);
|
||||||
|
async->prealloc_bufsz = n_pages << PAGE_SHIFT;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void comedi_buf_map_get(struct comedi_buf_map *bm)
|
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;
|
new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
|
||||||
|
|
||||||
/* if no change is required, do nothing */
|
/* if no change is required, do nothing */
|
||||||
if (async->prealloc_buf && async->prealloc_bufsz == new_size)
|
if (async->prealloc_bufsz == new_size)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* deallocate old buffer */
|
/* 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;
|
unsigned int n_pages = new_size >> PAGE_SHIFT;
|
||||||
|
|
||||||
__comedi_buf_alloc(dev, s, n_pages);
|
__comedi_buf_alloc(dev, s, n_pages);
|
||||||
|
if (!async->prealloc_bufsz)
|
||||||
if (!async->prealloc_buf) {
|
|
||||||
/* allocation failed */
|
|
||||||
__comedi_buf_free(dev, s);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
async->prealloc_bufsz = new_size;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -365,6 +313,7 @@ static unsigned int comedi_buf_munge(struct comedi_subdevice *s,
|
||||||
unsigned int num_bytes)
|
unsigned int num_bytes)
|
||||||
{
|
{
|
||||||
struct comedi_async *async = s->async;
|
struct comedi_async *async = s->async;
|
||||||
|
struct comedi_buf_page *buf_page_list = async->buf_map->page_list;
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
const unsigned int num_sample_bytes = comedi_bytes_per_sample(s);
|
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 */
|
/* don't munge partial samples */
|
||||||
num_bytes -= num_bytes % num_sample_bytes;
|
num_bytes -= num_bytes % num_sample_bytes;
|
||||||
while (count < num_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;
|
s->munge(s->device, s, buf_page_list[page].virt_addr + offset,
|
||||||
if (block_size > buf_end)
|
|
||||||
block_size = buf_end;
|
|
||||||
|
|
||||||
s->munge(s->device, s,
|
|
||||||
async->prealloc_buf + async->munge_ptr,
|
|
||||||
block_size, async->munge_chan);
|
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_chan %= async->cmd.chanlist_len;
|
||||||
async->munge_count += block_size;
|
async->munge_count += block_size;
|
||||||
async->munge_ptr += 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;
|
count += block_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,46 +509,52 @@ static void comedi_buf_memcpy_to(struct comedi_subdevice *s,
|
||||||
const void *data, unsigned int num_bytes)
|
const void *data, unsigned int num_bytes)
|
||||||
{
|
{
|
||||||
struct comedi_async *async = s->async;
|
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;
|
unsigned int write_ptr = async->buf_write_ptr;
|
||||||
|
|
||||||
while (num_bytes) {
|
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)
|
memcpy(buf_page_list[page].virt_addr + offset,
|
||||||
block_size = async->prealloc_bufsz - write_ptr;
|
data, block_size);
|
||||||
else
|
|
||||||
block_size = num_bytes;
|
|
||||||
|
|
||||||
memcpy(async->prealloc_buf + write_ptr, data, block_size);
|
|
||||||
|
|
||||||
data += block_size;
|
data += block_size;
|
||||||
num_bytes -= block_size;
|
num_bytes -= block_size;
|
||||||
|
write_ptr += block_size;
|
||||||
write_ptr = 0;
|
if (write_ptr == async->prealloc_bufsz)
|
||||||
|
write_ptr = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void comedi_buf_memcpy_from(struct comedi_subdevice *s,
|
static void comedi_buf_memcpy_from(struct comedi_subdevice *s,
|
||||||
void *dest, unsigned int nbytes)
|
void *dest, unsigned int nbytes)
|
||||||
{
|
{
|
||||||
void *src;
|
|
||||||
struct comedi_async *async = s->async;
|
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;
|
unsigned int read_ptr = async->buf_read_ptr;
|
||||||
|
|
||||||
while (nbytes) {
|
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;
|
memcpy(dest, buf_page_list[page].virt_addr + offset,
|
||||||
|
block_size);
|
||||||
if (nbytes >= async->prealloc_bufsz - read_ptr)
|
|
||||||
block_size = async->prealloc_bufsz - read_ptr;
|
|
||||||
else
|
|
||||||
block_size = nbytes;
|
|
||||||
|
|
||||||
memcpy(dest, src, block_size);
|
|
||||||
nbytes -= block_size;
|
nbytes -= block_size;
|
||||||
dest += 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;
|
goto done;
|
||||||
}
|
}
|
||||||
if (bm->dma_dir != DMA_NONE) {
|
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.
|
* Buffer pages are not contiguous, so temporarily modify VMA
|
||||||
* Address is in page_list[0].
|
* start and end addresses for each buffer page.
|
||||||
*/
|
*/
|
||||||
buf = &bm->page_list[0];
|
for (i = 0; i < n_pages; ++i) {
|
||||||
retval = dma_mmap_coherent(bm->dma_hw_dev, vma, buf->virt_addr,
|
buf = &bm->page_list[i];
|
||||||
buf->dma_addr, n_pages * PAGE_SIZE);
|
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 {
|
} else {
|
||||||
for (i = 0; i < n_pages; ++i) {
|
for (i = 0; i < n_pages; ++i) {
|
||||||
unsigned long pfn;
|
unsigned long pfn;
|
||||||
|
@ -2407,19 +2421,18 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
|
||||||
|
|
||||||
start += PAGE_SIZE;
|
start += PAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_MMU
|
#ifdef CONFIG_MMU
|
||||||
/*
|
/*
|
||||||
* Leaving behind a partial mapping of a buffer we're about to
|
* Leaving behind a partial mapping of a buffer we're about to drop is
|
||||||
* drop is unsafe, see remap_pfn_range_notrack().
|
* unsafe, see remap_pfn_range_notrack(). We need to zap the range
|
||||||
* We need to zap the range here ourselves instead of relying
|
* here ourselves instead of relying on the automatic zapping in
|
||||||
* on the automatic zapping in remap_pfn_range() because we call
|
* remap_pfn_range() because we call remap_pfn_range() in a loop.
|
||||||
* remap_pfn_range() in a loop.
|
*/
|
||||||
*/
|
if (retval)
|
||||||
if (retval)
|
zap_vma_ptes(vma, vma->vm_start, size);
|
||||||
zap_vma_ptes(vma, vma->vm_start, size);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
if (retval == 0) {
|
if (retval == 0) {
|
||||||
vma->vm_ops = &comedi_vm_ops;
|
vma->vm_ops = &comedi_vm_ops;
|
||||||
|
@ -2475,6 +2488,62 @@ done:
|
||||||
return mask;
|
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,
|
static ssize_t comedi_write(struct file *file, const char __user *buf,
|
||||||
size_t nbytes, loff_t *offset)
|
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);
|
add_wait_queue(&async->wait_head, &wait);
|
||||||
while (count == 0 && !retval) {
|
while (count == 0 && !retval) {
|
||||||
unsigned int runflags;
|
unsigned int runflags;
|
||||||
unsigned int wp, n1, n2;
|
|
||||||
|
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
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);
|
set_current_state(TASK_RUNNING);
|
||||||
wp = async->buf_write_ptr;
|
m = comedi_buf_copy_from_user(s, async->buf_write_ptr, buf, n);
|
||||||
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);
|
|
||||||
if (m) {
|
if (m) {
|
||||||
n -= m;
|
n -= m;
|
||||||
retval = -EFAULT;
|
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);
|
add_wait_queue(&async->wait_head, &wait);
|
||||||
while (count == 0 && !retval) {
|
while (count == 0 && !retval) {
|
||||||
unsigned int rp, n1, n2;
|
|
||||||
|
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
|
|
||||||
m = comedi_buf_read_n_available(s);
|
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);
|
set_current_state(TASK_RUNNING);
|
||||||
rp = async->buf_read_ptr;
|
m = comedi_buf_copy_to_user(s, buf, async->buf_read_ptr, n);
|
||||||
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);
|
|
||||||
if (m) {
|
if (m) {
|
||||||
n -= m;
|
n -= m;
|
||||||
retval = -EFAULT;
|
retval = -EFAULT;
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
* ranges).
|
* ranges).
|
||||||
*
|
*
|
||||||
* There are some hardware limitations:
|
* 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.
|
* ended inputs.
|
||||||
* b) DMA transfers must have the length aligned to two samples (32 bit),
|
* 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
|
* 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];
|
struct pci9118_dmabuf dmabuf[2];
|
||||||
int softsshdelay; /*
|
int softsshdelay; /*
|
||||||
* >0 use software S&H,
|
* >0 use software S&H,
|
||||||
* numer is requested delay in ns
|
* number is requested delay in ns
|
||||||
*/
|
*/
|
||||||
unsigned char softsshsample; /*
|
unsigned char softsshsample; /*
|
||||||
* polarity of S&H signal
|
* polarity of S&H signal
|
||||||
|
|
|
@ -215,7 +215,7 @@ static const int ni_irqpin[] = {
|
||||||
|
|
||||||
#include "ni_mio_common.c"
|
#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 = "NIC1900", .driver_data = 0},
|
||||||
{.id = "NIC2400", .driver_data = 0},
|
{.id = "NIC2400", .driver_data = 0},
|
||||||
{.id = "NIC2500", .driver_data = 0},
|
{.id = "NIC2500", .driver_data = 0},
|
||||||
|
|
|
@ -747,8 +747,6 @@ static int ni_pcidio_change(struct comedi_device *dev,
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
memset(s->async->prealloc_buf, 0xaa, s->async->prealloc_bufsz);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,22 +3,25 @@
|
||||||
* Copyright (c) 2021 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
|
* Copyright (c) 2021 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/cleanup.h>
|
||||||
#include <linux/counter.h>
|
#include <linux/counter.h>
|
||||||
#include <linux/gpio/consumer.h>
|
#include <linux/gpio/consumer.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/mod_devicetable.h>
|
#include <linux/mod_devicetable.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
#define INTERRUPT_CNT_NAME "interrupt-cnt"
|
#define INTERRUPT_CNT_NAME "interrupt-cnt"
|
||||||
|
|
||||||
struct interrupt_cnt_priv {
|
struct interrupt_cnt_priv {
|
||||||
atomic_t count;
|
atomic_long_t count;
|
||||||
struct gpio_desc *gpio;
|
struct gpio_desc *gpio;
|
||||||
int irq;
|
int irq;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
|
struct mutex lock;
|
||||||
struct counter_signal signals;
|
struct counter_signal signals;
|
||||||
struct counter_synapse synapses;
|
struct counter_synapse synapses;
|
||||||
struct counter_count cnts;
|
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 counter_device *counter = dev_id;
|
||||||
struct interrupt_cnt_priv *priv = counter_priv(counter);
|
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);
|
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);
|
struct interrupt_cnt_priv *priv = counter_priv(counter);
|
||||||
|
|
||||||
|
guard(mutex)(&priv->lock);
|
||||||
|
|
||||||
*enable = priv->enabled;
|
*enable = priv->enabled;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -51,6 +56,8 @@ static int interrupt_cnt_enable_write(struct counter_device *counter,
|
||||||
{
|
{
|
||||||
struct interrupt_cnt_priv *priv = counter_priv(counter);
|
struct interrupt_cnt_priv *priv = counter_priv(counter);
|
||||||
|
|
||||||
|
guard(mutex)(&priv->lock);
|
||||||
|
|
||||||
if (priv->enabled == enable)
|
if (priv->enabled == enable)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -89,7 +96,7 @@ static int interrupt_cnt_read(struct counter_device *counter,
|
||||||
{
|
{
|
||||||
struct interrupt_cnt_priv *priv = counter_priv(counter);
|
struct interrupt_cnt_priv *priv = counter_priv(counter);
|
||||||
|
|
||||||
*val = atomic_read(&priv->count);
|
*val = atomic_long_read(&priv->count);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -102,7 +109,7 @@ static int interrupt_cnt_write(struct counter_device *counter,
|
||||||
if (val != (typeof(priv->count.counter))val)
|
if (val != (typeof(priv->count.counter))val)
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
|
|
||||||
atomic_set(&priv->count, val);
|
atomic_long_set(&priv->count, val);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -227,6 +234,8 @@ static int interrupt_cnt_probe(struct platform_device *pdev)
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
mutex_init(&priv->lock);
|
||||||
|
|
||||||
ret = devm_counter_add(dev, counter);
|
ret = devm_counter_add(dev, counter);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return dev_err_probe(dev, ret, "Failed to add counter\n");
|
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),
|
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[] = {
|
static struct counter_count mchp_tc_counts[] = {
|
||||||
{
|
{
|
||||||
.id = 0,
|
.id = 0,
|
||||||
|
@ -356,7 +378,8 @@ static const struct counter_ops mchp_tc_ops = {
|
||||||
.function_read = mchp_tc_count_function_read,
|
.function_read = mchp_tc_count_function_read,
|
||||||
.function_write = mchp_tc_count_function_write,
|
.function_write = mchp_tc_count_function_write,
|
||||||
.action_read = mchp_tc_count_action_read,
|
.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 = {
|
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);
|
dev_dbg(dev, "has %d cc channels\n", priv->nchannels);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* encoder supported on TIM1 TIM2 TIM3 TIM4 TIM5 TIM8 */
|
/* 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))
|
#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[] = {
|
static const char * const stm32_timer_trigger_compat[] = {
|
||||||
"st,stm32-timer-trigger",
|
"st,stm32-timer-trigger",
|
||||||
"st,stm32h7-timer-trigger",
|
"st,stm32h7-timer-trigger",
|
||||||
|
"st,stm32mp25-timer-trigger",
|
||||||
};
|
};
|
||||||
|
|
||||||
static int stm32_timer_cnt_probe_encoder(struct device *dev,
|
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[] = {
|
static const struct of_device_id stm32_timer_cnt_of_match[] = {
|
||||||
{ .compatible = "st,stm32-timer-counter", },
|
{ .compatible = "st,stm32-timer-counter", },
|
||||||
|
{ .compatible = "st,stm32mp25-timer-counter", },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, stm32_timer_cnt_of_match);
|
MODULE_DEVICE_TABLE(of, stm32_timer_cnt_of_match);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
# Makefile for the Linux device tree
|
# Makefile for the Linux device tree
|
||||||
|
|
||||||
|
always-$(CONFIG_EISA) += devlist.h
|
||||||
obj-$(CONFIG_EISA) += eisa-bus.o
|
obj-$(CONFIG_EISA) += eisa-bus.o
|
||||||
obj-${CONFIG_EISA_PCI_EISA} += pci_eisa.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
|
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
|
$(obj)/eisa-bus.o: $(obj)/devlist.h
|
||||||
|
|
||||||
quiet_cmd_eisaid = GEN $@
|
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
|
clean-files := devlist.h
|
||||||
$(obj)/devlist.h: $(src)/eisa.ids include/linux/device.h
|
$(obj)/devlist.h: $(src)/eisa.ids include/linux/device.h FORCE
|
||||||
$(call cmd,eisaid)
|
$(call if_changed,eisaid)
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
struct eisa_device_info {
|
struct eisa_device_info {
|
||||||
struct eisa_device_id id;
|
struct eisa_device_id id;
|
||||||
char name[50];
|
char name[EISA_DEVICE_INFO_NAME_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_EISA_NAMES
|
#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);
|
img_buf = init_test_buffer(test, IMAGE_SIZE);
|
||||||
|
|
||||||
sgt = kunit_kzalloc(test, sizeof(*sgt), GFP_KERNEL);
|
sgt = kunit_kzalloc(test, sizeof(*sgt), GFP_KERNEL);
|
||||||
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sgt);
|
||||||
ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
|
ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
|
||||||
KUNIT_ASSERT_EQ(test, ret, 0);
|
KUNIT_ASSERT_EQ(test, ret, 0);
|
||||||
sg_init_one(sgt->sgl, img_buf, IMAGE_SIZE);
|
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
|
This driver can also be built as a module. If so, the module will
|
||||||
be called sbtsi_temp.
|
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
|
config SENSORS_SHT15
|
||||||
tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
|
tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
|
||||||
depends on GPIOLIB || COMPILE_TEST
|
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
|
To compile this driver as a module, choose M here: the module will be
|
||||||
called coresight-dummy.
|
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
|
endif
|
||||||
|
|
|
@ -22,6 +22,8 @@ condflags := \
|
||||||
$(call cc-option, -Wstringop-truncation)
|
$(call cc-option, -Wstringop-truncation)
|
||||||
subdir-ccflags-y += $(condflags)
|
subdir-ccflags-y += $(condflags)
|
||||||
|
|
||||||
|
CFLAGS_coresight-stm.o := -D__DISABLE_TRACE_MMIO__
|
||||||
|
|
||||||
obj-$(CONFIG_CORESIGHT) += coresight.o
|
obj-$(CONFIG_CORESIGHT) += coresight.o
|
||||||
coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \
|
coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \
|
||||||
coresight-sysfs.o coresight-syscfg.o coresight-config.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_DUMMY) += coresight-dummy.o
|
||||||
obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
|
obj-$(CONFIG_CORESIGHT_CTCU) += coresight-ctcu.o
|
||||||
coresight-ctcu-y := coresight-ctcu-core.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,
|
* containing the data page pointer for @offset. If @daddrp is not NULL,
|
||||||
* @daddrp points the DMA address of the beginning of the table.
|
* @daddrp points the DMA address of the beginning of the table.
|
||||||
*/
|
*/
|
||||||
static inline cate_t *catu_get_table(struct tmc_sg_table *catu_table,
|
static cate_t *catu_get_table(struct tmc_sg_table *catu_table, unsigned long offset,
|
||||||
unsigned long offset,
|
dma_addr_t *daddrp)
|
||||||
dma_addr_t *daddrp)
|
|
||||||
{
|
{
|
||||||
unsigned long buf_size = tmc_sg_table_buf_size(catu_table);
|
unsigned long buf_size = tmc_sg_table_buf_size(catu_table);
|
||||||
unsigned int table_nr, pg_idx, pg_offset;
|
unsigned int table_nr, pg_idx, pg_offset;
|
||||||
|
@ -165,12 +164,12 @@ static void catu_dump_table(struct tmc_sg_table *catu_table)
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#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
|
#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;
|
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;
|
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,
|
static int catu_enable(struct coresight_device *csdev, enum cs_mode mode,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc = 0;
|
||||||
struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
|
struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
|
||||||
|
|
||||||
CS_UNLOCK(catu_drvdata->base);
|
guard(raw_spinlock_irqsave)(&catu_drvdata->spinlock);
|
||||||
rc = catu_enable_hw(catu_drvdata, mode, data);
|
if (csdev->refcnt == 0) {
|
||||||
CS_LOCK(catu_drvdata->base);
|
CS_UNLOCK(catu_drvdata->base);
|
||||||
|
rc = catu_enable_hw(catu_drvdata, mode, data);
|
||||||
|
CS_LOCK(catu_drvdata->base);
|
||||||
|
}
|
||||||
|
if (!rc)
|
||||||
|
csdev->refcnt++;
|
||||||
return rc;
|
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)
|
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);
|
struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
|
||||||
|
|
||||||
CS_UNLOCK(catu_drvdata->base);
|
guard(raw_spinlock_irqsave)(&catu_drvdata->spinlock);
|
||||||
rc = catu_disable_hw(catu_drvdata);
|
if (--csdev->refcnt == 0) {
|
||||||
CS_LOCK(catu_drvdata->base);
|
CS_UNLOCK(catu_drvdata->base);
|
||||||
|
rc = catu_disable_hw(catu_drvdata);
|
||||||
|
CS_LOCK(catu_drvdata->base);
|
||||||
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,6 +557,7 @@ static int __catu_probe(struct device *dev, struct resource *res)
|
||||||
dev->platform_data = pdata;
|
dev->platform_data = pdata;
|
||||||
|
|
||||||
drvdata->base = base;
|
drvdata->base = base;
|
||||||
|
raw_spin_lock_init(&drvdata->spinlock);
|
||||||
catu_desc.access = CSDEV_ACCESS_IOMEM(base);
|
catu_desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||||
catu_desc.pdata = pdata;
|
catu_desc.pdata = pdata;
|
||||||
catu_desc.dev = dev;
|
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.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CATU;
|
||||||
catu_desc.ops = &catu_ops;
|
catu_desc.ops = &catu_ops;
|
||||||
|
|
||||||
|
coresight_clear_self_claim_tag(&catu_desc.access);
|
||||||
drvdata->csdev = coresight_register(&catu_desc);
|
drvdata->csdev = coresight_register(&catu_desc);
|
||||||
if (IS_ERR(drvdata->csdev))
|
if (IS_ERR(drvdata->csdev))
|
||||||
ret = PTR_ERR(drvdata->csdev);
|
ret = PTR_ERR(drvdata->csdev);
|
||||||
|
@ -702,7 +711,7 @@ static int __init catu_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
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);
|
tmc_etr_set_catu_ops(&etr_catu_buf_ops);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,7 @@ struct catu_drvdata {
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
struct coresight_device *csdev;
|
struct coresight_device *csdev;
|
||||||
int irq;
|
int irq;
|
||||||
|
raw_spinlock_t spinlock;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CATU_REG32(name, offset) \
|
#define CATU_REG32(name, offset) \
|
||||||
|
|
|
@ -228,7 +228,7 @@ struct cscfg_feature_csdev {
|
||||||
* @feats_csdev:references to the device features to enable.
|
* @feats_csdev:references to the device features to enable.
|
||||||
*/
|
*/
|
||||||
struct cscfg_config_csdev {
|
struct cscfg_config_csdev {
|
||||||
const struct cscfg_config_desc *config_desc;
|
struct cscfg_config_desc *config_desc;
|
||||||
struct coresight_device *csdev;
|
struct coresight_device *csdev;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
struct list_head node;
|
struct list_head node;
|
||||||
|
|
|
@ -129,34 +129,36 @@ coresight_find_out_connection(struct coresight_device *csdev,
|
||||||
return ERR_PTR(-ENODEV);
|
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)
|
static void coresight_set_self_claim_tag_unlocked(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)
|
|
||||||
{
|
{
|
||||||
csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
|
csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
|
||||||
CORESIGHT_CLAIMSET);
|
CORESIGHT_CLAIMSET);
|
||||||
isb();
|
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);
|
CORESIGHT_CLAIMCLR);
|
||||||
isb();
|
isb();
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(coresight_clear_self_claim_tag_unlocked);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* coresight_claim_device_unlocked : Claim the device for self-hosted usage
|
* 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 coresight_claim_device_unlocked(struct coresight_device *csdev)
|
||||||
{
|
{
|
||||||
|
int tag;
|
||||||
|
struct csdev_access *csa;
|
||||||
|
|
||||||
if (WARN_ON(!csdev))
|
if (WARN_ON(!csdev))
|
||||||
return -EINVAL;
|
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;
|
return -EBUSY;
|
||||||
|
|
||||||
coresight_set_claim_tags(csdev);
|
case CORESIGHT_CLAIM_EXTERNAL:
|
||||||
if (coresight_is_claimed_self_hosted(csdev))
|
/* External debug is an expected state, so log and report BUSY */
|
||||||
return 0;
|
dev_dbg(&csdev->dev, "Busy: Claimed by external debugger");
|
||||||
/* There was a race setting the tags, clean up and fail */
|
return -EBUSY;
|
||||||
coresight_clear_claim_tags(csdev);
|
|
||||||
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);
|
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);
|
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.
|
* Called with CS_UNLOCKed for the component.
|
||||||
*/
|
*/
|
||||||
void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
|
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))
|
if (WARN_ON(!csdev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (coresight_is_claimed_self_hosted(csdev))
|
if (coresight_read_claim_tags_unlocked(csdev) == CORESIGHT_CLAIM_SELF_HOSTED)
|
||||||
coresight_clear_claim_tags(csdev);
|
coresight_clear_self_claim_tag_unlocked(&csdev->access);
|
||||||
else
|
else
|
||||||
/*
|
/*
|
||||||
* The external agent may have not honoured our claim
|
* The external agent may have not honoured our claim
|
||||||
* and has manipulated it. Or something else has seriously
|
* and has manipulated it. Or something else has seriously
|
||||||
* gone wrong in our driver.
|
* 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);
|
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);
|
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
|
* 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
|
* @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 */
|
/* Enable all helpers adjacent to the path first */
|
||||||
ret = coresight_enable_helpers(csdev, mode, path);
|
ret = coresight_enable_helpers(csdev, mode, path);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err_disable_path;
|
||||||
/*
|
/*
|
||||||
* ETF devices are tricky... They can be a link or a sink,
|
* ETF devices are tricky... They can be a link or a sink,
|
||||||
* depending on how they are configured. If an ETF has been
|
* 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
|
* that need disabling. Disabling the path here
|
||||||
* would mean we could disrupt an existing session.
|
* would mean we could disrupt an existing session.
|
||||||
*/
|
*/
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
coresight_disable_helpers(csdev, path);
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CORESIGHT_DEV_TYPE_SOURCE:
|
case CORESIGHT_DEV_TYPE_SOURCE:
|
||||||
/* sources are enabled from either sysFS or Perf */
|
/* 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;
|
child = list_next_entry(nd, link)->csdev;
|
||||||
ret = coresight_enable_link(csdev, parent, child, source);
|
ret = coresight_enable_link(csdev, parent, child, source);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err_disable_helpers;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto err;
|
ret = -EINVAL;
|
||||||
|
goto err_disable_helpers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
err:
|
err_disable_helpers:
|
||||||
|
coresight_disable_helpers(csdev, path);
|
||||||
|
err_disable_path:
|
||||||
coresight_disable_path_from(path, nd);
|
coresight_disable_path_from(path, nd);
|
||||||
goto out;
|
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 true in successful case and power up the device.
|
||||||
* Return false when failed to get reference of module.
|
* 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;
|
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.
|
* @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;
|
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 */
|
/* 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 */
|
/* sink & correct subtype */
|
||||||
if (((csdev->type == CORESIGHT_DEV_TYPE_SINK) ||
|
if (((csdev->type == CORESIGHT_DEV_TYPE_SINK) ||
|
||||||
|
@ -959,6 +1011,7 @@ coresight_find_default_sink(struct coresight_device *csdev)
|
||||||
}
|
}
|
||||||
return csdev->def_sink;
|
return csdev->def_sink;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(coresight_find_default_sink);
|
||||||
|
|
||||||
static int coresight_remove_sink_ref(struct device *dev, void *data)
|
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.
|
* Returns the index of the entry, when found. Otherwise, -ENOENT.
|
||||||
*/
|
*/
|
||||||
static inline int coresight_search_device_idx(struct coresight_dev_list *dict,
|
static int coresight_search_device_idx(struct coresight_dev_list *dict,
|
||||||
struct fwnode_handle *fwnode)
|
struct fwnode_handle *fwnode)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -1585,17 +1638,17 @@ module_init(coresight_init);
|
||||||
module_exit(coresight_exit);
|
module_exit(coresight_exit);
|
||||||
|
|
||||||
int coresight_init_driver(const char *drv, struct amba_driver *amba_drv,
|
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;
|
int ret;
|
||||||
|
|
||||||
ret = amba_driver_register(amba_drv);
|
ret = __amba_driver_register(amba_drv, owner);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("%s: error registering AMBA driver\n", drv);
|
pr_err("%s: error registering AMBA driver\n", drv);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = platform_driver_register(pdev_drv);
|
ret = __platform_driver_register(pdev_drv, owner);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -774,7 +774,8 @@ static struct platform_driver debug_platform_driver = {
|
||||||
|
|
||||||
static int __init debug_init(void)
|
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)
|
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.ops = &cti_ops;
|
||||||
cti_desc.groups = drvdata->ctidev.con_groups;
|
cti_desc.groups = drvdata->ctidev.con_groups;
|
||||||
cti_desc.dev = dev;
|
cti_desc.dev = dev;
|
||||||
|
|
||||||
|
coresight_clear_self_claim_tag(&cti_desc.access);
|
||||||
drvdata->csdev = coresight_register(&cti_desc);
|
drvdata->csdev = coresight_register(&cti_desc);
|
||||||
if (IS_ERR(drvdata->csdev)) {
|
if (IS_ERR(drvdata->csdev)) {
|
||||||
ret = PTR_ERR(drvdata->csdev);
|
ret = PTR_ERR(drvdata->csdev);
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
#include <linux/coresight.h>
|
#include <linux/coresight.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/fwnode.h>
|
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/sysfs.h>
|
#include <linux/sysfs.h>
|
||||||
|
@ -17,6 +16,8 @@
|
||||||
|
|
||||||
#include "coresight-priv.h"
|
#include "coresight-priv.h"
|
||||||
|
|
||||||
|
struct fwnode_handle;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Device registers
|
* Device registers
|
||||||
* 0x000 - 0x144: CTI programming and status
|
* 0x000 - 0x144: CTI programming and status
|
||||||
|
|
|
@ -95,7 +95,7 @@ struct etb_drvdata {
|
||||||
static int etb_set_buffer(struct coresight_device *csdev,
|
static int etb_set_buffer(struct coresight_device *csdev,
|
||||||
struct perf_output_handle *handle);
|
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);
|
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.pdata = pdata;
|
||||||
desc.dev = dev;
|
desc.dev = dev;
|
||||||
desc.groups = coresight_etb_groups;
|
desc.groups = coresight_etb_groups;
|
||||||
|
|
||||||
|
coresight_clear_self_claim_tag(&desc.access);
|
||||||
drvdata->csdev = coresight_register(&desc);
|
drvdata->csdev = coresight_register(&desc);
|
||||||
if (IS_ERR(drvdata->csdev))
|
if (IS_ERR(drvdata->csdev))
|
||||||
return PTR_ERR(drvdata->csdev);
|
return PTR_ERR(drvdata->csdev);
|
||||||
|
|
|
@ -365,6 +365,18 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
|
||||||
continue;
|
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,
|
* No sink provided - look for a default sink for all the ETMs,
|
||||||
* where this event can be scheduled.
|
* where this event can be scheduled.
|
||||||
|
@ -450,6 +462,15 @@ err:
|
||||||
goto out;
|
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)
|
static void etm_event_start(struct perf_event *event, int flags)
|
||||||
{
|
{
|
||||||
int cpu = smp_processor_id();
|
int cpu = smp_processor_id();
|
||||||
|
@ -463,6 +484,14 @@ static void etm_event_start(struct perf_event *event, int flags)
|
||||||
if (!csdev)
|
if (!csdev)
|
||||||
goto fail;
|
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 ? */
|
/* Have we messed up our tracking ? */
|
||||||
if (WARN_ON(ctxt->event_data))
|
if (WARN_ON(ctxt->event_data))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -545,6 +574,55 @@ fail:
|
||||||
return;
|
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)
|
static void etm_event_stop(struct perf_event *event, int mode)
|
||||||
{
|
{
|
||||||
int cpu = smp_processor_id();
|
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 etm_event_data *event_data;
|
||||||
struct coresight_path *path;
|
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,
|
* If we still have access to the event_data via handle,
|
||||||
* confirm that we haven't messed up the tracking.
|
* confirm that we haven't messed up the tracking.
|
||||||
|
@ -899,7 +980,8 @@ int __init etm_perf_init(void)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
etm_pmu.capabilities = (PERF_PMU_CAP_EXCLUSIVE |
|
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.attr_groups = etm_pmu_attr_groups;
|
||||||
etm_pmu.task_ctx_nr = perf_sw_context;
|
etm_pmu.task_ctx_nr = perf_sw_context;
|
||||||
|
|
|
@ -229,7 +229,7 @@ struct etm_config {
|
||||||
* @config: structure holding configuration parameters.
|
* @config: structure holding configuration parameters.
|
||||||
*/
|
*/
|
||||||
struct etm_drvdata {
|
struct etm_drvdata {
|
||||||
void __iomem *base;
|
struct csdev_access csa;
|
||||||
struct clk *atclk;
|
struct clk *atclk;
|
||||||
struct coresight_device *csdev;
|
struct coresight_device *csdev;
|
||||||
spinlock_t spinlock;
|
spinlock_t spinlock;
|
||||||
|
@ -260,7 +260,7 @@ static inline void etm_writel(struct etm_drvdata *drvdata,
|
||||||
"invalid CP14 access to ETM reg: %#x", off);
|
"invalid CP14 access to ETM reg: %#x", off);
|
||||||
}
|
}
|
||||||
} else {
|
} 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);
|
"invalid CP14 access to ETM reg: %#x", off);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val = readl_relaxed(drvdata->base + off);
|
val = readl_relaxed(drvdata->csa.base + off);
|
||||||
}
|
}
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
|
|
|
@ -86,9 +86,9 @@ static void etm_set_pwrup(struct etm_drvdata *drvdata)
|
||||||
{
|
{
|
||||||
u32 etmpdcr;
|
u32 etmpdcr;
|
||||||
|
|
||||||
etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);
|
etmpdcr = readl_relaxed(drvdata->csa.base + ETMPDCR);
|
||||||
etmpdcr |= ETMPDCR_PWD_UP;
|
etmpdcr |= ETMPDCR_PWD_UP;
|
||||||
writel_relaxed(etmpdcr, drvdata->base + ETMPDCR);
|
writel_relaxed(etmpdcr, drvdata->csa.base + ETMPDCR);
|
||||||
/* Ensure pwrup completes before subsequent cp14 accesses */
|
/* Ensure pwrup completes before subsequent cp14 accesses */
|
||||||
mb();
|
mb();
|
||||||
isb();
|
isb();
|
||||||
|
@ -101,9 +101,9 @@ static void etm_clr_pwrup(struct etm_drvdata *drvdata)
|
||||||
/* Ensure pending cp14 accesses complete before clearing pwrup */
|
/* Ensure pending cp14 accesses complete before clearing pwrup */
|
||||||
mb();
|
mb();
|
||||||
isb();
|
isb();
|
||||||
etmpdcr = readl_relaxed(drvdata->base + ETMPDCR);
|
etmpdcr = readl_relaxed(drvdata->csa.base + ETMPDCR);
|
||||||
etmpdcr &= ~ETMPDCR_PWD_UP;
|
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 etm_config *config = &drvdata->config;
|
||||||
struct coresight_device *csdev = drvdata->csdev;
|
struct coresight_device *csdev = drvdata->csdev;
|
||||||
|
|
||||||
CS_UNLOCK(drvdata->base);
|
CS_UNLOCK(drvdata->csa.base);
|
||||||
|
|
||||||
rc = coresight_claim_device_unlocked(csdev);
|
rc = coresight_claim_device_unlocked(csdev);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
@ -427,7 +427,7 @@ static int etm_enable_hw(struct etm_drvdata *drvdata)
|
||||||
etm_clr_prog(drvdata);
|
etm_clr_prog(drvdata);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
CS_LOCK(drvdata->base);
|
CS_LOCK(drvdata->csa.base);
|
||||||
|
|
||||||
dev_dbg(&drvdata->csdev->dev, "cpu: %d enable smp call done: %d\n",
|
dev_dbg(&drvdata->csdev->dev, "cpu: %d enable smp call done: %d\n",
|
||||||
drvdata->cpu, rc);
|
drvdata->cpu, rc);
|
||||||
|
@ -549,7 +549,7 @@ static void etm_disable_hw(void *info)
|
||||||
struct etm_config *config = &drvdata->config;
|
struct etm_config *config = &drvdata->config;
|
||||||
struct coresight_device *csdev = drvdata->csdev;
|
struct coresight_device *csdev = drvdata->csdev;
|
||||||
|
|
||||||
CS_UNLOCK(drvdata->base);
|
CS_UNLOCK(drvdata->csa.base);
|
||||||
etm_set_prog(drvdata);
|
etm_set_prog(drvdata);
|
||||||
|
|
||||||
/* Read back sequencer and counters for post trace analysis */
|
/* Read back sequencer and counters for post trace analysis */
|
||||||
|
@ -561,7 +561,7 @@ static void etm_disable_hw(void *info)
|
||||||
etm_set_pwrdwn(drvdata);
|
etm_set_pwrdwn(drvdata);
|
||||||
coresight_disclaim_device_unlocked(csdev);
|
coresight_disclaim_device_unlocked(csdev);
|
||||||
|
|
||||||
CS_LOCK(drvdata->base);
|
CS_LOCK(drvdata->csa.base);
|
||||||
|
|
||||||
dev_dbg(&drvdata->csdev->dev,
|
dev_dbg(&drvdata->csdev->dev,
|
||||||
"cpu: %d disable smp call done\n", drvdata->cpu);
|
"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()))
|
if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CS_UNLOCK(drvdata->base);
|
CS_UNLOCK(drvdata->csa.base);
|
||||||
|
|
||||||
/* Setting the prog bit disables tracing immediately */
|
/* Setting the prog bit disables tracing immediately */
|
||||||
etm_set_prog(drvdata);
|
etm_set_prog(drvdata);
|
||||||
|
@ -586,7 +586,7 @@ static void etm_disable_perf(struct coresight_device *csdev)
|
||||||
etm_set_pwrdwn(drvdata);
|
etm_set_pwrdwn(drvdata);
|
||||||
coresight_disclaim_device_unlocked(csdev);
|
coresight_disclaim_device_unlocked(csdev);
|
||||||
|
|
||||||
CS_LOCK(drvdata->base);
|
CS_LOCK(drvdata->csa.base);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* perf will release trace ids when _free_aux()
|
* 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 */
|
/* Make sure all registers are accessible */
|
||||||
etm_os_unlock(drvdata);
|
etm_os_unlock(drvdata);
|
||||||
|
|
||||||
CS_UNLOCK(drvdata->base);
|
CS_UNLOCK(drvdata->csa.base);
|
||||||
|
|
||||||
/* First dummy read */
|
/* First dummy read */
|
||||||
(void)etm_readl(drvdata, ETMPDSR);
|
(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_ext_out = BMVAL(etmccr, 20, 22);
|
||||||
drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
|
drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
|
||||||
|
|
||||||
|
coresight_clear_self_claim_tag_unlocked(&drvdata->csa);
|
||||||
etm_set_pwrdwn(drvdata);
|
etm_set_pwrdwn(drvdata);
|
||||||
etm_clr_pwrup(drvdata);
|
etm_clr_pwrup(drvdata);
|
||||||
CS_LOCK(drvdata->base);
|
CS_LOCK(drvdata->csa.base);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init etm_hp_setup(void)
|
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))
|
if (IS_ERR(base))
|
||||||
return PTR_ERR(base);
|
return PTR_ERR(base);
|
||||||
|
|
||||||
drvdata->base = base;
|
desc.access = drvdata->csa = CSDEV_ACCESS_IOMEM(base);
|
||||||
desc.access = CSDEV_ACCESS_IOMEM(base);
|
|
||||||
|
|
||||||
spin_lock_init(&drvdata->spinlock);
|
spin_lock_init(&drvdata->spinlock);
|
||||||
|
|
||||||
|
|
|
@ -50,11 +50,11 @@ static ssize_t etmsr_show(struct device *dev,
|
||||||
|
|
||||||
pm_runtime_get_sync(dev->parent);
|
pm_runtime_get_sync(dev->parent);
|
||||||
spin_lock_irqsave(&drvdata->spinlock, flags);
|
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||||
CS_UNLOCK(drvdata->base);
|
CS_UNLOCK(drvdata->csa.base);
|
||||||
|
|
||||||
val = etm_readl(drvdata, ETMSR);
|
val = etm_readl(drvdata, ETMSR);
|
||||||
|
|
||||||
CS_LOCK(drvdata->base);
|
CS_LOCK(drvdata->csa.base);
|
||||||
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||||
pm_runtime_put(dev->parent);
|
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);
|
pm_runtime_get_sync(dev->parent);
|
||||||
spin_lock_irqsave(&drvdata->spinlock, flags);
|
spin_lock_irqsave(&drvdata->spinlock, flags);
|
||||||
|
|
||||||
CS_UNLOCK(drvdata->base);
|
CS_UNLOCK(drvdata->csa.base);
|
||||||
val = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK);
|
val = (etm_readl(drvdata, ETMSQR) & ETM_SQR_MASK);
|
||||||
CS_LOCK(drvdata->base);
|
CS_LOCK(drvdata->csa.base);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
spin_unlock_irqrestore(&drvdata->spinlock, flags);
|
||||||
pm_runtime_put(dev->parent);
|
pm_runtime_put(dev->parent);
|
||||||
|
|
|
@ -84,7 +84,7 @@ static int etm4_probe_cpu(unsigned int cpu);
|
||||||
* TRCIDR4.NUMPC > 0b0000 .
|
* TRCIDR4.NUMPC > 0b0000 .
|
||||||
* TRCSSCSR<n>.PC == 0b1
|
* 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) &&
|
return (n < drvdata->nr_ss_cmp) &&
|
||||||
drvdata->nr_pe &&
|
drvdata->nr_pe &&
|
||||||
|
@ -185,7 +185,7 @@ static void etm_write_os_lock(struct etmv4_drvdata *drvdata,
|
||||||
isb();
|
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)
|
struct csdev_access *csa)
|
||||||
{
|
{
|
||||||
WARN_ON(drvdata->cpu != smp_processor_id());
|
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);
|
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)
|
static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
|
||||||
{
|
{
|
||||||
int i, rc;
|
int i, rc;
|
||||||
|
@ -539,33 +577,8 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
|
||||||
etm4x_relaxed_write32(csa, trcpdcr | TRCPDCR_PU, TRCPDCR);
|
etm4x_relaxed_write32(csa, trcpdcr | TRCPDCR_PU, TRCPDCR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (!drvdata->paused)
|
||||||
* ETE mandates that the TRCRSR is written to before
|
rc = etm4_enable_trace_unit(drvdata);
|
||||||
* 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();
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
etm4_cs_lock(drvdata, csa);
|
etm4_cs_lock(drvdata, csa);
|
||||||
|
|
||||||
|
@ -808,6 +821,9 @@ static int etm4_enable_perf(struct coresight_device *csdev,
|
||||||
|
|
||||||
drvdata->trcid = path->trace_id;
|
drvdata->trcid = path->trace_id;
|
||||||
|
|
||||||
|
/* Populate pause state */
|
||||||
|
drvdata->paused = !!READ_ONCE(event->hw.aux_paused);
|
||||||
|
|
||||||
/* And enable it */
|
/* And enable it */
|
||||||
ret = etm4_enable_hw(drvdata);
|
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;
|
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
|
* Executing etm4_enable_hw on the cpu whose ETM is being enabled
|
||||||
* ensures that register writes occur when cpu is powered.
|
* 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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void etm4_disable_hw(void *info)
|
static void etm4_disable_trace_unit(struct etmv4_drvdata *drvdata)
|
||||||
{
|
{
|
||||||
u32 control;
|
u32 control;
|
||||||
struct etmv4_drvdata *drvdata = info;
|
|
||||||
struct etmv4_config *config = &drvdata->config;
|
|
||||||
struct coresight_device *csdev = drvdata->csdev;
|
struct coresight_device *csdev = drvdata->csdev;
|
||||||
struct device *etm_dev = &csdev->dev;
|
struct device *etm_dev = &csdev->dev;
|
||||||
struct csdev_access *csa = &csdev->access;
|
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);
|
control = etm4x_relaxed_read32(csa, TRCPRGCTLR);
|
||||||
|
|
||||||
|
@ -943,6 +949,28 @@ static void etm4_disable_hw(void *info)
|
||||||
* of ARM IHI 0064H.b.
|
* of ARM IHI 0064H.b.
|
||||||
*/
|
*/
|
||||||
isb();
|
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 */
|
/* read the status of the single shot comparators */
|
||||||
for (i = 0; i < drvdata->nr_ss_cmp; i++) {
|
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);
|
smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);
|
||||||
|
|
||||||
raw_spin_unlock(&drvdata->spinlock);
|
raw_spin_unlock(&drvdata->spinlock);
|
||||||
|
|
||||||
|
cscfg_csdev_disable_active_config(csdev);
|
||||||
|
|
||||||
cpus_read_unlock();
|
cpus_read_unlock();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1059,10 +1090,43 @@ static void etm4_disable(struct coresight_device *csdev,
|
||||||
coresight_set_mode(csdev, CS_MODE_DISABLED);
|
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 = {
|
static const struct coresight_ops_source etm4_source_ops = {
|
||||||
.cpu_id = etm4_cpu_id,
|
.cpu_id = etm4_cpu_id,
|
||||||
.enable = etm4_enable,
|
.enable = etm4_enable,
|
||||||
.disable = etm4_disable,
|
.disable = etm4_disable,
|
||||||
|
.resume_perf = etm4_resume_perf,
|
||||||
|
.pause_perf = etm4_pause_perf,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct coresight_ops etm4_cs_ops = {
|
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,
|
.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);
|
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
|
* tracing at the kernel EL and EL0, forcing to use the
|
||||||
* virtual time as the timestamp.
|
* 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_ExTRE |
|
||||||
TRFCR_EL1_E0TRE);
|
TRFCR_EL1_E0TRE);
|
||||||
|
|
||||||
|
@ -1372,11 +1436,13 @@ static void etm4_init_arch_data(void *info)
|
||||||
drvdata->nrseqstate = FIELD_GET(TRCIDR5_NUMSEQSTATE_MASK, etmidr5);
|
drvdata->nrseqstate = FIELD_GET(TRCIDR5_NUMSEQSTATE_MASK, etmidr5);
|
||||||
/* NUMCNTR, bits[30:28] number of counters available for tracing */
|
/* NUMCNTR, bits[30:28] number of counters available for tracing */
|
||||||
drvdata->nr_cntr = FIELD_GET(TRCIDR5_NUMCNTR_MASK, etmidr5);
|
drvdata->nr_cntr = FIELD_GET(TRCIDR5_NUMCNTR_MASK, etmidr5);
|
||||||
|
|
||||||
|
coresight_clear_self_claim_tag_unlocked(csa);
|
||||||
etm4_cs_lock(drvdata, csa);
|
etm4_cs_lock(drvdata, csa);
|
||||||
cpu_detect_trace_filtering(drvdata);
|
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);
|
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;
|
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_VIRTUAL:
|
||||||
case TRFCR_EL1_TS_GUEST_PHYSICAL:
|
case TRFCR_EL1_TS_GUEST_PHYSICAL:
|
||||||
case TRFCR_EL1_TS_PHYSICAL:
|
case TRFCR_EL1_TS_PHYSICAL:
|
||||||
val = FIELD_GET(TRFCR_EL1_TS_MASK, drvdata->trfcr);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
val = -1;
|
val = -1;
|
||||||
|
@ -2440,7 +2440,7 @@ static u32 etmv4_cross_read(const struct etmv4_drvdata *drvdata, u32 offset)
|
||||||
return reg.data;
|
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;
|
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);
|
return scnprintf(buf, PAGE_SIZE, "0x%x\n", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
static bool
|
||||||
etm4x_register_implemented(struct etmv4_drvdata *drvdata, u32 offset)
|
etm4x_register_implemented(struct etmv4_drvdata *drvdata, u32 offset)
|
||||||
{
|
{
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
|
|
|
@ -983,6 +983,7 @@ struct etmv4_save_state {
|
||||||
* @state_needs_restore: True when there is context to restore after PM exit
|
* @state_needs_restore: True when there is context to restore after PM exit
|
||||||
* @skip_power_up: Indicates if an implementation can skip powering up
|
* @skip_power_up: Indicates if an implementation can skip powering up
|
||||||
* the trace unit.
|
* the trace unit.
|
||||||
|
* @paused: Indicates if the trace unit is paused.
|
||||||
* @arch_features: Bitmap of arch features of etmv4 devices.
|
* @arch_features: Bitmap of arch features of etmv4 devices.
|
||||||
*/
|
*/
|
||||||
struct etmv4_drvdata {
|
struct etmv4_drvdata {
|
||||||
|
@ -1036,6 +1037,7 @@ struct etmv4_drvdata {
|
||||||
struct etmv4_save_state *save_state;
|
struct etmv4_save_state *save_state;
|
||||||
bool state_needs_restore;
|
bool state_needs_restore;
|
||||||
bool skip_power_up;
|
bool skip_power_up;
|
||||||
|
bool paused;
|
||||||
DECLARE_BITMAP(arch_features, ETM4_IMPDEF_FEATURE_MAX);
|
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;
|
drvdata->base = base;
|
||||||
desc.groups = coresight_funnel_groups;
|
desc.groups = coresight_funnel_groups;
|
||||||
desc.access = CSDEV_ACCESS_IOMEM(base);
|
desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||||
|
coresight_clear_self_claim_tag(&desc.access);
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_set_drvdata(dev, drvdata);
|
dev_set_drvdata(dev, drvdata);
|
||||||
|
@ -433,7 +434,8 @@ static struct amba_driver dynamic_funnel_driver = {
|
||||||
|
|
||||||
static int __init funnel_init(void)
|
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)
|
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);
|
EXPORT_SYMBOL_GPL(coresight_find_csdev_by_fwnode);
|
||||||
|
|
||||||
#ifdef CONFIG_OF
|
#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");
|
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;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct device_node *
|
static struct device_node *
|
||||||
of_coresight_get_output_ports_node(const struct device_node *node)
|
of_coresight_get_output_ports_node(const struct device_node *node)
|
||||||
{
|
{
|
||||||
return of_get_child_by_name(node, "out-ports");
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline int
|
static int
|
||||||
of_get_coresight_platform_data(struct device *dev,
|
of_get_coresight_platform_data(struct device *dev,
|
||||||
struct coresight_platform_data *pdata)
|
struct coresight_platform_data *pdata)
|
||||||
{
|
{
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int of_coresight_get_cpu(struct device *dev)
|
static int of_coresight_get_cpu(struct device *dev)
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
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_SLAVE 0
|
||||||
#define ACPI_CORESIGHT_LINK_MASTER 1
|
#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);
|
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
|
* acpi_guid_matches - Checks if the given object is a GUID object and
|
||||||
* that it matches the supplied the GUID.
|
* 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)
|
const guid_t *guid)
|
||||||
{
|
{
|
||||||
return is_acpi_guid(obj) &&
|
return is_acpi_guid(obj) &&
|
||||||
guid_equal((guid_t *)obj->buffer.pointer, guid);
|
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);
|
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);
|
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;
|
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
|
* }, // 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;
|
int i, n;
|
||||||
const union acpi_object *rev, *nr_graphs;
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
static bool
|
||||||
acpi_validate_coresight_graph(const union acpi_object *cs_graph)
|
acpi_validate_coresight_graph(const union acpi_object *cs_graph)
|
||||||
{
|
{
|
||||||
int nlinks;
|
int nlinks;
|
||||||
|
@ -794,14 +794,14 @@ acpi_get_coresight_platform_data(struct device *dev,
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static inline int
|
static int
|
||||||
acpi_get_coresight_platform_data(struct device *dev,
|
acpi_get_coresight_platform_data(struct device *dev,
|
||||||
struct coresight_platform_data *pdata)
|
struct coresight_platform_data *pdata)
|
||||||
{
|
{
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int acpi_coresight_get_cpu(struct device *dev)
|
static int acpi_coresight_get_cpu(struct device *dev)
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,11 @@ extern const struct device_type coresight_dev_type[];
|
||||||
* Coresight device CLAIM protocol.
|
* Coresight device CLAIM protocol.
|
||||||
* See PSCI - ARM DEN 0022D, Section: 6.8.1 Debug and Trace save and restore.
|
* 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 TIMEOUT_US 100
|
||||||
#define BMVAL(val, lsb, msb) ((val & GENMASK(msb, lsb)) >> lsb)
|
#define BMVAL(val, lsb, msb) ((val & GENMASK(msb, lsb)) >> lsb)
|
||||||
|
@ -56,10 +60,8 @@ struct cs_off_attribute {
|
||||||
u32 off;
|
u32 off;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ssize_t coresight_simple_show32(struct device *_dev,
|
ssize_t coresight_simple_show32(struct device *_dev, struct device_attribute *attr, char *buf);
|
||||||
struct device_attribute *attr, char *buf);
|
ssize_t coresight_simple_show_pair(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);
|
|
||||||
|
|
||||||
#define coresight_simple_reg32(name, offset) \
|
#define coresight_simple_reg32(name, offset) \
|
||||||
(&((struct cs_off_attribute[]) { \
|
(&((struct cs_off_attribute[]) { \
|
||||||
|
@ -156,8 +158,8 @@ void coresight_path_assign_trace_id(struct coresight_path *path,
|
||||||
enum cs_mode mode);
|
enum cs_mode mode);
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X)
|
#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM3X)
|
||||||
extern int etm_readl_cp14(u32 off, unsigned int *val);
|
int etm_readl_cp14(u32 off, unsigned int *val);
|
||||||
extern int etm_writel_cp14(u32 off, u32 val);
|
int etm_writel_cp14(u32 off, u32 val);
|
||||||
#else
|
#else
|
||||||
static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; }
|
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; }
|
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);
|
void (*remove)(struct coresight_device *csdev);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void coresight_set_cti_ops(const struct cti_assoc_op *cti_op);
|
void coresight_set_cti_ops(const struct cti_assoc_op *cti_op);
|
||||||
extern void coresight_remove_cti_ops(void);
|
void coresight_remove_cti_ops(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Macros and inline functions to handle CoreSight UCI data and driver
|
* 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);
|
void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev);
|
||||||
struct coresight_device *coresight_get_percpu_sink(int cpu);
|
struct coresight_device *coresight_get_percpu_sink(int cpu);
|
||||||
void coresight_disable_source(struct coresight_device *csdev, void *data);
|
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
|
#endif
|
||||||
|
|
|
@ -63,7 +63,7 @@ static void dynamic_replicator_reset(struct replicator_drvdata *drvdata)
|
||||||
/*
|
/*
|
||||||
* replicator_reset : Reset the replicator configuration to sane values.
|
* 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)
|
if (drvdata->base)
|
||||||
dynamic_replicator_reset(drvdata);
|
dynamic_replicator_reset(drvdata);
|
||||||
|
@ -262,6 +262,7 @@ static int replicator_probe(struct device *dev, struct resource *res)
|
||||||
drvdata->base = base;
|
drvdata->base = base;
|
||||||
desc.groups = replicator_groups;
|
desc.groups = replicator_groups;
|
||||||
desc.access = CSDEV_ACCESS_IOMEM(base);
|
desc.access = CSDEV_ACCESS_IOMEM(base);
|
||||||
|
coresight_clear_self_claim_tag(&desc.access);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fwnode_property_present(dev_fwnode(dev),
|
if (fwnode_property_present(dev_fwnode(dev),
|
||||||
|
@ -438,7 +439,8 @@ static struct amba_driver dynamic_replicator_driver = {
|
||||||
|
|
||||||
static int __init replicator_init(void)
|
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)
|
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