mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
ASoC: Updates for v7.2
There's been quite a lot of framework improvements this time around,
though mainly cleanups and robustness rather than user visible features.
The same pattern is seen with a lot of the driver work that's going on,
there are new features but a huge proportion of this is bug fixing and
cleanup work. We also have a good selectio of new device support.
- Improvements to SDCA jack handling from Charles Keepax.
- Use of device links to make suspend handling more robust from Richard
Fitzgerald.
- Use of a new helper to factor out a common pattern in SoundWire
enmeration from Charles Keepax.
- Slimming down of the component from Kuninori Morimoto.
- Simplification of format auto selection from Kuninori Morimoto.
- Lots of conversions to guard() from Bui Duc Phuc.
- Addition of a simple-amplifier driver supporting more featureful GPIO
controller amplifiers than the previous basic driver from Herve
Codina.
- Support for AMD ACP 7.x, Cirrus Logic CS42448/CS42888, Everest Semi
ES9356, Mediatek MT2701 and MT8196, Renesas RZ/G3E, Spacemit K3,
Texas Instruments TAC5xx2 and TAS67524.
-----BEGIN PGP SIGNATURE-----
iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmov9IgACgkQJNaLcl1U
h9BOYQf/fLQJlwAIQJu540syYQL9N7Lz/+6f41WEAeF86npaz1wvggwX7rWsOlCB
f+6bGiQ/QvYGrDlKBoIRvbrcUosYo5RcPveBhLUeYQ6w2wyhYR5bjF77YMFHHIWm
h+8wG4Cf59SnAvQ2sdctcKgaCbnJgN8IfTIhdGDQwDi2vf9AUO7o4pfKXO/wligq
4vBeuFLM+WgU5x0VhvwIU6yfa8MGSMvf/oX0bn3xYjOp2LyHzdfRGvoY/wa+6pFd
9QX2QsU6Yjrt5/zvuENwOq+nb3NbdDDqdQK8PRDnzYsbhpFj1RA5XRVShhk89h3F
TZyRqht++Vfs0b3CNW1Q59XZgxNX8A==
=3lzj
-----END PGP SIGNATURE-----
Merge tag 'asoc-v7.2' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v7.2
There's been quite a lot of framework improvements this time around,
though mainly cleanups and robustness rather than user visible features.
The same pattern is seen with a lot of the driver work that's going on,
there are new features but a huge proportion of this is bug fixing and
cleanup work. We also have a good selectio of new device support.
- Improvements to SDCA jack handling from Charles Keepax.
- Use of device links to make suspend handling more robust from Richard
Fitzgerald.
- Use of a new helper to factor out a common pattern in SoundWire
enmeration from Charles Keepax.
- Slimming down of the component from Kuninori Morimoto.
- Simplification of format auto selection from Kuninori Morimoto.
- Lots of conversions to guard() from Bui Duc Phuc.
- Addition of a simple-amplifier driver supporting more featureful GPIO
controller amplifiers than the previous basic driver from Herve
Codina.
- Support for AMD ACP 7.x, Cirrus Logic CS42448/CS42888, Everest Semi
ES9356, Mediatek MT2701 and MT8196, Renesas RZ/G3E, Spacemit K3,
Texas Instruments TAC5xx2 and TAS67524.
This commit is contained in:
commit
c5e90e8844
|
|
@ -30,6 +30,16 @@ properties:
|
|||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- const: core
|
||||
- const: iface
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
operating-points-v2: true
|
||||
|
|
@ -44,6 +54,25 @@ required:
|
|||
|
||||
additionalProperties: false
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- qcom,eliza-inline-crypto-engine
|
||||
- qcom,milos-inline-crypto-engine
|
||||
|
||||
then:
|
||||
required:
|
||||
- power-domains
|
||||
- clock-names
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 2
|
||||
clock-names:
|
||||
minItems: 2
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,sm8550-gcc.h>
|
||||
|
|
@ -52,7 +81,11 @@ examples:
|
|||
compatible = "qcom,sm8550-inline-crypto-engine",
|
||||
"qcom,inline-crypto-engine";
|
||||
reg = <0x01d88000 0x8000>;
|
||||
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
|
||||
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>,
|
||||
<&gcc GCC_UFS_PHY_AHB_CLK>;
|
||||
clock-names = "core",
|
||||
"iface";
|
||||
power-domains = <&gcc UFS_PHY_GDSC>;
|
||||
|
||||
operating-points-v2 = <&ice_opp_table>;
|
||||
|
||||
|
|
|
|||
|
|
@ -84,7 +84,8 @@ properties:
|
|||
This reference is provided for background information only.
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
items:
|
||||
- items:
|
||||
- minItems: 4
|
||||
items:
|
||||
- description: Phandle to HSP(High-Speed Peripheral) device
|
||||
- description: Offset of phy control register for internal
|
||||
or external clock selection
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
Bindings for I2S controller built into xtfpga Xtensa bitstreams.
|
||||
|
||||
Required properties:
|
||||
- compatible: shall be "cdns,xtfpga-i2s".
|
||||
- reg: memory region (address and length) with device registers.
|
||||
- interrupts: interrupt for the device.
|
||||
- clocks: phandle to the clk used as master clock. I2S bus clock
|
||||
is derived from it.
|
||||
|
||||
Examples:
|
||||
|
||||
i2s0: xtfpga-i2s@d080000 {
|
||||
#sound-dai-cells = <0>;
|
||||
compatible = "cdns,xtfpga-i2s";
|
||||
reg = <0x0d080000 0x40>;
|
||||
interrupts = <2 1>;
|
||||
clocks = <&cdce706 4>;
|
||||
};
|
||||
48
Documentation/devicetree/bindings/sound/cdns,xtfpga-i2s.yaml
Normal file
48
Documentation/devicetree/bindings/sound/cdns,xtfpga-i2s.yaml
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/cdns,xtfpga-i2s.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: I2S controller built into xtfpga Xtensa bitstreams
|
||||
|
||||
maintainers:
|
||||
- Max Filippov <jcmvbkbc@gmail.com>
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: cdns,xtfpga-i2s
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
description: phandle to the clk used as master clock. I2S bus clock is derived from it.
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2s@d080000 {
|
||||
compatible = "cdns,xtfpga-i2s";
|
||||
reg = <0x0d080000 0x40>;
|
||||
interrupts = <2 1>;
|
||||
clocks = <&cdce706 4>;
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
||||
|
|
@ -11,6 +11,7 @@ maintainers:
|
|||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
- $ref: /schemas/spi/spi-peripheral-props.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -21,6 +22,9 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
spi-max-frequency:
|
||||
maximum: 6000000
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
|
@ -86,3 +90,22 @@ examples:
|
|||
reset-gpios = <&gpio 1>;
|
||||
};
|
||||
};
|
||||
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cs-gpios = <&gpio 8 0>;
|
||||
|
||||
codec@0 {
|
||||
compatible = "cirrus,cs42888";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <6000000>;
|
||||
clocks = <&codec_mclk 0>;
|
||||
clock-names = "mclk";
|
||||
VA-supply = <®_audio>;
|
||||
VD-supply = <®_audio>;
|
||||
VLS-supply = <®_audio>;
|
||||
VLC-supply = <®_audio>;
|
||||
reset-gpios = <&gpio 1>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@ properties:
|
|||
items:
|
||||
- const: mclk
|
||||
|
||||
port:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
|
|
|
|||
|
|
@ -98,6 +98,10 @@ properties:
|
|||
- rpmsg-audio-channel
|
||||
- rpmsg-micfil-channel
|
||||
|
||||
hp-det-gpios:
|
||||
maxItems: 1
|
||||
description: The GPIO that detect headphones are plugged in
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
|
|
|
|||
|
|
@ -162,6 +162,13 @@ properties:
|
|||
of transmitter.
|
||||
type: boolean
|
||||
|
||||
fsl,sai-bit-clock-swap:
|
||||
description:
|
||||
Enable Bit Clock Swap, which swaps the bit clock used by the transmitter
|
||||
or receiver in asynchronous mode, i.e. makes transmitter use RX_BCLK and
|
||||
TX_SYNC, and vice versa, makes receiver use TX_BCLK and RX_SYNC.
|
||||
type: boolean
|
||||
|
||||
fsl,shared-interrupt:
|
||||
description: Interrupt is shared with other modules.
|
||||
type: boolean
|
||||
|
|
|
|||
270
Documentation/devicetree/bindings/sound/gpio-audio-amp.yaml
Normal file
270
Documentation/devicetree/bindings/sound/gpio-audio-amp.yaml
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/gpio-audio-amp.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Audio amplifier driven by GPIOs
|
||||
|
||||
maintainers:
|
||||
- Herve Codina <herve.codina@bootlin.com>
|
||||
|
||||
description: |
|
||||
Audio GPIO amplifiers are driven by GPIO in order to control the gain value
|
||||
of the amplifier, its mute function and/or its bypass function.
|
||||
|
||||
Those amplifiers are based on discrete components (analog switches, op-amps
|
||||
and more) where some of them, mostly analog switches, are controlled by GPIOs
|
||||
to adjust the gain value of the whole amplifier and/or to control
|
||||
the mute and/or bypass function.
|
||||
|
||||
For instance, the following piece of hardware is a GPIO amplifier
|
||||
|
||||
+5VA
|
||||
^
|
||||
|\ |
|
||||
| \
|
||||
Vin >---------------------------|+ \
|
||||
| +-------+-----> Vout
|
||||
.--\/\/\/--+------------|- / |
|
||||
| | | / |
|
||||
v | |/ | |
|
||||
GND o v |
|
||||
\ GND |
|
||||
gpio >-----------> \ |
|
||||
o o |
|
||||
| | |
|
||||
| '--\/\/\/--. |
|
||||
| +--\/\/\/--'
|
||||
'---------------'
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: gpio-audio-amp-mono
|
||||
description:
|
||||
A single channel amplifier. All features apply to this sole channel.
|
||||
|
||||
- const: gpio-audio-amp-stereo
|
||||
description:
|
||||
A dual channel amplifier (left and right). All features apply to both
|
||||
channels producing the same effect on both channels at the same time.
|
||||
|
||||
vdd-supply:
|
||||
description: Main power supply of the amplifier
|
||||
|
||||
vddio-supply:
|
||||
description: Power supply related to the control path
|
||||
|
||||
vdda1-supply:
|
||||
description: Analog power supply
|
||||
|
||||
vdda2-supply:
|
||||
description: Additional analog power supply
|
||||
|
||||
mute-gpios:
|
||||
description: GPIO to control the mute function
|
||||
maxItems: 1
|
||||
|
||||
bypass-gpios:
|
||||
description: GPIO to control the bypass function
|
||||
maxItems: 1
|
||||
|
||||
gain-gpios:
|
||||
description: |
|
||||
GPIOs to control the amplifier gain
|
||||
|
||||
The gain value is computed from GPIOs value from 0 to 2^N-1 with N the
|
||||
number of GPIO described. The first GPIO described is the lsb of the gain
|
||||
value.
|
||||
|
||||
For instance assuming 2 gpios
|
||||
gain-gpios = <&gpio1 GPIO_ACTIVE_HIGH> <&gpio2 GPIO_ACTIVE_HIGH>;
|
||||
The gain value will be the following:
|
||||
|
||||
gpio1 | gpio2 | gain
|
||||
------+-------+-----
|
||||
0 | 0 | 0b00 -> 0
|
||||
1 | 0 | 0b01 -> 1
|
||||
0 | 1 | 0b10 -> 2
|
||||
1 | 1 | 0b11 -> 3
|
||||
------+-------+-----
|
||||
|
||||
Note: The gain value, bits set to 1 or 0, indicate the state active (bit
|
||||
set) or the state inactive (bit unset) of the related GPIO. The
|
||||
physical voltage corresponding to this active/inactive state is
|
||||
given by the GPIO_ACTIVE_HIGH and GPIO_ACTIVE_LOW flags.
|
||||
|
||||
minItems: 1
|
||||
maxItems: 16
|
||||
|
||||
gain-ranges:
|
||||
$ref: /schemas/types.yaml#/definitions/int32-matrix
|
||||
description: |
|
||||
A list of one or more ranges of possible values. Each range is defined by
|
||||
the first and last point in the range. Each point is defined by the pair
|
||||
(GPIOs value, Gain in 0.01 dB unit).
|
||||
|
||||
Ranges can be contiguous or holes can be present between ranges if some
|
||||
gpios value should not be used. Also in a range the first point and the
|
||||
last point can be identical. In that case, the range contains only one
|
||||
item, the given point.
|
||||
|
||||
items:
|
||||
items:
|
||||
- description: GPIOs value of the first point in the range
|
||||
- description: Gain in 0.01 dB unit of the first point in the range
|
||||
- description: GPIOs value of the last point in the range
|
||||
- description: Gain in 0.01 dB unit of the last point in the range
|
||||
description: |
|
||||
A range defines a linear function (linear in dB) from the first point
|
||||
to the last point, both included. The number of items in the range is
|
||||
N = abs(first_point.gpio_value - last_point.gpio_value) + 1
|
||||
|
||||
It allows to define the gain range from the first_point.gain to
|
||||
the last_point.gain, both points included.
|
||||
|
||||
Gain (0.01 dB unit)
|
||||
^
|
||||
| last
|
||||
+- - - - - - - - - - + point
|
||||
| + .
|
||||
| + .
|
||||
| + .
|
||||
+- - - - + .
|
||||
| first . .
|
||||
| point . .
|
||||
| . .
|
||||
+--------+-----------+---> gpios
|
||||
value
|
||||
|
||||
Note: Even if first_point.gpio_value is lower than last_point.gpio_value
|
||||
and first_point.gain is lower than last_point.gain in the above
|
||||
graphic, all combination of values are supported leading to an
|
||||
increasing or a decreasing linear segment.
|
||||
|
||||
minItems: 1
|
||||
maxItems: 65536
|
||||
|
||||
gain-labels:
|
||||
$ref: /schemas/types.yaml#/definitions/string-array
|
||||
minItems: 2
|
||||
maxItems: 65536
|
||||
description: |
|
||||
List of the gain labels attached to the combination of GPIOs controlling
|
||||
the gain. The first label is related to the gain value 0, the second label
|
||||
is related to the gain value 1 and so on.
|
||||
|
||||
With 2 GPIOs controlling the gain, GPIOs value can be 0, 1, 2 and 3.
|
||||
Assuming that gain value set the hardware according to the following
|
||||
table:
|
||||
|
||||
GPIOs | Hardware
|
||||
value | amplification
|
||||
------+--------------
|
||||
0 | Low
|
||||
1 | Middle
|
||||
2 | High
|
||||
3 | Max
|
||||
------+--------------
|
||||
|
||||
The description using gain labels can be:
|
||||
gain-labels = "Low", "Middle", "High", "Max";
|
||||
|
||||
dependencies:
|
||||
gain-ranges: [ gain-gpios ]
|
||||
gain-labels: [ gain-gpios ]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- vdd-supply
|
||||
|
||||
anyOf:
|
||||
- required:
|
||||
- gain-gpios
|
||||
- required:
|
||||
- mute-gpios
|
||||
- required:
|
||||
- bypass-gpios
|
||||
|
||||
allOf:
|
||||
- $ref: component-common.yaml#
|
||||
- if:
|
||||
required:
|
||||
- gain-ranges
|
||||
then:
|
||||
properties:
|
||||
gain-labels: false
|
||||
- if:
|
||||
required:
|
||||
- gain-labels
|
||||
then:
|
||||
properties:
|
||||
gain-ranges: false
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
/* Gain controlled by gpios */
|
||||
amplifier-0 {
|
||||
compatible = "gpio-audio-amp-mono";
|
||||
vdd-supply = <®ulator>;
|
||||
gain-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>, <&gpio 1 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
/* Gain controlled by gpio using a simple range on a stereo amplifier */
|
||||
amplifier-1 {
|
||||
compatible = "gpio-audio-amp-stereo";
|
||||
vdd-supply = <®ulator>;
|
||||
gain-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>, <&gpio 1 GPIO_ACTIVE_HIGH>;
|
||||
gain-ranges = <0 (-300) 3 600>;
|
||||
};
|
||||
|
||||
/* Gain controlled by gpio with labels */
|
||||
amplifier-3 {
|
||||
compatible = "gpio-audio-amp-mono";
|
||||
vdd-supply = <®ulator>;
|
||||
gain-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
|
||||
gain-labels = "Low", "High";
|
||||
};
|
||||
|
||||
/* A mutable stereo amplifier without any gain control */
|
||||
amplifier-4 {
|
||||
compatible = "gpio-audio-amp-stereo";
|
||||
vdd-supply = <®ulator>;
|
||||
mute-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
|
||||
/*
|
||||
* Several supplies, gain controlled using more complex ranges, mute and
|
||||
* bypass.
|
||||
*
|
||||
* Assuming 3 gpios for controlling the gain with the following table
|
||||
* gpios value Gain
|
||||
* 0b000 Do not use (gpios value not allowed)
|
||||
* 0b001 - 3dB
|
||||
* 0b010 + 3dB
|
||||
* 0b011 + 10dB
|
||||
* 0b100 Do not use (gpios value not allowed)
|
||||
* 0b101 + 6dB
|
||||
* 0b110 + 7dB
|
||||
* 0b111 + 8dB
|
||||
*/
|
||||
amplifier-5 {
|
||||
compatible = "gpio-audio-amp-mono";
|
||||
vdd-supply = <®ulator>;
|
||||
vddio-supply = <®ulator1>;
|
||||
vdda1-supply = <®ulator2>;
|
||||
gain-gpios = <&gpio 0 GPIO_ACTIVE_HIGH>,
|
||||
<&gpio 1 GPIO_ACTIVE_HIGH>,
|
||||
<&gpio 2 GPIO_ACTIVE_HIGH>;
|
||||
gain-ranges = <1 (-300) 2 300>,
|
||||
<3 1000 3 1000>,
|
||||
<5 600 7 800>;
|
||||
mute-gpios = <&gpio 3 GPIO_ACTIVE_HIGH>;
|
||||
bypass-gpios = <&gpio 4 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
...
|
||||
|
|
@ -37,7 +37,13 @@ patternProperties:
|
|||
items:
|
||||
enum:
|
||||
- i2s
|
||||
- left_j
|
||||
- right_j
|
||||
- dsp_a
|
||||
- dsp_b
|
||||
- pdm
|
||||
- msb
|
||||
- lsb
|
||||
|
||||
dai-tdm-slot-num: true
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ properties:
|
|||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 34
|
||||
items:
|
||||
- description: audio infra sys clock
|
||||
- description: top audio mux 1
|
||||
|
|
@ -67,8 +68,13 @@ properties:
|
|||
- description: top audio a1 sys pd
|
||||
- description: top audio a2 sys pd
|
||||
- description: audio merge interface pd
|
||||
- description: HADDS2 PLL 294 MHz (HDMI audio path root)
|
||||
- description: HDMI audio interface pd
|
||||
- description: S/PDIF interface pd
|
||||
- description: audio APLL root pd
|
||||
|
||||
clock-names:
|
||||
minItems: 34
|
||||
items:
|
||||
- const: infra_sys_audio_clk
|
||||
- const: top_audio_mux1_sel
|
||||
|
|
@ -104,6 +110,10 @@ properties:
|
|||
- const: audio_a1sys_pd
|
||||
- const: audio_a2sys_pd
|
||||
- const: audio_mrgif_pd
|
||||
- const: hadds2pll_294m
|
||||
- const: audio_hdmi_pd
|
||||
- const: audio_spdf_pd
|
||||
- const: audio_apll_pd
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
|
@ -113,4 +123,17 @@ required:
|
|||
- clocks
|
||||
- clock-names
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: mediatek,mt7622-audio
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 34
|
||||
clock-names:
|
||||
maxItems: 34
|
||||
|
||||
additionalProperties: false
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/mediatek,mt2701-hdmi-audio.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek MT2701/MT7623N HDMI audio output
|
||||
|
||||
maintainers:
|
||||
- Daniel Golle <daniel@makrotopia.org>
|
||||
|
||||
description:
|
||||
Sound card routing the MT2701/MT7623N Audio Front End HDMI
|
||||
playback path to the on-chip HDMI transmitter. The AFE
|
||||
provides the DMA memif and internal I2S engine; the HDMI
|
||||
transmitter acts as the audio codec on the serialised link.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: mediatek,mt2701-hdmi-audio
|
||||
- items:
|
||||
- const: mediatek,mt7623n-hdmi-audio
|
||||
- const: mediatek,mt2701-hdmi-audio
|
||||
|
||||
mediatek,platform:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: Phandle of the MT2701/MT7623N AFE platform node.
|
||||
|
||||
mediatek,audio-codec:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: Phandle of the HDMI transmitter acting as audio codec.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- mediatek,platform
|
||||
- mediatek,audio-codec
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
sound-hdmi {
|
||||
compatible = "mediatek,mt7623n-hdmi-audio",
|
||||
"mediatek,mt2701-hdmi-audio";
|
||||
mediatek,platform = <&afe>;
|
||||
mediatek,audio-codec = <&hdmi0>;
|
||||
};
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/mediatek,mt6351-sound.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek MT6351 Audio CODEC
|
||||
|
||||
maintainers:
|
||||
- KaiChieh Chuang <kaichieh.chuang@mediatek.com>
|
||||
|
||||
description:
|
||||
MT6351 Audio CODEC is a part of the MediaTek MT6351 PMIC.
|
||||
It communicates with the SoC through the MediaTek PMIC wrapper(pwrap).
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: mediatek,mt6351-sound
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- "#sound-dai-cells"
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
sound {
|
||||
compatible = "mediatek,mt6351-sound";
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
||||
113
Documentation/devicetree/bindings/sound/mediatek,mt8196-afe.yaml
Normal file
113
Documentation/devicetree/bindings/sound/mediatek,mt8196-afe.yaml
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/mediatek,mt8196-afe.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek Audio Front End PCM controller for MT8196
|
||||
|
||||
maintainers:
|
||||
- Darren Ye <darren.ye@mediatek.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: mediatek,mt8196-afe
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
memory-region:
|
||||
maxItems: 1
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: mux for audio intbus
|
||||
- description: mux for audio engen1
|
||||
- description: mux for audio engen2
|
||||
- description: mux for audio h
|
||||
- description: audio apll1 clock
|
||||
- description: audio apll2 clock
|
||||
- description: audio apll12 divide for i2sin0
|
||||
- description: audio apll12 divide for i2sin1
|
||||
- description: audio apll12 divide for fmi2s
|
||||
- description: audio apll12 divide for tdmout mck
|
||||
- description: audio apll12 divide for tdmout bck
|
||||
- description: mux for adsp clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: top_aud_intbus
|
||||
- const: top_aud_eng1
|
||||
- const: top_aud_eng2
|
||||
- const: top_aud_h
|
||||
- const: apll1
|
||||
- const: apll2
|
||||
- const: apll12_div_i2sin0
|
||||
- const: apll12_div_i2sin1
|
||||
- const: apll12_div_fmi2s
|
||||
- const: apll12_div_tdmout_m
|
||||
- const: apll12_div_tdmout_b
|
||||
- const: top_adsp
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- memory-region
|
||||
- power-domains
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
afe@1a110000 {
|
||||
compatible = "mediatek,mt8196-afe";
|
||||
reg = <0 0x1a110000 0 0x9000>;
|
||||
interrupts = <GIC_SPI 351 IRQ_TYPE_LEVEL_HIGH 0>;
|
||||
memory-region = <&afe_dma_mem_reserved>;
|
||||
power-domains = <&scpsys 14>; //MT8196_POWER_DOMAIN_AUDIO
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&aud_pins_default>;
|
||||
clocks = <&vlp_cksys_clk 40>, //CLK_VLP_CK_AUD_INTBUS_SEL
|
||||
<&vlp_cksys_clk 38>, //CLK_VLP_CK_AUD_ENGEN1_SEL
|
||||
<&vlp_cksys_clk 39>, //CLK_VLP_CK_AUD_ENGEN2_SEL
|
||||
<&vlp_cksys_clk 37>, //CLK_VLP_CK_AUDIO_H_SEL
|
||||
<&vlp_cksys_clk 0>, //CLK_VLP_CK_VLP_APLL1
|
||||
<&vlp_cksys_clk 1>, //CLK_VLP_CK_VLP_APLL2
|
||||
<&cksys_clk 80>, //CLK_CK_APLL12_CK_DIV_I2SIN0
|
||||
<&cksys_clk 81>, //CLK_CK_APLL12_CK_DIV_I2SIN1
|
||||
<&cksys_clk 92>, //CLK_CK_APLL12_CK_DIV_FMI2S
|
||||
<&cksys_clk 93>, //CLK_CK_APLL12_CK_DIV_TDMOUT_M
|
||||
<&cksys_clk 94>, //CLK_CK_APLL12_CK_DIV_TDMOUT_B
|
||||
<&cksys_clk 45>; //CLK_CK_ADSP_SEL
|
||||
clock-names = "top_aud_intbus",
|
||||
"top_aud_eng1",
|
||||
"top_aud_eng2",
|
||||
"top_aud_h",
|
||||
"apll1",
|
||||
"apll2",
|
||||
"apll12_div_i2sin0",
|
||||
"apll12_div_i2sin1",
|
||||
"apll12_div_fmi2s",
|
||||
"apll12_div_tdmout_m",
|
||||
"apll12_div_tdmout_b",
|
||||
"top_adsp";
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/mediatek,mt8196-nau8825.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek MT8196 ASoC sound card
|
||||
|
||||
maintainers:
|
||||
- Darren Ye <darren.ye@mediatek.com>
|
||||
|
||||
allOf:
|
||||
- $ref: sound-card-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- mediatek,mt8196-nau8825-sound
|
||||
- mediatek,mt8196-rt5682s-sound
|
||||
- mediatek,mt8196-rt5650-sound
|
||||
|
||||
mediatek,platform:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: The phandle of MT8188 ASoC platform.
|
||||
|
||||
patternProperties:
|
||||
"^dai-link-[0-9]+$":
|
||||
type: object
|
||||
description:
|
||||
Container for dai-link level properties and CODEC sub-nodes.
|
||||
|
||||
properties:
|
||||
link-name:
|
||||
description:
|
||||
This property corresponds to the name of the BE dai-link to which
|
||||
we are going to update parameters in this node.
|
||||
items:
|
||||
enum:
|
||||
- TDM_DPTX_BE
|
||||
- I2SOUT6_BE
|
||||
- I2SIN6_BE
|
||||
- I2SOUT4_BE
|
||||
- I2SOUT3_BE
|
||||
|
||||
codec:
|
||||
description: Holds subnode which indicates codec dai.
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
sound-dai:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
required:
|
||||
- sound-dai
|
||||
|
||||
dai-format:
|
||||
description: audio format.
|
||||
items:
|
||||
enum:
|
||||
- i2s
|
||||
- right_j
|
||||
- left_j
|
||||
- dsp_a
|
||||
- dsp_b
|
||||
|
||||
mediatek,clk-provider:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description: Indicates dai-link clock master.
|
||||
enum:
|
||||
- cpu
|
||||
- codec
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- link-name
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- mediatek,platform
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
sound {
|
||||
compatible = "mediatek,mt8196-nau8825-sound";
|
||||
model = "mt8196-nau8825";
|
||||
mediatek,platform = <&afe>;
|
||||
dai-link-0 {
|
||||
link-name = "I2SOUT6_BE";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&nau8825>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
Mediatek MT6351 Audio Codec
|
||||
|
||||
The communication between MT6351 and SoC is through Mediatek PMIC wrapper.
|
||||
For more detail, please visit Mediatek PMIC wrapper documentation.
|
||||
|
||||
Must be a child node of PMIC wrapper.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "mediatek,mt6351-sound".
|
||||
|
||||
Example:
|
||||
|
||||
mt6351_snd {
|
||||
compatible = "mediatek,mt6351-sound";
|
||||
};
|
||||
|
|
@ -30,6 +30,20 @@ properties:
|
|||
clock-names:
|
||||
const: mclk
|
||||
|
||||
vdda-supply:
|
||||
description: Analog power supply
|
||||
|
||||
vddb-supply:
|
||||
description: Digital buffer (input/output) supply
|
||||
|
||||
vddc-supply:
|
||||
description: Digital core supply
|
||||
|
||||
vddspk-supply:
|
||||
description:
|
||||
Speaker supply (power supply pin for RSPKOUT, LSPKOUT, AUXOUT2 and
|
||||
AUXTOUT1 output drivers)
|
||||
|
||||
nuvoton,spk-btl:
|
||||
description:
|
||||
If set, configure the two loudspeaker outputs as a Bridge Tied Load output
|
||||
|
|
@ -54,5 +68,9 @@ examples:
|
|||
codec@1a {
|
||||
compatible = "nuvoton,nau8822";
|
||||
reg = <0x1a>;
|
||||
vdda-supply = <&vcca_3v3_s0>;
|
||||
vddb-supply = <&vcca_3v3_s0>;
|
||||
vddc-supply = <&vcca_3v3_s0>;
|
||||
vddspk-supply = <&vcca_3v3_s0>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ properties:
|
|||
0 - floating (reset value)
|
||||
1 - pull down
|
||||
2 - pull up
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
$ref: /schemas/types.yaml#/definitions/uint8-array
|
||||
minItems: 6
|
||||
maxItems: 6
|
||||
items:
|
||||
|
|
@ -130,6 +130,6 @@ examples:
|
|||
realtek,pow-ldo2-gpio = <&gpio 3 GPIO_ACTIVE_HIGH>;
|
||||
realtek,reset-gpio = <&gpio 3 GPIO_ACTIVE_LOW>;
|
||||
realtek,in1-differential;
|
||||
realtek,gpio-config = <0 0 0 0 0 2>;
|
||||
realtek,gpio-config = /bits/ 8 <0 0 0 0 0 2>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,9 +9,6 @@ title: Renesas FIFO-buffered Serial Interface (FSI)
|
|||
maintainers:
|
||||
- Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
$nodename:
|
||||
pattern: "^sound@.*"
|
||||
|
|
@ -38,7 +35,32 @@ properties:
|
|||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
minItems: 1
|
||||
items:
|
||||
- description: Main FSI module clock
|
||||
- description: |
|
||||
SPU bus/bridge clock. On R8A7740, this clock must be enabled to allow
|
||||
register access as the FSI block is connected behind the SPU bus.
|
||||
- description: CPG DIV6 functional clocks for FSI port A
|
||||
- description: CPG DIV6 functional clocks for FSI port B
|
||||
- description: FSI dividers for port A used for audio clock generation
|
||||
- description: FSI dividers for port B used for audio clock generation
|
||||
- description: External clock inputs for FSI port A provided by the board
|
||||
- description: External clock inputs for FSI port B provided by the board
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 8
|
||||
items:
|
||||
enum:
|
||||
- fck # Main FSI module clock
|
||||
- spu # optional SPU bus/bridge clock
|
||||
- icka # optional CPG DIV6 functional clocks for FSI port A
|
||||
- ickb # optional CPG DIV6 functional clocks for FSI port B
|
||||
- diva # optional FSI dividers for port A used for audio clock generation
|
||||
- divb # optional FSI dividers for port B used for audio clock generation
|
||||
- xcka # optional External clock inputs for FSI port A provided by the board
|
||||
- xckb # optional External clock inputs for FSI port B provided by the board
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
|
@ -69,6 +91,30 @@ required:
|
|||
|
||||
unevaluatedProperties: false
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,fsi2-r8a7740
|
||||
then:
|
||||
required:
|
||||
- clock-names
|
||||
|
||||
properties:
|
||||
clock-names:
|
||||
minItems: 2
|
||||
items:
|
||||
- const: fck
|
||||
- const: spu
|
||||
- enum: [icka, ickb, diva, divb, xcka, xckb]
|
||||
- enum: [icka, ickb, diva, divb, xcka, xckb]
|
||||
- enum: [icka, ickb, diva, divb, xcka, xckb]
|
||||
- enum: [icka, ickb, diva, divb, xcka, xckb]
|
||||
- enum: [icka, ickb, diva, divb, xcka, xckb]
|
||||
- enum: [icka, ickb, diva, divb, xcka, xckb]
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/r8a7740-clock.h>
|
||||
|
|
@ -77,7 +123,11 @@ examples:
|
|||
compatible = "renesas,fsi2-r8a7740", "renesas,sh_fsi2";
|
||||
reg = <0xfe1f0000 0x400>;
|
||||
interrupts = <GIC_SPI 9 0x4>;
|
||||
clocks = <&mstp3_clks R8A7740_CLK_FSI>;
|
||||
clocks = <&mstp3_clks R8A7740_CLK_FSI>, <&spu_clk>,
|
||||
<&fsia_clk>, <&fsiack_clk>, <&fsidiva_clk>,
|
||||
<&fsib_clk>, <&fsibck_clk>, <&fsidivb_clk>;
|
||||
clock-names = "fck", "spu", "icka", "xcka", "diva",
|
||||
"ickb", "xckb", "divb";
|
||||
power-domains = <&pd_a4mp>;
|
||||
|
||||
#sound-dai-cells = <1>;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,800 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/renesas,r9a09g047-sound.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas RZ/G3E Sound Controller
|
||||
|
||||
maintainers:
|
||||
- Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
- John Madieu <john.madieu.xa@bp.renesas.com>
|
||||
|
||||
description:
|
||||
The RZ/G3E (R9A09G047) sound controller is based on R-Car Sound IP
|
||||
with extended DMA channel support (up to 5 DMACs per direction),
|
||||
additional clock domains (47 clocks including per-SSI ADG clocks),
|
||||
and additional reset lines (14 including SCU, ADG and Audio DMAC
|
||||
peri-peri resets). SSI operates exclusively in BUSIF mode with
|
||||
2-4 BUSIF channels per SSI.
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: renesas,r9a09g047-sound
|
||||
|
||||
reg:
|
||||
maxItems: 5
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: scu
|
||||
- const: adg
|
||||
- const: ssiu
|
||||
- const: ssi
|
||||
- const: audmapp
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 1
|
||||
|
||||
"#clock-cells":
|
||||
const: 0
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
clocks:
|
||||
maxItems: 47
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: ssi-all
|
||||
- const: ssi-0
|
||||
- const: ssi-1
|
||||
- const: ssi-2
|
||||
- const: ssi-3
|
||||
- const: ssi-4
|
||||
- const: ssi-5
|
||||
- const: ssi-6
|
||||
- const: ssi-7
|
||||
- const: ssi-8
|
||||
- const: ssi-9
|
||||
- const: src-0
|
||||
- const: src-1
|
||||
- const: src-2
|
||||
- const: src-3
|
||||
- const: src-4
|
||||
- const: src-5
|
||||
- const: src-6
|
||||
- const: src-7
|
||||
- const: src-8
|
||||
- const: src-9
|
||||
- const: mix-0
|
||||
- const: mix-1
|
||||
- const: ctu-0
|
||||
- const: ctu-1
|
||||
- const: dvc-0
|
||||
- const: dvc-1
|
||||
- const: audio-clka
|
||||
- const: audio-clkb
|
||||
- const: audio-clkc
|
||||
- const: audio-clki
|
||||
- const: ssif_supply
|
||||
- const: scu
|
||||
- const: scu_x2
|
||||
- const: scu_supply
|
||||
- const: adg-ssi-0
|
||||
- const: adg-ssi-1
|
||||
- const: adg-ssi-2
|
||||
- const: adg-ssi-3
|
||||
- const: adg-ssi-4
|
||||
- const: adg-ssi-5
|
||||
- const: adg-ssi-6
|
||||
- const: adg-ssi-7
|
||||
- const: adg-ssi-8
|
||||
- const: adg-ssi-9
|
||||
- const: audmapp
|
||||
- const: adg
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 14
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: ssi-all
|
||||
- const: ssi-0
|
||||
- const: ssi-1
|
||||
- const: ssi-2
|
||||
- const: ssi-3
|
||||
- const: ssi-4
|
||||
- const: ssi-5
|
||||
- const: ssi-6
|
||||
- const: ssi-7
|
||||
- const: ssi-8
|
||||
- const: ssi-9
|
||||
- const: scu
|
||||
- const: adg
|
||||
- const: audmapp
|
||||
|
||||
dvc:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
patternProperties:
|
||||
"^dvc-[0-1]$":
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
dmas:
|
||||
maxItems: 5
|
||||
description:
|
||||
List of references to DMA specifiers, one per DMA
|
||||
controller, all for the transmission direction
|
||||
(DVC is playback-only). The dma-engine core falls
|
||||
through the list to find a free channel.
|
||||
|
||||
dma-names:
|
||||
maxItems: 5
|
||||
allOf:
|
||||
- items:
|
||||
enum:
|
||||
- tx
|
||||
|
||||
required:
|
||||
- dmas
|
||||
- dma-names
|
||||
|
||||
mix:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description:
|
||||
Per-channel Mixer (MIX) sub-nodes. Each mix-N node has no
|
||||
properties of its own. It exists so the driver can enumerate
|
||||
the MIX instances and so that DT labels can be attached to it
|
||||
for the dai/playback/capture phandle routing arrays.
|
||||
|
||||
patternProperties:
|
||||
"^mix-[0-1]$":
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
ctu:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description:
|
||||
Per-channel Channel Transfer Unit (CTU) sub-nodes. Each ctu-N
|
||||
node has no properties of its own. It exists so the driver
|
||||
can enumerate the CTU instances and so that DT labels can be
|
||||
attached to it for the dai/playback/capture phandle routing arrays.
|
||||
|
||||
patternProperties:
|
||||
"^ctu-[0-7]$":
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
src:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
patternProperties:
|
||||
"^src-[0-9]$":
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
dmas:
|
||||
maxItems: 10
|
||||
description:
|
||||
Must contain a list of pairs of references to DMA
|
||||
specifiers, one for transmission and one for reception,
|
||||
repeated for each DMA controller. The dma-engine core
|
||||
falls through the list to find a free channel.
|
||||
|
||||
dma-names:
|
||||
maxItems: 10
|
||||
allOf:
|
||||
- items:
|
||||
enum:
|
||||
- tx
|
||||
- rx
|
||||
|
||||
ssiu:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
patternProperties:
|
||||
"^ssiu-[0-9]+$":
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
dmas:
|
||||
maxItems: 10
|
||||
description:
|
||||
Must contain a list of pairs of references to DMA
|
||||
specifiers, one for transmission and one for reception,
|
||||
repeated for each DMA controller. The dma-engine core
|
||||
falls through the list to find a free channel.
|
||||
|
||||
dma-names:
|
||||
maxItems: 10
|
||||
allOf:
|
||||
- items:
|
||||
enum:
|
||||
- tx
|
||||
- rx
|
||||
|
||||
required:
|
||||
- dmas
|
||||
- dma-names
|
||||
|
||||
ssi:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
patternProperties:
|
||||
"^ssi-[0-9]$":
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
shared-pin:
|
||||
description: Shared clock pin.
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
|
||||
required:
|
||||
- interrupts
|
||||
|
||||
ports:
|
||||
$ref: audio-graph-port.yaml#/definitions/port-base
|
||||
unevaluatedProperties: false
|
||||
patternProperties:
|
||||
'^port@[0-9a-f]+$':
|
||||
$ref: audio-graph-port.yaml#/definitions/port-base
|
||||
unevaluatedProperties: false
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
endpoint:
|
||||
$ref: audio-graph-port.yaml#/definitions/endpoint-base
|
||||
unevaluatedProperties: false
|
||||
properties:
|
||||
playback:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
description:
|
||||
Ordered list of phandles to the in-SoC modules used
|
||||
by this DAI in the playback direction. Each phandle
|
||||
must reference one of the ssi-N, src-N, ctu-N,
|
||||
mix-N or dvc-N sub-nodes of the parent sound
|
||||
controller. The list order is the pipeline order
|
||||
from CPU to off-SoC endpoint.
|
||||
capture:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
description:
|
||||
Ordered list of phandles to the in-SoC modules used
|
||||
by this DAI in the capture direction. Each phandle
|
||||
must reference one of the ssi-N, src-N, ctu-N,
|
||||
mix-N or dvc-N sub-nodes of the parent sound
|
||||
controller. The list order is the pipeline order
|
||||
from off-SoC endpoint to CPU.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- "#sound-dai-cells"
|
||||
- "#clock-cells"
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- reset-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
sound@13c00000 {
|
||||
#sound-dai-cells = <1>;
|
||||
#clock-cells = <0>;
|
||||
compatible = "renesas,r9a09g047-sound";
|
||||
reg = <0x13c00000 0x10000>,
|
||||
<0x13c20000 0x10000>,
|
||||
<0x13c30000 0x1000>,
|
||||
<0x13c31000 0x1f000>,
|
||||
<0x13c50000 0x10000>;
|
||||
reg-names = "scu", "adg", "ssiu", "ssi", "audmapp";
|
||||
clocks = <&cpg 245>,
|
||||
<&cpg 385>, <&cpg 386>,
|
||||
<&cpg 387>, <&cpg 388>,
|
||||
<&cpg 389>, <&cpg 390>,
|
||||
<&cpg 391>, <&cpg 392>,
|
||||
<&cpg 393>, <&cpg 394>,
|
||||
<&cpg 372>, <&cpg 373>,
|
||||
<&cpg 374>, <&cpg 375>,
|
||||
<&cpg 376>, <&cpg 377>,
|
||||
<&cpg 378>, <&cpg 379>,
|
||||
<&cpg 380>, <&cpg 381>,
|
||||
<&cpg 370>, <&cpg 371>,
|
||||
<&cpg 370>, <&cpg 371>,
|
||||
<&cpg 368>, <&cpg 369>,
|
||||
<&cpg 251>, <&cpg 252>,
|
||||
<&cpg 253>, <&cpg 250>,
|
||||
<&cpg 384>,
|
||||
<&cpg 246>, <&cpg 247>,
|
||||
<&cpg 382>,
|
||||
<&cpg 352>, <&cpg 353>,
|
||||
<&cpg 354>, <&cpg 355>,
|
||||
<&cpg 356>, <&cpg 357>,
|
||||
<&cpg 358>, <&cpg 359>,
|
||||
<&cpg 360>, <&cpg 361>,
|
||||
<&cpg 248>, <&cpg 249>;
|
||||
clock-names = "ssi-all",
|
||||
"ssi-0", "ssi-1",
|
||||
"ssi-2", "ssi-3",
|
||||
"ssi-4", "ssi-5",
|
||||
"ssi-6", "ssi-7",
|
||||
"ssi-8", "ssi-9",
|
||||
"src-0", "src-1",
|
||||
"src-2", "src-3",
|
||||
"src-4", "src-5",
|
||||
"src-6", "src-7",
|
||||
"src-8", "src-9",
|
||||
"mix-0", "mix-1",
|
||||
"ctu-0", "ctu-1",
|
||||
"dvc-0", "dvc-1",
|
||||
"audio-clka", "audio-clkb",
|
||||
"audio-clkc", "audio-clki",
|
||||
"ssif_supply",
|
||||
"scu", "scu_x2",
|
||||
"scu_supply",
|
||||
"adg-ssi-0", "adg-ssi-1",
|
||||
"adg-ssi-2", "adg-ssi-3",
|
||||
"adg-ssi-4", "adg-ssi-5",
|
||||
"adg-ssi-6", "adg-ssi-7",
|
||||
"adg-ssi-8", "adg-ssi-9",
|
||||
"audmapp", "adg";
|
||||
power-domains = <&cpg>;
|
||||
resets = <&cpg 225>,
|
||||
<&cpg 226>, <&cpg 227>,
|
||||
<&cpg 228>, <&cpg 229>,
|
||||
<&cpg 230>, <&cpg 231>,
|
||||
<&cpg 232>, <&cpg 233>,
|
||||
<&cpg 234>, <&cpg 235>,
|
||||
<&cpg 236>, <&cpg 238>, <&cpg 237>;
|
||||
reset-names = "ssi-all",
|
||||
"ssi-0", "ssi-1",
|
||||
"ssi-2", "ssi-3",
|
||||
"ssi-4", "ssi-5",
|
||||
"ssi-6", "ssi-7",
|
||||
"ssi-8", "ssi-9",
|
||||
"scu", "adg",
|
||||
"audmapp";
|
||||
|
||||
ctu {
|
||||
ctu-0 { };
|
||||
ctu-1 { };
|
||||
ctu-2 { };
|
||||
ctu-3 { };
|
||||
ctu-4 { };
|
||||
ctu-5 { };
|
||||
ctu-6 { };
|
||||
ctu-7 { };
|
||||
};
|
||||
|
||||
dvc {
|
||||
dvc0: dvc-0 {
|
||||
dmas = <&dmac0 0x1db3>, <&dmac1 0x1db3>,
|
||||
<&dmac2 0x1db3>, <&dmac3 0x1db3>,
|
||||
<&dmac4 0x1db3>;
|
||||
dma-names = "tx", "tx", "tx", "tx", "tx";
|
||||
};
|
||||
dvc1: dvc-1 {
|
||||
dmas = <&dmac0 0x1db4>, <&dmac1 0x1db4>,
|
||||
<&dmac2 0x1db4>, <&dmac3 0x1db4>,
|
||||
<&dmac4 0x1db4>;
|
||||
dma-names = "tx", "tx", "tx", "tx", "tx";
|
||||
};
|
||||
};
|
||||
|
||||
mix {
|
||||
mix-0 { };
|
||||
mix-1 { };
|
||||
};
|
||||
|
||||
src {
|
||||
src0: src-0 {
|
||||
interrupts = <GIC_SPI 902 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmac0 0x1d9f>, <&dmac0 0x1da9>,
|
||||
<&dmac1 0x1d9f>, <&dmac1 0x1da9>,
|
||||
<&dmac2 0x1d9f>, <&dmac2 0x1da9>,
|
||||
<&dmac3 0x1d9f>, <&dmac3 0x1da9>,
|
||||
<&dmac4 0x1d9f>, <&dmac4 0x1da9>;
|
||||
dma-names = "rx", "tx", "rx", "tx", "rx", "tx",
|
||||
"rx", "tx", "rx", "tx";
|
||||
};
|
||||
src1: src-1 {
|
||||
interrupts = <GIC_SPI 903 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmac0 0x1da0>, <&dmac0 0x1daa>,
|
||||
<&dmac1 0x1da0>, <&dmac1 0x1daa>,
|
||||
<&dmac2 0x1da0>, <&dmac2 0x1daa>,
|
||||
<&dmac3 0x1da0>, <&dmac3 0x1daa>,
|
||||
<&dmac4 0x1da0>, <&dmac4 0x1daa>;
|
||||
dma-names = "rx", "tx", "rx", "tx", "rx", "tx",
|
||||
"rx", "tx", "rx", "tx";
|
||||
};
|
||||
src-2 {
|
||||
interrupts = <GIC_SPI 904 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmac0 0x1da1>, <&dmac0 0x1dab>,
|
||||
<&dmac1 0x1da1>, <&dmac1 0x1dab>,
|
||||
<&dmac2 0x1da1>, <&dmac2 0x1dab>,
|
||||
<&dmac3 0x1da1>, <&dmac3 0x1dab>,
|
||||
<&dmac4 0x1da1>, <&dmac4 0x1dab>;
|
||||
dma-names = "rx", "tx", "rx", "tx", "rx", "tx",
|
||||
"rx", "tx", "rx", "tx";
|
||||
};
|
||||
src-3 {
|
||||
interrupts = <GIC_SPI 905 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmac0 0x1da2>, <&dmac0 0x1dac>,
|
||||
<&dmac1 0x1da2>, <&dmac1 0x1dac>,
|
||||
<&dmac2 0x1da2>, <&dmac2 0x1dac>,
|
||||
<&dmac3 0x1da2>, <&dmac3 0x1dac>,
|
||||
<&dmac4 0x1da2>, <&dmac4 0x1dac>;
|
||||
dma-names = "rx", "tx", "rx", "tx", "rx", "tx",
|
||||
"rx", "tx", "rx", "tx";
|
||||
};
|
||||
src-4 {
|
||||
interrupts = <GIC_SPI 906 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmac0 0x1da3>, <&dmac0 0x1dad>,
|
||||
<&dmac1 0x1da3>, <&dmac1 0x1dad>,
|
||||
<&dmac2 0x1da3>, <&dmac2 0x1dad>,
|
||||
<&dmac3 0x1da3>, <&dmac3 0x1dad>,
|
||||
<&dmac4 0x1da3>, <&dmac4 0x1dad>;
|
||||
dma-names = "rx", "tx", "rx", "tx", "rx", "tx",
|
||||
"rx", "tx", "rx", "tx";
|
||||
};
|
||||
src-5 {
|
||||
interrupts = <GIC_SPI 907 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmac0 0x1da4>, <&dmac0 0x1dae>,
|
||||
<&dmac1 0x1da4>, <&dmac1 0x1dae>,
|
||||
<&dmac2 0x1da4>, <&dmac2 0x1dae>,
|
||||
<&dmac3 0x1da4>, <&dmac3 0x1dae>,
|
||||
<&dmac4 0x1da4>, <&dmac4 0x1dae>;
|
||||
dma-names = "rx", "tx", "rx", "tx", "rx", "tx",
|
||||
"rx", "tx", "rx", "tx";
|
||||
};
|
||||
src-6 {
|
||||
interrupts = <GIC_SPI 908 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmac0 0x1da5>, <&dmac0 0x1daf>,
|
||||
<&dmac1 0x1da5>, <&dmac1 0x1daf>,
|
||||
<&dmac2 0x1da5>, <&dmac2 0x1daf>,
|
||||
<&dmac3 0x1da5>, <&dmac3 0x1daf>,
|
||||
<&dmac4 0x1da5>, <&dmac4 0x1daf>;
|
||||
dma-names = "rx", "tx", "rx", "tx", "rx", "tx",
|
||||
"rx", "tx", "rx", "tx";
|
||||
};
|
||||
src-7 {
|
||||
interrupts = <GIC_SPI 909 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmac0 0x1da6>, <&dmac0 0x1db0>,
|
||||
<&dmac1 0x1da6>, <&dmac1 0x1db0>,
|
||||
<&dmac2 0x1da6>, <&dmac2 0x1db0>,
|
||||
<&dmac3 0x1da6>, <&dmac3 0x1db0>,
|
||||
<&dmac4 0x1da6>, <&dmac4 0x1db0>;
|
||||
dma-names = "rx", "tx", "rx", "tx", "rx", "tx",
|
||||
"rx", "tx", "rx", "tx";
|
||||
};
|
||||
src-8 {
|
||||
interrupts = <GIC_SPI 910 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmac0 0x1da7>, <&dmac0 0x1db1>,
|
||||
<&dmac1 0x1da7>, <&dmac1 0x1db1>,
|
||||
<&dmac2 0x1da7>, <&dmac2 0x1db1>,
|
||||
<&dmac3 0x1da7>, <&dmac3 0x1db1>,
|
||||
<&dmac4 0x1da7>, <&dmac4 0x1db1>;
|
||||
dma-names = "rx", "tx", "rx", "tx", "rx", "tx",
|
||||
"rx", "tx", "rx", "tx";
|
||||
};
|
||||
src-9 {
|
||||
interrupts = <GIC_SPI 911 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&dmac0 0x1da8>, <&dmac0 0x1db2>,
|
||||
<&dmac1 0x1da8>, <&dmac1 0x1db2>,
|
||||
<&dmac2 0x1da8>, <&dmac2 0x1db2>,
|
||||
<&dmac3 0x1da8>, <&dmac3 0x1db2>,
|
||||
<&dmac4 0x1da8>, <&dmac4 0x1db2>;
|
||||
dma-names = "rx", "tx", "rx", "tx", "rx", "tx",
|
||||
"rx", "tx", "rx", "tx";
|
||||
};
|
||||
};
|
||||
|
||||
ssi {
|
||||
ssi-0 {
|
||||
interrupts = <GIC_SPI 889 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
ssi-1 {
|
||||
interrupts = <GIC_SPI 890 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
ssi-2 {
|
||||
interrupts = <GIC_SPI 891 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
ssi3: ssi-3 {
|
||||
interrupts = <GIC_SPI 892 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
ssi4: ssi-4 {
|
||||
interrupts = <GIC_SPI 893 IRQ_TYPE_LEVEL_HIGH>;
|
||||
shared-pin;
|
||||
};
|
||||
ssi-5 {
|
||||
interrupts = <GIC_SPI 894 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
ssi-6 {
|
||||
interrupts = <GIC_SPI 895 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
ssi-7 {
|
||||
interrupts = <GIC_SPI 896 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
ssi-8 {
|
||||
interrupts = <GIC_SPI 897 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
ssi-9 {
|
||||
interrupts = <GIC_SPI 898 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
ssiu {
|
||||
ssiu-0 {
|
||||
dmas = <&dmac0 0x1d61>, <&dmac0 0x1d62>,
|
||||
<&dmac1 0x1d61>, <&dmac1 0x1d62>,
|
||||
<&dmac2 0x1d61>, <&dmac2 0x1d62>,
|
||||
<&dmac3 0x1d61>, <&dmac3 0x1d62>,
|
||||
<&dmac4 0x1d61>, <&dmac4 0x1d62>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-1 {
|
||||
dmas = <&dmac0 0x1d63>, <&dmac0 0x1d64>,
|
||||
<&dmac1 0x1d63>, <&dmac1 0x1d64>,
|
||||
<&dmac2 0x1d63>, <&dmac2 0x1d64>,
|
||||
<&dmac3 0x1d63>, <&dmac3 0x1d64>,
|
||||
<&dmac4 0x1d63>, <&dmac4 0x1d64>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-2 {
|
||||
dmas = <&dmac0 0x1d65>, <&dmac0 0x1d66>,
|
||||
<&dmac1 0x1d65>, <&dmac1 0x1d66>,
|
||||
<&dmac2 0x1d65>, <&dmac2 0x1d66>,
|
||||
<&dmac3 0x1d65>, <&dmac3 0x1d66>,
|
||||
<&dmac4 0x1d65>, <&dmac4 0x1d66>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-3 {
|
||||
dmas = <&dmac0 0x1d67>, <&dmac0 0x1d68>,
|
||||
<&dmac1 0x1d67>, <&dmac1 0x1d68>,
|
||||
<&dmac2 0x1d67>, <&dmac2 0x1d68>,
|
||||
<&dmac3 0x1d67>, <&dmac3 0x1d68>,
|
||||
<&dmac4 0x1d67>, <&dmac4 0x1d68>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-4 {
|
||||
dmas = <&dmac0 0x1d69>, <&dmac0 0x1d6a>,
|
||||
<&dmac1 0x1d69>, <&dmac1 0x1d6a>,
|
||||
<&dmac2 0x1d69>, <&dmac2 0x1d6a>,
|
||||
<&dmac3 0x1d69>, <&dmac3 0x1d6a>,
|
||||
<&dmac4 0x1d69>, <&dmac4 0x1d6a>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-5 {
|
||||
dmas = <&dmac0 0x1d6b>, <&dmac0 0x1d6c>,
|
||||
<&dmac1 0x1d6b>, <&dmac1 0x1d6c>,
|
||||
<&dmac2 0x1d6b>, <&dmac2 0x1d6c>,
|
||||
<&dmac3 0x1d6b>, <&dmac3 0x1d6c>,
|
||||
<&dmac4 0x1d6b>, <&dmac4 0x1d6c>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-6 {
|
||||
dmas = <&dmac0 0x1d6d>, <&dmac0 0x1d6e>,
|
||||
<&dmac1 0x1d6d>, <&dmac1 0x1d6e>,
|
||||
<&dmac2 0x1d6d>, <&dmac2 0x1d6e>,
|
||||
<&dmac3 0x1d6d>, <&dmac3 0x1d6e>,
|
||||
<&dmac4 0x1d6d>, <&dmac4 0x1d6e>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-7 {
|
||||
dmas = <&dmac0 0x1d6f>, <&dmac0 0x1d70>,
|
||||
<&dmac1 0x1d6f>, <&dmac1 0x1d70>,
|
||||
<&dmac2 0x1d6f>, <&dmac2 0x1d70>,
|
||||
<&dmac3 0x1d6f>, <&dmac3 0x1d70>,
|
||||
<&dmac4 0x1d6f>, <&dmac4 0x1d70>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-8 {
|
||||
dmas = <&dmac0 0x1d71>, <&dmac0 0x1d72>,
|
||||
<&dmac1 0x1d71>, <&dmac1 0x1d72>,
|
||||
<&dmac2 0x1d71>, <&dmac2 0x1d72>,
|
||||
<&dmac3 0x1d71>, <&dmac3 0x1d72>,
|
||||
<&dmac4 0x1d71>, <&dmac4 0x1d72>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-9 {
|
||||
dmas = <&dmac0 0x1d73>, <&dmac0 0x1d74>,
|
||||
<&dmac1 0x1d73>, <&dmac1 0x1d74>,
|
||||
<&dmac2 0x1d73>, <&dmac2 0x1d74>,
|
||||
<&dmac3 0x1d73>, <&dmac3 0x1d74>,
|
||||
<&dmac4 0x1d73>, <&dmac4 0x1d74>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-10 {
|
||||
dmas = <&dmac0 0x1d75>, <&dmac0 0x1d76>,
|
||||
<&dmac1 0x1d75>, <&dmac1 0x1d76>,
|
||||
<&dmac2 0x1d75>, <&dmac2 0x1d76>,
|
||||
<&dmac3 0x1d75>, <&dmac3 0x1d76>,
|
||||
<&dmac4 0x1d75>, <&dmac4 0x1d76>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-11 {
|
||||
dmas = <&dmac0 0x1d77>, <&dmac0 0x1d78>,
|
||||
<&dmac1 0x1d77>, <&dmac1 0x1d78>,
|
||||
<&dmac2 0x1d77>, <&dmac2 0x1d78>,
|
||||
<&dmac3 0x1d77>, <&dmac3 0x1d78>,
|
||||
<&dmac4 0x1d77>, <&dmac4 0x1d78>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-12 {
|
||||
dmas = <&dmac0 0x1d79>, <&dmac0 0x1d7a>,
|
||||
<&dmac1 0x1d79>, <&dmac1 0x1d7a>,
|
||||
<&dmac2 0x1d79>, <&dmac2 0x1d7a>,
|
||||
<&dmac3 0x1d79>, <&dmac3 0x1d7a>,
|
||||
<&dmac4 0x1d79>, <&dmac4 0x1d7a>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-13 {
|
||||
dmas = <&dmac0 0x1d7b>, <&dmac0 0x1d7c>,
|
||||
<&dmac1 0x1d7b>, <&dmac1 0x1d7c>,
|
||||
<&dmac2 0x1d7b>, <&dmac2 0x1d7c>,
|
||||
<&dmac3 0x1d7b>, <&dmac3 0x1d7c>,
|
||||
<&dmac4 0x1d7b>, <&dmac4 0x1d7c>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-14 {
|
||||
dmas = <&dmac0 0x1d7d>, <&dmac0 0x1d7e>,
|
||||
<&dmac1 0x1d7d>, <&dmac1 0x1d7e>,
|
||||
<&dmac2 0x1d7d>, <&dmac2 0x1d7e>,
|
||||
<&dmac3 0x1d7d>, <&dmac3 0x1d7e>,
|
||||
<&dmac4 0x1d7d>, <&dmac4 0x1d7e>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-15 {
|
||||
dmas = <&dmac0 0x1d7f>, <&dmac0 0x1d80>,
|
||||
<&dmac1 0x1d7f>, <&dmac1 0x1d80>,
|
||||
<&dmac2 0x1d7f>, <&dmac2 0x1d80>,
|
||||
<&dmac3 0x1d7f>, <&dmac3 0x1d80>,
|
||||
<&dmac4 0x1d7f>, <&dmac4 0x1d80>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-16 {
|
||||
dmas = <&dmac0 0x1d81>, <&dmac0 0x1d82>,
|
||||
<&dmac1 0x1d81>, <&dmac1 0x1d82>,
|
||||
<&dmac2 0x1d81>, <&dmac2 0x1d82>,
|
||||
<&dmac3 0x1d81>, <&dmac3 0x1d82>,
|
||||
<&dmac4 0x1d81>, <&dmac4 0x1d82>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-17 {
|
||||
dmas = <&dmac0 0x1d83>, <&dmac0 0x1d84>,
|
||||
<&dmac1 0x1d83>, <&dmac1 0x1d84>,
|
||||
<&dmac2 0x1d83>, <&dmac2 0x1d84>,
|
||||
<&dmac3 0x1d83>, <&dmac3 0x1d84>,
|
||||
<&dmac4 0x1d83>, <&dmac4 0x1d84>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-18 {
|
||||
dmas = <&dmac0 0x1d85>, <&dmac0 0x1d86>,
|
||||
<&dmac1 0x1d85>, <&dmac1 0x1d86>,
|
||||
<&dmac2 0x1d85>, <&dmac2 0x1d86>,
|
||||
<&dmac3 0x1d85>, <&dmac3 0x1d86>,
|
||||
<&dmac4 0x1d85>, <&dmac4 0x1d86>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-19 {
|
||||
dmas = <&dmac0 0x1d87>, <&dmac0 0x1d88>,
|
||||
<&dmac1 0x1d87>, <&dmac1 0x1d88>,
|
||||
<&dmac2 0x1d87>, <&dmac2 0x1d88>,
|
||||
<&dmac3 0x1d87>, <&dmac3 0x1d88>,
|
||||
<&dmac4 0x1d87>, <&dmac4 0x1d88>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-20 {
|
||||
dmas = <&dmac0 0x1d89>, <&dmac0 0x1d8a>,
|
||||
<&dmac1 0x1d89>, <&dmac1 0x1d8a>,
|
||||
<&dmac2 0x1d89>, <&dmac2 0x1d8a>,
|
||||
<&dmac3 0x1d89>, <&dmac3 0x1d8a>,
|
||||
<&dmac4 0x1d89>, <&dmac4 0x1d8a>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-21 {
|
||||
dmas = <&dmac0 0x1d8b>, <&dmac0 0x1d8c>,
|
||||
<&dmac1 0x1d8b>, <&dmac1 0x1d8c>,
|
||||
<&dmac2 0x1d8b>, <&dmac2 0x1d8c>,
|
||||
<&dmac3 0x1d8b>, <&dmac3 0x1d8c>,
|
||||
<&dmac4 0x1d8b>, <&dmac4 0x1d8c>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-22 {
|
||||
dmas = <&dmac0 0x1d8d>, <&dmac0 0x1d8e>,
|
||||
<&dmac1 0x1d8d>, <&dmac1 0x1d8e>,
|
||||
<&dmac2 0x1d8d>, <&dmac2 0x1d8e>,
|
||||
<&dmac3 0x1d8d>, <&dmac3 0x1d8e>,
|
||||
<&dmac4 0x1d8d>, <&dmac4 0x1d8e>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-23 {
|
||||
dmas = <&dmac0 0x1d8f>, <&dmac0 0x1d90>,
|
||||
<&dmac1 0x1d8f>, <&dmac1 0x1d90>,
|
||||
<&dmac2 0x1d8f>, <&dmac2 0x1d90>,
|
||||
<&dmac3 0x1d8f>, <&dmac3 0x1d90>,
|
||||
<&dmac4 0x1d8f>, <&dmac4 0x1d90>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-24 {
|
||||
dmas = <&dmac0 0x1d91>, <&dmac0 0x1d92>,
|
||||
<&dmac1 0x1d91>, <&dmac1 0x1d92>,
|
||||
<&dmac2 0x1d91>, <&dmac2 0x1d92>,
|
||||
<&dmac3 0x1d91>, <&dmac3 0x1d92>,
|
||||
<&dmac4 0x1d91>, <&dmac4 0x1d92>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-25 {
|
||||
dmas = <&dmac0 0x1d93>, <&dmac0 0x1d94>,
|
||||
<&dmac1 0x1d93>, <&dmac1 0x1d94>,
|
||||
<&dmac2 0x1d93>, <&dmac2 0x1d94>,
|
||||
<&dmac3 0x1d93>, <&dmac3 0x1d94>,
|
||||
<&dmac4 0x1d93>, <&dmac4 0x1d94>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-26 {
|
||||
dmas = <&dmac0 0x1d95>, <&dmac0 0x1d96>,
|
||||
<&dmac1 0x1d95>, <&dmac1 0x1d96>,
|
||||
<&dmac2 0x1d95>, <&dmac2 0x1d96>,
|
||||
<&dmac3 0x1d95>, <&dmac3 0x1d96>,
|
||||
<&dmac4 0x1d95>, <&dmac4 0x1d96>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
ssiu-27 {
|
||||
dmas = <&dmac0 0x1d97>, <&dmac0 0x1d98>,
|
||||
<&dmac1 0x1d97>, <&dmac1 0x1d98>,
|
||||
<&dmac2 0x1d97>, <&dmac2 0x1d98>,
|
||||
<&dmac3 0x1d97>, <&dmac3 0x1d98>,
|
||||
<&dmac4 0x1d97>, <&dmac4 0x1d98>;
|
||||
dma-names = "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx", "tx", "rx";
|
||||
};
|
||||
};
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
rsnd_endpoint0: endpoint {
|
||||
remote-endpoint = <&codec_endpoint>;
|
||||
dai-format = "i2s";
|
||||
bitclock-master = <&rsnd_endpoint0>;
|
||||
frame-master = <&rsnd_endpoint0>;
|
||||
playback = <&ssi3>, <&src1>, <&dvc1>;
|
||||
capture = <&ssi4>, <&src0>, <&dvc0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -45,8 +45,8 @@ properties:
|
|||
|
||||
clocks:
|
||||
items:
|
||||
- description: clock for SPDIF bus
|
||||
- description: clock for SPDIF controller
|
||||
- description: clock for SPDIF bus
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
$id: http://devicetree.org/schemas/sound/spacemit,k1-i2s.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: K1 I2S controller
|
||||
title: SpacemiT K1/K3 I2S controller
|
||||
|
||||
description:
|
||||
The I2S bus (Inter-IC sound bus) is a serial link for digital
|
||||
|
|
@ -15,27 +15,54 @@ maintainers:
|
|||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: spacemit,k3-i2s
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 7
|
||||
clock-names:
|
||||
minItems: 7
|
||||
else:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 4
|
||||
clock-names:
|
||||
maxItems: 4
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: spacemit,k1-i2s
|
||||
enum:
|
||||
- spacemit,k1-i2s
|
||||
- spacemit,k3-i2s
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 4
|
||||
items:
|
||||
- description: clock for I2S sysclk
|
||||
- description: clock for I2S bclk
|
||||
- description: clock for I2S bus
|
||||
- description: clock for I2S controller
|
||||
- description: clock for I2S sysclk divider
|
||||
- description: clock for I2S common sysclk
|
||||
- description: clock for I2S common bclk
|
||||
|
||||
clock-names:
|
||||
minItems: 4
|
||||
items:
|
||||
- const: sysclk
|
||||
- const: bclk
|
||||
- const: bus
|
||||
- const: func
|
||||
- const: sysclk_div
|
||||
- const: c_sysclk
|
||||
- const: c_bclk
|
||||
|
||||
dmas:
|
||||
minItems: 1
|
||||
|
|
|
|||
|
|
@ -71,6 +71,9 @@ properties:
|
|||
ti,tas2572: 6.6-W Digital Input smart amp with I/V sense and integrated
|
||||
13-V Class-H Boost
|
||||
|
||||
ti,tas2573: Boosted Class-D Audio Amplifier with Integrated DSP and IV
|
||||
Sense
|
||||
|
||||
ti,tas2574: 8.5-W Digital Input smart amp with I/V sense and integrated
|
||||
15-V Class-H Boost
|
||||
|
||||
|
|
@ -121,6 +124,7 @@ properties:
|
|||
- ti,tas2568
|
||||
- ti,tas2570
|
||||
- ti,tas2572
|
||||
- ti,tas2573
|
||||
- ti,tas2574
|
||||
- ti,tas5802
|
||||
- ti,tas5806m
|
||||
|
|
@ -183,6 +187,7 @@ allOf:
|
|||
contains:
|
||||
enum:
|
||||
- ti,tas2563
|
||||
- ti,tas2573
|
||||
- ti,tas5825
|
||||
then:
|
||||
properties:
|
||||
|
|
|
|||
280
Documentation/devicetree/bindings/sound/ti,tas67524.yaml
Normal file
280
Documentation/devicetree/bindings/sound/ti,tas67524.yaml
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/ti,tas67524.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Texas Instruments TAS67524 Audio Amplifier
|
||||
|
||||
maintainers:
|
||||
- Sen Wang <sen@ti.com>
|
||||
|
||||
description:
|
||||
The TAS67524 is a four-channel, digital-input, automotive
|
||||
Class-D audio amplifier with load diagnostics and an integrated
|
||||
DSP for audio processing.
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- ti,tas6754
|
||||
- const: ti,tas67524
|
||||
- const: ti,tas67524
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
'#sound-dai-cells':
|
||||
const: 1
|
||||
description: |
|
||||
The device exposes three DAIs, selected by index.
|
||||
0 - Standard Audio Path (Playback)
|
||||
1 - Low-Latency Playback Path (Playback)
|
||||
2 - Sensory Feedback (Capture - Vpredict and Isense)
|
||||
By default, all four channels of each DAI are active.
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
description:
|
||||
Active-low falling-edge interrupt from the FAULT pin. When provided,
|
||||
the driver uses IRQ-driven fault reporting instead of polling.
|
||||
|
||||
powerdown-gpios:
|
||||
maxItems: 1
|
||||
description:
|
||||
GPIO connected to the PD pin, active low. Controls the internal
|
||||
digital circuitry power state. When asserted the device enters
|
||||
full power-down mode and all register state is lost. Can be omitted if
|
||||
PD pin is hardwired or externally controlled.
|
||||
|
||||
standby-gpios:
|
||||
maxItems: 1
|
||||
description:
|
||||
GPIO connected to the STBY pin, active low. Controls the analog
|
||||
power stage. When asserted the device enters Deep Sleep mode but
|
||||
remains I2C-accessible with registers retained. Can be omitted if
|
||||
STBY pin is tied to PD or hardwired.
|
||||
|
||||
dvdd-supply:
|
||||
description:
|
||||
Digital logic supply (1.62 V to 3.6 V). All three supply rails must
|
||||
be within their recommended operating ranges before the PD pin is
|
||||
released.
|
||||
|
||||
pvdd-supply:
|
||||
description:
|
||||
Output FET power supply (4.5 V to 19 V). All three supply rails must
|
||||
be within their recommended operating ranges before the PD pin is
|
||||
released.
|
||||
|
||||
vbat-supply:
|
||||
description:
|
||||
Battery supply for the Class-D output stage (4.5 V to 19 V). Optional
|
||||
when PVDD and VBAT are connected to the same supply rail. When absent,
|
||||
VBAT is assumed hardwired to PVDD.
|
||||
|
||||
ti,fast-boot:
|
||||
type: boolean
|
||||
description:
|
||||
Skip DC load diagnostic sweep at power-on to reduce boot latency.
|
||||
Automatic diagnostics after fault conditions remain enabled. Hardware
|
||||
overcurrent protection is always active.
|
||||
|
||||
ti,audio-slot-no:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
TDM slot offset for the standard audio playback path via SDIN1. A value
|
||||
of 4 maps to slot 4. If omitted, slot assignment is derived from the
|
||||
tx_mask provided via set_tdm_slot(). Without either property, no slot
|
||||
mapping is configured.
|
||||
|
||||
ti,llp-slot-no:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
TDM slot offset for the low-latency playback path via SDIN1. If omitted,
|
||||
slot assignment is derived from the tx_mask provided via set_tdm_slot().
|
||||
Without either property, no slot mapping is configured. Disabled outside
|
||||
of LLP mode, and only relevant for TDM formats.
|
||||
|
||||
ti,vpredict-slot-no:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
In TDM mode, enables Vpredict output and assigns its starting slot;
|
||||
four consecutive slots carry Vpredict Ch1-4 on SDOUT1. May coexist
|
||||
with ti,isense-slot-no using separate non-overlapping slots.
|
||||
|
||||
In I2S mode, enables Vpredict output on SDOUT1 (Ch1/Ch2) and SDOUT2
|
||||
(Ch3/Ch4). The slot value is unused. Requires a GPIO configured as
|
||||
sdout2 for Ch3/Ch4; without it only Ch1/Ch2 are output. Mutually
|
||||
exclusive with ti,isense-slot-no; if both are set, Vpredict takes
|
||||
priority.
|
||||
|
||||
Irrelevant in Left-J and Right-J modes.
|
||||
|
||||
ti,isense-slot-no:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: |
|
||||
In TDM mode, enables Isense output and assigns its starting slot;
|
||||
four consecutive slots carry Isense Ch1-4 on SDOUT1. May coexist
|
||||
with ti,vpredict-slot-no using separate non-overlapping slots.
|
||||
|
||||
In I2S mode, enables Isense output on SDOUT1 (Ch1/Ch2) and SDOUT2
|
||||
(Ch3/Ch4). The slot value is unused. Requires a GPIO configured as
|
||||
SDOUT2 for Ch3/Ch4; without it only Ch1/Ch2 are output. Mutually
|
||||
exclusive with ti,vpredict-slot-no; Vpredict takes priority if both
|
||||
are set.
|
||||
|
||||
Irrelevant in Left-J and Right-J modes.
|
||||
|
||||
ti,gpio1-function:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description:
|
||||
Function for the GPIO_1 pin. When omitted, GPIO_1 remains in its
|
||||
power-on default state.
|
||||
enum:
|
||||
- low # Output: driven low
|
||||
- auto-mute # Output: high when all channels are auto-muted
|
||||
- auto-mute-ch4 # Output: high when channel 4 is auto-muted
|
||||
- auto-mute-ch3 # Output: high when channel 3 is auto-muted
|
||||
- auto-mute-ch2 # Output: high when channel 2 is auto-muted
|
||||
- auto-mute-ch1 # Output: high when channel 1 is auto-muted
|
||||
- sdout2 # Output: Routes secondary serial data output 2
|
||||
- sdout1 # Output: Re-routes secondary serial data output 1
|
||||
- warn # Output: warning signal (OTW, CBC)
|
||||
- fault # Output: fault signal (OTSD, OC, DC)
|
||||
- clock-sync # Output: clock synchronisation
|
||||
- invalid-clock # Output: high when clock is invalid
|
||||
- high # Output: driven high
|
||||
- mute # Input: external mute control
|
||||
- phase-sync # Input: phase synchronisation
|
||||
- sdin2 # Input: secondary SDIN2 for I2S/LJ/RJ ch3/ch4
|
||||
- deep-sleep # Input: asserted transitions device to Deep Sleep
|
||||
- hiz # Input: asserted transitions device to Hi-Z
|
||||
- play # Input: asserted transitions device to Play
|
||||
- sleep # Input: asserted transitions device to Sleep
|
||||
|
||||
ti,gpio2-function:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description:
|
||||
Function for the GPIO_2 pin. When omitted, GPIO_2 remains in its
|
||||
power-on default state.
|
||||
enum:
|
||||
- low # Output: driven low
|
||||
- auto-mute # Output: high when all channels are auto-muted
|
||||
- auto-mute-ch4 # Output: high when channel 4 is auto-muted
|
||||
- auto-mute-ch3 # Output: high when channel 3 is auto-muted
|
||||
- auto-mute-ch2 # Output: high when channel 2 is auto-muted
|
||||
- auto-mute-ch1 # Output: high when channel 1 is auto-muted
|
||||
- sdout2 # Output: Routes secondary serial data output 2
|
||||
- sdout1 # Output: Re-routes secondary serial data output 1
|
||||
- warn # Output: warning signal (OTW, CBC)
|
||||
- fault # Output: fault signal (OTSD, OC, DC)
|
||||
- clock-sync # Output: clock synchronisation
|
||||
- invalid-clock # Output: high when clock is invalid
|
||||
- high # Output: driven high
|
||||
- mute # Input: external mute control
|
||||
- phase-sync # Input: phase synchronisation
|
||||
- sdin2 # Input: secondary SDIN2 for I2S/LJ/RJ ch3/ch4
|
||||
- deep-sleep # Input: asserted transitions device to Deep Sleep
|
||||
- hiz # Input: asserted transitions device to Hi-Z
|
||||
- play # Input: asserted transitions device to Play
|
||||
- sleep # Input: asserted transitions device to Sleep
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
properties:
|
||||
port@0:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
description: Standard audio playback port (DAI 0).
|
||||
|
||||
port@1:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
description: Low-latency playback port (LLP) (DAI 1).
|
||||
|
||||
port@2:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
description: Sensory feedback capture port (DAI 2).
|
||||
|
||||
port:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- '#sound-dai-cells'
|
||||
- dvdd-supply
|
||||
- pvdd-supply
|
||||
|
||||
anyOf:
|
||||
- required: [powerdown-gpios]
|
||||
- required: [standby-gpios]
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
amplifier@70 {
|
||||
compatible = "ti,tas67524";
|
||||
reg = <0x70>;
|
||||
#sound-dai-cells = <1>;
|
||||
sound-name-prefix = "TAS0";
|
||||
|
||||
standby-gpios = <&main_gpio0 33 GPIO_ACTIVE_LOW>;
|
||||
|
||||
dvdd-supply = <&dvdd_1v8>;
|
||||
pvdd-supply = <&pvdd_12v>;
|
||||
vbat-supply = <&vbat_12v>;
|
||||
|
||||
ti,audio-slot-no = <0>;
|
||||
ti,llp-slot-no = <4>;
|
||||
ti,vpredict-slot-no = <0>;
|
||||
ti,isense-slot-no = <4>;
|
||||
|
||||
ti,gpio2-function = "warn";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
tas0_audio_ep: endpoint {
|
||||
dai-format = "dsp_b";
|
||||
remote-endpoint = <&be_tas0_audio_ep>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
tas0_anc_ep: endpoint {
|
||||
remote-endpoint = <&be_tas0_anc_ep>;
|
||||
};
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
|
||||
tas0_fb_ep: endpoint {
|
||||
remote-endpoint = <&be_tas0_fb_ep>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -1097,7 +1097,7 @@ output (with ``--no-upload`` option) to kernel bugzilla or alsa-devel
|
|||
ML (see the section `Links and Addresses`_).
|
||||
|
||||
``power_save`` and ``power_save_controller`` options are for power-saving
|
||||
mode. See powersave.rst for details.
|
||||
mode. See Documentation/sound/designs/powersave.rst for details.
|
||||
|
||||
Note 2: If you get click noises on output, try the module option
|
||||
``position_fix=1`` or ``2``. ``position_fix=1`` will use the SD_LPIB
|
||||
|
|
@ -1168,7 +1168,7 @@ line_outs_monitor
|
|||
enable_monitor
|
||||
Enable Analog Out on Channel 63/64 by default.
|
||||
|
||||
See hdspm.rst for details.
|
||||
See Documentation/sound/cards/hdspm.rst for details.
|
||||
|
||||
Module snd-ice1712
|
||||
------------------
|
||||
|
|
|
|||
|
|
@ -7,3 +7,4 @@ Codec-Specific Information
|
|||
:maxdepth: 2
|
||||
|
||||
cs35l56
|
||||
tas675x
|
||||
|
|
|
|||
820
Documentation/sound/codecs/tas675x.rst
Normal file
820
Documentation/sound/codecs/tas675x.rst
Normal file
|
|
@ -0,0 +1,820 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
======================================
|
||||
TAS675x Codec Mixer Controls
|
||||
======================================
|
||||
|
||||
This document describes the ALSA mixer controls for the TAS675x
|
||||
4-channel amplifier driver.
|
||||
|
||||
For device tree bindings, see:
|
||||
Documentation/devicetree/bindings/sound/ti,tas67524.yaml
|
||||
|
||||
DSP Signal Path Mode
|
||||
====================
|
||||
|
||||
DSP Signal Path Mode
|
||||
--------------------
|
||||
|
||||
:Description: Signal processing mode selection.
|
||||
:Type: Enumerated
|
||||
:Default: Normal
|
||||
:Options: Normal, LLP, FFLP
|
||||
:Register: 0x32 bits [1:0]
|
||||
|
||||
Normal
|
||||
Full DSP with all features available.
|
||||
|
||||
LLP (Low Latency Path)
|
||||
Bypasses DSP processing. DSP protection features (Thermal Foldback,
|
||||
PVDD Foldback, Clip Detect) and Real-Time Load Diagnostics unavailable.
|
||||
|
||||
FFLP (Full Feature Low Latency Path)
|
||||
Reduced latency. Real-Time Load Diagnostics unavailable.
|
||||
|
||||
The following controls are unavailable in LLP mode:
|
||||
``Thermal Foldback Switch``, ``PVDD Foldback Switch``,
|
||||
``DC Blocker Bypass Switch``, ``Clip Detect Switch``, ``Audio SDOUT Switch``.
|
||||
|
||||
The following controls require Normal mode (unavailable in FFLP and LLP):
|
||||
``CHx RTLDG Switch``, ``RTLDG Clip Mask Switch``, ``ISENSE Calibration Switch``,
|
||||
``RTLDG Open Load Threshold``, ``RTLDG Short Load Threshold``,
|
||||
``CHx RTLDG Impedance``.
|
||||
|
||||
Volume Controls
|
||||
===============
|
||||
|
||||
Analog Playback Volume
|
||||
----------------------
|
||||
|
||||
:Description: Analog output gain for all channels (CH1/CH2 and CH3/CH4 pairs).
|
||||
:Type: Volume (TLV)
|
||||
:Default: 0 dB
|
||||
:Range: -15.5 dB to 0 dB (0.5 dB steps)
|
||||
:Register: 0x4A (CH1/CH2), 0x4B (CH3/CH4)
|
||||
|
||||
Analog Gain Ramp Step
|
||||
---------------------
|
||||
|
||||
:Description: Anti-pop ramp step duration for analog gain transitions.
|
||||
:Type: Enumerated
|
||||
:Default: 15us
|
||||
:Options: 15us, 60us, 200us, 400us
|
||||
:Register: 0x4E bits [3:2]
|
||||
|
||||
CHx Digital Playback Volume
|
||||
---------------------------
|
||||
|
||||
:Description: Per-channel digital volume control (x = 1, 2, 3, 4).
|
||||
:Type: Volume (TLV)
|
||||
:Default: 0 dB
|
||||
:Range: -103 dB to 0 dB (0.5 dB steps)
|
||||
:Bounds: 0x30 (min/mute) to 0xFF (max)
|
||||
:Register: 0x40 (CH1), 0x41 (CH2), 0x42 (CH3), 0x43 (CH4)
|
||||
|
||||
Volume Ramp Down Rate
|
||||
---------------------
|
||||
|
||||
:Description: Update frequency during mute transition.
|
||||
:Type: Enumerated
|
||||
:Default: 16 FS
|
||||
:Options: 4 FS, 16 FS, 32 FS, Instant
|
||||
:Register: 0x44 bits [7:6]
|
||||
|
||||
Volume Ramp Down Step
|
||||
---------------------
|
||||
|
||||
:Description: dB change per update during mute.
|
||||
:Type: Enumerated
|
||||
:Default: 0.5dB
|
||||
:Options: 4dB, 2dB, 1dB, 0.5dB
|
||||
:Register: 0x44 bits [5:4]
|
||||
|
||||
Volume Ramp Up Rate
|
||||
-------------------
|
||||
|
||||
:Description: Update frequency during unmute transition.
|
||||
:Type: Enumerated
|
||||
:Default: 16 FS
|
||||
:Options: 4 FS, 16 FS, 32 FS, Instant
|
||||
:Register: 0x44 bits [3:2]
|
||||
|
||||
Volume Ramp Up Step
|
||||
-------------------
|
||||
|
||||
:Description: dB change per update during unmute.
|
||||
:Type: Enumerated
|
||||
:Default: 0.5dB
|
||||
:Options: 4dB, 2dB, 1dB, 0.5dB
|
||||
:Register: 0x44 bits [1:0]
|
||||
|
||||
CH1/2 Volume Combine
|
||||
--------------------
|
||||
|
||||
:Description: Links digital volume controls for CH1 and CH2.
|
||||
:Type: Enumerated
|
||||
:Default: Independent
|
||||
:Options: Independent, CH2 follows CH1, CH1 follows CH2
|
||||
:Register: 0x46 bits [1:0]
|
||||
|
||||
CH3/4 Volume Combine
|
||||
--------------------
|
||||
|
||||
:Description: Links digital volume controls for CH3 and CH4.
|
||||
:Type: Enumerated
|
||||
:Default: Independent
|
||||
:Options: Independent, CH4 follows CH3, CH3 follows CH4
|
||||
:Register: 0x46 bits [3:2]
|
||||
|
||||
Auto Mute & Silence Detection
|
||||
==============================
|
||||
|
||||
CHx Auto Mute Switch
|
||||
--------------------
|
||||
|
||||
:Description: Enables automatic muting on zero-signal detection (x = 1, 2, 3, 4).
|
||||
:Type: Boolean Switch
|
||||
:Default: Disabled (0)
|
||||
:Register: 0x47 bit [0] (CH1), bit [1] (CH2), bit [2] (CH3), bit [3] (CH4)
|
||||
|
||||
Auto Mute Combine Switch
|
||||
------------------------
|
||||
|
||||
:Description: Coordinated muting behaviour across all channels.
|
||||
:Type: Boolean Switch
|
||||
:Default: Disabled (0)
|
||||
:Behavior: Disabled: channels mute independently when their signal is zero.
|
||||
Enabled: all channels mute together only when all detect zero
|
||||
signal; unmute when any channel has non-zero signal.
|
||||
:Register: 0x47 bit [4]
|
||||
|
||||
CHx Auto Mute Time
|
||||
------------------
|
||||
|
||||
:Description: Duration of zero signal before muting triggers (x = 1, 2, 3, 4).
|
||||
:Type: Enumerated
|
||||
:Default: 11.5ms
|
||||
:Options: 11.5ms, 53ms, 106.5ms, 266.5ms, 535ms, 1065ms, 2665ms, 5330ms
|
||||
:Register: 0x48 bits [7:4] (CH1), bits [3:0] (CH2),
|
||||
0x49 bits [7:4] (CH3), bits [3:0] (CH4)
|
||||
:Note: Values are at 96 kHz. At 48 kHz, times are doubled.
|
||||
|
||||
Clock & EMI Management
|
||||
======================
|
||||
|
||||
Spread Spectrum Mode
|
||||
--------------------
|
||||
|
||||
:Description: Frequency dithering mode to reduce peak EMI.
|
||||
:Type: Enumerated
|
||||
:Default: Disabled
|
||||
:Options: Disabled, Triangle, Random, Triangle and Random
|
||||
:Register: 0x61 bits [1:0]
|
||||
|
||||
SS Triangle Range
|
||||
-----------------
|
||||
|
||||
:Description: Frequency deviation range for Triangle spread spectrum.
|
||||
:Type: Enumerated
|
||||
:Default: 6.5%
|
||||
:Options: 6.5%, 13.5%, 5%, 10%
|
||||
:Register: 0x62 bits [1:0]
|
||||
:Note: Applies only when Spread Spectrum Mode includes Triangle.
|
||||
|
||||
SS Random Range
|
||||
---------------
|
||||
|
||||
:Description: Frequency deviation range for Random spread spectrum.
|
||||
:Type: Enumerated
|
||||
:Default: 0.83%
|
||||
:Options: 0.83%, 2.50%, 5.83%, 12.50%, 25.83%
|
||||
:Register: 0x62 bits [6:4]
|
||||
:Note: Applies only when Spread Spectrum Mode includes Random.
|
||||
|
||||
SS Random Dwell Range
|
||||
---------------------
|
||||
|
||||
:Description: Dwell time range for Random spread spectrum (FSS = spread
|
||||
spectrum modulation frequency).
|
||||
:Type: Enumerated
|
||||
:Default: 1/FSS to 2/FSS
|
||||
:Options: 1/FSS to 2/FSS, 1/FSS to 4/FSS, 1/FSS to 8/FSS, 1/FSS to 15/FSS
|
||||
:Register: 0x62 bits [3:2]
|
||||
:Note: Applies only when Spread Spectrum Mode includes Random.
|
||||
|
||||
SS Triangle Dwell Min
|
||||
---------------------
|
||||
|
||||
:Description: Minimum dwell time at Triangle spread spectrum frequency extremes.
|
||||
:Type: Integer
|
||||
:Default: 0
|
||||
:Range: 0 to 15 (0 = feature disabled)
|
||||
:Register: 0x66 bits [7:4]
|
||||
:Note: Counts in FSS clock cycles. The modulator holds the extreme
|
||||
frequency for at least this many FSS cycles before reversing.
|
||||
When Dwell Min equals Dwell Max, the dwell feature is inactive.
|
||||
For FSS values at each PWM frequency refer to the "Spread
|
||||
Spectrum" section of the TRM.
|
||||
|
||||
SS Triangle Dwell Max
|
||||
---------------------
|
||||
|
||||
:Description: Maximum dwell time at Triangle spread spectrum frequency extremes.
|
||||
:Type: Integer
|
||||
:Default: 0
|
||||
:Range: 0 to 15 (0 = feature disabled)
|
||||
:Register: 0x66 bits [3:0]
|
||||
:Note: Counts in FSS clock cycles. Must be >= Dwell Min. When Dwell Max
|
||||
equals Dwell Min, the dwell feature is inactive.
|
||||
|
||||
Hardware Protection
|
||||
===================
|
||||
|
||||
OTSD Auto Recovery Switch
|
||||
--------------------------
|
||||
|
||||
:Description: Enables automatic recovery from over-temperature shutdown.
|
||||
:Type: Boolean Switch
|
||||
:Default: Disabled (0)
|
||||
:Register: 0x8F bit [1]
|
||||
:Note: When disabled, manual fault clearing is required after OTSD events.
|
||||
|
||||
Overcurrent Limit Level
|
||||
-----------------------
|
||||
|
||||
:Description: Current-limit trip point sensitivity.
|
||||
:Type: Enumerated
|
||||
:Default: Level 4
|
||||
:Options: Level 4, Level 3, Level 2, Level 1
|
||||
:Register: 0x55 bits [1:0]
|
||||
:Note: Level 4 is the least sensitive (highest trip current); Level 1 is
|
||||
the most sensitive. The exact ILIM values depend on operating
|
||||
conditions (PVDD voltage, switching frequency, and temperature).
|
||||
Refer to the Electrical Characteristics table and the
|
||||
"Overcurrent Limit (Cycle-By-Cycle)" section of the TRM.
|
||||
|
||||
CHx OTW Threshold
|
||||
-----------------
|
||||
|
||||
:Description: Over-temperature warning threshold per channel (x = 1, 2, 3, 4).
|
||||
:Type: Enumerated
|
||||
:Default: >95C
|
||||
:Options: Disabled, >95C, >110C, >125C, >135C, >145C, >155C, >165C
|
||||
:Register: 0xE2 bits [6:4] (CH1), bits [2:0] (CH2),
|
||||
0xE3 bits [6:4] (CH3), bits [2:0] (CH4)
|
||||
|
||||
Temperature and Voltage Monitoring
|
||||
===================================
|
||||
|
||||
PVDD Sense
|
||||
----------
|
||||
|
||||
:Description: Supply voltage sense register.
|
||||
:Type: Integer (read-only)
|
||||
:Range: 0 to 255
|
||||
:Conversion: value × 0.19 V
|
||||
:Register: 0x74
|
||||
|
||||
Global Temperature
|
||||
------------------
|
||||
|
||||
:Description: Global die temperature sense register.
|
||||
:Type: Integer (read-only)
|
||||
:Range: 0 to 255
|
||||
:Conversion: (value × 0.5 °C) − 50 °C
|
||||
:Register: 0x75
|
||||
|
||||
CHx Temperature Range
|
||||
---------------------
|
||||
|
||||
:Description: Per-channel coarse temperature range indicator (x = 1, 2, 3, 4).
|
||||
:Type: Integer (read-only)
|
||||
:Range: 0 to 3
|
||||
:Mapping: 0 = <80 °C, 1 = 80–100 °C, 2 = 100–120 °C, 3 = >120 °C
|
||||
:Register: 0xBB bits [7:6] (CH1), bits [5:4] (CH2),
|
||||
0xBC bits [3:2] (CH3), bits [1:0] (CH4)
|
||||
|
||||
Load Diagnostics
|
||||
================
|
||||
|
||||
The TAS675x provides three load diagnostic modes:
|
||||
|
||||
DC Load Diagnostics (DC LDG)
|
||||
Measures DC resistance to detect S2G (short-to-ground), S2P
|
||||
(short-to-power), OL (open load), and SL (shorted load) faults.
|
||||
|
||||
AC Load Diagnostics (AC LDG)
|
||||
Measures complex AC impedance at a configurable frequency. Detects
|
||||
capacitive loads and tweeter configurations.
|
||||
|
||||
Real-Time Load Diagnostics (RTLDG)
|
||||
Monitors impedance continuously during playback using a pilot tone.
|
||||
Normal DSP mode only, at 48 kHz or 96 kHz.
|
||||
|
||||
Fast Boot Mode
|
||||
--------------
|
||||
|
||||
By default the device runs DC load diagnostics at initialization before
|
||||
accepting audio. Setting ``ti,fast-boot`` in the device tree bypasses this
|
||||
initial diagnostic run for faster startup. Automatic diagnostics after
|
||||
fault recovery remain enabled.
|
||||
|
||||
DC Load Diagnostics
|
||||
-------------------
|
||||
|
||||
The ``CHx DC LDG Report`` 4-bit fault field uses the following encoding:
|
||||
|
||||
====== =========== ===================================================
|
||||
Bit Fault Description
|
||||
====== =========== ===================================================
|
||||
[3] S2G Short-to-Ground
|
||||
[2] S2P Short-to-Power
|
||||
[1] OL Open Load
|
||||
[0] SL Shorted Load
|
||||
====== =========== ===================================================
|
||||
|
||||
DC LDG Trigger
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
:Description: Triggers manual DC load diagnostics on all channels.
|
||||
:Type: Boolean (write-only)
|
||||
:Note: Returns -EBUSY if any DAI stream (playback or capture) is active.
|
||||
The driver manages all channel state transitions. Blocks until
|
||||
diagnostics complete or time out (300 ms).
|
||||
|
||||
DC LDG Auto Diagnostics Switch
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description: Enables automatic DC diagnostics after fault recovery.
|
||||
:Type: Boolean Switch
|
||||
:Default: Enabled (1)
|
||||
:Register: 0xB0 bit [0]
|
||||
:Note: Active-low, when enabled, affected channels re-run diagnostics after
|
||||
fault recovery and retry approximately every 750 ms until resolved.
|
||||
|
||||
CHx LO LDG Switch
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description: Enables line output load detection per channel (x = 1, 2, 3, 4).
|
||||
:Type: Boolean Switch
|
||||
:Default: Disabled (0)
|
||||
:Register: 0xB1 bit [3] (CH1), bit [2] (CH2), bit [1] (CH3), bit [0] (CH4)
|
||||
:Note: When enabled and DC diagnostics report OL, the device tests for
|
||||
a high-impedance line output load.
|
||||
|
||||
DC LDG SLOL Ramp Time
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description: Voltage ramp time for shorted-load and open-load detection.
|
||||
:Type: Enumerated
|
||||
:Default: 15 ms
|
||||
:Options: 15 ms, 30 ms, 10 ms, 20 ms
|
||||
:Register: 0xB2 bits [7:6]
|
||||
|
||||
DC LDG SLOL Settling Time
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description: Settling time for shorted-load and open-load detection.
|
||||
:Type: Enumerated
|
||||
:Default: 10 ms
|
||||
:Options: 10 ms, 5 ms, 20 ms, 15 ms
|
||||
:Register: 0xB2 bits [5:4]
|
||||
|
||||
DC LDG S2PG Ramp Time
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description: Voltage ramp time for short-to-power and short-to-ground detection.
|
||||
:Type: Enumerated
|
||||
:Default: 5 ms
|
||||
:Options: 5 ms, 2.5 ms, 10 ms, 15 ms
|
||||
:Register: 0xB2 bits [3:2]
|
||||
|
||||
DC LDG S2PG Settling Time
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description: Settling time for short-to-power and short-to-ground detection.
|
||||
:Type: Enumerated
|
||||
:Default: 10 ms
|
||||
:Options: 10 ms, 5 ms, 20 ms, 30 ms
|
||||
:Register: 0xB2 bits [1:0]
|
||||
|
||||
CHx DC LDG SL Threshold
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description: Shorted-load detection threshold per channel (x = 1, 2, 3, 4).
|
||||
:Type: Enumerated
|
||||
:Default: 1 Ohm
|
||||
:Options: 0.5 Ohm, 1 Ohm, 1.5 Ohm, 2 Ohm, 2.5 Ohm,
|
||||
3 Ohm, 3.5 Ohm, 4 Ohm, 4.5 Ohm, 5 Ohm
|
||||
:Register: 0xB3 bits [7:4] (CH1), bits [3:0] (CH2),
|
||||
0xB4 bits [7:4] (CH3), bits [3:0] (CH4)
|
||||
|
||||
DC LDG Result
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
:Description: Overall DC diagnostic result register.
|
||||
:Type: Integer (read-only)
|
||||
:Range: 0x00 to 0xFF
|
||||
:Register: 0xC2
|
||||
:Bit Encoding:
|
||||
|
||||
======== =====================================================
|
||||
Bits Description
|
||||
======== =====================================================
|
||||
[7:4] Line output detection result, one bit per channel
|
||||
[3:0] DC diagnostic pass/fail per channel (1=pass, 0=fail)
|
||||
======== =====================================================
|
||||
|
||||
CHx DC LDG Report
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description: DC diagnostic fault status per channel (x = 1, 2, 3, 4).
|
||||
:Type: Integer (read-only)
|
||||
:Range: 0x0 to 0xF
|
||||
:Register: 0xC0 bits [7:4] (CH1), bits [3:0] (CH2),
|
||||
0xC1 bits [7:4] (CH3), bits [3:0] (CH4)
|
||||
:Note: See fault bit encoding table at the start of this section.
|
||||
|
||||
CHx LO LDG Report
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description: Line output load detection result per channel (x = 1, 2, 3, 4).
|
||||
:Type: Boolean (read-only)
|
||||
:Values: 0 = not detected, 1 = line output load detected
|
||||
:Register: 0xC2 bit [7] (CH1), bit [6] (CH2), bit [5] (CH3), bit [4] (CH4)
|
||||
|
||||
CHx DC Resistance
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description: Measured DC load resistance per channel (x = 1, 2, 3, 4).
|
||||
:Type: Float (read-only, displayed in ohms)
|
||||
:Resolution: 0.1 ohm per code (10-bit value)
|
||||
:Range: 0.0 to 102.3 ohms
|
||||
:Register: 0xD9 bits [7:6]/[5:4]/[3:2]/[1:0] (MSB for CH1–CH4),
|
||||
0xDA (CH1 LSB), 0xDB (CH2 LSB), 0xDC (CH3 LSB), 0xDD (CH4 LSB)
|
||||
|
||||
AC Load Diagnostics
|
||||
-------------------
|
||||
|
||||
AC LDG Trigger
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
:Description: Triggers AC impedance measurement on all channels.
|
||||
:Type: Boolean (write-only)
|
||||
:Note: Returns -EBUSY if any DAI stream (playback or capture) is active.
|
||||
The driver transitions all channels to SLEEP state before starting
|
||||
the measurement. Blocks until diagnostics complete or time out.
|
||||
|
||||
AC LDG Gain
|
||||
~~~~~~~~~~~
|
||||
|
||||
:Description: Measurement resolution for AC diagnostics.
|
||||
:Type: Boolean Switch
|
||||
:Default: 1 (Gain 8)
|
||||
:Values: 0 = 0.8 ohm/code (Gain 1), 1 = 0.1 ohm/code (Gain 8)
|
||||
:Register: 0xB5 bit [4]
|
||||
:Note: Gain 8 recommended for load impedances below 8 ohms.
|
||||
|
||||
AC LDG Test Frequency
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description: Test signal frequency for AC impedance measurement.
|
||||
:Type: Integer
|
||||
:Default: 200 (0xC8 = 18.75 kHz)
|
||||
:Range: 0x01 to 0xFF (0x00 reserved)
|
||||
:Formula: Frequency = 93.75 Hz × register value
|
||||
:Register: 0xB8
|
||||
|
||||
CHx AC LDG Real / CHx AC LDG Imag
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description: Real and imaginary AC impedance components per channel
|
||||
(x = 1, 2, 3, 4).
|
||||
:Type: Integer (read-only)
|
||||
:Range: 0x00 to 0xFF (8-bit signed)
|
||||
:Register: 0xC3 (CH1 Real), 0xC4 (CH1 Imag), 0xC5 (CH2 Real), 0xC6 (CH2 Imag),
|
||||
0xC7 (CH3 Real), 0xC8 (CH3 Imag), 0xC9 (CH4 Real), 0xCA (CH4 Imag)
|
||||
:Note: Scale set by AC LDG Gain.
|
||||
|
||||
Speaker Protection & Detection
|
||||
-------------------------------
|
||||
|
||||
Tweeter Detection Switch
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description: Enables tweeter detection using the AC impedance magnitude comparator.
|
||||
:Type: Boolean Switch
|
||||
:Default: Enabled (1)
|
||||
:Register: 0xB6 bit [0]
|
||||
:Note: The underlying register bit is TWEETER DETECT DISABLE (active-low).
|
||||
Control value 1 = detection enabled (register bit 0), 0 = disabled
|
||||
(register bit 1).
|
||||
|
||||
Tweeter Detect Threshold
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description: Magnitude threshold for tweeter detection.
|
||||
:Type: Integer
|
||||
:Default: 0
|
||||
:Range: 0x00 to 0xFF
|
||||
:Resolution: 0.8 ohm/code (AC LDG Gain=0) or 0.1 ohm/code (AC LDG Gain=1)
|
||||
:Register: 0xB7
|
||||
|
||||
CHx Tweeter Detect Report
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Description: Tweeter detection result per channel (x = 1, 2, 3, 4).
|
||||
:Type: Boolean (read-only)
|
||||
:Values: 0 = no tweeter detected, 1 = tweeter detected
|
||||
:Register: 0xCB bit [3] (CH1), bit [2] (CH2), bit [1] (CH3), bit [0] (CH4)
|
||||
|
||||
DSP Protection Features
|
||||
=======================
|
||||
|
||||
These controls are unavailable in LLP mode.
|
||||
|
||||
Thermal Foldback Switch
|
||||
-----------------------
|
||||
|
||||
:Description: Enables dynamic gain reduction based on die temperature.
|
||||
:Type: Boolean Switch
|
||||
:Default: Disabled (0)
|
||||
:Register: 0x3A bit [0]
|
||||
|
||||
PVDD Foldback Switch
|
||||
--------------------
|
||||
|
||||
:Description: Enables automatic gain limiting when supply voltage drops
|
||||
(Automatic Gain Limiter).
|
||||
:Type: Boolean Switch
|
||||
:Default: Disabled (0)
|
||||
:Register: 0x3A bit [4]
|
||||
|
||||
DC Blocker Bypass Switch
|
||||
------------------------
|
||||
|
||||
:Description: Bypasses the DC-blocking high-pass filter.
|
||||
:Type: Boolean Switch
|
||||
:Default: Not bypassed (0)
|
||||
:Register: 0x39 bit [0]
|
||||
|
||||
Clip Detect Switch
|
||||
------------------
|
||||
|
||||
:Description: Enables DSP-based clip detection (Pseudo-Analog Clip Detect).
|
||||
:Type: Boolean Switch
|
||||
:Default: Disabled (0)
|
||||
:Register: 0x93 bit [6]
|
||||
|
||||
Audio SDOUT Switch
|
||||
------------------
|
||||
|
||||
:Description: Routes post-processed audio to the SDOUT pin instead of
|
||||
Vpredict data.
|
||||
:Type: Boolean Switch
|
||||
:Default: Disabled (0)
|
||||
:Register: 0x3A bit [5]
|
||||
:Note: When enabled, replaces Vpredict data on SDOUT with post-processed
|
||||
SDIN. All SDOUT configurations that apply to Vpredict also apply
|
||||
to SDIN-to-SDOUT transmission.
|
||||
|
||||
Real-Time Load Diagnostics
|
||||
===========================
|
||||
|
||||
These controls require Normal DSP mode at 48 kHz or 96 kHz. They are
|
||||
unavailable at 192 kHz and in FFLP and LLP modes.
|
||||
|
||||
|
||||
CHx RTLDG Switch
|
||||
----------------
|
||||
|
||||
:Description: Enables real-time impedance monitoring during playback
|
||||
(x = 1, 2, 3, 4).
|
||||
:Type: Boolean Switch
|
||||
:Default: Disabled (0)
|
||||
:Register: 0x37 bit [3] (CH1), bit [2] (CH2), bit [1] (CH3), bit [0] (CH4)
|
||||
|
||||
RTLDG Clip Mask Switch
|
||||
----------------------
|
||||
|
||||
:Description: Suppresses impedance updates during clipping events.
|
||||
:Type: Boolean Switch
|
||||
:Default: Enabled (1)
|
||||
:Register: 0x37 bit [4]
|
||||
|
||||
ISENSE Calibration Switch
|
||||
--------------------------
|
||||
|
||||
:Description: Enables current sense calibration for accurate impedance
|
||||
measurements.
|
||||
:Type: Boolean Switch
|
||||
:Default: Disabled (0)
|
||||
:Register: 0x5B bit [3]
|
||||
|
||||
RTLDG Open Load Threshold
|
||||
--------------------------
|
||||
|
||||
:Description: DSP coefficient for open load fault detection threshold.
|
||||
:Type: DSP coefficient (extended control)
|
||||
:Register: DSP Book 0x8C, page 0x22, 0x98
|
||||
|
||||
RTLDG Short Load Threshold
|
||||
---------------------------
|
||||
|
||||
:Description: DSP coefficient for shorted load fault detection threshold.
|
||||
:Type: DSP coefficient (extended control)
|
||||
:Register: DSP Book 0x8C, page 0x22, 0x9C
|
||||
|
||||
CHx RTLDG Impedance
|
||||
-------------------
|
||||
|
||||
:Description: Real-time load impedance per channel (x = 1, 2, 3, 4).
|
||||
:Type: Float (read-only, displayed in ohms)
|
||||
:Register: 0xD1–0xD2 (CH1), 0xD3–0xD4 (CH2), 0xD5–0xD6 (CH3), 0xD7–0xD8 (CH4)
|
||||
:Note: Valid only during PLAY state with RTLDG enabled at 48 or
|
||||
96 kHz. Holds stale data in SLEEP, MUTE, or Hi-Z states.
|
||||
|
||||
Fault Monitoring
|
||||
================
|
||||
|
||||
The driver monitors faults via IRQ or periodic polling (fallback when
|
||||
no ``interrupts`` DT property is present). Detected faults are logged
|
||||
and cleared so affected channels can recover.
|
||||
|
||||
Kernel log messages use the format::
|
||||
|
||||
tas675x <addr>: <Name> Latched: 0x<value>
|
||||
|
||||
Critical faults are logged at ``CRIT`` level; warnings at ``WARN``.
|
||||
|
||||
The following fault registers are monitored:
|
||||
|
||||
Critical Faults
|
||||
---------------
|
||||
|
||||
These faults place affected channels into the FAULT state. The driver
|
||||
issues fault clear (register 0x01 bit 3) to allow recovery.
|
||||
|
||||
Overtemperature Shutdown (0x87)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
======== ==========================================
|
||||
Bits Description
|
||||
======== ==========================================
|
||||
[4] Global OTSD
|
||||
[3:0] CH1-CH4 OTSD respectively
|
||||
======== ==========================================
|
||||
|
||||
Fires when die temperature exceeds the OTSD threshold. If auto-recovery
|
||||
is enabled (``OTSD Auto Recovery Switch``), channels return to their
|
||||
previous state after cooling. Otherwise fault clear is required.
|
||||
|
||||
Overcurrent / DC Fault (0x8E)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
======== ==========================================
|
||||
Bits Description
|
||||
======== ==========================================
|
||||
[7:4] Overcurrent Shutdown, CH1-CH4 respectively
|
||||
[3:0] DC Fault, CH1-CH4 respectively
|
||||
======== ==========================================
|
||||
|
||||
Overcurrent shutdown occurs when output current reaches the shutdown
|
||||
threshold (e.g. output short to GND). DC fault fires when DC offset
|
||||
exceeds the DCFAULT threshold.
|
||||
|
||||
Real-Time Load Diagnostic Fault (0x8B)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
======== ==========================================
|
||||
Bits Description
|
||||
======== ==========================================
|
||||
[7:4] Shorted Load faults, CH1-CH4 respectively
|
||||
[3:0] Open Load faults, CH1-CH4 respectively
|
||||
======== ==========================================
|
||||
|
||||
Reported during playback when RTLDG detects impedance outside the
|
||||
configured open/short thresholds. Requires RTLDG and current sense to
|
||||
be enabled, and a sampling rate of 48 kHz or 96 kHz.
|
||||
|
||||
CBC Fault/Warning (0x8D)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
======== ==========================================
|
||||
Bits Description
|
||||
======== ==========================================
|
||||
[7:4] Load current warning, CH1-CH4 respectively
|
||||
[3:0] Load current fault, CH1-CH4 respectively
|
||||
======== ==========================================
|
||||
|
||||
Cycle-by-cycle current limiting events. A warning fires when the
|
||||
current limit is active for at least 25% of a 21.3 ms window. A fault
|
||||
fires if the warning persists for 170.4 ms continuously.
|
||||
|
||||
Warnings
|
||||
--------
|
||||
|
||||
These conditions are logged but do not place channels into FAULT state.
|
||||
Corresponding register bits are cleared when read. Nonetheless, the driver
|
||||
still clears all events as warnings also latch the (mapped) FAULT pin.
|
||||
|
||||
Power Fault (0x86)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
======== ==========================================
|
||||
Bits Description
|
||||
======== ==========================================
|
||||
[7] DVDD Power-On-Reset
|
||||
[4] DVDD Undervoltage
|
||||
[3] PVDD Overvoltage
|
||||
[2] VBAT Overvoltage
|
||||
[1] PVDD Undervoltage
|
||||
[0] VBAT Undervoltage
|
||||
======== ==========================================
|
||||
|
||||
Supply-related events. DVDD POR at bit 7 is expected after every
|
||||
power-up and can be ignored.
|
||||
|
||||
CP / OUTM Soft Short Fault (0x7D)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
======== ==========================================
|
||||
Bits Description
|
||||
======== ==========================================
|
||||
[5:2] OUTM soft short, CH4-CH1 respectively
|
||||
[1] Charge Pump UVLO (latched)
|
||||
[0] Charge Pump UVLO (unlatched/live status)
|
||||
======== ==========================================
|
||||
|
||||
Per-channel out_minus soft short faults and charge pump undervoltage lockout.
|
||||
|
||||
Clock Fault (0x8A)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
======== ==========================================
|
||||
Bits Description
|
||||
======== ==========================================
|
||||
[0] Clock error
|
||||
======== ==========================================
|
||||
|
||||
Fires on clock halt or unsupported SCLK/FSYNC ratio. Only logged when
|
||||
a stream is active (suppressed during idle to avoid noise from normal
|
||||
stream stop/start transitions). See `Clock Fault Behaviour`_ below.
|
||||
|
||||
Overtemperature Warning (0x88)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
======== ==========================================
|
||||
Bits Description
|
||||
======== ==========================================
|
||||
[4] Global OTW
|
||||
[3:0] CH1-CH4 OTW respectively
|
||||
======== ==========================================
|
||||
|
||||
Fires when temperature crosses the OTW threshold. The device continues
|
||||
to operate. Only logged on change to avoid log spam.
|
||||
|
||||
Clip Warning (0x89)
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
======== ==========================================
|
||||
Bits Description
|
||||
======== ==========================================
|
||||
[3:0] CH1-CH4 clip detected respectively
|
||||
======== ==========================================
|
||||
|
||||
Fires when the audio signal magnitude exceeds the clip detection
|
||||
threshold. Requires Clip Detect to be enabled. Only logged when a
|
||||
stream is active.
|
||||
|
||||
Driver Known Limitations
|
||||
========================
|
||||
|
||||
Clock Fault Behaviour
|
||||
---------------------
|
||||
|
||||
On Stream Stop
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Every time a playback stream stops the FAULT pin briefly asserts. The
|
||||
ASoC PCM trigger stop sequence calls DAIs in reverse order, so the CPU
|
||||
DAI stops SCLK before the codec can transition to sleep. The device
|
||||
detects the clock halt and latches ``CLK_FAULT_LATCHED``, which asserts
|
||||
the FAULT pin. The driver clears the latch in the ``mute_stream``
|
||||
callback that follows, so the FAULT pin flicker lasts only a few
|
||||
milliseconds. Audio output is not affected and no kernel log message
|
||||
is produced.
|
||||
|
||||
On Rapid Rate Switching
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When streams are started in rapid succession, an intermittent
|
||||
``Clock Fault Latched: 0x01`` message may appear in the kernel log.
|
||||
A (conservative) ~0.5 second gap between sessions eliminates this.
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
- TAS675x Technical Reference Manual: SLOU589A
|
||||
- Device Tree Bindings: Documentation/devicetree/bindings/sound/ti,tas67524.yaml
|
||||
- ALSA Control Name Conventions: Documentation/sound/designs/control-names.rst
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
ALSA SoC Layer
|
||||
==============
|
||||
|
||||
The documentation is spilt into the following sections:-
|
||||
The documentation is split into the following sections:-
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
|
|
|||
|
|
@ -75,4 +75,4 @@ Each SoC DSP driver usually supplies the following features :-
|
|||
3. DMA IO to/from DSP buffers (if applicable)
|
||||
4. Definition of DSP front end (FE) PCM devices.
|
||||
|
||||
Please see DPCM.txt for a description of item 4.
|
||||
Please see dpcm.rst for a description of item 4.
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ Returns 0 on success, and -EOPNOTSUPP on failure.
|
|||
- ``usbdev``: the usb device that was discovered
|
||||
- ``sdev``: capabilities of the device
|
||||
|
||||
**snd_soc_usb_connect()** notifies the ASoC USB DCPM BE DAI link of a USB
|
||||
**snd_soc_usb_connect()** notifies the ASoC USB DPCM BE DAI link of a USB
|
||||
audio device detection. This can be utilized in the BE DAI
|
||||
driver to keep track of available USB audio devices. This is intended
|
||||
to be called by the USB offload driver residing in USB SND.
|
||||
|
|
@ -118,7 +118,7 @@ Returns 0 on success, negative error code on failure.
|
|||
- ``usbdev``: the usb device that was removed
|
||||
- ``sdev``: capabilities to free
|
||||
|
||||
**snd_soc_usb_disconnect()** notifies the ASoC USB DCPM BE DAI link of a USB
|
||||
**snd_soc_usb_disconnect()** notifies the ASoC USB DPCM BE DAI link of a USB
|
||||
audio device removal. This is intended to be called by the USB offload
|
||||
driver that resides in USB SND.
|
||||
|
||||
|
|
|
|||
22
MAINTAINERS
22
MAINTAINERS
|
|
@ -6535,7 +6535,7 @@ F: include/linux/blk-cgroup.h
|
|||
|
||||
CONTROL GROUP - CPUSET
|
||||
M: Waiman Long <longman@redhat.com>
|
||||
R: Chen Ridong <chenridong@huaweicloud.com>
|
||||
R: Ridong Chen <ridong.chen@linux.dev>
|
||||
L: cgroups@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git
|
||||
|
|
@ -15051,6 +15051,15 @@ F: arch/loongarch/
|
|||
F: drivers/*/*loongarch*
|
||||
F: drivers/cpufreq/loongson3_cpufreq.c
|
||||
|
||||
LOONGSON AUDIO (ASoC) DRIVERS
|
||||
M: Binbin Zhou <zhoubinbin@loongson.cn>
|
||||
L: linux-sound@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/sound/loongson,ls-audio-card.yaml
|
||||
F: Documentation/devicetree/bindings/sound/loongson,ls2k1000-i2s.yaml
|
||||
F: sound/soc/loongson/loongson_*.c
|
||||
F: sound/soc/loongson/loongson_*.h
|
||||
|
||||
LOONGSON GPIO DRIVER
|
||||
M: Yinbo Zhu <zhuyinbo@loongson.cn>
|
||||
L: linux-gpio@vger.kernel.org
|
||||
|
|
@ -25037,6 +25046,13 @@ F: include/sound/dmaengine_pcm.h
|
|||
F: sound/core/pcm_dmaengine.c
|
||||
F: sound/soc/soc-generic-dmaengine-pcm.c
|
||||
|
||||
SOUND - SOC LAYER / GPIO AUDIO AMPLIFIER
|
||||
M: Herve Codina <herve.codina@bootlin.com>
|
||||
L: linux-sound@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/sound/gpio-audio-amp.yaml
|
||||
F: sound/soc/codecs/simple-amplifier.c
|
||||
|
||||
SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
|
||||
M: Liam Girdwood <lgirdwood@gmail.com>
|
||||
M: Mark Brown <broonie@kernel.org>
|
||||
|
|
@ -26372,17 +26388,20 @@ TEXAS INSTRUMENTS AUDIO (ASoC/HDA) DRIVERS
|
|||
M: Shenghao Ding <shenghao-ding@ti.com>
|
||||
M: Kevin Lu <kevin-lu@ti.com>
|
||||
M: Baojun Xu <baojun.xu@ti.com>
|
||||
M: Sen Wang <sen@ti.com>
|
||||
L: linux-sound@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/sound/ti,tas2552.yaml
|
||||
F: Documentation/devicetree/bindings/sound/ti,tas2562.yaml
|
||||
F: Documentation/devicetree/bindings/sound/ti,tas2770.yaml
|
||||
F: Documentation/devicetree/bindings/sound/ti,tas27xx.yaml
|
||||
F: Documentation/devicetree/bindings/sound/ti,tas67524.yaml
|
||||
F: Documentation/devicetree/bindings/sound/ti,tpa6130a2.yaml
|
||||
F: Documentation/devicetree/bindings/sound/ti,pcm1681.yaml
|
||||
F: Documentation/devicetree/bindings/sound/ti,pcm3168a.yaml
|
||||
F: Documentation/devicetree/bindings/sound/ti,tlv320*.yaml
|
||||
F: Documentation/devicetree/bindings/sound/ti,tlv320adcx140.yaml
|
||||
F: Documentation/sound/codecs/tas675x*
|
||||
F: include/sound/tas2*.h
|
||||
F: include/sound/tlv320*.h
|
||||
F: sound/hda/codecs/side-codecs/tas2781_hda_i2c.c
|
||||
|
|
@ -26396,6 +26415,7 @@ F: sound/soc/codecs/pcm3168a*.*
|
|||
F: sound/soc/codecs/pcm5102a.c
|
||||
F: sound/soc/codecs/pcm512x*.*
|
||||
F: sound/soc/codecs/tas2*.*
|
||||
F: sound/soc/codecs/tas675x*.*
|
||||
F: sound/soc/codecs/tlv320*.*
|
||||
F: sound/soc/codecs/tpa6130a2.*
|
||||
|
||||
|
|
|
|||
5
Makefile
5
Makefile
|
|
@ -2,7 +2,7 @@
|
|||
VERSION = 7
|
||||
PATCHLEVEL = 1
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc6
|
||||
EXTRAVERSION = -rc7
|
||||
NAME = Baby Opossum Posse
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
@ -607,6 +607,7 @@ KBUILD_RUSTFLAGS := $(rust_common_flags) \
|
|||
-Crelocation-model=static \
|
||||
-Zfunction-sections=n \
|
||||
-Wclippy::float_arithmetic
|
||||
KBUILD_RUSTFLAGS_OPTION_CHKS :=
|
||||
|
||||
KBUILD_AFLAGS_KERNEL :=
|
||||
KBUILD_CFLAGS_KERNEL :=
|
||||
|
|
@ -643,7 +644,7 @@ export KBUILD_USERCFLAGS KBUILD_USERLDFLAGS
|
|||
|
||||
export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS KBUILD_LDFLAGS
|
||||
export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
|
||||
export KBUILD_RUSTFLAGS RUSTFLAGS_KERNEL RUSTFLAGS_MODULE
|
||||
export KBUILD_RUSTFLAGS RUSTFLAGS_KERNEL RUSTFLAGS_MODULE KBUILD_RUSTFLAGS_OPTION_CHKS
|
||||
export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
|
||||
export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_RUSTFLAGS_MODULE KBUILD_LDFLAGS_MODULE
|
||||
export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL KBUILD_RUSTFLAGS_KERNEL
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ config ARM
|
|||
select MMU_GATHER_RCU_TABLE_FREE if SMP && ARM_LPAE
|
||||
select HAVE_REGS_AND_STACK_ACCESS_API
|
||||
select HAVE_RSEQ
|
||||
select HAVE_RUST if CPU_LITTLE_ENDIAN && CPU_32v7
|
||||
select HAVE_RUST if CPU_LITTLE_ENDIAN && CPU_32v7 && !KASAN
|
||||
select HAVE_STACKPROTECTOR
|
||||
select HAVE_SYSCALL_TRACEPOINTS
|
||||
select HAVE_UID16
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ flash@30000000 {
|
|||
partitions {
|
||||
compatible = "redboot-fis";
|
||||
/* Eraseblock at 0xfe0000 */
|
||||
fis-index-block = <0x1fc>;
|
||||
fis-index-block = <0x7f>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ flash@30000000 {
|
|||
partitions {
|
||||
compatible = "redboot-fis";
|
||||
/* Eraseblock at 0xfe0000 */
|
||||
fis-index-block = <0x1fc>;
|
||||
fis-index-block = <0x7f>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -990,9 +990,9 @@ gmac: ethernet@f802c000 {
|
|||
<62 IRQ_TYPE_LEVEL_HIGH 3>, /* Queue 3 */
|
||||
<63 IRQ_TYPE_LEVEL_HIGH 3>, /* Queue 4 */
|
||||
<64 IRQ_TYPE_LEVEL_HIGH 3>; /* Queue 5 */
|
||||
clocks = <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_GCK 24>, <&pmc PMC_TYPE_GCK 67>;
|
||||
clock-names = "hclk", "pclk", "tx_clk", "tsu_clk";
|
||||
assigned-clocks = <&pmc PMC_TYPE_GCK 67>;
|
||||
clocks = <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_PERIPHERAL 24>, <&pmc PMC_TYPE_GCK 24>;
|
||||
clock-names = "hclk", "pclk", "tsu_clk";
|
||||
assigned-clocks = <&pmc PMC_TYPE_GCK 24>;
|
||||
assigned-clock-rates = <266666666>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
|
|
|||
|
|
@ -58,8 +58,15 @@ static unsigned long ac97_reset_config[] = {
|
|||
GPIO95_AC97_nRESET,
|
||||
};
|
||||
|
||||
void pxa27x_configure_ac97reset(int reset_gpio, bool to_gpio)
|
||||
void pxa27x_configure_ac97reset(struct gpio_desc *gpiod, bool to_gpio)
|
||||
{
|
||||
int reset_gpio;
|
||||
|
||||
if (!gpiod)
|
||||
return;
|
||||
|
||||
reset_gpio = desc_to_gpio(gpiod);
|
||||
|
||||
/*
|
||||
* This helper function is used to work around a bug in the pxa27x's
|
||||
* ac97 controller during a warm reset. The configuration of the
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus)
|
|||
}
|
||||
|
||||
socfpga_scu_base_addr = of_iomap(np, 0);
|
||||
of_node_put(np);
|
||||
if (!socfpga_scu_base_addr)
|
||||
return;
|
||||
scu_enable(socfpga_scu_base_addr);
|
||||
|
|
|
|||
|
|
@ -63,6 +63,9 @@ else
|
|||
KBUILD_CFLAGS += -fasynchronous-unwind-tables
|
||||
KBUILD_AFLAGS += -fasynchronous-unwind-tables
|
||||
KBUILD_RUSTFLAGS += -Cforce-unwind-tables=y -Zuse-sync-unwind=n
|
||||
# Work around rustc bug on compilers without
|
||||
# https://github.com/rust-lang/rust/pull/156973.
|
||||
KBUILD_RUSTFLAGS += $(if $(call rustc-min-version,109800),,-Zllvm_module_flag=uwtable:u32:2:max)
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y)
|
||||
|
|
|
|||
|
|
@ -843,7 +843,11 @@ ice: crypto@1d88000 {
|
|||
"qcom,inline-crypto-engine";
|
||||
reg = <0x0 0x01d88000 0x0 0x18000>;
|
||||
|
||||
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
|
||||
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>,
|
||||
<&gcc GCC_UFS_PHY_AHB_CLK>;
|
||||
clock-names = "core",
|
||||
"iface";
|
||||
power-domains = <&gcc GCC_UFS_PHY_GDSC>;
|
||||
};
|
||||
|
||||
tcsr_mutex: hwlock@1f40000 {
|
||||
|
|
|
|||
|
|
@ -2314,11 +2314,9 @@ usb_mp_qmpphy0: phy@fa3000 {
|
|||
|
||||
clocks = <&gcc GCC_USB3_MP_PHY_AUX_CLK>,
|
||||
<&tcsr TCSR_USB3_0_CLKREF_EN>,
|
||||
<&rpmhcc RPMH_CXO_CLK>,
|
||||
<&gcc GCC_USB3_MP_PHY_COM_AUX_CLK>,
|
||||
<&gcc GCC_USB3_MP_PHY_PIPE_0_CLK>;
|
||||
clock-names = "aux",
|
||||
"clkref",
|
||||
"ref",
|
||||
"com_aux",
|
||||
"pipe";
|
||||
|
|
@ -2343,11 +2341,9 @@ usb_mp_qmpphy1: phy@fa5000 {
|
|||
|
||||
clocks = <&gcc GCC_USB3_MP_PHY_AUX_CLK>,
|
||||
<&tcsr TCSR_USB3_1_CLKREF_EN>,
|
||||
<&rpmhcc RPMH_CXO_CLK>,
|
||||
<&gcc GCC_USB3_MP_PHY_COM_AUX_CLK>,
|
||||
<&gcc GCC_USB3_MP_PHY_PIPE_1_CLK>;
|
||||
clock-names = "aux",
|
||||
"clkref",
|
||||
"ref",
|
||||
"com_aux",
|
||||
"pipe";
|
||||
|
|
@ -2482,15 +2478,13 @@ usb_1_qmpphy: phy@fde000 {
|
|||
reg = <0x0 0x00fde000 0x0 0x8000>;
|
||||
|
||||
clocks = <&gcc GCC_USB3_SEC_PHY_AUX_CLK>,
|
||||
<&rpmhcc RPMH_CXO_CLK>,
|
||||
<&tcsr TCSR_USB4_1_CLKREF_EN>,
|
||||
<&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>,
|
||||
<&gcc GCC_USB3_SEC_PHY_PIPE_CLK>,
|
||||
<&tcsr TCSR_USB4_1_CLKREF_EN>;
|
||||
<&gcc GCC_USB3_SEC_PHY_PIPE_CLK>;
|
||||
clock-names = "aux",
|
||||
"ref",
|
||||
"com_aux",
|
||||
"usb3_pipe",
|
||||
"clkref";
|
||||
"usb3_pipe";
|
||||
|
||||
power-domains = <&gcc GCC_USB_1_PHY_GDSC>;
|
||||
|
||||
|
|
@ -3750,15 +3744,13 @@ usb_2_qmpphy: phy@88e1000 {
|
|||
reg = <0x0 0x088e1000 0x0 0x8000>;
|
||||
|
||||
clocks = <&gcc GCC_USB3_TERT_PHY_AUX_CLK>,
|
||||
<&rpmhcc RPMH_CXO_CLK>,
|
||||
<&tcsr TCSR_USB4_2_CLKREF_EN>,
|
||||
<&gcc GCC_USB3_TERT_PHY_COM_AUX_CLK>,
|
||||
<&gcc GCC_USB3_TERT_PHY_PIPE_CLK>,
|
||||
<&tcsr TCSR_USB4_2_CLKREF_EN>;
|
||||
<&gcc GCC_USB3_TERT_PHY_PIPE_CLK>;
|
||||
clock-names = "aux",
|
||||
"ref",
|
||||
"com_aux",
|
||||
"usb3_pipe",
|
||||
"clkref";
|
||||
"usb3_pipe";
|
||||
|
||||
power-domains = <&gcc GCC_USB_2_PHY_GDSC>;
|
||||
|
||||
|
|
|
|||
|
|
@ -1275,7 +1275,11 @@ ice: crypto@1d88000 {
|
|||
"qcom,inline-crypto-engine";
|
||||
reg = <0x0 0x01d88000 0x0 0x18000>;
|
||||
|
||||
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
|
||||
clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>,
|
||||
<&gcc GCC_UFS_PHY_AHB_CLK>;
|
||||
clock-names = "core",
|
||||
"iface";
|
||||
power-domains = <&gcc UFS_PHY_GDSC>;
|
||||
};
|
||||
|
||||
tcsr_mutex: hwlock@1f40000 {
|
||||
|
|
|
|||
|
|
@ -982,12 +982,6 @@ &i2c8 {
|
|||
status = "okay";
|
||||
};
|
||||
|
||||
&i2c20 {
|
||||
clock-frequency = <400000>;
|
||||
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&lpass_tlmm {
|
||||
spkr_01_sd_n_active: spkr-01-sd-n-active-state {
|
||||
pins = "gpio12";
|
||||
|
|
@ -1308,6 +1302,7 @@ right_tweeter: speaker@0,1 {
|
|||
&tlmm {
|
||||
gpio-reserved-ranges = <44 4>, /* SPI11 (TPM) */
|
||||
<76 4>, /* SPI19 (TZ Protected) */
|
||||
<80 2>, /* I2C20 (Battery SMBus) */
|
||||
<238 1>; /* UFS Reset */
|
||||
|
||||
cam_rgb_default: cam-rgb-default-state {
|
||||
|
|
|
|||
|
|
@ -260,6 +260,7 @@ CONFIG_PCI_ENDPOINT=y
|
|||
CONFIG_PCI_ENDPOINT_CONFIGFS=y
|
||||
CONFIG_PCI_EPF_TEST=m
|
||||
CONFIG_PCI_PWRCTRL_GENERIC=m
|
||||
CONFIG_POWER_SEQUENCING_PCIE_M2=m
|
||||
CONFIG_DEVTMPFS=y
|
||||
CONFIG_DEVTMPFS_MOUNT=y
|
||||
CONFIG_FW_LOADER_USER_HELPER=y
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ static inline bool kvm_s2_trans_exec_el0(struct kvm *kvm, struct kvm_s2_trans *t
|
|||
u8 xn = FIELD_GET(KVM_PTE_LEAF_ATTR_HI_S2_XN, trans->desc);
|
||||
|
||||
if (!kvm_has_xnx(kvm))
|
||||
xn &= FIELD_PREP(KVM_PTE_LEAF_ATTR_HI_S2_XN, 0b10);
|
||||
xn &= 0b10;
|
||||
|
||||
switch (xn) {
|
||||
case 0b00:
|
||||
|
|
@ -148,7 +148,7 @@ static inline bool kvm_s2_trans_exec_el1(struct kvm *kvm, struct kvm_s2_trans *t
|
|||
u8 xn = FIELD_GET(KVM_PTE_LEAF_ATTR_HI_S2_XN, trans->desc);
|
||||
|
||||
if (!kvm_has_xnx(kvm))
|
||||
xn &= FIELD_PREP(KVM_PTE_LEAF_ATTR_HI_S2_XN, 0b10);
|
||||
xn &= 0b10;
|
||||
|
||||
switch (xn) {
|
||||
case 0b00:
|
||||
|
|
|
|||
|
|
@ -1569,7 +1569,8 @@ int __kvm_at_s12(struct kvm_vcpu *vcpu, u32 op, u64 vaddr)
|
|||
/* Do the stage-2 translation */
|
||||
ipa = (par & GENMASK_ULL(47, 12)) | (vaddr & GENMASK_ULL(11, 0));
|
||||
out.esr = 0;
|
||||
ret = kvm_walk_nested_s2(vcpu, ipa, &out);
|
||||
scoped_guard(srcu, &vcpu->kvm->srcu)
|
||||
ret = kvm_walk_nested_s2(vcpu, ipa, &out);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
@ -1665,7 +1666,8 @@ int __kvm_find_s1_desc_level(struct kvm_vcpu *vcpu, u64 va, u64 ipa, int *level)
|
|||
}
|
||||
|
||||
/* Walk the guest's PT, looking for a match along the way */
|
||||
ret = walk_s1(vcpu, &wi, &wr, va);
|
||||
scoped_guard(srcu, &vcpu->kvm->srcu)
|
||||
ret = walk_s1(vcpu, &wi, &wr, va);
|
||||
switch (ret) {
|
||||
case -EINTR:
|
||||
/* We interrupted the walk on a match, return the level */
|
||||
|
|
|
|||
|
|
@ -181,6 +181,8 @@ static inline void __deactivate_cptr_traps_vhe(struct kvm_vcpu *vcpu)
|
|||
val |= CPACR_EL1_ZEN;
|
||||
if (cpus_have_final_cap(ARM64_SME))
|
||||
val |= CPACR_EL1_SMEN;
|
||||
if (cpus_have_final_cap(ARM64_HAS_S1POE))
|
||||
val |= CPACR_EL1_E0POE;
|
||||
|
||||
write_sysreg(val, cpacr_el1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -925,7 +925,9 @@ static bool stage2_pte_cacheable(struct kvm_pgtable *pgt, kvm_pte_t pte)
|
|||
|
||||
static bool stage2_pte_executable(kvm_pte_t pte)
|
||||
{
|
||||
return kvm_pte_valid(pte) && !(pte & KVM_PTE_LEAF_ATTR_HI_S2_XN);
|
||||
enum kvm_pgtable_prot prot = kvm_pgtable_stage2_pte_prot(pte);
|
||||
|
||||
return prot & (KVM_PGTABLE_PROT_UX | KVM_PGTABLE_PROT_PX);
|
||||
}
|
||||
|
||||
static u64 stage2_map_walker_phys_addr(const struct kvm_pgtable_visit_ctx *ctx,
|
||||
|
|
|
|||
|
|
@ -89,21 +89,28 @@ int kvm_vcpu_init_nested(struct kvm_vcpu *vcpu)
|
|||
* again, and there is no reason to affect the whole VM for this.
|
||||
*/
|
||||
num_mmus = atomic_read(&kvm->online_vcpus) * S2_MMU_PER_VCPU;
|
||||
tmp = kvrealloc(kvm->arch.nested_mmus,
|
||||
size_mul(sizeof(*kvm->arch.nested_mmus), num_mmus),
|
||||
GFP_KERNEL_ACCOUNT | __GFP_ZERO);
|
||||
if (!tmp)
|
||||
return -ENOMEM;
|
||||
|
||||
swap(kvm->arch.nested_mmus, tmp);
|
||||
if (num_mmus > kvm->arch.nested_mmus_size) {
|
||||
tmp = kvcalloc(num_mmus, sizeof(*tmp), GFP_KERNEL_ACCOUNT);
|
||||
if (!tmp)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* If we went through a realocation, adjust the MMU back-pointers in
|
||||
* the previously initialised kvm_pgtable structures.
|
||||
*/
|
||||
if (kvm->arch.nested_mmus != tmp)
|
||||
for (int i = 0; i < kvm->arch.nested_mmus_size; i++)
|
||||
kvm->arch.nested_mmus[i].pgt->mmu = &kvm->arch.nested_mmus[i];
|
||||
write_lock(&kvm->mmu_lock);
|
||||
|
||||
if (kvm->arch.nested_mmus_size) {
|
||||
memcpy(tmp, kvm->arch.nested_mmus,
|
||||
size_mul(sizeof(*tmp), kvm->arch.nested_mmus_size));
|
||||
|
||||
for (int i = 0; i < kvm->arch.nested_mmus_size; i++)
|
||||
tmp[i].pgt->mmu = &tmp[i];
|
||||
}
|
||||
|
||||
swap(kvm->arch.nested_mmus, tmp);
|
||||
|
||||
write_unlock(&kvm->mmu_lock);
|
||||
|
||||
kvfree(tmp);
|
||||
}
|
||||
|
||||
for (int i = kvm->arch.nested_mmus_size; !ret && i < num_mmus; i++)
|
||||
ret = init_nested_s2_mmu(kvm, &kvm->arch.nested_mmus[i]);
|
||||
|
|
|
|||
|
|
@ -597,8 +597,10 @@ static void vgic_its_invalidate_cache(struct vgic_its *its)
|
|||
unsigned long idx;
|
||||
|
||||
xa_for_each(&its->translation_cache, idx, irq) {
|
||||
xa_erase(&its->translation_cache, idx);
|
||||
vgic_put_irq(kvm, irq);
|
||||
/* Only the context that erases the entry drops its cache ref. */
|
||||
irq = xa_erase(&its->translation_cache, idx);
|
||||
if (irq)
|
||||
vgic_put_irq(kvm, irq);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,10 @@ CONFIG_EXPOLINE_AUTO=y
|
|||
CONFIG_CHSC_SCH=y
|
||||
CONFIG_VFIO_CCW=m
|
||||
CONFIG_VFIO_AP=m
|
||||
CONFIG_VFIO_DEVICE_CDEV=y
|
||||
CONFIG_IOMMUFD_DRIVER=y
|
||||
CONFIG_IOMMUFD_DRIVER_CORE=y
|
||||
CONFIG_IOMMUFD=y
|
||||
CONFIG_CMM=m
|
||||
CONFIG_APPLDATA_BASE=y
|
||||
CONFIG_S390_HYPFS_FS=y
|
||||
|
|
|
|||
|
|
@ -54,6 +54,10 @@ CONFIG_EXPOLINE_AUTO=y
|
|||
CONFIG_CHSC_SCH=y
|
||||
CONFIG_VFIO_CCW=m
|
||||
CONFIG_VFIO_AP=m
|
||||
CONFIG_VFIO_DEVICE_CDEV=y
|
||||
CONFIG_IOMMUFD_DRIVER=y
|
||||
CONFIG_IOMMUFD_DRIVER_CORE=y
|
||||
CONFIG_IOMMUFD=y
|
||||
CONFIG_CMM=m
|
||||
CONFIG_APPLDATA_BASE=y
|
||||
CONFIG_S390_HYPFS_FS=y
|
||||
|
|
|
|||
|
|
@ -12,12 +12,11 @@
|
|||
#if defined(CONFIG_BUG) && defined(CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS)
|
||||
|
||||
#ifdef CONFIG_DEBUG_BUGVERBOSE
|
||||
#define __BUG_ENTRY_VERBOSE(format, file, line) \
|
||||
" .long " format " - . # bug_entry::format\n" \
|
||||
#define __BUG_ENTRY_VERBOSE(file, line) \
|
||||
" .long " file " - . # bug_entry::file\n" \
|
||||
" .short " line " # bug_entry::line\n"
|
||||
#else
|
||||
#define __BUG_ENTRY_VERBOSE(format, file, line)
|
||||
#define __BUG_ENTRY_VERBOSE(file, line)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEBUG_BUGVERBOSE_DETAILED
|
||||
|
|
@ -28,9 +27,10 @@
|
|||
|
||||
#define __BUG_ENTRY(format, file, line, flags, size) \
|
||||
" .section __bug_table,\"aw\"\n" \
|
||||
"1: .long 0b - . # bug_entry::bug_addr\n" \
|
||||
__BUG_ENTRY_VERBOSE(format, file, line) \
|
||||
" .short "flags" # bug_entry::flags\n" \
|
||||
"1: .long 0b - . # bug_entry::bug_addr\n"\
|
||||
" .long " format " - . # bug_entry::format\n" \
|
||||
__BUG_ENTRY_VERBOSE(file, line) \
|
||||
" .short "flags" # bug_entry::flags\n" \
|
||||
" .org 1b+"size"\n" \
|
||||
" .previous"
|
||||
|
||||
|
|
|
|||
|
|
@ -12,5 +12,6 @@ void gmap_helper_zap_one_page(struct mm_struct *mm, unsigned long vmaddr);
|
|||
void gmap_helper_discard(struct mm_struct *mm, unsigned long vmaddr, unsigned long end);
|
||||
int gmap_helper_disable_cow_sharing(void);
|
||||
void gmap_helper_try_set_pte_unused(struct mm_struct *mm, unsigned long vmaddr);
|
||||
pte_t *try_get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl);
|
||||
|
||||
#endif /* _ASM_S390_GMAP_HELPERS_H */
|
||||
|
|
|
|||
|
|
@ -7,4 +7,6 @@
|
|||
#define __ALIGN .balign CONFIG_FUNCTION_ALIGNMENT, 0x07
|
||||
#define __ALIGN_STR __stringify(__ALIGN)
|
||||
|
||||
#define _THIS_IP_ ({ unsigned long __ip; asm volatile("larl %0, ." : "=d" (__ip)); __ip; })
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ int kvm_s390_faultin_gfn(struct kvm_vcpu *vcpu, struct kvm *kvm, struct guest_fa
|
|||
struct kvm_s390_mmu_cache *mc = NULL;
|
||||
struct kvm_memory_slot *slot;
|
||||
unsigned long inv_seq;
|
||||
int foll, rc = 0;
|
||||
int rc = -EAGAIN;
|
||||
int foll;
|
||||
|
||||
foll = f->write_attempt ? FOLL_WRITE : 0;
|
||||
foll |= f->attempt_pfault ? FOLL_NOWAIT : 0;
|
||||
|
|
@ -53,7 +54,14 @@ int kvm_s390_faultin_gfn(struct kvm_vcpu *vcpu, struct kvm *kvm, struct guest_fa
|
|||
return 0;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (!mc) {
|
||||
local_mc = kvm_s390_new_mmu_cache();
|
||||
if (!local_mc)
|
||||
return -ENOMEM;
|
||||
mc = local_mc;
|
||||
}
|
||||
|
||||
while (rc == -EAGAIN) {
|
||||
f->valid = false;
|
||||
inv_seq = kvm->mmu_invalidate_seq;
|
||||
/* Pairs with the smp_wmb() in kvm_mmu_invalidate_end(). */
|
||||
|
|
@ -93,14 +101,7 @@ int kvm_s390_faultin_gfn(struct kvm_vcpu *vcpu, struct kvm *kvm, struct guest_fa
|
|||
if (is_error_pfn(f->pfn))
|
||||
return -EFAULT;
|
||||
|
||||
if (!mc) {
|
||||
local_mc = kvm_s390_new_mmu_cache();
|
||||
if (!local_mc)
|
||||
return -ENOMEM;
|
||||
mc = local_mc;
|
||||
}
|
||||
|
||||
/* Loop, will automatically release the faulted page. */
|
||||
/* Loop, release the faulted page. */
|
||||
if (mmu_invalidate_retry_gfn_unsafe(kvm, inv_seq, f->gfn)) {
|
||||
kvm_release_faultin_page(kvm, f->page, true, false);
|
||||
continue;
|
||||
|
|
@ -110,20 +111,19 @@ int kvm_s390_faultin_gfn(struct kvm_vcpu *vcpu, struct kvm *kvm, struct guest_fa
|
|||
if (!mmu_invalidate_retry_gfn(kvm, inv_seq, f->gfn)) {
|
||||
f->valid = true;
|
||||
rc = gmap_link(mc, kvm->arch.gmap, f, slot);
|
||||
kvm_release_faultin_page(kvm, f->page, !!rc, f->write_attempt);
|
||||
f->page = NULL;
|
||||
}
|
||||
kvm_release_faultin_page(kvm, f->page, !!rc, f->write_attempt);
|
||||
}
|
||||
kvm_release_faultin_page(kvm, f->page, true, false);
|
||||
|
||||
if (rc == -ENOMEM) {
|
||||
rc = kvm_s390_mmu_cache_topup(mc);
|
||||
if (rc)
|
||||
return rc;
|
||||
} else if (rc != -EAGAIN) {
|
||||
return rc;
|
||||
rc = -EAGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int kvm_s390_get_guest_page(struct kvm *kvm, struct guest_fault *f, gfn_t gfn, bool w)
|
||||
|
|
|
|||
|
|
@ -1466,15 +1466,17 @@ static int _do_shadow_crste(struct gmap *sg, gpa_t raddr, union crste *host, uni
|
|||
struct guest_fault *f, bool p)
|
||||
{
|
||||
union crste newcrste, oldcrste;
|
||||
gfn_t gfn;
|
||||
unsigned long mask;
|
||||
gfn_t r_gfn;
|
||||
int rc;
|
||||
|
||||
lockdep_assert_held(&sg->kvm->mmu_lock);
|
||||
lockdep_assert_held(&sg->parent->children_lock);
|
||||
|
||||
gfn = f->gfn & (is_pmd(*table) ? _SEGMENT_FR_MASK : _REGION3_FR_MASK);
|
||||
mask = is_pmd(*table) ? _SEGMENT_FR_MASK : _REGION3_FR_MASK;
|
||||
r_gfn = gpa_to_gfn(raddr) & mask;
|
||||
scoped_guard(spinlock, &sg->host_to_rmap_lock)
|
||||
rc = gmap_insert_rmap(sg, gfn, gpa_to_gfn(raddr), host->h.tt);
|
||||
rc = gmap_insert_rmap(sg, f->gfn & mask, r_gfn, host->h.tt);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
|
|
@ -1497,8 +1499,7 @@ static int _do_shadow_crste(struct gmap *sg, gpa_t raddr, union crste *host, uni
|
|||
return -EAGAIN;
|
||||
|
||||
newcrste = _crste_fc1(f->pfn, oldcrste.h.tt, 0, !p);
|
||||
gfn = gpa_to_gfn(raddr);
|
||||
while (!dat_crstep_xchg_atomic(table, READ_ONCE(*table), newcrste, gfn, sg->asce))
|
||||
while (!dat_crstep_xchg_atomic(table, READ_ONCE(*table), newcrste, r_gfn, sg->asce))
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -395,15 +395,28 @@ static long _gmap_unmap_crste(union crste *crstep, gfn_t gfn, gfn_t next, struct
|
|||
struct gmap_unmap_priv *priv = walk->priv;
|
||||
struct folio *folio = NULL;
|
||||
union crste old = *crstep;
|
||||
bool ok;
|
||||
|
||||
if (!old.h.fc)
|
||||
return 0;
|
||||
|
||||
if (old.s.fc1.pr && test_bit(GMAP_FLAG_EXPORT_ON_UNMAP, &priv->gmap->flags))
|
||||
folio = phys_to_folio(crste_origin_large(old));
|
||||
/* No races should happen because kvm->mmu_lock is held in write mode */
|
||||
KVM_BUG_ON(!gmap_crstep_xchg_atomic(priv->gmap, crstep, old, _CRSTE_EMPTY(old.h.tt), gfn),
|
||||
priv->gmap->kvm);
|
||||
/*
|
||||
* No races should happen because kvm->mmu_lock is held in write mode,
|
||||
* but the unmap operation could have triggered an unshadow, which
|
||||
* causes gmap_crstep_xchg_atomic() to return false and clear the
|
||||
* vsie_notif bit. Allow the operation to fail once, if the old crste
|
||||
* had the vsie_notif bit set. A second failure is not allowed, for
|
||||
* the reasons above.
|
||||
*/
|
||||
ok = gmap_crstep_xchg_atomic(priv->gmap, crstep, old, _CRSTE_EMPTY(old.h.tt), gfn);
|
||||
if (!ok) {
|
||||
KVM_BUG_ON(!old.s.fc1.vsie_notif, priv->gmap->kvm);
|
||||
old.s.fc1.vsie_notif = 0;
|
||||
ok = gmap_crstep_xchg_atomic(priv->gmap, crstep, old, _CRSTE_EMPTY(old.h.tt), gfn);
|
||||
KVM_BUG_ON(!ok, priv->gmap->kvm);
|
||||
}
|
||||
if (folio)
|
||||
uv_convert_from_secure_folio(folio);
|
||||
|
||||
|
|
|
|||
|
|
@ -273,11 +273,14 @@ static inline bool __must_check _gmap_crstep_xchg_atomic(struct gmap *gmap, unio
|
|||
gmap_unmap_prefix(gmap, gfn, gfn + align);
|
||||
}
|
||||
if (crste_leaf(oldcrste) && crste_needs_unshadow(oldcrste, newcrste)) {
|
||||
newcrste = oldcrste;
|
||||
newcrste.s.fc1.vsie_notif = 0;
|
||||
if (needs_lock)
|
||||
gmap_handle_vsie_unshadow_event(gmap, gfn);
|
||||
else
|
||||
_gmap_handle_vsie_unshadow_event(gmap, gfn);
|
||||
dat_crstep_xchg_atomic(crstep, oldcrste, newcrste, gfn, gmap->asce);
|
||||
return false;
|
||||
}
|
||||
if (!oldcrste.s.fc1.d && newcrste.s.fc1.d && !newcrste.s.fc1.s)
|
||||
SetPageDirty(phys_to_page(crste_origin_large(newcrste)));
|
||||
|
|
|
|||
|
|
@ -999,7 +999,10 @@ static int kvm_s390_set_mem_control(struct kvm *kvm, struct kvm_device_attr *att
|
|||
break;
|
||||
}
|
||||
case KVM_S390_VM_MEM_LIMIT_SIZE: {
|
||||
struct kvm_memslots *slots;
|
||||
struct kvm_memory_slot *ms;
|
||||
unsigned long new_limit;
|
||||
int bkt;
|
||||
|
||||
if (kvm_is_ucontrol(kvm))
|
||||
return -EINVAL;
|
||||
|
|
@ -1007,6 +1010,9 @@ static int kvm_s390_set_mem_control(struct kvm *kvm, struct kvm_device_attr *att
|
|||
if (get_user(new_limit, (u64 __user *)attr->addr))
|
||||
return -EFAULT;
|
||||
|
||||
guard(mutex)(&kvm->lock);
|
||||
|
||||
new_limit = ALIGN(new_limit, HPAGE_SIZE);
|
||||
if (kvm->arch.mem_limit != KVM_S390_NO_MEM_LIMIT &&
|
||||
new_limit > kvm->arch.mem_limit)
|
||||
return -E2BIG;
|
||||
|
|
@ -1014,12 +1020,27 @@ static int kvm_s390_set_mem_control(struct kvm *kvm, struct kvm_device_attr *att
|
|||
if (!new_limit)
|
||||
return -EINVAL;
|
||||
|
||||
ret = -EBUSY;
|
||||
if (!kvm->created_vcpus)
|
||||
ret = gmap_set_limit(kvm->arch.gmap, gpa_to_gfn(new_limit));
|
||||
if (kvm->created_vcpus)
|
||||
return -EBUSY;
|
||||
|
||||
ret = 0;
|
||||
scoped_guard(mutex, &kvm->slots_lock) {
|
||||
slots = kvm_memslots(kvm);
|
||||
if (slots && !kvm_memslots_empty(slots)) {
|
||||
kvm_for_each_memslot(ms, bkt, slots) {
|
||||
if (gpa_to_gfn(new_limit) < ms->base_gfn + ms->npages) {
|
||||
ret = -EBUSY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ret)
|
||||
ret = gmap_set_limit(kvm->arch.gmap, gpa_to_gfn(new_limit));
|
||||
}
|
||||
if (ret)
|
||||
break;
|
||||
VM_EVENT(kvm, 3, "SET: max guest address: %lu", new_limit);
|
||||
VM_EVENT(kvm, 3, "New guest asce: 0x%p",
|
||||
(void *)kvm->arch.gmap->asce.val);
|
||||
VM_EVENT(kvm, 3, "New guest asce: 0x%p", (void *)kvm->arch.gmap->asce.val);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
@ -5672,6 +5693,8 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
|
|||
return -EINVAL;
|
||||
if ((new->base_gfn + new->npages) * PAGE_SIZE > kvm->arch.mem_limit)
|
||||
return -EINVAL;
|
||||
if (!asce_contains_gfn(kvm->arch.gmap->asce, new->base_gfn + new->npages - 1))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!kvm->arch.migration_mode)
|
||||
|
|
|
|||
|
|
@ -1188,6 +1188,7 @@ static void _essa_clear_cbrl(struct kvm_vcpu *vcpu, unsigned long *cbrl, int len
|
|||
union crste *crstep;
|
||||
union pgste pgste;
|
||||
union pte *ptep;
|
||||
hva_t hva;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&vcpu->kvm->mmu_lock);
|
||||
|
|
@ -1199,8 +1200,11 @@ static void _essa_clear_cbrl(struct kvm_vcpu *vcpu, unsigned long *cbrl, int len
|
|||
if (!ptep || ptep->s.pr)
|
||||
continue;
|
||||
pgste = pgste_get_lock(ptep);
|
||||
if (pgste.usage == PGSTE_GPS_USAGE_UNUSED || pgste.zero)
|
||||
gmap_helper_zap_one_page(vcpu->kvm->mm, cbrl[i]);
|
||||
if (pgste.usage == PGSTE_GPS_USAGE_UNUSED || pgste.zero) {
|
||||
hva = gpa_to_hva(vcpu->kvm, cbrl[i]);
|
||||
if (!kvm_is_error_hva(hva))
|
||||
gmap_helper_zap_one_page(vcpu->kvm->mm, hva);
|
||||
}
|
||||
pgste_set_unlock(ptep, pgste);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/pagewalk.h>
|
||||
#include <linux/sched/mm.h>
|
||||
#include <linux/mmu_notifier.h>
|
||||
#include <asm/gmap_helpers.h>
|
||||
#include "kvm-s390.h"
|
||||
#include "dat.h"
|
||||
#include "gaccess.h"
|
||||
|
|
@ -73,6 +74,7 @@ static bool should_export_before_import(struct uv_cb_header *uvcb, struct mm_str
|
|||
struct pv_make_secure {
|
||||
void *uvcb;
|
||||
struct folio *folio;
|
||||
struct kvm *kvm;
|
||||
int rc;
|
||||
bool needs_export;
|
||||
};
|
||||
|
|
@ -103,9 +105,21 @@ static void _kvm_s390_pv_make_secure(struct guest_fault *f)
|
|||
{
|
||||
struct pv_make_secure *priv = f->priv;
|
||||
struct folio *folio;
|
||||
spinlock_t *ptl; /* pte lock from try_get_locked_pte() */
|
||||
pte_t *ptep;
|
||||
|
||||
folio = pfn_folio(f->pfn);
|
||||
priv->rc = -EAGAIN;
|
||||
|
||||
if (!mmap_read_trylock(priv->kvm->mm))
|
||||
return;
|
||||
|
||||
ptep = try_get_locked_pte(priv->kvm->mm, gfn_to_hva(priv->kvm, f->gfn), &ptl);
|
||||
if (IS_ERR_VALUE(ptep)) {
|
||||
priv->rc = PTR_ERR(ptep);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (folio_trylock(folio)) {
|
||||
priv->rc = __kvm_s390_pv_make_secure(f, folio);
|
||||
if (priv->rc == -E2BIG || priv->rc == -EBUSY) {
|
||||
|
|
@ -114,6 +128,11 @@ static void _kvm_s390_pv_make_secure(struct guest_fault *f)
|
|||
}
|
||||
folio_unlock(folio);
|
||||
}
|
||||
|
||||
if (ptep)
|
||||
pte_unmap_unlock(ptep, ptl);
|
||||
out:
|
||||
mmap_read_unlock(priv->kvm->mm);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -127,7 +146,7 @@ static void _kvm_s390_pv_make_secure(struct guest_fault *f)
|
|||
*/
|
||||
int kvm_s390_pv_make_secure(struct kvm *kvm, unsigned long gaddr, void *uvcb)
|
||||
{
|
||||
struct pv_make_secure priv = { .uvcb = uvcb };
|
||||
struct pv_make_secure priv = { .uvcb = uvcb, .kvm = kvm, };
|
||||
struct guest_fault f = {
|
||||
.write_attempt = true,
|
||||
.gfn = gpa_to_gfn(gaddr),
|
||||
|
|
|
|||
|
|
@ -17,22 +17,68 @@
|
|||
#include <asm/gmap_helpers.h>
|
||||
|
||||
/**
|
||||
* ptep_zap_softleaf_entry() - discard a software leaf entry.
|
||||
* try_get_locked_pte() - like get_locked_pte(), but atomic and with trylock
|
||||
* @mm: the mm
|
||||
* @entry: the software leaf entry that needs to be zapped
|
||||
* @vmaddr: the userspace virtual address whose pte is to be found
|
||||
* @ptl: will be set to the pointer to the lock used to lock the pte in case
|
||||
* of success.
|
||||
*
|
||||
* Discards the given software leaf entry. If the leaf entry was an actual
|
||||
* swap entry (and not a migration entry, for example), the actual swapped
|
||||
* page is also discarded from swap.
|
||||
* This function returns the pointer to the pte corresponding to @addr in @mm,
|
||||
* similarly to get_locked_pte(). Unlike get_locked_pte(), no attempt is made
|
||||
* to allocate missing page tables. If a missing or large entry is found, the
|
||||
* function will return NULL. If the ptl lock is contended, %-EAGAIN is
|
||||
* returned.
|
||||
*
|
||||
* In case of success, *@ptl will point to the locked pte lock for the returned
|
||||
* pte, like get_locked_pte() does.
|
||||
*
|
||||
* Context: mmap_lock or vma lock for read or for write needs to be held.
|
||||
* Return:
|
||||
* * %NULL if the pte cannot be reached.
|
||||
* * %-EAGAIN if the pte can be reached, but cannot be locked.
|
||||
* * the pointer to the pte corresponding to @addr in @mm, if it can be reached
|
||||
* and locked.
|
||||
*/
|
||||
static void ptep_zap_softleaf_entry(struct mm_struct *mm, softleaf_t entry)
|
||||
pte_t *try_get_locked_pte(struct mm_struct *mm, unsigned long vmaddr, spinlock_t **ptl)
|
||||
{
|
||||
if (softleaf_is_swap(entry))
|
||||
dec_mm_counter(mm, MM_SWAPENTS);
|
||||
else if (softleaf_is_migration(entry))
|
||||
dec_mm_counter(mm, mm_counter(softleaf_to_folio(entry)));
|
||||
swap_put_entries_direct(entry, 1);
|
||||
pmd_t *pmdp, pmd, pmdval;
|
||||
pud_t *pudp, pud;
|
||||
p4d_t *p4dp, p4d;
|
||||
pgd_t *pgdp, pgd;
|
||||
pte_t *ptep;
|
||||
|
||||
pgdp = pgd_offset(mm, vmaddr);
|
||||
pgd = pgdp_get(pgdp);
|
||||
if (pgd_none(pgd) || !pgd_present(pgd))
|
||||
return NULL;
|
||||
p4dp = p4d_offset(pgdp, vmaddr);
|
||||
p4d = p4dp_get(p4dp);
|
||||
if (p4d_none(p4d) || !p4d_present(p4d))
|
||||
return NULL;
|
||||
pudp = pud_offset(p4dp, vmaddr);
|
||||
pud = pudp_get(pudp);
|
||||
if (pud_none(pud) || pud_leaf(pud) || !pud_present(pud))
|
||||
return NULL;
|
||||
pmdp = pmd_offset(pudp, vmaddr);
|
||||
pmd = pmdp_get_lockless(pmdp);
|
||||
if (pmd_none(pmd) || pmd_leaf(pmd) || !pmd_present(pmd))
|
||||
return NULL;
|
||||
ptep = pte_offset_map_rw_nolock(mm, pmdp, vmaddr, &pmdval, ptl);
|
||||
if (!ptep)
|
||||
return NULL;
|
||||
|
||||
if (spin_trylock(*ptl)) {
|
||||
if (unlikely(!pmd_same(pmdval, pmdp_get_lockless(pmdp)))) {
|
||||
pte_unmap_unlock(ptep, *ptl);
|
||||
return ERR_PTR(-EAGAIN);
|
||||
}
|
||||
return ptep;
|
||||
}
|
||||
|
||||
pte_unmap(ptep);
|
||||
return ERR_PTR(-EAGAIN);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(try_get_locked_pte);
|
||||
|
||||
/**
|
||||
* gmap_helper_zap_one_page() - discard a page if it was swapped.
|
||||
|
|
@ -46,7 +92,8 @@ static void ptep_zap_softleaf_entry(struct mm_struct *mm, softleaf_t entry)
|
|||
void gmap_helper_zap_one_page(struct mm_struct *mm, unsigned long vmaddr)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
spinlock_t *ptl;
|
||||
spinlock_t *ptl; /* Lock for the host (userspace) page table */
|
||||
softleaf_t sl;
|
||||
pte_t *ptep;
|
||||
|
||||
mmap_assert_locked(mm);
|
||||
|
|
@ -57,11 +104,13 @@ void gmap_helper_zap_one_page(struct mm_struct *mm, unsigned long vmaddr)
|
|||
return;
|
||||
|
||||
/* Get pointer to the page table entry */
|
||||
ptep = get_locked_pte(mm, vmaddr, &ptl);
|
||||
if (unlikely(!ptep))
|
||||
ptep = try_get_locked_pte(mm, vmaddr, &ptl);
|
||||
if (IS_ERR_OR_NULL(ptep))
|
||||
return;
|
||||
if (pte_swap(*ptep)) {
|
||||
ptep_zap_softleaf_entry(mm, softleaf_from_pte(*ptep));
|
||||
sl = softleaf_from_pte(*ptep);
|
||||
if (pte_swap(*ptep) && softleaf_is_swap(sl)) {
|
||||
dec_mm_counter(mm, MM_SWAPENTS);
|
||||
swap_put_entries_direct(sl, 1);
|
||||
pte_clear(mm, vmaddr, ptep);
|
||||
}
|
||||
pte_unmap_unlock(ptep, ptl);
|
||||
|
|
@ -113,37 +162,9 @@ EXPORT_SYMBOL_GPL(gmap_helper_discard);
|
|||
*/
|
||||
void gmap_helper_try_set_pte_unused(struct mm_struct *mm, unsigned long vmaddr)
|
||||
{
|
||||
pmd_t *pmdp, pmd, pmdval;
|
||||
pud_t *pudp, pud;
|
||||
p4d_t *p4dp, p4d;
|
||||
pgd_t *pgdp, pgd;
|
||||
spinlock_t *ptl; /* Lock for the host (userspace) page table */
|
||||
pte_t *ptep;
|
||||
|
||||
pgdp = pgd_offset(mm, vmaddr);
|
||||
pgd = pgdp_get(pgdp);
|
||||
if (pgd_none(pgd) || !pgd_present(pgd))
|
||||
return;
|
||||
|
||||
p4dp = p4d_offset(pgdp, vmaddr);
|
||||
p4d = p4dp_get(p4dp);
|
||||
if (p4d_none(p4d) || !p4d_present(p4d))
|
||||
return;
|
||||
|
||||
pudp = pud_offset(p4dp, vmaddr);
|
||||
pud = pudp_get(pudp);
|
||||
if (pud_none(pud) || pud_leaf(pud) || !pud_present(pud))
|
||||
return;
|
||||
|
||||
pmdp = pmd_offset(pudp, vmaddr);
|
||||
pmd = pmdp_get_lockless(pmdp);
|
||||
if (pmd_none(pmd) || pmd_leaf(pmd) || !pmd_present(pmd))
|
||||
return;
|
||||
|
||||
ptep = pte_offset_map_rw_nolock(mm, pmdp, vmaddr, &pmdval, &ptl);
|
||||
if (!ptep)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Several paths exists that takes the ptl lock and then call the
|
||||
* mmu_notifier, which takes the mmu_lock. The unmap path, instead,
|
||||
|
|
@ -156,21 +177,12 @@ void gmap_helper_try_set_pte_unused(struct mm_struct *mm, unsigned long vmaddr)
|
|||
* If the lock is contended the bit is not set and the deadlock is
|
||||
* avoided.
|
||||
*/
|
||||
if (spin_trylock(ptl)) {
|
||||
/*
|
||||
* Make sure the pte we are touching is still the correct
|
||||
* one. In theory this check should not be needed, but
|
||||
* better safe than sorry.
|
||||
* Disabling interrupts or holding the mmap lock is enough to
|
||||
* guarantee that no concurrent updates to the page tables
|
||||
* are possible.
|
||||
*/
|
||||
if (likely(pmd_same(pmdval, pmdp_get_lockless(pmdp))))
|
||||
__atomic64_or(_PAGE_UNUSED, (long *)ptep);
|
||||
spin_unlock(ptl);
|
||||
}
|
||||
ptep = try_get_locked_pte(mm, vmaddr, &ptl);
|
||||
if (IS_ERR_OR_NULL(ptep))
|
||||
return;
|
||||
|
||||
pte_unmap(ptep);
|
||||
__atomic64_or(_PAGE_UNUSED, (long *)ptep);
|
||||
pte_unmap_unlock(ptep, ptl);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gmap_helper_try_set_pte_unused);
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,10 @@ KBUILD_CFLAGS += -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -mno-sse4a
|
|||
KBUILD_RUSTFLAGS += --target=$(objtree)/scripts/target.json
|
||||
KBUILD_RUSTFLAGS += -Ctarget-feature=-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2
|
||||
|
||||
# The target.json file is not available when invoking rustc-option, so use the
|
||||
# built-in target when checking whether flags are supported instead.
|
||||
KBUILD_RUSTFLAGS_OPTION_CHKS += --target=x86_64-unknown-none
|
||||
|
||||
#
|
||||
# CFLAGS for compiling floating point code inside the kernel.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -14,6 +14,14 @@ endif
|
|||
|
||||
KBUILD_RUSTFLAGS += --target=$(objtree)/scripts/target.json
|
||||
|
||||
# The target.json file is not available when invoking rustc-option, so use the
|
||||
# built-in target when checking whether flags are supported instead.
|
||||
ifeq ($(CONFIG_X86_32),y)
|
||||
KBUILD_RUSTFLAGS_OPTION_CHKS += --target=i686-unknown-linux-gnu
|
||||
else
|
||||
KBUILD_RUSTFLAGS_OPTION_CHKS += --target=x86_64-unknown-linux-gnu
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_X86_32),y)
|
||||
START := 0x8048000
|
||||
|
||||
|
|
|
|||
|
|
@ -518,7 +518,7 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
|
|||
break;
|
||||
case 0x50 ... 0x5f:
|
||||
case 0x80 ... 0xaf:
|
||||
case 0xc0 ... 0xcf:
|
||||
case 0xc0 ... 0xef:
|
||||
setup_force_cpu_cap(X86_FEATURE_ZEN6);
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -377,7 +377,12 @@ static const struct x86_cpu_id snc_cpu_ids[] __initconst = {
|
|||
|
||||
static __init int snc_get_config(void)
|
||||
{
|
||||
int ret = topology_num_nodes_per_package();
|
||||
int ret;
|
||||
|
||||
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
|
||||
return 1;
|
||||
|
||||
ret = topology_num_nodes_per_package();
|
||||
|
||||
if (ret > 1 && !x86_match_cpu(snc_cpu_ids)) {
|
||||
pr_warn("CoD enabled system? Resctrl not supported\n");
|
||||
|
|
|
|||
|
|
@ -3313,37 +3313,6 @@ void sev_guest_memory_reclaimed(struct kvm *kvm)
|
|||
sev_writeback_caches(kvm);
|
||||
}
|
||||
|
||||
void sev_free_vcpu(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vcpu_svm *svm;
|
||||
|
||||
if (!is_sev_es_guest(vcpu))
|
||||
return;
|
||||
|
||||
svm = to_svm(vcpu);
|
||||
|
||||
/*
|
||||
* If it's an SNP guest, then the VMSA was marked in the RMP table as
|
||||
* a guest-owned page. Transition the page to hypervisor state before
|
||||
* releasing it back to the system.
|
||||
*/
|
||||
if (is_sev_snp_guest(vcpu)) {
|
||||
u64 pfn = __pa(svm->sev_es.vmsa) >> PAGE_SHIFT;
|
||||
|
||||
if (kvm_rmp_make_shared(vcpu->kvm, pfn, PG_LEVEL_4K))
|
||||
goto skip_vmsa_free;
|
||||
}
|
||||
|
||||
if (vcpu->arch.guest_state_protected)
|
||||
sev_flush_encrypted_page(vcpu, svm->sev_es.vmsa);
|
||||
|
||||
__free_page(virt_to_page(svm->sev_es.vmsa));
|
||||
|
||||
skip_vmsa_free:
|
||||
if (svm->sev_es.ghcb_sa_free)
|
||||
kvfree(svm->sev_es.ghcb_sa);
|
||||
}
|
||||
|
||||
static void dump_ghcb(struct vcpu_svm *svm)
|
||||
{
|
||||
struct vmcb_control_area *control = &svm->vmcb->control;
|
||||
|
|
@ -3583,6 +3552,20 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void __sev_es_unmap_ghcb(struct vcpu_svm *svm)
|
||||
{
|
||||
if (svm->sev_es.ghcb_sa_free) {
|
||||
kvfree(svm->sev_es.ghcb_sa);
|
||||
svm->sev_es.ghcb_sa = NULL;
|
||||
svm->sev_es.ghcb_sa_free = false;
|
||||
}
|
||||
|
||||
if (svm->sev_es.ghcb) {
|
||||
kvm_vcpu_unmap(&svm->vcpu, &svm->sev_es.ghcb_map);
|
||||
svm->sev_es.ghcb = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void sev_es_unmap_ghcb(struct vcpu_svm *svm)
|
||||
{
|
||||
/* Clear any indication that the vCPU is in a type of AP Reset Hold */
|
||||
|
|
@ -3591,31 +3574,51 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm)
|
|||
if (!svm->sev_es.ghcb)
|
||||
return;
|
||||
|
||||
if (svm->sev_es.ghcb_sa_free) {
|
||||
/*
|
||||
* The scratch area lives outside the GHCB, so there is a
|
||||
* buffer that, depending on the operation performed, may
|
||||
* need to be synced, then freed.
|
||||
*/
|
||||
if (svm->sev_es.ghcb_sa_sync) {
|
||||
kvm_write_guest(svm->vcpu.kvm,
|
||||
svm->sev_es.sw_scratch,
|
||||
svm->sev_es.ghcb_sa,
|
||||
svm->sev_es.ghcb_sa_len);
|
||||
svm->sev_es.ghcb_sa_sync = false;
|
||||
}
|
||||
|
||||
kvfree(svm->sev_es.ghcb_sa);
|
||||
svm->sev_es.ghcb_sa = NULL;
|
||||
svm->sev_es.ghcb_sa_free = false;
|
||||
/*
|
||||
* If the scratch area lives outside the GHCB, there's a buffer that,
|
||||
* depending on the operation performed, may need to be synced.
|
||||
*/
|
||||
if (svm->sev_es.ghcb_sa_sync) {
|
||||
kvm_write_guest(svm->vcpu.kvm, svm->sev_es.sw_scratch,
|
||||
svm->sev_es.ghcb_sa, svm->sev_es.ghcb_sa_len);
|
||||
svm->sev_es.ghcb_sa_sync = false;
|
||||
}
|
||||
|
||||
trace_kvm_vmgexit_exit(svm->vcpu.vcpu_id, svm->sev_es.ghcb);
|
||||
|
||||
sev_es_sync_to_ghcb(svm);
|
||||
|
||||
kvm_vcpu_unmap(&svm->vcpu, &svm->sev_es.ghcb_map);
|
||||
svm->sev_es.ghcb = NULL;
|
||||
__sev_es_unmap_ghcb(svm);
|
||||
}
|
||||
|
||||
void sev_free_vcpu(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
struct vcpu_svm *svm;
|
||||
|
||||
if (!is_sev_es_guest(vcpu))
|
||||
return;
|
||||
|
||||
svm = to_svm(vcpu);
|
||||
|
||||
/*
|
||||
* If it's an SNP guest, then the VMSA was marked in the RMP table as
|
||||
* a guest-owned page. Transition the page to hypervisor state before
|
||||
* releasing it back to the system.
|
||||
*/
|
||||
if (is_sev_snp_guest(vcpu)) {
|
||||
u64 pfn = __pa(svm->sev_es.vmsa) >> PAGE_SHIFT;
|
||||
|
||||
if (kvm_rmp_make_shared(vcpu->kvm, pfn, PG_LEVEL_4K))
|
||||
goto skip_vmsa_free;
|
||||
}
|
||||
|
||||
if (vcpu->arch.guest_state_protected)
|
||||
sev_flush_encrypted_page(vcpu, svm->sev_es.vmsa);
|
||||
|
||||
__free_page(virt_to_page(svm->sev_es.vmsa));
|
||||
|
||||
skip_vmsa_free:
|
||||
__sev_es_unmap_ghcb(svm);
|
||||
}
|
||||
|
||||
int pre_sev_run(struct vcpu_svm *svm, int cpu)
|
||||
|
|
@ -3685,6 +3688,8 @@ static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 min_len)
|
|||
goto e_scratch;
|
||||
}
|
||||
|
||||
WARN_ON_ONCE(svm->sev_es.ghcb_sa_sync || svm->sev_es.ghcb_sa_free);
|
||||
|
||||
if ((scratch_gpa_beg & PAGE_MASK) == control->ghcb_gpa) {
|
||||
/* Scratch area begins within GHCB */
|
||||
ghcb_scratch_beg = control->ghcb_gpa +
|
||||
|
|
@ -3706,6 +3711,8 @@ static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 min_len)
|
|||
scratch_va = (void *)svm->sev_es.ghcb;
|
||||
scratch_va += (scratch_gpa_beg - control->ghcb_gpa);
|
||||
|
||||
svm->sev_es.ghcb_sa_sync = false;
|
||||
svm->sev_es.ghcb_sa_free = false;
|
||||
svm->sev_es.ghcb_sa_len = ghcb_scratch_end - scratch_gpa_beg;
|
||||
} else {
|
||||
/* GHCB v2 requires the scratch area to be within the GHCB. */
|
||||
|
|
@ -3841,13 +3848,11 @@ struct psc_buffer {
|
|||
struct psc_entry entries[];
|
||||
} __packed;
|
||||
|
||||
static int snp_begin_psc(struct vcpu_svm *svm);
|
||||
static int snp_do_psc(struct vcpu_svm *svm);
|
||||
|
||||
static void snp_complete_psc(struct vcpu_svm *svm, u64 psc_ret)
|
||||
{
|
||||
svm->sev_es.psc_inflight = 0;
|
||||
svm->sev_es.psc_idx = 0;
|
||||
svm->sev_es.psc_2m = false;
|
||||
memset(&svm->sev_es.psc, 0, sizeof(svm->sev_es.psc));
|
||||
|
||||
/*
|
||||
* PSC requests always get a "no action" response in SW_EXITINFO1, with
|
||||
|
|
@ -3860,9 +3865,8 @@ static void snp_complete_psc(struct vcpu_svm *svm, u64 psc_ret)
|
|||
|
||||
static void __snp_complete_one_psc(struct vcpu_svm *svm)
|
||||
{
|
||||
struct psc_buffer *psc = svm->sev_es.ghcb_sa;
|
||||
struct psc_entry *entries = psc->entries;
|
||||
struct psc_hdr *hdr = &psc->hdr;
|
||||
struct vcpu_sev_es_state *sev_es = &svm->sev_es;
|
||||
struct psc_buffer *guest_psc = sev_es->ghcb_sa;
|
||||
__u16 idx;
|
||||
|
||||
/*
|
||||
|
|
@ -3870,14 +3874,15 @@ static void __snp_complete_one_psc(struct vcpu_svm *svm)
|
|||
* corresponding entries in the guest's PSC buffer and zero out the
|
||||
* count of in-flight PSC entries.
|
||||
*/
|
||||
for (idx = svm->sev_es.psc_idx; svm->sev_es.psc_inflight;
|
||||
svm->sev_es.psc_inflight--, idx++) {
|
||||
struct psc_entry entry = READ_ONCE(entries[idx]);
|
||||
for (idx = sev_es->psc.cur_idx; sev_es->psc.batch_size;
|
||||
sev_es->psc.batch_size--, idx++) {
|
||||
struct psc_entry entry = READ_ONCE(guest_psc->entries[idx]);
|
||||
|
||||
entries[idx].cur_page = entry.pagesize ? 512 : 1;
|
||||
guest_psc->entries[idx].cur_page = entry.pagesize ? 512 : 1;
|
||||
}
|
||||
|
||||
hdr->cur_entry = idx;
|
||||
sev_es->psc.cur_idx = idx;
|
||||
guest_psc->hdr.cur_entry = idx;
|
||||
}
|
||||
|
||||
static int snp_complete_one_psc(struct kvm_vcpu *vcpu)
|
||||
|
|
@ -3892,63 +3897,30 @@ static int snp_complete_one_psc(struct kvm_vcpu *vcpu)
|
|||
__snp_complete_one_psc(svm);
|
||||
|
||||
/* Handle the next range (if any). */
|
||||
return snp_begin_psc(svm);
|
||||
return snp_do_psc(svm);
|
||||
}
|
||||
|
||||
static int snp_begin_psc(struct vcpu_svm *svm)
|
||||
static int snp_do_psc(struct vcpu_svm *svm)
|
||||
{
|
||||
struct vcpu_sev_es_state *sev_es = &svm->sev_es;
|
||||
struct psc_buffer *psc = sev_es->ghcb_sa;
|
||||
struct psc_entry *entries = psc->entries;
|
||||
struct psc_buffer *guest_psc = sev_es->ghcb_sa;
|
||||
struct kvm_vcpu *vcpu = &svm->vcpu;
|
||||
struct psc_hdr *hdr = &psc->hdr;
|
||||
struct psc_entry entry_start;
|
||||
u16 idx, idx_start, idx_end, max_nr_entries;
|
||||
int npages;
|
||||
bool huge;
|
||||
u64 gfn;
|
||||
|
||||
if (!user_exit_on_hypercall(vcpu->kvm, KVM_HC_MAP_GPA_RANGE)) {
|
||||
snp_complete_psc(svm, VMGEXIT_PSC_ERROR_GENERIC);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* GHCB v2 requires the scratch area to reside within the GHCB itself,
|
||||
* and PSC requests are only supported for GHCB v2+. Thus it should be
|
||||
* impossible to exceed the max PSC entry count (which is derived from
|
||||
* the size of the shared GHCB buffer).
|
||||
*/
|
||||
max_nr_entries = (sev_es->ghcb_sa_len - sizeof(struct psc_hdr)) /
|
||||
sizeof(struct psc_entry);
|
||||
if (WARN_ON_ONCE(max_nr_entries > VMGEXIT_PSC_MAX_COUNT)) {
|
||||
snp_complete_psc(svm, VMGEXIT_PSC_ERROR_GENERIC);
|
||||
return 1;
|
||||
}
|
||||
u16 idx;
|
||||
|
||||
next_range:
|
||||
/* There should be no other PSCs in-flight at this point. */
|
||||
if (WARN_ON_ONCE(svm->sev_es.psc_inflight)) {
|
||||
if (WARN_ON_ONCE(svm->sev_es.psc.batch_size)) {
|
||||
snp_complete_psc(svm, VMGEXIT_PSC_ERROR_GENERIC);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The PSC descriptor buffer can be modified by a misbehaved guest after
|
||||
* validation, so take care to only use validated copies of values used
|
||||
* for things like array indexing.
|
||||
*/
|
||||
idx_start = READ_ONCE(hdr->cur_entry);
|
||||
idx_end = READ_ONCE(hdr->end_entry);
|
||||
|
||||
if (idx_end >= max_nr_entries) {
|
||||
snp_complete_psc(svm, VMGEXIT_PSC_ERROR_INVALID_HDR);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Find the start of the next range which needs processing. */
|
||||
for (idx = idx_start; idx <= idx_end; idx++, hdr->cur_entry++) {
|
||||
entry_start = READ_ONCE(entries[idx]);
|
||||
for (idx = sev_es->psc.cur_idx; idx <= sev_es->psc.end_idx; idx++) {
|
||||
entry_start = READ_ONCE(guest_psc->entries[idx]);
|
||||
|
||||
gfn = entry_start.gfn;
|
||||
huge = entry_start.pagesize;
|
||||
|
|
@ -3974,32 +3946,40 @@ static int snp_begin_psc(struct vcpu_svm *svm)
|
|||
|
||||
if (npages)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Increment the guest-visible index to communicate the current
|
||||
* entry back to the guest, e.g. in case of failure. No need
|
||||
* for READ_ONCE() as KVM doesn't consume the field, i.e. a
|
||||
* misbehaving guest can only break itself.
|
||||
*/
|
||||
guest_psc->hdr.cur_entry++;
|
||||
}
|
||||
|
||||
if (idx > idx_end) {
|
||||
if (idx > sev_es->psc.end_idx) {
|
||||
/* Nothing more to process. */
|
||||
snp_complete_psc(svm, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
svm->sev_es.psc_2m = huge;
|
||||
svm->sev_es.psc_idx = idx;
|
||||
svm->sev_es.psc_inflight = 1;
|
||||
sev_es->psc.is_2m = huge;
|
||||
sev_es->psc.cur_idx = idx;
|
||||
sev_es->psc.batch_size = 1;
|
||||
|
||||
/*
|
||||
* Find all subsequent PSC entries that contain adjacent GPA
|
||||
* ranges/operations and can be combined into a single
|
||||
* KVM_HC_MAP_GPA_RANGE exit.
|
||||
*/
|
||||
while (++idx <= idx_end) {
|
||||
struct psc_entry entry = READ_ONCE(entries[idx]);
|
||||
while (++idx <= sev_es->psc.end_idx) {
|
||||
struct psc_entry entry = READ_ONCE(guest_psc->entries[idx]);
|
||||
|
||||
if (entry.operation != entry_start.operation ||
|
||||
entry.gfn != entry_start.gfn + npages ||
|
||||
entry.cur_page || !!entry.pagesize != huge)
|
||||
break;
|
||||
|
||||
svm->sev_es.psc_inflight++;
|
||||
sev_es->psc.batch_size++;
|
||||
npages += huge ? 512 : 1;
|
||||
}
|
||||
|
||||
|
|
@ -4041,6 +4021,46 @@ static int snp_begin_psc(struct vcpu_svm *svm)
|
|||
BUG();
|
||||
}
|
||||
|
||||
static int snp_begin_psc(struct vcpu_svm *svm)
|
||||
{
|
||||
struct vcpu_sev_es_state *sev_es = &svm->sev_es;
|
||||
struct psc_buffer *guest_psc = sev_es->ghcb_sa;
|
||||
u16 max_nr_entries;
|
||||
|
||||
if (!user_exit_on_hypercall(svm->vcpu.kvm, KVM_HC_MAP_GPA_RANGE)) {
|
||||
snp_complete_psc(svm, VMGEXIT_PSC_ERROR_GENERIC);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* GHCB v2 requires the scratch area to reside within the GHCB itself,
|
||||
* and PSC requests are only supported for GHCB v2+. Thus it should be
|
||||
* impossible to exceed the max PSC entry count (which is derived from
|
||||
* the size of the shared GHCB buffer).
|
||||
*/
|
||||
max_nr_entries = (sev_es->ghcb_sa_len - sizeof(struct psc_hdr)) /
|
||||
sizeof(struct psc_entry);
|
||||
if (WARN_ON_ONCE(max_nr_entries > VMGEXIT_PSC_MAX_COUNT)) {
|
||||
snp_complete_psc(svm, VMGEXIT_PSC_ERROR_GENERIC);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The PSC descriptor buffer can be modified by a misbehaved guest after
|
||||
* validation, so take care to only use validated copies of values used
|
||||
* for things like array indexing.
|
||||
*/
|
||||
sev_es->psc.cur_idx = READ_ONCE(guest_psc->hdr.cur_entry);
|
||||
sev_es->psc.end_idx = READ_ONCE(guest_psc->hdr.end_entry);
|
||||
|
||||
if (sev_es->psc.end_idx >= max_nr_entries) {
|
||||
snp_complete_psc(svm, VMGEXIT_PSC_ERROR_INVALID_HDR);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return snp_do_psc(svm);
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoked as part of svm_vcpu_reset() processing of an init event.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -257,9 +257,12 @@ struct vcpu_sev_es_state {
|
|||
bool ghcb_sa_free;
|
||||
|
||||
/* SNP Page-State-Change buffer entries currently being processed */
|
||||
u16 psc_idx;
|
||||
u16 psc_inflight;
|
||||
bool psc_2m;
|
||||
struct {
|
||||
u16 cur_idx;
|
||||
u16 end_idx;
|
||||
u16 batch_size;
|
||||
bool is_2m;
|
||||
} psc;
|
||||
|
||||
u64 ghcb_registered_gpa;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
/* Copyright 2025 Arm, Ltd. */
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <drm/ethosu_accel.h>
|
||||
|
|
@ -163,17 +164,30 @@ static u64 dma_length(struct ethosu_validated_cmdstream_info *info,
|
|||
s8 mode = dma_st->mode;
|
||||
u64 len = dma->len;
|
||||
|
||||
if (len == U64_MAX)
|
||||
return U64_MAX;
|
||||
|
||||
if (mode >= 1) {
|
||||
if (dma->stride[0] < 0 && (u64)(-dma->stride[0]) > len)
|
||||
return U64_MAX;
|
||||
len += dma->stride[0];
|
||||
len *= dma_st->size0;
|
||||
if (check_mul_overflow(len, (u64)dma_st->size0, &len))
|
||||
return U64_MAX;
|
||||
}
|
||||
if (mode == 2) {
|
||||
if (dma->stride[1] < 0 && (u64)(-dma->stride[1]) > len)
|
||||
return U64_MAX;
|
||||
len += dma->stride[1];
|
||||
len *= dma_st->size1;
|
||||
if (check_mul_overflow(len, (u64)dma_st->size1, &len))
|
||||
return U64_MAX;
|
||||
}
|
||||
if (dma->region >= 0) {
|
||||
u64 end;
|
||||
|
||||
if (check_add_overflow(len, dma->offset, &end))
|
||||
return U64_MAX;
|
||||
info->region_size[dma->region] = max(info->region_size[dma->region], end);
|
||||
}
|
||||
if (dma->region >= 0)
|
||||
info->region_size[dma->region] = max(info->region_size[dma->region],
|
||||
len + dma->offset);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
|
@ -387,6 +401,8 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
|
|||
return -EFAULT;
|
||||
|
||||
i++;
|
||||
if (i >= size / 4)
|
||||
return -EINVAL;
|
||||
bocmds[i] = cmds[1];
|
||||
addr = cmd_to_addr(cmds);
|
||||
}
|
||||
|
|
@ -395,6 +411,8 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
|
|||
case NPU_OP_DMA_START:
|
||||
srclen = dma_length(info, &st.dma, &st.dma.src);
|
||||
dstlen = dma_length(info, &st.dma, &st.dma.dst);
|
||||
if (srclen == U64_MAX || dstlen == U64_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
if (st.dma.dst.region >= 0)
|
||||
info->output_region[st.dma.dst.region] = true;
|
||||
|
|
@ -431,8 +449,7 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
|
|||
return ret;
|
||||
break;
|
||||
case NPU_OP_RESIZE: // U85 only
|
||||
WARN_ON(1); // TODO
|
||||
break;
|
||||
return -EINVAL;
|
||||
case NPU_SET_KERNEL_WIDTH_M1:
|
||||
st.ifm.width = param;
|
||||
break;
|
||||
|
|
@ -464,7 +481,7 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
|
|||
st.ifm.broadcast = param;
|
||||
break;
|
||||
case NPU_SET_IFM_REGION:
|
||||
st.ifm.region = param & 0x7f;
|
||||
st.ifm.region = param & 0x7;
|
||||
break;
|
||||
case NPU_SET_IFM_WIDTH0_M1:
|
||||
st.ifm.width0 = param;
|
||||
|
|
@ -599,7 +616,7 @@ static int ethosu_gem_cmdstream_copy_and_validate(struct drm_device *ddev,
|
|||
if (ethosu_is_u65(edev))
|
||||
st.scale[1].length = cmds[1];
|
||||
else
|
||||
st.weight[1].length = cmds[1];
|
||||
st.weight[2].length = cmds[1];
|
||||
break;
|
||||
case NPU_SET_WEIGHT3_BASE:
|
||||
st.weight[3].base = addr;
|
||||
|
|
|
|||
|
|
@ -259,6 +259,22 @@ static int ivpu_fw_parse(struct ivpu_device *vdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!PAGE_ALIGNED(runtime_addr)) {
|
||||
ivpu_err(vdev, "Runtime address 0x%llx not page aligned\n", runtime_addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!PAGE_ALIGNED(runtime_size)) {
|
||||
ivpu_err(vdev, "Runtime size %llu not page aligned\n", runtime_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (runtime_size < image_size) {
|
||||
ivpu_err(vdev, "Runtime size too small: %llu, image size: %llu\n",
|
||||
runtime_size, image_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!ivpu_is_within_range(image_load_addr, image_size, &vdev->hw->ranges.runtime)) {
|
||||
ivpu_err(vdev, "Invalid firmware load address: 0x%llx and size %llu\n",
|
||||
image_load_addr, image_size);
|
||||
|
|
|
|||
|
|
@ -98,6 +98,11 @@ static void fw_log_print_buffer(struct vpu_tracing_buffer_header *log, const cha
|
|||
u32 log_start = only_new_msgs ? READ_ONCE(log->read_index) : 0;
|
||||
u32 log_end = READ_ONCE(log->write_index);
|
||||
|
||||
if (log_start >= data_size)
|
||||
log_start = 0;
|
||||
if (log_end > data_size)
|
||||
log_end = data_size;
|
||||
|
||||
if (log->wrap_count == log->read_wrap_count) {
|
||||
if (log_end <= log_start) {
|
||||
drm_printf(p, "==== %s \"%s\" log empty ====\n", prefix, log->name);
|
||||
|
|
|
|||
|
|
@ -291,6 +291,13 @@ int ivpu_ms_get_info_ioctl(struct drm_device *dev, void *data, struct drm_file *
|
|||
if (ret)
|
||||
goto unlock;
|
||||
|
||||
if (info_size > ivpu_bo_size(bo)) {
|
||||
ivpu_warn_ratelimited(vdev, "MS info overflow: %#llx > %#zx\n",
|
||||
info_size, ivpu_bo_size(bo));
|
||||
ret = -EOVERFLOW;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (args->buffer_size < info_size) {
|
||||
ret = -ENOSPC;
|
||||
goto unlock;
|
||||
|
|
|
|||
|
|
@ -327,7 +327,7 @@ config PANEL_CHANGE_MESSAGE
|
|||
say 'N' and keep the default message with the version.
|
||||
|
||||
config PANEL_BOOT_MESSAGE
|
||||
depends on PANEL_CHANGE_MESSAGE="y"
|
||||
depends on PANEL_CHANGE_MESSAGE
|
||||
string "New initialization message"
|
||||
default ""
|
||||
help
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ static int linedisp_display(struct linedisp *linedisp, const char *msg,
|
|||
count = strlen(msg);
|
||||
|
||||
/* if the string ends with a newline, trim it */
|
||||
if (msg[count - 1] == '\n')
|
||||
if (count && msg[count - 1] == '\n')
|
||||
count--;
|
||||
|
||||
if (!count) {
|
||||
|
|
|
|||
|
|
@ -86,10 +86,7 @@ static const struct linedisp_ops max6959_linedisp_ops = {
|
|||
|
||||
static int max6959_enable(struct max6959_priv *priv, bool enable)
|
||||
{
|
||||
u8 mask = REG_CONFIGURATION_S_BIT;
|
||||
u8 value = enable ? mask : 0;
|
||||
|
||||
return regmap_update_bits(priv->regmap, REG_CONFIGURATION, mask, value);
|
||||
return regmap_assign_bits(priv->regmap, REG_CONFIGURATION, REG_CONFIGURATION_S_BIT, enable);
|
||||
}
|
||||
|
||||
static void max6959_power_off(void *priv)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ static void acpm_dvfs_set_xfer(struct acpm_xfer *xfer, u32 *cmd, size_t cmdlen,
|
|||
if (response) {
|
||||
xfer->rxcnt = cmdlen;
|
||||
xfer->rxd = cmd;
|
||||
} else {
|
||||
xfer->rxcnt = 0;
|
||||
xfer->rxd = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,11 +7,12 @@
|
|||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/container_of.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/find.h>
|
||||
#include <linux/firmware/samsung/exynos-acpm-protocol.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
|
|
@ -104,12 +105,15 @@ struct acpm_queue {
|
|||
*
|
||||
* @cmd: pointer to where the data shall be saved.
|
||||
* @n_cmd: number of 32-bit commands.
|
||||
* @response: true if the client expects the RX data.
|
||||
* @rxcnt: expected length of the response in 32-bit words.
|
||||
* @completed: flag indicating if the firmware response has been fully
|
||||
* processed.
|
||||
*/
|
||||
struct acpm_rx_data {
|
||||
u32 *cmd;
|
||||
size_t n_cmd;
|
||||
bool response;
|
||||
size_t rxcnt;
|
||||
bool completed;
|
||||
};
|
||||
|
||||
#define ACPM_SEQNUM_MAX 64
|
||||
|
|
@ -199,31 +203,33 @@ static void acpm_get_saved_rx(struct acpm_chan *achan,
|
|||
const struct acpm_rx_data *rx_data = &achan->rx_data[tx_seqnum - 1];
|
||||
u32 rx_seqnum;
|
||||
|
||||
if (!rx_data->response)
|
||||
if (!rx_data->rxcnt)
|
||||
return;
|
||||
|
||||
rx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, rx_data->cmd[0]);
|
||||
|
||||
if (rx_seqnum == tx_seqnum) {
|
||||
if (rx_seqnum == tx_seqnum)
|
||||
memcpy(xfer->rxd, rx_data->cmd, xfer->rxcnt * sizeof(*xfer->rxd));
|
||||
clear_bit(rx_seqnum - 1, achan->bitmap_seqnum);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* acpm_get_rx() - get response from RX queue.
|
||||
* @achan: ACPM channel info.
|
||||
* @xfer: reference to the transfer to get response for.
|
||||
* @native_match: pointer to a boolean set to true if the thread natively
|
||||
* processed its own sequence number during this call.
|
||||
*
|
||||
* Return: 0 on success, -errno otherwise.
|
||||
*/
|
||||
static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
|
||||
static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer,
|
||||
bool *native_match)
|
||||
{
|
||||
u32 rx_front, rx_seqnum, tx_seqnum, seqnum;
|
||||
const void __iomem *base, *addr;
|
||||
struct acpm_rx_data *rx_data;
|
||||
u32 i, val, mlen;
|
||||
bool rx_set = false;
|
||||
|
||||
*native_match = false;
|
||||
|
||||
guard(mutex)(&achan->rx_lock);
|
||||
|
||||
|
|
@ -232,10 +238,8 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
|
|||
|
||||
tx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, xfer->txd[0]);
|
||||
|
||||
if (i == rx_front) {
|
||||
acpm_get_saved_rx(achan, xfer, tx_seqnum);
|
||||
if (i == rx_front)
|
||||
return 0;
|
||||
}
|
||||
|
||||
base = achan->rx.base;
|
||||
mlen = achan->mlen;
|
||||
|
|
@ -256,11 +260,16 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
|
|||
seqnum = rx_seqnum - 1;
|
||||
rx_data = &achan->rx_data[seqnum];
|
||||
|
||||
if (rx_data->response) {
|
||||
if (rx_data->rxcnt) {
|
||||
if (rx_seqnum == tx_seqnum) {
|
||||
__ioread32_copy(xfer->rxd, addr, xfer->rxcnt);
|
||||
rx_set = true;
|
||||
clear_bit(seqnum, achan->bitmap_seqnum);
|
||||
/*
|
||||
* Signal completion to the polling thread.
|
||||
* Pairs with smp_load_acquire() in polling
|
||||
* loop.
|
||||
*/
|
||||
smp_store_release(&rx_data->completed, true);
|
||||
*native_match = true;
|
||||
} else {
|
||||
/*
|
||||
* The RX data corresponds to another request.
|
||||
|
|
@ -268,10 +277,23 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
|
|||
* clear yet the bitmap. It will be cleared
|
||||
* after the response is copied to the request.
|
||||
*/
|
||||
__ioread32_copy(rx_data->cmd, addr, xfer->rxcnt);
|
||||
__ioread32_copy(rx_data->cmd, addr,
|
||||
rx_data->rxcnt);
|
||||
/*
|
||||
* Signal completion to the polling thread.
|
||||
* Pairs with smp_load_acquire() in polling
|
||||
* loop.
|
||||
*/
|
||||
smp_store_release(&rx_data->completed, true);
|
||||
}
|
||||
} else {
|
||||
clear_bit(seqnum, achan->bitmap_seqnum);
|
||||
/*
|
||||
* Signal completion to the polling thread.
|
||||
* Pairs with smp_load_acquire() in polling loop.
|
||||
*/
|
||||
smp_store_release(&rx_data->completed, true);
|
||||
if (rx_seqnum == tx_seqnum)
|
||||
*native_match = true;
|
||||
}
|
||||
|
||||
i = (i + 1) % achan->qlen;
|
||||
|
|
@ -280,13 +302,6 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
|
|||
/* We saved all responses, mark RX empty. */
|
||||
writel(rx_front, achan->rx.rear);
|
||||
|
||||
/*
|
||||
* If the response was not in this iteration of the queue, check if the
|
||||
* RX data was previously saved.
|
||||
*/
|
||||
if (!rx_set)
|
||||
acpm_get_saved_rx(achan, xfer, tx_seqnum);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -301,6 +316,7 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
|
|||
const struct acpm_xfer *xfer)
|
||||
{
|
||||
struct device *dev = achan->acpm->dev;
|
||||
bool native_match;
|
||||
ktime_t timeout;
|
||||
u32 seqnum;
|
||||
int ret;
|
||||
|
|
@ -309,12 +325,25 @@ static int acpm_dequeue_by_polling(struct acpm_chan *achan,
|
|||
|
||||
timeout = ktime_add_us(ktime_get(), ACPM_POLL_TIMEOUT_US);
|
||||
do {
|
||||
ret = acpm_get_rx(achan, xfer);
|
||||
ret = acpm_get_rx(achan, xfer, &native_match);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!test_bit(seqnum - 1, achan->bitmap_seqnum))
|
||||
/*
|
||||
* Safely check if our specific transaction has been processed.
|
||||
* smp_load_acquire prevents the CPU from speculatively
|
||||
* executing subsequent instructions before the transaction is
|
||||
* synchronized.
|
||||
*/
|
||||
if (smp_load_acquire(&achan->rx_data[seqnum - 1].completed)) {
|
||||
/* Retrieve payload if another thread cached it for us */
|
||||
if (!native_match)
|
||||
acpm_get_saved_rx(achan, xfer, seqnum);
|
||||
|
||||
/* Relinquish ownership of the sequence slot */
|
||||
clear_bit_unlock(seqnum - 1, achan->bitmap_seqnum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Determined experimentally. */
|
||||
udelay(20);
|
||||
|
|
@ -362,29 +391,48 @@ static int acpm_wait_for_queue_slots(struct acpm_chan *achan, u32 next_tx_front)
|
|||
* TX queue.
|
||||
* @achan: ACPM channel info.
|
||||
* @xfer: reference to the transfer being prepared.
|
||||
*
|
||||
* Return: 0 on success, -errno otherwise.
|
||||
*/
|
||||
static void acpm_prepare_xfer(struct acpm_chan *achan,
|
||||
const struct acpm_xfer *xfer)
|
||||
static int acpm_prepare_xfer(struct acpm_chan *achan,
|
||||
const struct acpm_xfer *xfer)
|
||||
{
|
||||
struct acpm_rx_data *rx_data;
|
||||
u32 *txd = (u32 *)xfer->txd;
|
||||
unsigned long size = ACPM_SEQNUM_MAX - 1;
|
||||
unsigned long bit = achan->seqnum;
|
||||
|
||||
/* Prevent chan->seqnum from being re-used */
|
||||
do {
|
||||
if (++achan->seqnum == ACPM_SEQNUM_MAX)
|
||||
achan->seqnum = 1;
|
||||
} while (test_bit(achan->seqnum - 1, achan->bitmap_seqnum));
|
||||
bit = find_next_zero_bit(achan->bitmap_seqnum, size, bit);
|
||||
if (bit >= size) {
|
||||
bit = find_first_zero_bit(achan->bitmap_seqnum, size);
|
||||
if (bit >= size) {
|
||||
dev_err_ratelimited(achan->acpm->dev,
|
||||
"ACPM sequence number pool exhausted\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute the atomic set to formally claim the bit and establish
|
||||
* LKMM Acquire semantics against the RX thread's clear_bit_unlock().
|
||||
* A loop is unnecessary because allocations are strictly serialized
|
||||
* by tx_lock.
|
||||
*/
|
||||
if (WARN_ON_ONCE(test_and_set_bit_lock(bit, achan->bitmap_seqnum)))
|
||||
return -EIO;
|
||||
|
||||
/* Flag the index based on seqnum. (seqnum: 1~63, bitmap: 0~62) */
|
||||
achan->seqnum = bit + 1;
|
||||
txd[0] |= FIELD_PREP(ACPM_PROTOCOL_SEQNUM, achan->seqnum);
|
||||
|
||||
/* Clear data for upcoming responses */
|
||||
rx_data = &achan->rx_data[achan->seqnum - 1];
|
||||
rx_data = &achan->rx_data[bit];
|
||||
rx_data->completed = false;
|
||||
memset(rx_data->cmd, 0, sizeof(*rx_data->cmd) * rx_data->n_cmd);
|
||||
if (xfer->rxd)
|
||||
rx_data->response = true;
|
||||
/* zero means no response expected */
|
||||
rx_data->rxcnt = xfer->rxcnt;
|
||||
|
||||
/* Flag the index based on seqnum. (seqnum: 1~63, bitmap: 0~62) */
|
||||
set_bit(achan->seqnum - 1, achan->bitmap_seqnum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -444,7 +492,9 @@ int acpm_do_xfer(struct acpm_handle *handle, const struct acpm_xfer *xfer)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
acpm_prepare_xfer(achan, xfer);
|
||||
ret = acpm_prepare_xfer(achan, xfer);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Write TX command. */
|
||||
__iowrite32_copy(achan->tx.base + achan->mlen * tx_front,
|
||||
|
|
@ -526,10 +576,11 @@ static int acpm_achan_alloc_cmds(struct acpm_chan *achan)
|
|||
|
||||
/**
|
||||
* acpm_free_mbox_chans() - free mailbox channels.
|
||||
* @acpm: pointer to driver data.
|
||||
* @data: pointer to driver data.
|
||||
*/
|
||||
static void acpm_free_mbox_chans(struct acpm_info *acpm)
|
||||
static void acpm_free_mbox_chans(void *data)
|
||||
{
|
||||
struct acpm_info *acpm = data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < acpm->num_chans; i++)
|
||||
|
|
@ -557,6 +608,10 @@ static int acpm_channels_init(struct acpm_info *acpm)
|
|||
if (!acpm->chans)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, acpm_free_mbox_chans, acpm);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to add mbox free action.\n");
|
||||
|
||||
chans_shmem = acpm->sram_base + readl(&shmem->chans);
|
||||
|
||||
for (i = 0; i < acpm->num_chans; i++) {
|
||||
|
|
@ -578,10 +633,8 @@ static int acpm_channels_init(struct acpm_info *acpm)
|
|||
cl->dev = dev;
|
||||
|
||||
achan->chan = mbox_request_channel(cl, 0);
|
||||
if (IS_ERR(achan->chan)) {
|
||||
acpm_free_mbox_chans(acpm);
|
||||
if (IS_ERR(achan->chan))
|
||||
return PTR_ERR(achan->chan);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -240,6 +240,14 @@ static void of_gpio_try_fixup_polarity(const struct device_node *np,
|
|||
* treats it as "active low".
|
||||
*/
|
||||
{ "ti,tsc2005", "reset-gpios", false },
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_SND_SOC_WSA881X)
|
||||
/*
|
||||
* WSA881 powerdown is always active low, but some device trees
|
||||
* missed this when first contributed. It also has a very strange
|
||||
* compatible.
|
||||
*/
|
||||
{ "sdw10217201000", "powerdown-gpios", false },
|
||||
#endif
|
||||
};
|
||||
unsigned int i;
|
||||
|
|
|
|||
|
|
@ -394,7 +394,8 @@ void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa,
|
|||
uint64_t start_page, uint64_t num_pages,
|
||||
uint64_t flags, void *dst)
|
||||
{
|
||||
u32 i, idx;
|
||||
u32 i, j, t, idx;
|
||||
u64 page_base;
|
||||
|
||||
/* The SYSTEM flag indicates the pages aren't in VRAM. */
|
||||
WARN_ON_ONCE(flags & AMDGPU_PTE_SYSTEM);
|
||||
|
|
@ -402,9 +403,12 @@ void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa,
|
|||
if (!drm_dev_enter(adev_to_drm(adev), &idx))
|
||||
return;
|
||||
|
||||
for (i = 0; i < num_pages; ++i) {
|
||||
amdgpu_gmc_set_pte_pde(adev, dst,
|
||||
start_page + i, pa + AMDGPU_GPU_PAGE_SIZE * i, flags);
|
||||
page_base = pa;
|
||||
for (i = 0, t = 0; i < num_pages; i++) {
|
||||
for (j = 0; j < AMDGPU_GPU_PAGES_IN_CPU_PAGE; j++, t++) {
|
||||
amdgpu_gmc_set_pte_pde(adev, dst, start_page + t, page_base, flags);
|
||||
page_base += AMDGPU_GPU_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
drm_dev_exit(idx);
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ int amdgpu_gmc_set_pte_pde(struct amdgpu_device *adev, void *cpu_pt_addr,
|
|||
/*
|
||||
* The following is for PTE only. GART does not have PDEs.
|
||||
*/
|
||||
value = addr & 0x0000FFFFFFFFF000ULL;
|
||||
value = addr & adev->gmc.pte_addr_mask;
|
||||
value |= flags;
|
||||
writeq(value, ptr + (gpu_page_idx * 8));
|
||||
|
||||
|
|
@ -1003,7 +1003,7 @@ void amdgpu_gmc_noretry_set(struct amdgpu_device *adev)
|
|||
gc_ver == IP_VERSION(9, 4, 3) ||
|
||||
gc_ver == IP_VERSION(9, 4, 4) ||
|
||||
gc_ver == IP_VERSION(9, 5, 0) ||
|
||||
gc_ver >= IP_VERSION(10, 3, 0));
|
||||
gc_ver >= IP_VERSION(10, 1, 0));
|
||||
|
||||
if (!amdgpu_sriov_xnack_support(adev))
|
||||
gmc->noretry = 1;
|
||||
|
|
|
|||
|
|
@ -280,6 +280,7 @@ struct amdgpu_gmc {
|
|||
u64 real_vram_size;
|
||||
int vram_mtrr;
|
||||
u64 mc_mask;
|
||||
uint64_t pte_addr_mask;
|
||||
const struct firmware *fw; /* MC firmware */
|
||||
uint32_t fw_version;
|
||||
struct amdgpu_irq_src vm_fault;
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ int amdgpu_gtt_mgr_alloc_entries(struct amdgpu_gtt_mgr *mgr,
|
|||
int r;
|
||||
|
||||
/* Align to TLB L2 cache entry size to work around "V bit HW bug" */
|
||||
if (adev->asic_type == CHIP_TAHITI) {
|
||||
if (adev->family == AMDGPU_FAMILY_SI) {
|
||||
alignment = 32 * 1024 / AMDGPU_GPU_PAGE_SIZE;
|
||||
num_pages = ALIGN(num_pages, alignment);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ static bool amdgpu_hmm_invalidate_gfx(struct mmu_interval_notifier *mni,
|
|||
{
|
||||
struct amdgpu_bo *bo = container_of(mni, struct amdgpu_bo, notifier);
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
struct amdgpu_bo *vm_root = bo->vm_bo->vm->root.bo;
|
||||
long r;
|
||||
|
||||
if (!mmu_notifier_range_blockable(range))
|
||||
|
|
@ -77,8 +78,9 @@ static bool amdgpu_hmm_invalidate_gfx(struct mmu_interval_notifier *mni,
|
|||
mmu_interval_set_seq(mni, cur_seq);
|
||||
|
||||
amdgpu_vm_bo_invalidate(bo, false);
|
||||
r = dma_resv_wait_timeout(bo->tbo.base.resv, DMA_RESV_USAGE_BOOKKEEP,
|
||||
false, MAX_SCHEDULE_TIMEOUT);
|
||||
r = dma_resv_wait_timeout(vm_root->tbo.base.resv,
|
||||
DMA_RESV_USAGE_BOOKKEEP, false,
|
||||
MAX_SCHEDULE_TIMEOUT);
|
||||
mutex_unlock(&adev->notifier_lock);
|
||||
if (r <= 0)
|
||||
DRM_ERROR("(%ld) failed to wait for user bo\n", r);
|
||||
|
|
|
|||
|
|
@ -173,16 +173,17 @@ void amdgpu_seq64_unmap(struct amdgpu_device *adev, struct amdgpu_fpriv *fpriv)
|
|||
int amdgpu_seq64_alloc(struct amdgpu_device *adev, u64 *va,
|
||||
u64 *gpu_addr, u64 **cpu_addr)
|
||||
{
|
||||
unsigned long bit_pos;
|
||||
unsigned long bit_pos = 0;
|
||||
|
||||
for (;;) {
|
||||
bit_pos = find_first_zero_bit(adev->seq64.used, adev->seq64.num_sem);
|
||||
do {
|
||||
bit_pos = find_next_zero_bit(adev->seq64.used,
|
||||
adev->seq64.num_sem, bit_pos);
|
||||
if (bit_pos >= adev->seq64.num_sem)
|
||||
return -ENOSPC;
|
||||
|
||||
if (!test_and_set_bit(bit_pos, adev->seq64.used))
|
||||
break;
|
||||
}
|
||||
bit_pos++;
|
||||
} while (1);
|
||||
|
||||
*va = bit_pos * sizeof(u64) + amdgpu_seq64_get_va_base(adev);
|
||||
|
||||
|
|
|
|||
|
|
@ -532,10 +532,6 @@ amdgpu_userq_destroy(struct amdgpu_userq_mgr *uq_mgr, struct amdgpu_usermode_que
|
|||
amdgpu_bo_unreserve(queue->db_obj.obj);
|
||||
amdgpu_bo_unref(&queue->db_obj.obj);
|
||||
|
||||
amdgpu_bo_reserve(queue->wptr_obj.obj, true);
|
||||
amdgpu_bo_unpin(queue->wptr_obj.obj);
|
||||
amdgpu_bo_unreserve(queue->wptr_obj.obj);
|
||||
amdgpu_bo_unref(&queue->wptr_obj.obj);
|
||||
kfree(queue);
|
||||
|
||||
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
|
||||
|
|
@ -887,7 +883,7 @@ amdgpu_userq_restore_all(struct amdgpu_userq_mgr *uq_mgr)
|
|||
continue;
|
||||
}
|
||||
|
||||
r = amdgpu_userq_restore_helper(queue);
|
||||
r = amdgpu_userq_map_helper(queue);
|
||||
if (r)
|
||||
ret = r;
|
||||
|
||||
|
|
@ -1124,7 +1120,7 @@ amdgpu_userq_evict_all(struct amdgpu_userq_mgr *uq_mgr)
|
|||
|
||||
/* Try to unmap all the queues in this process ctx */
|
||||
xa_for_each(&uq_mgr->userq_xa, queue_id, queue) {
|
||||
r = amdgpu_userq_preempt_helper(queue);
|
||||
r = amdgpu_userq_unmap_helper(queue);
|
||||
if (r)
|
||||
ret = r;
|
||||
}
|
||||
|
|
@ -1344,8 +1340,7 @@ int amdgpu_userq_start_sched_for_enforce_isolation(struct amdgpu_device *adev,
|
|||
}
|
||||
|
||||
void amdgpu_userq_gem_va_unmap_validate(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va_mapping *mapping,
|
||||
uint64_t saddr)
|
||||
struct amdgpu_bo_va_mapping *mapping)
|
||||
{
|
||||
u32 ip_mask = amdgpu_userq_get_supported_ip_mask(adev);
|
||||
struct amdgpu_bo_va *bo_va = mapping->bo_va;
|
||||
|
|
@ -1354,12 +1349,9 @@ void amdgpu_userq_gem_va_unmap_validate(struct amdgpu_device *adev,
|
|||
if (!ip_mask)
|
||||
return;
|
||||
|
||||
dev_warn_once(adev->dev, "now unmapping a vital queue va:%llx\n", saddr);
|
||||
/**
|
||||
* The userq VA mapping reservation should include the eviction fence,
|
||||
* if the eviction fence can't signal successfully during unmapping,
|
||||
* then driver will warn to flag this improper unmap of the userq VA.
|
||||
* Note: The eviction fence may be attached to different BOs, and this
|
||||
* The userq VA mapping reservation should include the eviction fence.
|
||||
* Note: The eviction fence may be attached to different BOs and this
|
||||
* unmap is only for one kind of userq VAs, so at this point suppose
|
||||
* the eviction fence is always unsignaled.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -182,6 +182,5 @@ int amdgpu_userq_input_va_validate(struct amdgpu_device *adev,
|
|||
u64 addr, u64 expected_size, u64 *va_out);
|
||||
|
||||
void amdgpu_userq_gem_va_unmap_validate(struct amdgpu_device *adev,
|
||||
struct amdgpu_bo_va_mapping *mapping,
|
||||
uint64_t saddr);
|
||||
struct amdgpu_bo_va_mapping *mapping);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2006,7 +2006,7 @@ int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
|
|||
* from user space.
|
||||
*/
|
||||
if (unlikely(bo_va->userq_va_mapped))
|
||||
amdgpu_userq_gem_va_unmap_validate(adev, mapping, saddr);
|
||||
amdgpu_userq_gem_va_unmap_validate(adev, mapping);
|
||||
|
||||
list_del(&mapping->list);
|
||||
amdgpu_vm_it_remove(mapping, &vm->va);
|
||||
|
|
|
|||
|
|
@ -449,12 +449,10 @@ static void gfxhub_v11_5_0_set_fault_enable_default(struct amdgpu_device *adev,
|
|||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
if (!value) {
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
}
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, !value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -454,12 +454,10 @@ static void gfxhub_v12_0_set_fault_enable_default(struct amdgpu_device *adev,
|
|||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
if (!value) {
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
}
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, !value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -633,19 +633,17 @@ static void gfxhub_v12_1_xcc_set_fault_enable_default(struct amdgpu_device *adev
|
|||
tmp = REG_SET_FIELD(tmp,
|
||||
GCVM_L2_PROTECTION_FAULT_CNTL_LO32,
|
||||
OTHER_CLIENT_ID_NO_RETRY_FAULT_INTERRUPT, value);
|
||||
if (!value)
|
||||
tmp = REG_SET_FIELD(tmp,
|
||||
GCVM_L2_PROTECTION_FAULT_CNTL_LO32,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp,
|
||||
GCVM_L2_PROTECTION_FAULT_CNTL_LO32,
|
||||
CRASH_ON_NO_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, GET_INST(GC, i),
|
||||
regGCVM_L2_PROTECTION_FAULT_CNTL_LO32, tmp);
|
||||
|
||||
tmp = RREG32_SOC15(GC, GET_INST(GC, i),
|
||||
regGCVM_L2_PROTECTION_FAULT_CNTL_HI32);
|
||||
if (!value)
|
||||
tmp = REG_SET_FIELD(tmp,
|
||||
GCVM_L2_PROTECTION_FAULT_CNTL_HI32,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp,
|
||||
GCVM_L2_PROTECTION_FAULT_CNTL_HI32,
|
||||
CRASH_ON_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, GET_INST(GC, i),
|
||||
regGCVM_L2_PROTECTION_FAULT_CNTL_HI32, tmp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -403,12 +403,10 @@ static void gfxhub_v1_0_set_fault_enable_default(struct amdgpu_device *adev,
|
|||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
if (!value) {
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
}
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, !value);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, 0, mmVM_L2_PROTECTION_FAULT_CNTL, tmp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -516,12 +516,10 @@ static void gfxhub_v1_2_xcc_set_fault_enable_default(struct amdgpu_device *adev,
|
|||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
if (!value) {
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
}
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, !value);
|
||||
tmp = REG_SET_FIELD(tmp, VM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, GET_INST(GC, i), regVM_L2_PROTECTION_FAULT_CNTL, tmp);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -418,12 +418,10 @@ static void gfxhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev,
|
|||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
if (!value) {
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
}
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, !value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, 0, mmGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -449,12 +449,10 @@ static void gfxhub_v2_1_set_fault_enable_default(struct amdgpu_device *adev,
|
|||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
if (!value) {
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
}
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, !value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, 0, mmGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -446,12 +446,10 @@ static void gfxhub_v3_0_set_fault_enable_default(struct amdgpu_device *adev,
|
|||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
if (!value) {
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
}
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, !value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -434,12 +434,10 @@ static void gfxhub_v3_0_3_set_fault_enable_default(struct amdgpu_device *adev,
|
|||
WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
|
||||
if (!value) {
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, 1);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, 1);
|
||||
}
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_NO_RETRY_FAULT, !value);
|
||||
tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL,
|
||||
CRASH_ON_RETRY_FAULT, !value);
|
||||
WREG32_SOC15(GC, 0, regGCVM_L2_PROTECTION_FAULT_CNTL, tmp);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -847,6 +847,7 @@ static int gmc_v10_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
* internal address space.
|
||||
*/
|
||||
adev->gmc.mc_mask = 0xffffffffffffULL; /* 48 bit MC */
|
||||
adev->gmc.pte_addr_mask = 0x0000FFFFFFFFF000ULL; /* 48 bit PA */
|
||||
|
||||
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(44));
|
||||
if (r) {
|
||||
|
|
|
|||
|
|
@ -821,6 +821,7 @@ static int gmc_v11_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
* internal address space.
|
||||
*/
|
||||
adev->gmc.mc_mask = 0xffffffffffffULL; /* 48 bit MC */
|
||||
adev->gmc.pte_addr_mask = 0x0000FFFFFFFFF000ULL; /* 48 bit PA */
|
||||
|
||||
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(44));
|
||||
if (r) {
|
||||
|
|
|
|||
|
|
@ -812,8 +812,9 @@ static int gmc_v12_0_gart_init(struct amdgpu_device *adev)
|
|||
|
||||
static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
|
||||
{
|
||||
int r, vram_width = 0, vram_type = 0, vram_vendor = 0;
|
||||
int r, vram_width = 0, vram_type = 0, vram_vendor = 0, dma_addr_bits;
|
||||
struct amdgpu_device *adev = ip_block->adev;
|
||||
uint64_t pte_addr_mask = 0;
|
||||
int i;
|
||||
|
||||
adev->mmhub.funcs->init(adev);
|
||||
|
|
@ -843,6 +844,8 @@ static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
* block size 512 (9bit)
|
||||
*/
|
||||
amdgpu_vm_adjust_size(adev, 256 * 1024, 9, 3, 48);
|
||||
pte_addr_mask = 0x0000FFFFFFFFF000ULL; /* 48 bit PA */
|
||||
dma_addr_bits = 44;
|
||||
break;
|
||||
case IP_VERSION(12, 1, 0):
|
||||
bitmap_set(adev->vmhubs_mask, AMDGPU_GFXHUB(0),
|
||||
|
|
@ -855,9 +858,13 @@ static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
* block size 512 (9bit)
|
||||
*/
|
||||
amdgpu_vm_adjust_size(adev, 128 * 1024 * 1024, 9, 4, 57);
|
||||
pte_addr_mask = 0x000FFFFFFFFFF000ULL; /* 52 bit PA */
|
||||
dma_addr_bits = 52;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
dev_warn(adev->dev, "Unrecognized GC IP version: 0x%08x\n",
|
||||
amdgpu_ip_version(adev, GC_HWIP, 0));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* This interrupt is VMC page fault.*/
|
||||
|
|
@ -911,14 +918,15 @@ static int gmc_v12_0_sw_init(struct amdgpu_ip_block *ip_block)
|
|||
* internal address space.
|
||||
*/
|
||||
adev->gmc.mc_mask = AMDGPU_GMC_HOLE_MASK;
|
||||
adev->gmc.pte_addr_mask = pte_addr_mask;
|
||||
|
||||
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(44));
|
||||
r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(dma_addr_bits));
|
||||
if (r) {
|
||||
drm_warn(adev_to_drm(adev), "No suitable DMA available.\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
adev->need_swiotlb = drm_need_swiotlb(44);
|
||||
adev->need_swiotlb = drm_need_swiotlb(dma_addr_bits);
|
||||
|
||||
r = gmc_v12_0_mc_init(adev);
|
||||
if (r)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user