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:
Takashi Iwai 2026-06-15 20:19:22 +02:00
commit c5e90e8844
800 changed files with 44580 additions and 6053 deletions

View File

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

View File

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

View File

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

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

View File

@ -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 = <&reg_audio>;
VD-supply = <&reg_audio>;
VLS-supply = <&reg_audio>;
VLC-supply = <&reg_audio>;
reset-gpios = <&gpio 1>;
};
};

View File

@ -27,6 +27,10 @@ properties:
items:
- const: mclk
port:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
"#sound-dai-cells":
const: 0

View File

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

View File

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

View 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 = <&regulator>;
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 = <&regulator>;
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 = <&regulator>;
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 = <&regulator>;
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 = <&regulator>;
vddio-supply = <&regulator1>;
vdda1-supply = <&regulator2>;
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>;
};
...

View File

@ -37,7 +37,13 @@ patternProperties:
items:
enum:
- i2s
- left_j
- right_j
- dsp_a
- dsp_b
- pdm
- msb
- lsb
dai-tdm-slot-num: true

View File

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

View 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/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>;
};

View File

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

View 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";
};
};
...

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

@ -7,3 +7,4 @@ Codec-Specific Information
:maxdepth: 2
cs35l56
tas675x

View 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 = 80100 °C, 2 = 100120 °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 CH1CH4),
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: 0xD10xD2 (CH1), 0xD30xD4 (CH2), 0xD50xD6 (CH3), 0xD70xD8 (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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -146,7 +146,7 @@ flash@30000000 {
partitions {
compatible = "redboot-fis";
/* Eraseblock at 0xfe0000 */
fis-index-block = <0x1fc>;
fis-index-block = <0x7f>;
};
};

View File

@ -134,7 +134,7 @@ flash@30000000 {
partitions {
compatible = "redboot-fis";
/* Eraseblock at 0xfe0000 */
fis-index-block = <0x1fc>;
fis-index-block = <0x7f>;
};
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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