mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
ASoC: Updates for v7.4
There's an awful lot of cleanup work in this pull request, lots from Bui
Duc Phuc, Pengpeng Hou, HyeongJun An and Chancel Liu cleaning up detail
issues in drivers in addition to Mormoto-san's ongoing framework work.
This time Morimoto-san's work included enabling auto_selectable_formats
so there's less manual configuration required for DAI links.
There's also been a huge amount of upstreaming activity from Qualcomm,
some pain there but hopefully enough has now landed for things to be
smoother in future.
- Use auto_selectable_formats in most drivers to reduce the amount of
manual configuration required for DAI links.
- Support for compressed audio on SOF IPC4 systems.
- Support for AMD ACP 7.B and 7.F, AmLogic A9 and T7, Airoha AN7581,
ESS Technology ES9039Q2M, Intel Cherry Trail with RT5688, Nuvoton
NAU83G60, nVidia systems with WM8994, Qualcomm QAIF, Senary I2S, WCD9378
and various platforms, Realtek RT766 and RT767, Senary SN624x
I also mistakenly merged some SPI changes in here then applied more
patches on top before I noticed (it looks like this was b4's base
selection logic picking a bad base for some ASoC work), highlights there
are:
- Improvements for spidev_test to cover additional use cases, plus be a
bit easier to use.
- Push more Tegra210 QSPI handling into interrupt context for
performance improvements.
- Support for Qualcomm QPIC SNAND v2 and RealTek RTD1625 NOR.
- Documentation clarifications.
- Fixes for some runtime PM and error handling issues.
- Support for R-Car Gen5.
(this should also be going in via my SPI pull request)
-----BEGIN PGP SIGNATURE-----
iHUEABYKAB0WIQReagvpf3TrrA7BoYYv73Ows9A4iQUCatYeBwAKCRAv73Ows9A4
iZGkAP42Kan4kjk94MkmNDLX76vzffRYznFmexPQGrFqwkzt/gD+Kd5NDbDs5U4m
D5rPlU6xLbRAl+8VztbWX2lhTWZPKwA=
=MEqI
-----END PGP SIGNATURE-----
Merge tag 'asoc-v7.4' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v7.4
There's an awful lot of cleanup work in this pull request, lots from Bui
Duc Phuc, Pengpeng Hou, HyeongJun An and Chancel Liu cleaning up detail
issues in drivers in addition to Mormoto-san's ongoing framework work.
This time Morimoto-san's work included enabling auto_selectable_formats
so there's less manual configuration required for DAI links.
There's also been a huge amount of upstreaming activity from Qualcomm,
some pain there but hopefully enough has now landed for things to be
smoother in future.
- Use auto_selectable_formats in most drivers to reduce the amount of
manual configuration required for DAI links.
- Support for compressed audio on SOF IPC4 systems.
- Support for AMD ACP 7.B and 7.F, AmLogic A9 and T7, Airoha AN7581,
ESS Technology ES9039Q2M, Intel Cherry Trail with RT5688, Nuvoton
NAU83G60, nVidia systems with WM8994, Qualcomm QAIF, Senary I2S, WCD9378
and various platforms, Realtek RT766 and RT767, Senary SN624x
I also mistakenly merged some SPI changes in here then applied more
patches on top before I noticed (it looks like this was b4's base
selection logic picking a bad base for some ASoC work), highlights there
are:
- Improvements for spidev_test to cover additional use cases, plus be a
bit easier to use.
- Push more Tegra210 QSPI handling into interrupt context for
performance improvements.
- Support for Qualcomm QPIC SNAND v2 and RealTek RTD1625 NOR.
- Documentation clarifications.
- Fixes for some runtime PM and error handling issues.
- Support for R-Car Gen5.
(this should also be going in via my SPI pull request)
This commit is contained in:
commit
31fd009c28
|
|
@ -17,7 +17,8 @@ Description: (WO) Instantiate a new SPI device on bus B, where B
|
|||
with delete_device; platform and DT devices are not
|
||||
affected.
|
||||
|
||||
Example:
|
||||
Example::
|
||||
|
||||
# echo spidev 0 > /sys/class/spi_master/spi0/new_device
|
||||
# echo spidev 0 10000000 > /sys/class/spi_master/spi0/new_device
|
||||
# echo spidev 0 10000000 3 > /sys/class/spi_master/spi0/new_device
|
||||
|
|
@ -30,5 +31,6 @@ Description: (WO) Remove a SPI device previously created via
|
|||
new_device. Takes a single parameter: the chip select
|
||||
number of the device to remove.
|
||||
|
||||
Example:
|
||||
Example::
|
||||
|
||||
# echo 0 > /sys/class/spi_master/spi0/delete_device
|
||||
|
|
|
|||
|
|
@ -52,11 +52,11 @@ examples:
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
audio-codec@3c {
|
||||
compatible = "adi,adau1372";
|
||||
reg = <0x3c>;
|
||||
#sound-dai-cells = <0>;
|
||||
clock-names = "mclk";
|
||||
clocks = <&adau1372z_xtal>;
|
||||
compatible = "adi,adau1372";
|
||||
reg = <0x3c>;
|
||||
#sound-dai-cells = <0>;
|
||||
clock-names = "mclk";
|
||||
clocks = <&adau1372z_xtal>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -68,20 +68,20 @@ examples:
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
adau7118_codec: audio-codec@14 {
|
||||
compatible = "adi,adau7118";
|
||||
reg = <0x14>;
|
||||
#sound-dai-cells = <0>;
|
||||
iovdd-supply = <&supply>;
|
||||
dvdd-supply = <&supply>;
|
||||
adi,pdm-clk-map = <1 1 0 0>;
|
||||
adi,decimation-ratio = <16>;
|
||||
compatible = "adi,adau7118";
|
||||
reg = <0x14>;
|
||||
#sound-dai-cells = <0>;
|
||||
iovdd-supply = <&supply>;
|
||||
dvdd-supply = <&supply>;
|
||||
adi,pdm-clk-map = <1 1 0 0>;
|
||||
adi,decimation-ratio = <16>;
|
||||
};
|
||||
};
|
||||
|
||||
/* example with hw standalone mode */
|
||||
adau7118_codec_hw: adau7118-codec-hw {
|
||||
compatible = "adi,adau7118";
|
||||
#sound-dai-cells = <0>;
|
||||
iovdd-supply = <&supply>;
|
||||
dvdd-supply = <&supply>;
|
||||
compatible = "adi,adau7118";
|
||||
#sound-dai-cells = <0>;
|
||||
iovdd-supply = <&supply>;
|
||||
dvdd-supply = <&supply>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/airoha,an7581-afe.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Airoha AFE PCM controller for AN7581
|
||||
|
||||
maintainers:
|
||||
- Christian Marangi <ansuelsmth@gmail.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: airoha,an7581-afe
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
afe@1fbe2200 {
|
||||
compatible = "airoha,an7581-afe";
|
||||
reg = <0x1fbe2200 0x9000>;
|
||||
|
||||
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
|
||||
};
|
||||
|
||||
...
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/airoha,an7581-wm8960.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Airoha AN7581 sound card with WM8960 codec
|
||||
|
||||
maintainers:
|
||||
- Christian Marangi <ansuelsmth@gmail.com>
|
||||
|
||||
allOf:
|
||||
- $ref: sound-card-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: airoha,an7581-wm8960-sound
|
||||
|
||||
platform:
|
||||
type: object
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
sound-dai:
|
||||
items:
|
||||
- description: The phandle of AN7581 platform.
|
||||
|
||||
required:
|
||||
- sound-dai
|
||||
|
||||
codec:
|
||||
type: object
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
sound-dai:
|
||||
items:
|
||||
- description: The phandle of WM8960 i2c codec.
|
||||
|
||||
required:
|
||||
- sound-dai
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- audio-routing
|
||||
- platform
|
||||
- codec
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
sound {
|
||||
compatible = "airoha,an7581-wm8960-sound";
|
||||
model = "an7581-wm8960";
|
||||
audio-routing =
|
||||
"Headphone", "HP_L",
|
||||
"Headphone", "HP_R",
|
||||
"LINPUT1", "AMIC",
|
||||
"RINPUT1", "AMIC";
|
||||
|
||||
platform {
|
||||
sound-dai = <&afe>;
|
||||
};
|
||||
|
||||
codec {
|
||||
sound-dai = <&wm8960>;
|
||||
};
|
||||
};
|
||||
|
|
@ -94,20 +94,20 @@ examples:
|
|||
audio-routing = "I2S ENCODER I2S IN", "I2S FIFO Playback";
|
||||
|
||||
dai-link-0 {
|
||||
sound-dai = <&i2s_fifo>;
|
||||
sound-dai = <&i2s_fifo>;
|
||||
};
|
||||
|
||||
dai-link-1 {
|
||||
sound-dai = <&i2s_encoder>;
|
||||
dai-format = "i2s";
|
||||
mclk-fs = <256>;
|
||||
sound-dai = <&i2s_encoder>;
|
||||
dai-format = "i2s";
|
||||
mclk-fs = <256>;
|
||||
|
||||
codec-0 {
|
||||
sound-dai = <&codec0>;
|
||||
};
|
||||
codec-0 {
|
||||
sound-dai = <&codec0>;
|
||||
};
|
||||
|
||||
codec-1 {
|
||||
sound-dai = <&codec1>;
|
||||
};
|
||||
codec-1 {
|
||||
sound-dai = <&codec1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -34,6 +34,12 @@ properties:
|
|||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
powerdown-gpios:
|
||||
maxItems: 1
|
||||
description:
|
||||
GPIO connected to the 'PDN' pin, if any. Needs to be set low to
|
||||
power down the codec, hence the GPIO must be GPIO_ACTIVE_LOW.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
@ -42,6 +48,8 @@ unevaluatedProperties: false
|
|||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
|
@ -49,14 +57,16 @@ examples:
|
|||
compatible = "asahi-kasei,ak4619";
|
||||
reg = <0x10>;
|
||||
|
||||
powerdown-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
|
||||
|
||||
clocks = <&rcar_sound>;
|
||||
clock-names = "mclk";
|
||||
|
||||
#sound-dai-cells = <0>;
|
||||
port {
|
||||
ak4619_endpoint: endpoint {
|
||||
remote-endpoint = <&rsnd_endpoint>;
|
||||
};
|
||||
ak4619_endpoint: endpoint {
|
||||
remote-endpoint = <&rsnd_endpoint>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ definitions:
|
|||
allOf:
|
||||
- $ref: /schemas/graph.yaml#/$defs/endpoint-base
|
||||
- $ref: /schemas/sound/dai-params.yaml#
|
||||
- $ref: /schemas/sound/tdm-slot.yaml#
|
||||
properties:
|
||||
mclk-fs:
|
||||
$ref: simple-card.yaml#/definitions/mclk-fs
|
||||
|
|
@ -48,6 +49,9 @@ definitions:
|
|||
bitclock-inversion:
|
||||
description: dai-link uses bit clock inversion
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
continuous-clock:
|
||||
description: dai-link bit clock runs continuously rather than gated
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
frame-master:
|
||||
description: Indicates dai-link frame master.
|
||||
oneOf:
|
||||
|
|
@ -82,12 +86,6 @@ definitions:
|
|||
- msb
|
||||
- lsb
|
||||
|
||||
dai-tdm-slot-num:
|
||||
description: Number of slots in use.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
dai-tdm-slot-width:
|
||||
description: Width in bits for each slot.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
dai-tdm-slot-width-map:
|
||||
description: Mapping of sample widths to slot widths. For hardware
|
||||
that cannot support a fixed slot width or a slot width always
|
||||
|
|
|
|||
|
|
@ -53,6 +53,76 @@ properties:
|
|||
maximum: 3
|
||||
default: 2
|
||||
|
||||
cirrus,sync-lsw-txid:
|
||||
description:
|
||||
Transmitter ID to use for long software (LSW) data packets
|
||||
on the SYNC bus.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 7
|
||||
default: 0
|
||||
|
||||
cirrus,sync-sw-txid:
|
||||
description:
|
||||
Transmitter ID to use for short software (SW) data packets
|
||||
on the SYNC bus.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 7
|
||||
default: 0
|
||||
|
||||
cirrus,ldpm-group1-boost-select:
|
||||
type: boolean
|
||||
description:
|
||||
When in a valid group 1 level dependent power management (LDPM) state
|
||||
the integrated boost converter will enter the configured low power mode.
|
||||
|
||||
cirrus,boost-low-power-mode:
|
||||
description:
|
||||
Configures the integrated boost converter reaction to a low power mode
|
||||
request.
|
||||
0 = No reaction
|
||||
1 = Force boost DCM low power mode
|
||||
2 = Force boost static bypass
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
default: 2
|
||||
enum:
|
||||
- 0
|
||||
- 1
|
||||
- 2
|
||||
|
||||
cirrus,ldpm-group1-amp-select:
|
||||
type: boolean
|
||||
description:
|
||||
When in a valid group 1 level dependent power management (LDPM) state
|
||||
the amplifier will enter the configured low power mode.
|
||||
|
||||
cirrus,amplifier-low-power-mode:
|
||||
description:
|
||||
Configures the amplifier output stage reaction to a low power mode
|
||||
request.
|
||||
0 = Stop output switching (noise gate mode)
|
||||
1 = Noise floor reduction mode
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
default: 1
|
||||
enum:
|
||||
- 0
|
||||
- 1
|
||||
|
||||
cirrus,ldpm-group2-vmon-select:
|
||||
type: boolean
|
||||
description:
|
||||
When in a valid group 2 level dependent power management (LDPM) state
|
||||
the voltage monitor (VMON) circuit is put into a low power operational
|
||||
state.
|
||||
|
||||
cirrus,ldpm-group2-imon-select:
|
||||
type: boolean
|
||||
description:
|
||||
When in a valid group 2 level dependent power management (LDPM) state
|
||||
the current monitor (IMON) circuit is put into a low power operational
|
||||
state.
|
||||
|
||||
patternProperties:
|
||||
"^cirrus,gpio-ctrl[1-3]$":
|
||||
description:
|
||||
|
|
@ -121,6 +191,30 @@ patternProperties:
|
|||
minimum: 0
|
||||
maximum: 7
|
||||
default: 0
|
||||
|
||||
"^cirrus,ldpm-group[1-2]-pcm-threshold-db$":
|
||||
description:
|
||||
Amplifier level dependent power management (LDPM) threshold. Input
|
||||
referred threshold of the PCM audio signal in which the level is low
|
||||
enough for the LDPM group to engage after entry delay. A value of dB
|
||||
-2147483648 is assumed to mean true zero data with an LSB dither.
|
||||
$ref: /schemas/types.yaml#/definitions/int32-array
|
||||
minItems: 1
|
||||
maxItems: 1
|
||||
items:
|
||||
enum: [-2147483648, -102, -96, -90, -84, -78, -72, -66]
|
||||
|
||||
"^cirrus,ldpm-group[1-2]-delay-ms$":
|
||||
description:
|
||||
Amplifier level dependent power management (LDPM) state entry delay.
|
||||
Time that the incoming audio signal must be below the PCM threshold
|
||||
before the LDPM group engages.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 1
|
||||
maxItems: 1
|
||||
items:
|
||||
enum: [5, 10, 25, 50, 100, 250, 500, 1000]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
@ -135,25 +229,37 @@ examples:
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cs35l45: cs35l45@2 {
|
||||
#sound-dai-cells = <1>;
|
||||
compatible = "cirrus,cs35l45";
|
||||
reg = <2>;
|
||||
spi-max-frequency = <5000000>;
|
||||
vdd-a-supply = <&dummy_vreg>;
|
||||
vdd-batt-supply = <&dummy_vreg>;
|
||||
reset-gpios = <&gpio 110 0>;
|
||||
cirrus,asp-sdout-hiz-ctrl = <(CS35L45_ASP_TX_HIZ_UNUSED |
|
||||
CS35L45_ASP_TX_HIZ_DISABLED)>;
|
||||
cirrus,gpio-ctrl1 {
|
||||
gpio-ctrl = <0x2>;
|
||||
};
|
||||
cirrus,gpio-ctrl2 {
|
||||
gpio-ctrl = <0x2>;
|
||||
};
|
||||
cirrus,gpio-ctrl3 {
|
||||
gpio-ctrl = <0x1>;
|
||||
gpio-dir = <0x1>;
|
||||
};
|
||||
cs35l45: audio-codec@2 {
|
||||
#sound-dai-cells = <1>;
|
||||
compatible = "cirrus,cs35l45";
|
||||
reg = <2>;
|
||||
spi-max-frequency = <5000000>;
|
||||
vdd-a-supply = <&dummy_vreg>;
|
||||
vdd-batt-supply = <&dummy_vreg>;
|
||||
reset-gpios = <&gpio 110 0>;
|
||||
cirrus,asp-sdout-hiz-ctrl = <(CS35L45_ASP_TX_HIZ_UNUSED |
|
||||
CS35L45_ASP_TX_HIZ_DISABLED)>;
|
||||
cirrus,sync-lsw-txid = <0x1>;
|
||||
cirrus,sync-sw-txid = <0x1>;
|
||||
cirrus,ldpm-group1-pcm-threshold-db = <(-66)>;
|
||||
cirrus,ldpm-group1-delay-ms = <500>;
|
||||
cirrus,ldpm-group1-boost-select;
|
||||
cirrus,boost-low-power-mode = <CS35L45_BST_LPMODE_DCM_MODE>;
|
||||
cirrus,ldpm-group1-amp-select;
|
||||
cirrus,amplifier-low-power-mode = <CS35L45_AMP_LPMODE_NFR_MODE>;
|
||||
cirrus,ldpm-group2-pcm-threshold-db = <(-102)>;
|
||||
cirrus,ldpm-group2-delay-ms = <1000>;
|
||||
cirrus,ldpm-group2-vmon-select;
|
||||
cirrus,ldpm-group2-imon-select;
|
||||
cirrus,gpio-ctrl1 {
|
||||
gpio-ctrl = <0x2>;
|
||||
};
|
||||
cirrus,gpio-ctrl2 {
|
||||
gpio-ctrl = <0x2>;
|
||||
};
|
||||
cirrus,gpio-ctrl3 {
|
||||
gpio-ctrl = <0x1>;
|
||||
gpio-dir = <0x1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -49,11 +49,11 @@ unevaluatedProperties: false
|
|||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
codec@48 {
|
||||
compatible = "cirrus,cs4270";
|
||||
reg = <0x48>;
|
||||
};
|
||||
codec@48 {
|
||||
compatible = "cirrus,cs4270";
|
||||
reg = <0x48>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -199,28 +199,28 @@ examples:
|
|||
- |
|
||||
#include <dt-bindings/sound/cs42l42.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cs42l42: cs42l42@48 {
|
||||
compatible = "cirrus,cs42l42";
|
||||
reg = <0x48>;
|
||||
VA-supply = <&dummy_vreg>;
|
||||
VP-supply = <&dummy_vreg>;
|
||||
VCP-supply = <&dummy_vreg>;
|
||||
VD_FILT-supply = <&dummy_vreg>;
|
||||
VL-supply = <&dummy_vreg>;
|
||||
audio-codec@48 {
|
||||
compatible = "cirrus,cs42l42";
|
||||
reg = <0x48>;
|
||||
VA-supply = <&dummy_vreg>;
|
||||
VP-supply = <&dummy_vreg>;
|
||||
VCP-supply = <&dummy_vreg>;
|
||||
VD_FILT-supply = <&dummy_vreg>;
|
||||
VL-supply = <&dummy_vreg>;
|
||||
|
||||
reset-gpios = <&axi_gpio_0 1 0>;
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <55 8>;
|
||||
reset-gpios = <&axi_gpio_0 1 0>;
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <55 8>;
|
||||
|
||||
cirrus,ts-inv = <CS42L42_TS_INV_DIS>;
|
||||
cirrus,ts-dbnc-rise = <CS42L42_TS_DBNCE_1000>;
|
||||
cirrus,ts-dbnc-fall = <CS42L42_TS_DBNCE_0>;
|
||||
cirrus,btn-det-init-dbnce = <100>;
|
||||
cirrus,btn-det-event-dbnce = <10>;
|
||||
cirrus,bias-lvls = <0x0F 0x08 0x04 0x01>;
|
||||
cirrus,hs-bias-ramp-rate = <CS42L42_HSBIAS_RAMP_SLOW>;
|
||||
};
|
||||
cirrus,ts-inv = <CS42L42_TS_INV_DIS>;
|
||||
cirrus,ts-dbnc-rise = <CS42L42_TS_DBNCE_1000>;
|
||||
cirrus,ts-dbnc-fall = <CS42L42_TS_DBNCE_0>;
|
||||
cirrus,btn-det-init-dbnce = <100>;
|
||||
cirrus,btn-det-event-dbnce = <10>;
|
||||
cirrus,bias-lvls = <0x0F 0x08 0x04 0x01>;
|
||||
cirrus,hs-bias-ramp-rate = <CS42L42_HSBIAS_RAMP_SLOW>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -43,14 +43,14 @@ examples:
|
|||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
jack_codec: codec@4b {
|
||||
compatible = "cirrus,cs42l84";
|
||||
reg = <0x4b>;
|
||||
reset-gpios = <&pinctrl_nub 4 GPIO_ACTIVE_LOW>;
|
||||
interrupts-extended = <&pinctrl_ap 180 IRQ_TYPE_LEVEL_LOW>;
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
||||
jack_codec: codec@4b {
|
||||
compatible = "cirrus,cs42l84";
|
||||
reg = <0x4b>;
|
||||
reset-gpios = <&pinctrl_nub 4 GPIO_ACTIVE_LOW>;
|
||||
interrupts-extended = <&pinctrl_ap 180 IRQ_TYPE_LEVEL_LOW>;
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -75,37 +75,37 @@ unevaluatedProperties: false
|
|||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
codec@48 {
|
||||
compatible = "cirrus,cs42888";
|
||||
reg = <0x48>;
|
||||
clocks = <&codec_mclk 0>;
|
||||
clock-names = "mclk";
|
||||
VA-supply = <®_audio>;
|
||||
VD-supply = <®_audio>;
|
||||
VLS-supply = <®_audio>;
|
||||
VLC-supply = <®_audio>;
|
||||
reset-gpios = <&gpio 1>;
|
||||
};
|
||||
codec@48 {
|
||||
compatible = "cirrus,cs42888";
|
||||
reg = <0x48>;
|
||||
clocks = <&codec_mclk 0>;
|
||||
clock-names = "mclk";
|
||||
VA-supply = <®_audio>;
|
||||
VD-supply = <®_audio>;
|
||||
VLS-supply = <®_audio>;
|
||||
VLC-supply = <®_audio>;
|
||||
reset-gpios = <&gpio 1>;
|
||||
};
|
||||
};
|
||||
|
||||
spi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cs-gpios = <&gpio 8 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
cs-gpios = <&gpio 8 0>;
|
||||
|
||||
codec@0 {
|
||||
compatible = "cirrus,cs42888";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <6000000>;
|
||||
clocks = <&codec_mclk 0>;
|
||||
clock-names = "mclk";
|
||||
VA-supply = <®_audio>;
|
||||
VD-supply = <®_audio>;
|
||||
VLS-supply = <®_audio>;
|
||||
VLC-supply = <®_audio>;
|
||||
reset-gpios = <&gpio 1>;
|
||||
};
|
||||
codec@0 {
|
||||
compatible = "cirrus,cs42888";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <6000000>;
|
||||
clocks = <&codec_mclk 0>;
|
||||
clock-names = "mclk";
|
||||
VA-supply = <®_audio>;
|
||||
VD-supply = <®_audio>;
|
||||
VLS-supply = <®_audio>;
|
||||
VLC-supply = <®_audio>;
|
||||
reset-gpios = <&gpio 1>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,49 +0,0 @@
|
|||
* Texas Instruments SoC audio setups with TLV320AIC3X Codec
|
||||
|
||||
Required properties:
|
||||
- compatible : "ti,da830-evm-audio" : forDM365/DA8xx/OMAPL1x/AM33xx
|
||||
- ti,model : The user-visible name of this sound complex.
|
||||
- ti,audio-codec : The phandle of the TLV320AIC3x audio codec
|
||||
- ti,mcasp-controller : The phandle of the McASP controller
|
||||
- ti,audio-routing : A list of the connections between audio components.
|
||||
Each entry is a pair of strings, the first being the connection's sink,
|
||||
the second being the connection's source. Valid names for sources and
|
||||
sinks are the codec's pins, and the jacks on the board:
|
||||
|
||||
Optional properties:
|
||||
- ti,codec-clock-rate : The Codec Clock rate (in Hz) applied to the Codec.
|
||||
- clocks : Reference to the master clock
|
||||
- clock-names : The clock should be named "mclk"
|
||||
- Either codec-clock-rate or the codec-clock reference has to be defined. If
|
||||
the both are defined the driver attempts to set referenced clock to the
|
||||
defined rate and takes the rate from the clock reference.
|
||||
|
||||
Board connectors:
|
||||
|
||||
* Headphone Jack
|
||||
* Line Out
|
||||
* Mic Jack
|
||||
* Line In
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
sound {
|
||||
compatible = "ti,da830-evm-audio";
|
||||
ti,model = "DA830 EVM";
|
||||
ti,audio-codec = <&tlv320aic3x>;
|
||||
ti,mcasp-controller = <&mcasp1>;
|
||||
ti,codec-clock-rate = <12000000>;
|
||||
ti,audio-routing =
|
||||
"Headphone Jack", "HPLOUT",
|
||||
"Headphone Jack", "HPROUT",
|
||||
"Line Out", "LLOUT",
|
||||
"Line Out", "RLOUT",
|
||||
"MIC3L", "Mic Bias 2V",
|
||||
"MIC3R", "Mic Bias 2V",
|
||||
"Mic Bias 2V", "Mic Jack",
|
||||
"LINE1L", "Line In",
|
||||
"LINE2L", "Line In",
|
||||
"LINE1R", "Line In",
|
||||
"LINE2R", "Line In";
|
||||
};
|
||||
|
|
@ -195,44 +195,44 @@ examples:
|
|||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
codec: da7219@1a {
|
||||
compatible = "dlg,da7219";
|
||||
reg = <0x1a>;
|
||||
codec: audio-codec@1a {
|
||||
compatible = "dlg,da7219";
|
||||
reg = <0x1a>;
|
||||
|
||||
interrupt-parent = <&gpio6>;
|
||||
interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupt-parent = <&gpio6>;
|
||||
interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
VDD-supply = <&vdd_reg>;
|
||||
VDDMIC-supply = <&vddmic_reg>;
|
||||
VDDIO-supply = <&vddio_reg>;
|
||||
VDD-supply = <&vdd_reg>;
|
||||
VDDMIC-supply = <&vddmic_reg>;
|
||||
VDDIO-supply = <&vddio_reg>;
|
||||
|
||||
#clock-cells = <1>;
|
||||
clock-output-names = "da7219-dai-wclk", "da7219-dai-bclk";
|
||||
#clock-cells = <1>;
|
||||
clock-output-names = "da7219-dai-wclk", "da7219-dai-bclk";
|
||||
|
||||
clocks = <&clks 201>;
|
||||
clock-names = "mclk";
|
||||
clocks = <&clks 201>;
|
||||
clock-names = "mclk";
|
||||
|
||||
dlg,micbias-lvl = <2600>;
|
||||
dlg,mic-amp-in-sel = "diff";
|
||||
dlg,micbias-lvl = <2600>;
|
||||
dlg,mic-amp-in-sel = "diff";
|
||||
|
||||
da7219_aad {
|
||||
dlg,btn-cfg = <50>;
|
||||
dlg,mic-det-thr = <500>;
|
||||
dlg,jack-ins-deb = <20>;
|
||||
dlg,jack-ins-det-pty = "low";
|
||||
dlg,jack-det-rate = "32_64";
|
||||
dlg,jack-rem-deb = <1>;
|
||||
da7219_aad {
|
||||
dlg,btn-cfg = <50>;
|
||||
dlg,mic-det-thr = <500>;
|
||||
dlg,jack-ins-deb = <20>;
|
||||
dlg,jack-ins-det-pty = "low";
|
||||
dlg,jack-det-rate = "32_64";
|
||||
dlg,jack-rem-deb = <1>;
|
||||
|
||||
dlg,a-d-btn-thr = <0xa>;
|
||||
dlg,d-b-btn-thr = <0x16>;
|
||||
dlg,b-c-btn-thr = <0x21>;
|
||||
dlg,c-mic-btn-thr = <0x3E>;
|
||||
dlg,a-d-btn-thr = <0xa>;
|
||||
dlg,d-b-btn-thr = <0x16>;
|
||||
dlg,b-c-btn-thr = <0x21>;
|
||||
dlg,c-mic-btn-thr = <0x3E>;
|
||||
|
||||
dlg,btn-avg = <4>;
|
||||
dlg,adc-1bit-rpt = <1>;
|
||||
};
|
||||
};
|
||||
dlg,btn-avg = <4>;
|
||||
dlg,adc-1bit-rpt = <1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/esstech,es9039q2m.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ESS Technology ES9039Q2M audio DAC
|
||||
|
||||
maintainers:
|
||||
- Karl Asseily <karl@asseily.com>
|
||||
|
||||
description:
|
||||
The ES9039Q2M is a 32-bit two-channel audio DAC supporting PCM to 768 kHz,
|
||||
DSD64 to DSD1024, DoP and S/PDIF. It is controlled over I2C or SPI when the
|
||||
MODE pin selects software mode; this binding covers the I2C interface. The
|
||||
part contains an asynchronous sample rate converter, so the system clock need
|
||||
not be synchronous with the audio bit or frame clocks.
|
||||
|
||||
The four supplies are all nominally 3.3V and the datasheet requires a set
|
||||
order - AVDD first, then VCCA about 200us later, then AVCC_DAC1 and
|
||||
AVCC_DAC2, and the reverse on the way down. DVDD, the part's 1.2V rail, is
|
||||
on-chip and needs only its decoupling capacitor - it is not a supply input
|
||||
and has no property here.
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: esstech,es9039q2m
|
||||
|
||||
reg:
|
||||
description:
|
||||
I2C address, selected by the ADDR0 and ADDR1 pins - 0x48, 0x49, 0x4a or
|
||||
0x4b for GND/GND, GND/AVDD, AVDD/GND and AVDD/AVDD respectively.
|
||||
enum: [ 0x48, 0x49, 0x4a, 0x4b ]
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
const: mclk
|
||||
|
||||
avdd-supply:
|
||||
description:
|
||||
3.3V supply for the part's internal digital regulator, pin AVDD. It is
|
||||
the first rail up and the last down, per the ordering described above.
|
||||
|
||||
vcca-supply:
|
||||
description: 3.3V analogue supply, pin VCCA.
|
||||
|
||||
avcc-dac1-supply:
|
||||
description:
|
||||
3.3V reference supply for the channel 1 analogue output stage, pin
|
||||
AVCC_DAC1. The datasheet allows this rail to move by up to 15% where a
|
||||
calibrating regulator tracks the DAC's output impedance.
|
||||
|
||||
avcc-dac2-supply:
|
||||
description:
|
||||
3.3V reference supply for the channel 2 analogue output stage, pin
|
||||
AVCC_DAC2, with the same 15% allowance as channel 1.
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- avdd-supply
|
||||
- vcca-supply
|
||||
- avcc-dac1-supply
|
||||
- avcc-dac2-supply
|
||||
- "#sound-dai-cells"
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
audio-codec@48 {
|
||||
compatible = "esstech,es9039q2m";
|
||||
reg = <0x48>;
|
||||
#sound-dai-cells = <0>;
|
||||
clocks = <&dac_mclk>;
|
||||
clock-names = "mclk";
|
||||
avdd-supply = <&dac_3v3>;
|
||||
vcca-supply = <&dac_3v3>;
|
||||
avcc-dac1-supply = <&dac_avcc1>;
|
||||
avcc-dac2-supply = <&dac_avcc2>;
|
||||
};
|
||||
};
|
||||
|
|
@ -84,6 +84,11 @@ properties:
|
|||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
everest,jack-detect-inverted:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
Defined to invert the jack detection.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ properties:
|
|||
a. Register initialization settings
|
||||
b. DSP effect parameters
|
||||
c. Multi-scene sound effect configurations(optional)
|
||||
It's gernerated by FourSemi's tuning tool.
|
||||
It's generated by FourSemi's tuning tool.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
|
|
|||
|
|
@ -55,6 +55,14 @@ properties:
|
|||
- const: imx/easrc/easrc-imx8mn.bin
|
||||
description: The coefficient table for the filters
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
patternProperties:
|
||||
"^port@[0-3]$":
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
description: port for an independent conversion path
|
||||
|
||||
fsl,asrc-rate:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 8000
|
||||
|
|
@ -106,4 +114,41 @@ examples:
|
|||
firmware-name = "imx/easrc/easrc-imx8mn.bin";
|
||||
fsl,asrc-rate = <8000>;
|
||||
fsl,asrc-format = <2>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
playback-only;
|
||||
endpoint {
|
||||
remote-endpoint = <&fe00_ep>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
playback-only;
|
||||
endpoint {
|
||||
remote-endpoint = <&fe01_ep>;
|
||||
};
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
capture-only;
|
||||
endpoint {
|
||||
remote-endpoint = <&fe02_ep>;
|
||||
};
|
||||
};
|
||||
|
||||
port@3 {
|
||||
reg = <3>;
|
||||
capture-only;
|
||||
endpoint {
|
||||
remote-endpoint = <&fe03_ep>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -78,9 +78,19 @@ properties:
|
|||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
patternProperties:
|
||||
"^port@[0-2]$":
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
description: port for an independent conversion path
|
||||
|
||||
port:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
deprecated: true
|
||||
description: deprecated, use ports instead
|
||||
|
||||
fsl,asrc-rate:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
|
@ -125,6 +135,10 @@ required:
|
|||
- fsl,asrc-width
|
||||
|
||||
allOf:
|
||||
- not:
|
||||
required:
|
||||
- port
|
||||
- ports
|
||||
- $ref: dai-common.yaml#
|
||||
- if:
|
||||
properties:
|
||||
|
|
@ -180,11 +194,32 @@ examples:
|
|||
fsl,asrc-rate = <48000>;
|
||||
fsl,asrc-width = <16>;
|
||||
|
||||
port {
|
||||
playback-only;
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
asrc_endpoint: endpoint {
|
||||
remote-endpoint = <&fe00_ep>;
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
playback-only;
|
||||
endpoint {
|
||||
remote-endpoint = <&fe00_ep>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
capture-only;
|
||||
endpoint {
|
||||
remote-endpoint = <&fe01_ep>;
|
||||
};
|
||||
};
|
||||
|
||||
port@2 {
|
||||
reg = <2>;
|
||||
capture-only;
|
||||
endpoint {
|
||||
remote-endpoint = <&fe02_ep>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -260,13 +260,13 @@ examples:
|
|||
playback-only;
|
||||
|
||||
sai1_endpoint0: endpoint {
|
||||
dai-tdm-slot-num = <8>;
|
||||
dai-tdm-slot-width = <32>;
|
||||
dai-tdm-slot-width-map = <32 8 32>;
|
||||
dai-format = "dsp_a";
|
||||
bitclock-master;
|
||||
frame-master;
|
||||
remote-endpoint = <&mcodec01_ep>;
|
||||
dai-tdm-slot-num = <8>;
|
||||
dai-tdm-slot-width = <32>;
|
||||
dai-tdm-slot-width-map = <32 8 32>;
|
||||
dai-format = "dsp_a";
|
||||
bitclock-master;
|
||||
frame-master;
|
||||
remote-endpoint = <&mcodec01_ep>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,10 @@ properties:
|
|||
The dai cell indexes reference the following interfaces:
|
||||
0: S2 interface
|
||||
|
||||
ports:
|
||||
$ref: audio-graph-port.yaml#/definitions/ports
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
|||
|
|
@ -105,10 +105,10 @@ examples:
|
|||
format = "i2s";
|
||||
fsl,mclk-equal-bclk;
|
||||
cpu {
|
||||
sound-dai = <&sai1>;
|
||||
sound-dai = <&sai1>;
|
||||
};
|
||||
codec {
|
||||
sound-dai = <&ak4458_1>, <&ak4458_2>;
|
||||
sound-dai = <&ak4458_1>, <&ak4458_2>;
|
||||
};
|
||||
};
|
||||
fe-dai-link {
|
||||
|
|
|
|||
|
|
@ -101,10 +101,10 @@ examples:
|
|||
mux-ssi1 {
|
||||
fsl,audmux-port = <0>;
|
||||
fsl,port-config = <
|
||||
IMX_AUDMUX_V2_PTCR_SYN 0
|
||||
IMX_AUDMUX_V2_PTCR_TFSEL(2) 0
|
||||
IMX_AUDMUX_V2_PTCR_TCSEL(2) 0
|
||||
IMX_AUDMUX_V2_PTCR_TFSDIR 0
|
||||
IMX_AUDMUX_V2_PTCR_SYN 0
|
||||
IMX_AUDMUX_V2_PTCR_TFSEL(2) 0
|
||||
IMX_AUDMUX_V2_PTCR_TCSEL(2) 0
|
||||
IMX_AUDMUX_V2_PTCR_TFSDIR 0
|
||||
IMX_AUDMUX_V2_PTCR_TCLKDIR IMX_AUDMUX_V2_PDCR_RXDSEL(2)
|
||||
>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -42,10 +42,10 @@ examples:
|
|||
compatible = "invensense,ics43432";
|
||||
|
||||
port {
|
||||
endpoint {
|
||||
remote-endpoint = <&i2s1_endpoint>;
|
||||
dai-format = "i2s";
|
||||
};
|
||||
endpoint {
|
||||
remote-endpoint = <&i2s1_endpoint>;
|
||||
dai-format = "i2s";
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ examples:
|
|||
sound-dai = <&i2s>;
|
||||
};
|
||||
codec {
|
||||
sound-dai = <&es8323>;
|
||||
sound-dai = <&es8323>;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
@ -104,6 +104,6 @@ examples:
|
|||
};
|
||||
|
||||
codec {
|
||||
sound-dai = <&es8388>;
|
||||
sound-dai = <&es8388>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ properties:
|
|||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 34
|
||||
minItems: 33
|
||||
items:
|
||||
- description: audio infra sys clock
|
||||
- description: top audio mux 1
|
||||
|
|
@ -74,7 +74,7 @@ properties:
|
|||
- description: audio APLL root pd
|
||||
|
||||
clock-names:
|
||||
minItems: 34
|
||||
minItems: 33
|
||||
items:
|
||||
- const: infra_sys_audio_clk
|
||||
- const: top_audio_mux1_sel
|
||||
|
|
@ -132,8 +132,10 @@ allOf:
|
|||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 34
|
||||
minItems: 33
|
||||
maxItems: 33
|
||||
clock-names:
|
||||
maxItems: 34
|
||||
minItems: 33
|
||||
maxItems: 33
|
||||
|
||||
additionalProperties: false
|
||||
|
|
|
|||
|
|
@ -84,15 +84,15 @@ examples:
|
|||
<&topckgen CLK_TOP_I2S2_M_SEL>,
|
||||
<&topckgen CLK_TOP_I2S3_M_SEL>,
|
||||
<&topckgen CLK_TOP_I2S3_B_SEL>;
|
||||
clock-names = "infra_sys_audio_clk",
|
||||
"top_pdn_audio",
|
||||
"top_pdn_aud_intbus",
|
||||
"bck0",
|
||||
"bck1",
|
||||
"i2s0_m",
|
||||
"i2s1_m",
|
||||
"i2s2_m",
|
||||
"i2s3_m",
|
||||
"i2s3_b";
|
||||
memory-region = <&afe_dma_mem>;
|
||||
clock-names = "infra_sys_audio_clk",
|
||||
"top_pdn_audio",
|
||||
"top_pdn_aud_intbus",
|
||||
"bck0",
|
||||
"bck1",
|
||||
"i2s0_m",
|
||||
"i2s1_m",
|
||||
"i2s2_m",
|
||||
"i2s3_m",
|
||||
"i2s3_b";
|
||||
memory-region = <&afe_dma_mem>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -182,47 +182,47 @@ examples:
|
|||
<&topckgen CLK_TOP_APLL12_DIV4>,
|
||||
<&topckgen CLK_TOP_APLL12_DIVB>,
|
||||
<&clk26m>;
|
||||
clock-names = "aud_afe_clk",
|
||||
"aud_dac_clk",
|
||||
"aud_dac_predis_clk",
|
||||
"aud_adc_clk",
|
||||
"aud_adc_adda6_clk",
|
||||
"aud_apll22m_clk",
|
||||
"aud_apll24m_clk",
|
||||
"aud_apll1_tuner_clk",
|
||||
"aud_apll2_tuner_clk",
|
||||
"aud_i2s1_bclk_sw",
|
||||
"aud_i2s2_bclk_sw",
|
||||
"aud_i2s3_bclk_sw",
|
||||
"aud_i2s4_bclk_sw",
|
||||
"aud_tdm_clk",
|
||||
"aud_tml_clk",
|
||||
"aud_infra_clk",
|
||||
"mtkaif_26m_clk",
|
||||
"top_mux_audio",
|
||||
"top_mux_aud_intbus",
|
||||
"top_syspll_d2_d4",
|
||||
"top_mux_aud_1",
|
||||
"top_apll1_ck",
|
||||
"top_mux_aud_2",
|
||||
"top_apll2_ck",
|
||||
"top_mux_aud_eng1",
|
||||
"top_apll1_d8",
|
||||
"top_mux_aud_eng2",
|
||||
"top_apll2_d8",
|
||||
"top_i2s0_m_sel",
|
||||
"top_i2s1_m_sel",
|
||||
"top_i2s2_m_sel",
|
||||
"top_i2s3_m_sel",
|
||||
"top_i2s4_m_sel",
|
||||
"top_i2s5_m_sel",
|
||||
"top_apll12_div0",
|
||||
"top_apll12_div1",
|
||||
"top_apll12_div2",
|
||||
"top_apll12_div3",
|
||||
"top_apll12_div4",
|
||||
"top_apll12_divb",
|
||||
"top_clk26m_clk";
|
||||
clock-names = "aud_afe_clk",
|
||||
"aud_dac_clk",
|
||||
"aud_dac_predis_clk",
|
||||
"aud_adc_clk",
|
||||
"aud_adc_adda6_clk",
|
||||
"aud_apll22m_clk",
|
||||
"aud_apll24m_clk",
|
||||
"aud_apll1_tuner_clk",
|
||||
"aud_apll2_tuner_clk",
|
||||
"aud_i2s1_bclk_sw",
|
||||
"aud_i2s2_bclk_sw",
|
||||
"aud_i2s3_bclk_sw",
|
||||
"aud_i2s4_bclk_sw",
|
||||
"aud_tdm_clk",
|
||||
"aud_tml_clk",
|
||||
"aud_infra_clk",
|
||||
"mtkaif_26m_clk",
|
||||
"top_mux_audio",
|
||||
"top_mux_aud_intbus",
|
||||
"top_syspll_d2_d4",
|
||||
"top_mux_aud_1",
|
||||
"top_apll1_ck",
|
||||
"top_mux_aud_2",
|
||||
"top_apll2_ck",
|
||||
"top_mux_aud_eng1",
|
||||
"top_apll1_d8",
|
||||
"top_mux_aud_eng2",
|
||||
"top_apll2_d8",
|
||||
"top_i2s0_m_sel",
|
||||
"top_i2s1_m_sel",
|
||||
"top_i2s2_m_sel",
|
||||
"top_i2s3_m_sel",
|
||||
"top_i2s4_m_sel",
|
||||
"top_i2s5_m_sel",
|
||||
"top_apll12_div0",
|
||||
"top_apll12_div1",
|
||||
"top_apll12_div2",
|
||||
"top_apll12_div3",
|
||||
"top_apll12_div4",
|
||||
"top_apll12_divb",
|
||||
"top_clk26m_clk";
|
||||
};
|
||||
|
||||
...
|
||||
|
|
|
|||
|
|
@ -167,30 +167,30 @@ examples:
|
|||
"HDMI1", "TX";
|
||||
|
||||
hs-playback-dai-link {
|
||||
link-name = "I2S0";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&da7219>;
|
||||
};
|
||||
link-name = "I2S0";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&da7219>;
|
||||
};
|
||||
};
|
||||
|
||||
hs-capture-dai-link {
|
||||
link-name = "I2S1";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&da7219>;
|
||||
};
|
||||
link-name = "I2S1";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&da7219>;
|
||||
};
|
||||
};
|
||||
|
||||
spk-dp-playback-dai-link {
|
||||
link-name = "I2S3";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&anx_bridge_dp>, <&max98357a>;
|
||||
};
|
||||
link-name = "I2S3";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&anx_bridge_dp>, <&max98357a>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -171,30 +171,30 @@ examples:
|
|||
"HDMI1", "TX";
|
||||
|
||||
hs-playback-dai-link {
|
||||
link-name = "I2S0";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&rt5682s 0>;
|
||||
};
|
||||
link-name = "I2S0";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&rt5682s 0>;
|
||||
};
|
||||
};
|
||||
|
||||
hs-capture-dai-link {
|
||||
link-name = "I2S1";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&rt5682s 0>;
|
||||
};
|
||||
link-name = "I2S1";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&rt5682s 0>;
|
||||
};
|
||||
};
|
||||
|
||||
spk-hdmi-playback-dai-link {
|
||||
link-name = "I2S3";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&it6505dptx>, <&rt1019p>;
|
||||
};
|
||||
link-name = "I2S3";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&it6505dptx>, <&rt1019p>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -165,38 +165,38 @@ examples:
|
|||
"Speakers", "Speaker";
|
||||
|
||||
spk-playback-dai-link {
|
||||
link-name = "I2S3";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&rt1015p>;
|
||||
};
|
||||
link-name = "I2S3";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&rt1015p>;
|
||||
};
|
||||
};
|
||||
|
||||
hs-playback-dai-link {
|
||||
link-name = "I2S8";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&rt5682 0>;
|
||||
};
|
||||
link-name = "I2S8";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&rt5682 0>;
|
||||
};
|
||||
};
|
||||
|
||||
hs-capture-dai-link {
|
||||
link-name = "I2S9";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&rt5682 0>;
|
||||
};
|
||||
link-name = "I2S9";
|
||||
dai-format = "i2s";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&rt5682 0>;
|
||||
};
|
||||
};
|
||||
|
||||
displayport-dai-link {
|
||||
link-name = "TDM";
|
||||
dai-format = "dsp_a";
|
||||
codec {
|
||||
sound-dai = <&anx_bridge_dp>;
|
||||
};
|
||||
link-name = "TDM";
|
||||
dai-format = "dsp_a";
|
||||
codec {
|
||||
sound-dai = <&anx_bridge_dp>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -156,46 +156,46 @@ examples:
|
|||
"Ext Spk", "Speaker";
|
||||
|
||||
mm-dai-link {
|
||||
link-name = "ETDM1_IN_BE";
|
||||
mediatek,clk-provider = "cpu";
|
||||
link-name = "ETDM1_IN_BE";
|
||||
mediatek,clk-provider = "cpu";
|
||||
};
|
||||
|
||||
hs-playback-dai-link {
|
||||
link-name = "ETDM1_OUT_BE";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&headset_codec>;
|
||||
};
|
||||
link-name = "ETDM1_OUT_BE";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&headset_codec>;
|
||||
};
|
||||
};
|
||||
|
||||
hs-capture-dai-link {
|
||||
link-name = "ETDM2_IN_BE";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&headset_codec>;
|
||||
};
|
||||
link-name = "ETDM2_IN_BE";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&headset_codec>;
|
||||
};
|
||||
};
|
||||
|
||||
spk-playback-dai-link {
|
||||
link-name = "ETDM2_OUT_BE";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&spk_amplifier>;
|
||||
};
|
||||
link-name = "ETDM2_OUT_BE";
|
||||
mediatek,clk-provider = "cpu";
|
||||
codec {
|
||||
sound-dai = <&spk_amplifier>;
|
||||
};
|
||||
};
|
||||
|
||||
hdmi-dai-link {
|
||||
link-name = "ETDM3_OUT_BE";
|
||||
codec {
|
||||
sound-dai = <&hdmi_tx>;
|
||||
};
|
||||
link-name = "ETDM3_OUT_BE";
|
||||
codec {
|
||||
sound-dai = <&hdmi_tx>;
|
||||
};
|
||||
};
|
||||
|
||||
displayport-dai-link {
|
||||
link-name = "DPTX_BE";
|
||||
codec {
|
||||
sound-dai = <&dp_tx>;
|
||||
};
|
||||
link-name = "DPTX_BE";
|
||||
codec {
|
||||
sound-dai = <&dp_tx>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
115
Documentation/devicetree/bindings/sound/nuvoton,nau8360.yaml
Normal file
115
Documentation/devicetree/bindings/sound/nuvoton,nau8360.yaml
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/nuvoton,nau8360.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Nuvoton NAU83G60 Stereo Class-D Amplifier with DSP
|
||||
|
||||
description:
|
||||
Stereo Class-D Amplifier with DSP and I/V-sense.
|
||||
This device supports I2C.
|
||||
|
||||
maintainers:
|
||||
- Neo Chang <YLCHANG2@nuvoton.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- nuvoton,nau8360
|
||||
|
||||
reg:
|
||||
description: The I2C address is determined by the hardware pins.
|
||||
enum: [0x1a, 0x1b, 0x4a, 0x4b]
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
const: mclk
|
||||
|
||||
firmware-name:
|
||||
description:
|
||||
List of DSP core firmware filenames. Both Left and Right DSP firmware
|
||||
must be provided and loaded. In PBTL mode, the Left DSP must use the
|
||||
same binary file as the Right DSP.
|
||||
items:
|
||||
- description: Left DSP core firmware filename.
|
||||
- description: Right DSP core firmware filename.
|
||||
|
||||
nuvoton,pbtl-enable:
|
||||
type: boolean
|
||||
description: NAU83G60 supports PBTL mode for mono output.
|
||||
|
||||
nuvoton,dac-cur-enable:
|
||||
type: boolean
|
||||
description:
|
||||
Adjust DAC output current to match speaker impedance and prevent
|
||||
hardware damage. +3.2dB when present, 0dB by default.
|
||||
|
||||
nuvoton,dsp-rx-slot-mapping:
|
||||
description:
|
||||
Configures the TDM slot routing for DSP RX functions.
|
||||
Each integer assigns a specific DSP internal function to a TDM slot.
|
||||
The indices of the array correspond to the following hardware functions
|
||||
(0) DACL
|
||||
(1) DACR
|
||||
(2) ANCL
|
||||
(3) ANCR
|
||||
Assigned slots must be unique, except 255 which disables the function.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 4
|
||||
maxItems: 4
|
||||
items:
|
||||
enum: [ 0, 1, 2, 3, 4, 5, 6, 7, 255 ]
|
||||
|
||||
nuvoton,dsp-tx-slot-mapping:
|
||||
description:
|
||||
Configures the TDM slot routing for DSP TX functions.
|
||||
Each integer assigns a specific DSP internal function to a TDM slot.
|
||||
The indices of the array correspond to the following hardware functions
|
||||
(0) AECL (Acoustic echo cancellation left)
|
||||
(1) AECR (Acoustic echo cancellation right)
|
||||
(2) ISNSL (Current sense left)
|
||||
(3) ISNSR (Current sense right)
|
||||
(4) VSNSL (Voltage sense left)
|
||||
(5) VSNSR (Voltage sense right)
|
||||
(6) TJ (Junction temperature)
|
||||
(7) VBAT (Battery voltage)
|
||||
Assigned slots must be unique, except 255 which disables the function.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 8
|
||||
maxItems: 8
|
||||
items:
|
||||
enum: [ 0, 1, 2, 3, 4, 5, 6, 7, 255 ]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- firmware-name
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
codec@1a {
|
||||
compatible = "nuvoton,nau8360";
|
||||
reg = <0x1a>;
|
||||
#sound-dai-cells = <0>;
|
||||
firmware-name = "NAU83G60.kcs.bin.l", "NAU83G60.kcs.bin.r";
|
||||
nuvoton,dac-cur-enable;
|
||||
nuvoton,pbtl-enable;
|
||||
nuvoton,dsp-rx-slot-mapping = <0 1 2 3>;
|
||||
nuvoton,dsp-tx-slot-mapping = <0 1 2 3 4 5 6 7>;
|
||||
};
|
||||
};
|
||||
|
|
@ -48,6 +48,11 @@ properties:
|
|||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: The phandle of audio codec
|
||||
|
||||
nvidia,aux-devs:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
description: List of phandles pointing to auxiliary devices,
|
||||
such as amplifiers or dsp, to be added to the sound card.
|
||||
|
||||
nvidia,spkr-en-gpios:
|
||||
maxItems: 1
|
||||
description: The GPIO that enables the speakers
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/nvidia,tegra-audio-wm8994.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NVIDIA Tegra audio complex with WM8994 CODEC
|
||||
|
||||
maintainers:
|
||||
- Svyatoslav Ryhel <clamor95@gmail.com>
|
||||
|
||||
allOf:
|
||||
- $ref: nvidia,tegra-audio-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- pattern: '^[a-z0-9]+,tegra-audio-wm8994(-[a-z0-9]+)+$'
|
||||
- const: nvidia,tegra-audio-wm8994
|
||||
|
||||
nvidia,audio-routing:
|
||||
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||
description: |
|
||||
A list of the connections between audio components.
|
||||
Each entry is a pair of strings, the first being the connection's sink,
|
||||
the second being the connection's source. Valid names for sources and
|
||||
sinks are the pins (documented in the binding document),
|
||||
and the jacks on the board.
|
||||
minItems: 2
|
||||
items:
|
||||
enum:
|
||||
# Board Connectors
|
||||
- Headphone Jack
|
||||
- Int Spk
|
||||
- Earpiece
|
||||
- Line Out
|
||||
- Mic Jack
|
||||
- Int Mic
|
||||
- Internal Mic 1
|
||||
- Internal Mic 2
|
||||
- FM Radio
|
||||
|
||||
# CODEC Pins
|
||||
- SPKOUTLP
|
||||
- SPKOUTLN
|
||||
- SPKOUTRP
|
||||
- SPKOUTRN
|
||||
- HPOUT1L
|
||||
- HPOUT1R
|
||||
- HPOUT2P
|
||||
- HPOUT2N
|
||||
- LINEOUT1P
|
||||
- LINEOUT1N
|
||||
- LINEOUT2P
|
||||
- LINEOUT2N
|
||||
- IN1LN
|
||||
- IN1LP
|
||||
- IN2LN
|
||||
- IN2LP:VXRN
|
||||
- IN1RN
|
||||
- IN1RP
|
||||
- IN2RN
|
||||
- IN2RP:VXRP
|
||||
- DMIC1DAT
|
||||
- DMIC2DAT
|
||||
- MICBIAS1
|
||||
- MICBIAS2
|
||||
|
||||
required:
|
||||
- nvidia,i2s-controller
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/tegra20-car.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
sound {
|
||||
compatible = "lg,tegra-audio-wm8994-star",
|
||||
"nvidia,tegra-audio-wm8994";
|
||||
nvidia,model = "LG Optimus 2X WM8994";
|
||||
|
||||
nvidia,audio-routing =
|
||||
"Headphone Jack", "HPOUT1L",
|
||||
"Headphone Jack", "HPOUT1R",
|
||||
"Int Spk", "SPKOUTLN",
|
||||
"Int Spk", "SPKOUTLP",
|
||||
"Earpiece", "HPOUT2N",
|
||||
"Earpiece", "HPOUT2P",
|
||||
"IN2RN", "MICBIAS2",
|
||||
"IN2RN", "Mic Jack",
|
||||
"IN1LN", "MICBIAS1",
|
||||
"IN1LN", "Internal Mic 1",
|
||||
"IN1RN", "MICBIAS1",
|
||||
"IN1RN", "Internal Mic 2";
|
||||
|
||||
nvidia,i2s-controller = <&tegra_i2s1>;
|
||||
nvidia,audio-codec = <&wm8994>;
|
||||
|
||||
nvidia,hp-det-gpios = <&gpio 51 GPIO_ACTIVE_HIGH>;
|
||||
nvidia,mic-det-gpios = <&gpio 27 GPIO_ACTIVE_HIGH>;
|
||||
nvidia,ext-mic-en-gpios = <&gpio 57 GPIO_ACTIVE_HIGH>;
|
||||
nvidia,coupled-mic-hp-det;
|
||||
|
||||
clocks = <&tegra_car TEGRA20_CLK_PLL_A>,
|
||||
<&tegra_car TEGRA20_CLK_PLL_A_OUT0>,
|
||||
<&tegra_car TEGRA20_CLK_CDEV1>;
|
||||
clock-names = "pll_a", "pll_a_out0", "mclk";
|
||||
};
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
NVIDIA Tegra30 AHUB (Audio Hub)
|
||||
|
||||
Required properties:
|
||||
- compatible : For Tegra30, must contain "nvidia,tegra30-ahub". For Tegra114,
|
||||
must contain "nvidia,tegra114-ahub". For Tegra124, must contain
|
||||
"nvidia,tegra124-ahub". Otherwise, must contain "nvidia,<chip>-ahub",
|
||||
plus at least one of the above, where <chip> is tegra132.
|
||||
- reg : Should contain the register physical address and length for each of
|
||||
the AHUB's register blocks.
|
||||
- Tegra30 requires 2 entries, for the APBIF and AHUB/AUDIO register blocks.
|
||||
- Tegra114 requires an additional entry, for the APBIF2 register block.
|
||||
- interrupts : Should contain AHUB interrupt
|
||||
- clocks : Must contain an entry for each entry in clock-names.
|
||||
See ../clocks/clock-bindings.txt for details.
|
||||
- clock-names : Must include the following entries:
|
||||
- d_audio
|
||||
- apbif
|
||||
- resets : Must contain an entry for each entry in reset-names.
|
||||
See ../reset/reset.txt for details.
|
||||
- reset-names : Must include the following entries:
|
||||
Tegra30 and later:
|
||||
- d_audio
|
||||
- apbif
|
||||
- i2s0
|
||||
- i2s1
|
||||
- i2s2
|
||||
- i2s3
|
||||
- i2s4
|
||||
- dam0
|
||||
- dam1
|
||||
- dam2
|
||||
- spdif
|
||||
Tegra114 and later additionally require:
|
||||
- amx
|
||||
- adx
|
||||
Tegra124 and later additionally require:
|
||||
- amx1
|
||||
- adx1
|
||||
- afc0
|
||||
- afc1
|
||||
- afc2
|
||||
- afc3
|
||||
- afc4
|
||||
- afc5
|
||||
- ranges : The bus address mapping for the configlink register bus.
|
||||
Can be empty since the mapping is 1:1.
|
||||
- dmas : Must contain an entry for each entry in clock-names.
|
||||
See ../dma/dma.txt for details.
|
||||
- dma-names : Must include the following entries:
|
||||
- rx0 .. rx<n>
|
||||
- tx0 .. tx<n>
|
||||
... where n is:
|
||||
Tegra30: 3
|
||||
Tegra114, Tegra124: 9
|
||||
- #address-cells : For the configlink bus. Should be <1>;
|
||||
- #size-cells : For the configlink bus. Should be <1>.
|
||||
|
||||
AHUB client modules need to specify the IDs of their CIFs (Client InterFaces).
|
||||
For RX CIFs, the numbers indicate the register number within AHUB routing
|
||||
register space (APBIF 0..3 RX, I2S 0..5 RX, DAM 0..2 RX 0..1, SPDIF RX 0..1).
|
||||
For TX CIFs, the numbers indicate the bit position within the AHUB routing
|
||||
registers (APBIF 0..3 TX, I2S 0..5 TX, DAM 0..2 TX, SPDIF TX 0..1).
|
||||
|
||||
Example:
|
||||
|
||||
ahub@70080000 {
|
||||
compatible = "nvidia,tegra30-ahub";
|
||||
reg = <0x70080000 0x200 0x70080200 0x100>;
|
||||
interrupts = < 0 103 0x04 >;
|
||||
nvidia,dma-request-selector = <&apbdma 1>;
|
||||
clocks = <&tegra_car 106>, <&tegra_car 107>;
|
||||
clock-names = "d_audio", "apbif";
|
||||
resets = <&tegra_car 106>, <&tegra_car 107>, <&tegra_car 30>,
|
||||
<&tegra_car 11>, <&tegra_car 18>, <&tegra_car 101>,
|
||||
<&tegra_car 102>, <&tegra_car 108>, <&tegra_car 109>,
|
||||
<&tegra_car 110>, <&tegra_car 10>;
|
||||
reset-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
|
||||
"i2s3", "i2s4", "dam0", "dam1", "dam2",
|
||||
"spdif";
|
||||
dmas = <&apbdma 1>, <&apbdma 1>;
|
||||
<&apbdma 2>, <&apbdma 2>;
|
||||
<&apbdma 3>, <&apbdma 3>;
|
||||
<&apbdma 4>, <&apbdma 4>;
|
||||
dma-names = "rx0", "tx0", "rx1", "tx1", "rx2", "tx2", "rx3", "tx3";
|
||||
ranges;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
};
|
||||
289
Documentation/devicetree/bindings/sound/nvidia,tegra30-ahub.yaml
Normal file
289
Documentation/devicetree/bindings/sound/nvidia,tegra30-ahub.yaml
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/nvidia,tegra30-ahub.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NVIDIA Tegra30 AHUB (Audio Hub)
|
||||
|
||||
maintainers:
|
||||
- Thierry Reding <thierry.reding@gmail.com>
|
||||
- Jon Hunter <jonathanh@nvidia.com>
|
||||
|
||||
description:
|
||||
AHUB client modules need to specify the IDs of their CIFs (Client
|
||||
InterFaces). For RX CIFs, the numbers indicate the register number within
|
||||
AHUB routing register space (APBIF 0..3 RX, I2S 0..5 RX, DAM 0..2 RX 0..1,
|
||||
SPDIF RX 0..1). For TX CIFs, the numbers indicate the bit position within
|
||||
the AHUB routing registers (APBIF 0..3 TX, I2S 0..5 TX, DAM 0..2 TX, SPDIF
|
||||
TX 0..1).
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: nvidia,tegra30-ahub
|
||||
- const: nvidia,tegra114-ahub
|
||||
- const: nvidia,tegra124-ahub
|
||||
- items:
|
||||
- const: nvidia,tegra132-ahub
|
||||
- const: nvidia,tegra124-ahub
|
||||
|
||||
reg:
|
||||
minItems: 2
|
||||
maxItems: 3
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: digital audio clock
|
||||
- description: module clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: d_audio
|
||||
- const: apbif
|
||||
|
||||
resets:
|
||||
minItems: 11
|
||||
maxItems: 21
|
||||
|
||||
reset-names:
|
||||
minItems: 11
|
||||
maxItems: 21
|
||||
|
||||
ranges: true
|
||||
|
||||
dmas:
|
||||
minItems: 8
|
||||
maxItems: 20
|
||||
|
||||
dma-names:
|
||||
minItems: 8
|
||||
maxItems: 20
|
||||
|
||||
"#address-cells":
|
||||
enum: [1, 2]
|
||||
|
||||
"#size-cells":
|
||||
enum: [1, 2]
|
||||
|
||||
patternProperties:
|
||||
"^i2s@[0-9a-f]+$":
|
||||
type: object
|
||||
required:
|
||||
- compatible
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- reset-names
|
||||
- ranges
|
||||
- dmas
|
||||
- dma-names
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
const: nvidia,tegra30-ahub
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: APBIF registers
|
||||
- description: AHUB/AUDIO registers
|
||||
|
||||
resets:
|
||||
maxItems: 11
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: d_audio
|
||||
- const: apbif
|
||||
- const: i2s0
|
||||
- const: i2s1
|
||||
- const: i2s2
|
||||
- const: i2s3
|
||||
- const: i2s4
|
||||
- const: dam0
|
||||
- const: dam1
|
||||
- const: dam2
|
||||
- const: spdif
|
||||
|
||||
dmas:
|
||||
maxItems: 8
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: rx0
|
||||
- const: tx0
|
||||
- const: rx1
|
||||
- const: tx1
|
||||
- const: rx2
|
||||
- const: tx2
|
||||
- const: rx3
|
||||
- const: tx3
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
const: nvidia,tegra114-ahub
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: APBIF registers
|
||||
- description: AHUB/AUDIO registers
|
||||
- description: APBIF2 registers
|
||||
|
||||
resets:
|
||||
minItems: 13
|
||||
maxItems: 13
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: d_audio
|
||||
- const: apbif
|
||||
- const: i2s0
|
||||
- const: i2s1
|
||||
- const: i2s2
|
||||
- const: i2s3
|
||||
- const: i2s4
|
||||
- const: dam0
|
||||
- const: dam1
|
||||
- const: dam2
|
||||
- const: spdif
|
||||
- const: amx
|
||||
- const: adx
|
||||
|
||||
dmas:
|
||||
minItems: 20
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: rx0
|
||||
- const: tx0
|
||||
- const: rx1
|
||||
- const: tx1
|
||||
- const: rx2
|
||||
- const: tx2
|
||||
- const: rx3
|
||||
- const: tx3
|
||||
- const: rx4
|
||||
- const: tx4
|
||||
- const: rx5
|
||||
- const: tx5
|
||||
- const: rx6
|
||||
- const: tx6
|
||||
- const: rx7
|
||||
- const: tx7
|
||||
- const: rx8
|
||||
- const: tx8
|
||||
- const: rx9
|
||||
- const: tx9
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: nvidia,tegra124-ahub
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
items:
|
||||
- description: APBIF registers
|
||||
- description: AHUB/AUDIO registers
|
||||
- description: APBIF2 registers
|
||||
|
||||
resets:
|
||||
minItems: 21
|
||||
|
||||
reset-names:
|
||||
items:
|
||||
- const: d_audio
|
||||
- const: apbif
|
||||
- const: i2s0
|
||||
- const: i2s1
|
||||
- const: i2s2
|
||||
- const: i2s3
|
||||
- const: i2s4
|
||||
- const: dam0
|
||||
- const: dam1
|
||||
- const: dam2
|
||||
- const: spdif
|
||||
- const: amx
|
||||
- const: amx1
|
||||
- const: adx
|
||||
- const: adx1
|
||||
- const: afc0
|
||||
- const: afc1
|
||||
- const: afc2
|
||||
- const: afc3
|
||||
- const: afc4
|
||||
- const: afc5
|
||||
|
||||
dmas:
|
||||
minItems: 20
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: rx0
|
||||
- const: tx0
|
||||
- const: rx1
|
||||
- const: tx1
|
||||
- const: rx2
|
||||
- const: tx2
|
||||
- const: rx3
|
||||
- const: tx3
|
||||
- const: rx4
|
||||
- const: tx4
|
||||
- const: rx5
|
||||
- const: tx5
|
||||
- const: rx6
|
||||
- const: tx6
|
||||
- const: rx7
|
||||
- const: tx7
|
||||
- const: rx8
|
||||
- const: tx8
|
||||
- const: rx9
|
||||
- const: tx9
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/tegra30-car.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
|
||||
ahub@70080000 {
|
||||
compatible = "nvidia,tegra30-ahub";
|
||||
reg = <0x70080000 0x200>,
|
||||
<0x70080200 0x100>;
|
||||
interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&tegra_car TEGRA30_CLK_D_AUDIO>,
|
||||
<&tegra_car TEGRA30_CLK_APBIF>;
|
||||
clock-names = "d_audio", "apbif";
|
||||
resets = <&tegra_car 106>, <&tegra_car 107>, <&tegra_car 30>,
|
||||
<&tegra_car 11>, <&tegra_car 18>, <&tegra_car 101>,
|
||||
<&tegra_car 102>, <&tegra_car 108>, <&tegra_car 109>,
|
||||
<&tegra_car 110>, <&tegra_car 10>;
|
||||
reset-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
|
||||
"i2s3", "i2s4", "dam0", "dam1", "dam2",
|
||||
"spdif";
|
||||
dmas = <&apbdma 1>, <&apbdma 1>,
|
||||
<&apbdma 2>, <&apbdma 2>,
|
||||
<&apbdma 3>, <&apbdma 3>,
|
||||
<&apbdma 4>, <&apbdma 4>;
|
||||
dma-names = "rx0", "tx0", "rx1", "tx1", "rx2", "tx2", "rx3", "tx3";
|
||||
ranges;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
};
|
||||
|
|
@ -18,6 +18,7 @@ properties:
|
|||
- items:
|
||||
- enum:
|
||||
- qcom,sdm660-wcd-digital-codec
|
||||
- qcom,sdm670-wcd-digital-codec
|
||||
- const: qcom,msm8916-wcd-digital-codec
|
||||
|
||||
- const: qcom,msm8916-wcd-digital-codec
|
||||
|
|
|
|||
|
|
@ -20,9 +20,24 @@ properties:
|
|||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
memory-region:
|
||||
minItems: 1
|
||||
items:
|
||||
- description:
|
||||
Control-path buffer (audio_heap_mem) for platforms where the DSP
|
||||
runs in a stage-2 protected context (e.g. modem-DSP).
|
||||
- description:
|
||||
Data-path buffer pool from which per-stream DMA buffers are
|
||||
allocated.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- iommus
|
||||
|
||||
oneOf:
|
||||
- required:
|
||||
- iommus
|
||||
- required:
|
||||
- memory-region
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
|
|
|
|||
|
|
@ -75,11 +75,11 @@ examples:
|
|||
#size-cells = <0>;
|
||||
|
||||
dai@10 {
|
||||
reg = <PRIMARY_MI2S_RX>;
|
||||
clocks = <&q6prmcc LPASS_CLK_ID_PRI_MI2S_IBIT
|
||||
LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
|
||||
<&q6prmcc LPASS_CLK_ID_MCLK_1
|
||||
LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
|
||||
clock-names = "bclk", "mclk";
|
||||
reg = <PRIMARY_MI2S_RX>;
|
||||
clocks = <&q6prmcc LPASS_CLK_ID_PRI_MI2S_IBIT
|
||||
LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
|
||||
<&q6prmcc LPASS_CLK_ID_MCLK_1
|
||||
LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
|
||||
clock-names = "bclk", "mclk";
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -108,10 +108,15 @@ patternProperties:
|
|||
properties:
|
||||
reg:
|
||||
contains:
|
||||
# TDM DAI ID range from PRIMARY_TDM_RX_0 - QUINARY_TDM_TX_7
|
||||
# TDM DAI ID range from PRIMARY_TDM_RX_0 - QUINARY_TDM_TX_7 and
|
||||
# AIF_TDM_RX_0 - AIF_TDM_TX_12
|
||||
items:
|
||||
minimum: 24
|
||||
maximum: 103
|
||||
oneOf:
|
||||
- minimum: 24
|
||||
maximum: 103
|
||||
- minimum: 179
|
||||
maximum: 204
|
||||
|
||||
then:
|
||||
required:
|
||||
- qcom,tdm-sync-mode
|
||||
|
|
@ -127,7 +132,8 @@ patternProperties:
|
|||
contains:
|
||||
# MI2S DAI ID range PRIMARY_MI2S_RX - QUATERNARY_MI2S_TX and
|
||||
# QUINARY_MI2S_RX - QUINARY_MI2S_TX and
|
||||
# LPI_MI2S_RX_0 - LPI_MI2S_TX_6
|
||||
# LPI_MI2S_RX_0 - LPI_MI2S_TX_6 and
|
||||
# AIF_MI2S_RX_0 - AIF_MI2S_TX_12
|
||||
items:
|
||||
oneOf:
|
||||
- minimum: 16
|
||||
|
|
@ -136,6 +142,8 @@ patternProperties:
|
|||
maximum: 128
|
||||
- minimum: 137
|
||||
maximum: 152
|
||||
- minimum: 153
|
||||
maximum: 178
|
||||
then:
|
||||
required:
|
||||
- qcom,sd-lines
|
||||
|
|
|
|||
|
|
@ -0,0 +1,290 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/qcom,shikra-qaif-cpu.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm Audio Interface (QAIF) CPU DAI Controller
|
||||
|
||||
maintainers:
|
||||
- Harendra Gautam <harendra.gautam@oss.qualcomm.com>
|
||||
|
||||
description: |
|
||||
The Qualcomm Audio Interface (QAIF) is a fully configurable DMA-based
|
||||
audio subsystem controller. It serialises and deserialises PCM audio
|
||||
between system memory and external serial audio peripherals (PCM, TDM,
|
||||
I2S, MI2S) through the AIF path, and transfers parallel audio between
|
||||
memory and an internal WCD codec through the CIF path.
|
||||
|
||||
AIF (Audio Interface): up to 13 multi-lane Unified Audio Interfaces,
|
||||
each supporting up to 8 independent data lanes. Each lane is individually
|
||||
configurable as TX (output/speaker) or RX (input/mic). All lanes of an
|
||||
interface share a single bit clock and frame sync. Supported modes are
|
||||
PCM (short/long sync), TDM, and MI2S (stereo/mono). Per-interface
|
||||
configuration includes sync source (master/slave), sync mode, sync delay,
|
||||
sync inversion, slot width (8/16/24/32-bit), sample width, active slot
|
||||
masks (up to 32 slots), bits-per-lane frame size, lane enable/direction
|
||||
masks, loopback, output-enable control, and full-cycle path support for
|
||||
long chip-to-chip connections.
|
||||
|
||||
CIF (Codec Interface): up to 10 RDDMA (playback) and 10 WRDMA (capture)
|
||||
channels connecting to an internal codec over a parallel bus. Each channel
|
||||
supports active-channel enable mask (up to 16 channels), frame-sync
|
||||
selection, frame-sync delay, frame-sync output gating, dynamic clock
|
||||
gating, and 16-bit packing/unpacking.
|
||||
|
||||
Note on RX/TX naming convention: in QAIF, TX refers to the output
|
||||
(speaker/playback) direction and RX refers to the input (mic/capture)
|
||||
direction. This applies to both AIF lane directions and CIF slot/mask
|
||||
properties.
|
||||
|
||||
DMA engine: RDDMA fetches audio from DDR/TCM/LPM into a shared SRAM
|
||||
latency buffer (SHRAM) and drains it to the interface. WRDMA collects
|
||||
data from the interface into SHRAM and writes it to memory. Each DMA
|
||||
owns a private SHRAM region defined by start address and length registers.
|
||||
Burst sizes of 1/2/4/8/16 beats (64-bit) are supported with up to 4
|
||||
outstanding transactions per DMA. Two QSB master ports (QXM0 for TCM,
|
||||
QXM1 for DDR/LPM) provide the memory interface.
|
||||
|
||||
Resources are partitioned among up to 5 Execution Engines (EEs) via
|
||||
EE map registers. Each EE owns a set of DMAs, audio interfaces, and
|
||||
interface groups, and receives its own independent interrupt output.
|
||||
The interrupt hierarchy has a two-level structure: a summary register
|
||||
identifies the event class (DMA period, underflow/overflow, error
|
||||
response, audio interface underflow/overflow, group done, rate detector,
|
||||
VFR), and per-resource status registers identify the specific channel.
|
||||
|
||||
Interface grouping (bonding) allows up to 6 groups of audio and codec
|
||||
interfaces to start synchronously and align their DMA period interrupts
|
||||
within half a frame duration using the RDDMA padding feature.
|
||||
|
||||
Two rate detector blocks measure the frequency of incoming frame sync or
|
||||
word select signals and generate interrupts on rate change, undetected
|
||||
rate, or sync timeout.
|
||||
|
||||
Block diagram::
|
||||
|
||||
System Memory (DDR / LPM / TCM)
|
||||
+---------------------------------+
|
||||
| Circular Buffers (ping-pong) |
|
||||
+----------+----------+-----------+
|
||||
| ^
|
||||
64-bit AXI 64-bit AXI
|
||||
| |
|
||||
+----------v----------+-----------+
|
||||
| QSB Master Ports |
|
||||
| +----------+ +----------+ |
|
||||
| | QXM0 | | QXM1 | |
|
||||
| +----+-----+ +-----+----+ |
|
||||
+-------|--------------|----------+
|
||||
| |
|
||||
+-------v--------------v----------+
|
||||
| Shared RAM (SHRAM) |
|
||||
| +------------+ +------------+ |
|
||||
| | QXM0 Read | | QXM0 Write | |
|
||||
| | SHRAM | | SHRAM | |
|
||||
| +------------+ +------------+ |
|
||||
| +------------+ +------------+ |
|
||||
| | QXM1 Read | | QXM1 Write | |
|
||||
| | SHRAM | | SHRAM | |
|
||||
| +------------+ +------------+ |
|
||||
+---+--------+--------+-------+---+
|
||||
| | | |
|
||||
+---v--+ +--v---+ +--v---+ +-v----+
|
||||
|RDDMA | |RDDMA | |WRDMA | |WRDMA |
|
||||
| AIF | | CIF | | AIF | | CIF |
|
||||
|[0..n]| |[0..n]| |[0..n]| |[0..n]|
|
||||
+--+---+ +--+---+ +--+---+ +-+----+
|
||||
| | ^ ^
|
||||
| TX | TX | RX | RX
|
||||
v v | |
|
||||
+--+--------------------+ +----+----------+
|
||||
| Unified Audio Intf | | Codec DMA |
|
||||
| (AIF 0..12) | | Interface |
|
||||
| | | (CIF) |
|
||||
| AUD_INTFa block: | | |
|
||||
| - Serializer (TX) | | RDDMA: DDR -> |
|
||||
| - De-serializer (RX) | | internal |
|
||||
| - Sync gen/detect | | codec |
|
||||
| - Up to 8 data lanes | | WRDMA: codec |
|
||||
| - PCM / TDM / MI2S | | -> DDR |
|
||||
| - Near Pad Logic | | Up to 16 ch |
|
||||
+--+--------------------+ +----+----------+
|
||||
| Lane 0..7 (TX/RX) | Parallel bus
|
||||
| Bit clk + Frame sync | + Frame sync
|
||||
v v
|
||||
+--+--------+ +------+------+
|
||||
| External | | Internal |
|
||||
| Serial | | Digital |
|
||||
| Peripherals| | Codec |
|
||||
| (PCM/TDM/ | | (Bolero/ |
|
||||
| MI2S) | | WCD) |
|
||||
+-----------+ +-------------+
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,shikra-qaif-cpu
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
description:
|
||||
QAIF summary interrupt for this Execution Engine.
|
||||
|
||||
iommus:
|
||||
maxItems: 1
|
||||
|
||||
dma-coherent: true
|
||||
|
||||
clocks:
|
||||
maxItems: 9
|
||||
|
||||
clock-names:
|
||||
description:
|
||||
Core clocks for register access and DMA, followed by one bit
|
||||
clock per AIF interface.
|
||||
items:
|
||||
- const: lpass_config
|
||||
- const: lpass_core_axim
|
||||
- const: aud_dma
|
||||
- const: aud_dma_mem
|
||||
- const: bus
|
||||
- const: aif_if0_ibit
|
||||
- const: aif_if1_ibit
|
||||
- const: aif_if2_ibit
|
||||
- const: aif_if3_ibit
|
||||
|
||||
'#sound-dai-cells':
|
||||
const: 1
|
||||
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
patternProperties:
|
||||
'^aif@[0-9a-f]+$':
|
||||
type: object
|
||||
description:
|
||||
QAIF AIF interface child node for PCM, TDM or MI2S configuration.
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/sound/tdm-slot.yaml#
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
description:
|
||||
DAI ID of the AIF interface (QAIF_MI2S_AIF* or QAIF_TDM_AIF*).
|
||||
|
||||
dai-format:
|
||||
description: Serial audio interface format (MI2S, TDM or PCM).
|
||||
enum: [i2s, dsp_a, dsp_b]
|
||||
|
||||
dai-tdm-slot-width:
|
||||
enum: [8, 16, 24, 32]
|
||||
|
||||
dai-tdm-slot-num:
|
||||
minimum: 1
|
||||
maximum: 32
|
||||
|
||||
dai-tdm-slot-rx-mask:
|
||||
minItems: 1
|
||||
maxItems: 32
|
||||
|
||||
dai-tdm-slot-tx-mask:
|
||||
minItems: 1
|
||||
maxItems: 32
|
||||
|
||||
qcom,qaif-aif-lane-map:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
description:
|
||||
Per-lane direction map, one entry per lane starting from lane 0.
|
||||
Use 0 for TX (output/speaker) and 1 for RX (input/mic).
|
||||
minItems: 1
|
||||
maxItems: 8
|
||||
items:
|
||||
enum: [0, 1]
|
||||
|
||||
required:
|
||||
- reg
|
||||
- dai-format
|
||||
- qcom,qaif-aif-lane-map
|
||||
|
||||
if:
|
||||
properties:
|
||||
dai-format:
|
||||
enum: [dsp_a, dsp_b]
|
||||
then:
|
||||
required:
|
||||
- dai-tdm-slot-width
|
||||
- dai-tdm-slot-num
|
||||
- dai-tdm-slot-rx-mask
|
||||
- dai-tdm-slot-tx-mask
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- iommus
|
||||
- clocks
|
||||
- clock-names
|
||||
- '#sound-dai-cells'
|
||||
- '#address-cells'
|
||||
- '#size-cells'
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
soc {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
qaif_cpu: audio-controller@a000000 {
|
||||
compatible = "qcom,shikra-qaif-cpu";
|
||||
reg = <0x0 0x0a000000 0x0 0x20000>;
|
||||
interrupts = <GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH>;
|
||||
iommus = <&apps_smmu 0x1c0 0x0>;
|
||||
clocks = <&gcc 213>,
|
||||
<&gcc 214>,
|
||||
<&audiocorecc 15>,
|
||||
<&audiocorecc 17>,
|
||||
<&audiocorecc 18>,
|
||||
<&audiocorecc 5>,
|
||||
<&audiocorecc 8>,
|
||||
<&audiocorecc 11>,
|
||||
<&audiocorecc 14>;
|
||||
clock-names = "lpass_config",
|
||||
"lpass_core_axim",
|
||||
"aud_dma",
|
||||
"aud_dma_mem",
|
||||
"bus",
|
||||
"aif_if0_ibit",
|
||||
"aif_if1_ibit",
|
||||
"aif_if2_ibit",
|
||||
"aif_if3_ibit";
|
||||
#sound-dai-cells = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
aif@b5 {
|
||||
reg = <181>;
|
||||
dai-format = "dsp_a";
|
||||
dai-tdm-slot-width = <32>;
|
||||
dai-tdm-slot-num = <2>;
|
||||
dai-tdm-slot-rx-mask = <1 1>;
|
||||
dai-tdm-slot-tx-mask = <1 1>;
|
||||
qcom,qaif-aif-lane-map = <1 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -36,8 +36,10 @@ properties:
|
|||
- ayaneo,pocket-s2-sndcard
|
||||
- fairphone,fp4-sndcard
|
||||
- fairphone,fp5-sndcard
|
||||
- motorola,dubai-sndcard
|
||||
- qcom,apq8096-sndcard
|
||||
- qcom,glymur-sndcard
|
||||
- qcom,nord-sndcard
|
||||
- qcom,qcm6490-idp-sndcard
|
||||
- qcom,qcs615-sndcard
|
||||
- qcom,qcs6490-rb3gen2-sndcard
|
||||
|
|
@ -54,6 +56,7 @@ properties:
|
|||
- qcom,sm8250-sndcard
|
||||
- qcom,sm8450-sndcard
|
||||
- qcom,x1e80100-sndcard
|
||||
- thundercomm,qcs6490-rubikpi3-sndcard
|
||||
|
||||
audio-routing:
|
||||
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||
|
|
|
|||
105
Documentation/devicetree/bindings/sound/qcom,wcd9378-sdw.yaml
Normal file
105
Documentation/devicetree/bindings/sound/qcom,wcd9378-sdw.yaml
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/qcom,wcd9378-sdw.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Qualcomm WCD9378 (Tambora) SoundWire codec
|
||||
|
||||
maintainers:
|
||||
- Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
|
||||
|
||||
description:
|
||||
Qualcomm WCD9378 (Tambora) SoundWire codec. The same silicon can be
|
||||
fused for a mobile (non-SDCA) mode or an SDCA-compliant mode; the
|
||||
qcom,sdca-compliant property selects the latter and is required by
|
||||
this driver.
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sdw20217011000
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
qcom,sdca-compliant:
|
||||
description:
|
||||
Present when the codec is fused as SDCA-compliant. The mobile
|
||||
(non-SDCA) variant carries the same class-ID compatible and is
|
||||
handled by a different driver.
|
||||
type: boolean
|
||||
|
||||
qcom,port-mapping:
|
||||
description:
|
||||
Each entry maps a slave data port to a master data port.
|
||||
Entries are in order starting from slave port 1; slave port 0
|
||||
is reserved and not represented. SDCA-compliant mode uses 8
|
||||
entries covering DP1..DP8.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 8
|
||||
maxItems: 8
|
||||
|
||||
reset-gpios:
|
||||
description: GPIO used to release the codec from reset.
|
||||
maxItems: 1
|
||||
|
||||
vdd-buck-supply:
|
||||
description: 1.8 V analog buck supply.
|
||||
|
||||
vdd-rxtx-supply:
|
||||
description: 1.8 V RX/TX supply.
|
||||
|
||||
vdd-io-supply:
|
||||
description: Digital I/O supply.
|
||||
|
||||
vdd-mic-bias-supply:
|
||||
description: Mic bias supply.
|
||||
|
||||
'#sound-dai-cells':
|
||||
const: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- qcom,sdca-compliant
|
||||
- qcom,port-mapping
|
||||
- reset-gpios
|
||||
- vdd-buck-supply
|
||||
- vdd-rxtx-supply
|
||||
- vdd-io-supply
|
||||
- vdd-mic-bias-supply
|
||||
- '#sound-dai-cells'
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
soundwire@7630000 {
|
||||
reg = <0x07630000 0x10000>;
|
||||
#address-cells = <2>;
|
||||
#size-cells = <0>;
|
||||
|
||||
wcd9378c_sdw: audio-codec@0,3 {
|
||||
compatible = "sdw20217011000";
|
||||
reg = <0 3>;
|
||||
|
||||
qcom,sdca-compliant;
|
||||
|
||||
qcom,port-mapping = <2 2 3 4 5 6 7 8>;
|
||||
|
||||
reset-gpios = <&tlmm 191 GPIO_ACTIVE_LOW>;
|
||||
|
||||
vdd-buck-supply = <&vreg_l15b_1p8>;
|
||||
vdd-rxtx-supply = <&vreg_l15b_1p8>;
|
||||
vdd-io-supply = <&vreg_l18b_1p2>;
|
||||
vdd-mic-bias-supply = <&vreg_bob1>;
|
||||
|
||||
#sound-dai-cells = <1>;
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -44,6 +44,14 @@ properties:
|
|||
'#gpio-cells':
|
||||
const: 2
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: phandle and clock specifier for the codec MCLK1 input.
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: mclk1
|
||||
|
||||
realtek,pow-ldo2-gpio:
|
||||
maxItems: 1
|
||||
description: CODEC's POW_LDO2 pin.
|
||||
|
|
@ -127,6 +135,8 @@ examples:
|
|||
interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
clocks = <&osc>;
|
||||
clock-names = "mclk1";
|
||||
realtek,pow-ldo2-gpio = <&gpio 3 GPIO_ACTIVE_HIGH>;
|
||||
realtek,reset-gpio = <&gpio 3 GPIO_ACTIVE_LOW>;
|
||||
realtek,in1-differential;
|
||||
|
|
|
|||
|
|
@ -432,14 +432,14 @@ examples:
|
|||
"ssi.1", "ssi.0";
|
||||
|
||||
rcar_sound,dvc {
|
||||
dvc0: dvc-0 {
|
||||
dmas = <&audma0 0xbc>;
|
||||
dma-names = "tx";
|
||||
};
|
||||
dvc1: dvc-1 {
|
||||
dmas = <&audma0 0xbe>;
|
||||
dma-names = "tx";
|
||||
};
|
||||
dvc0: dvc-0 {
|
||||
dmas = <&audma0 0xbc>;
|
||||
dma-names = "tx";
|
||||
};
|
||||
dvc1: dvc-1 {
|
||||
dmas = <&audma0 0xbe>;
|
||||
dma-names = "tx";
|
||||
};
|
||||
};
|
||||
|
||||
rcar_sound,mix {
|
||||
|
|
|
|||
|
|
@ -95,20 +95,20 @@ examples:
|
|||
ssi0: ssi@10049c00 {
|
||||
compatible = "renesas,r9a07g044-ssi",
|
||||
"renesas,rz-ssi";
|
||||
reg = <0x10049c00 0x400>;
|
||||
interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 327 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 328 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "int_req", "dma_rx", "dma_tx";
|
||||
clocks = <&cpg CPG_MOD R9A07G044_SSI0_PCLK2>,
|
||||
<&cpg CPG_MOD R9A07G044_SSI0_PCLK_SFR>,
|
||||
<&audio_clk1>,
|
||||
<&audio_clk2>;
|
||||
clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2";
|
||||
power-domains = <&cpg>;
|
||||
resets = <&cpg R9A07G044_SSI0_RST_M2_REG>;
|
||||
dmas = <&dmac 0x2655>,
|
||||
<&dmac 0x2656>;
|
||||
dma-names = "tx", "rx";
|
||||
#sound-dai-cells = <0>;
|
||||
reg = <0x10049c00 0x400>;
|
||||
interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<GIC_SPI 327 IRQ_TYPE_EDGE_RISING>,
|
||||
<GIC_SPI 328 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-names = "int_req", "dma_rx", "dma_tx";
|
||||
clocks = <&cpg CPG_MOD R9A07G044_SSI0_PCLK2>,
|
||||
<&cpg CPG_MOD R9A07G044_SSI0_PCLK_SFR>,
|
||||
<&audio_clk1>,
|
||||
<&audio_clk2>;
|
||||
clock-names = "ssi", "ssi_sfr", "audio_clk1", "audio_clk2";
|
||||
power-domains = <&cpg>;
|
||||
resets = <&cpg R9A07G044_SSI0_RST_M2_REG>;
|
||||
dmas = <&dmac 0x2655>,
|
||||
<&dmac 0x2656>;
|
||||
dma-names = "tx", "rx";
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/stericsson,ux500-msp-i2s.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ST-Ericsson Ux500 Multichannel Serial Port
|
||||
|
||||
maintainers:
|
||||
- Linus Walleij <linusw@kernel.org>
|
||||
|
||||
description:
|
||||
The Ux500 Multichannel Serial Port (MSP) is a synchronous serial audio
|
||||
interface supporting I2S and PCM/TDM protocols. Data is transferred to and
|
||||
from memory using the Ux500 DMA controller.
|
||||
|
||||
allOf:
|
||||
- $ref: dai-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: stericsson,ux500-msp-i2s
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
v-ape-supply:
|
||||
description: Analog power engine supply
|
||||
|
||||
dmas:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
dma-names:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
items:
|
||||
enum: [ rx, tx ]
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: MSP functional clock
|
||||
- description: MSP APB bus clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: msp
|
||||
- const: apb_pclk
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
'#sound-dai-cells':
|
||||
const: 0
|
||||
|
||||
port:
|
||||
$ref: audio-graph-port.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- v-ape-supply
|
||||
- dmas
|
||||
- dma-names
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
- '#sound-dai-cells'
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/reset/stericsson,db8500-prcc-reset.h>
|
||||
|
||||
msp@80123000 {
|
||||
compatible = "stericsson,ux500-msp-i2s";
|
||||
reg = <0x80123000 0x1000>;
|
||||
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
|
||||
v-ape-supply = <&db8500_vape_reg>;
|
||||
dmas = <&dma 31 0 0x12>, <&dma 31 0 0x10>;
|
||||
dma-names = "rx", "tx";
|
||||
clocks = <&prcc_kclk 1 3>, <&prcc_pclk 1 3>;
|
||||
clock-names = "msp", "apb_pclk";
|
||||
resets = <&prcc_reset DB8500_PRCC_1 DB8500_PRCC_1_RESET_MSP0>;
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
||||
|
||||
...
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/sound/ti,da830-evm-audio.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Texas Instruments SoC audio setups with TLV320AIC3X Codec
|
||||
|
||||
maintainers:
|
||||
- Eduard Bostina <egbostina@gmail.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ti,da830-evm-audio
|
||||
|
||||
ti,model:
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
description: The user-visible name of this sound complex.
|
||||
|
||||
ti,audio-codec:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: The phandle of the TLV320AIC3x audio codec
|
||||
|
||||
ti,mcasp-controller:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: The phandle of the McASP controller
|
||||
|
||||
ti,audio-routing:
|
||||
$ref: /schemas/types.yaml#/definitions/non-unique-string-array
|
||||
description:
|
||||
A list of the connections between audio components. Each entry is a
|
||||
pair of strings, the first being the connection's sink, the second
|
||||
being the connection's source. Valid names for sources and sinks
|
||||
are the codec's pins, and the jacks on the board (Headphone Jack,
|
||||
Line Out, Mic Jack, Line In).
|
||||
|
||||
ti,codec-clock-rate:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description: The Codec Clock rate (in Hz) applied to the Codec.
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
description: Reference to the master clock
|
||||
|
||||
clock-names:
|
||||
const: mclk
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- ti,model
|
||||
- ti,audio-codec
|
||||
- ti,mcasp-controller
|
||||
- ti,audio-routing
|
||||
|
||||
anyOf:
|
||||
- required:
|
||||
- ti,codec-clock-rate
|
||||
- required:
|
||||
- clocks
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
sound {
|
||||
compatible = "ti,da830-evm-audio";
|
||||
ti,model = "DA830 EVM";
|
||||
ti,audio-codec = <&tlv320aic3x>;
|
||||
ti,mcasp-controller = <&mcasp1>;
|
||||
ti,codec-clock-rate = <12000000>;
|
||||
ti,audio-routing =
|
||||
"Headphone Jack", "HPLOUT",
|
||||
"Headphone Jack", "HPROUT",
|
||||
"Line Out", "LLOUT",
|
||||
"Line Out", "RLOUT",
|
||||
"MIC3L", "Mic Bias 2V",
|
||||
"MIC3R", "Mic Bias 2V",
|
||||
"Mic Bias 2V", "Mic Jack",
|
||||
"LINE1L", "Line In",
|
||||
"LINE2L", "Line In",
|
||||
"LINE1R", "Line In",
|
||||
"LINE2R", "Line In";
|
||||
};
|
||||
|
|
@ -21,6 +21,22 @@ properties:
|
|||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
description: System clock (SCK)
|
||||
|
||||
clock-names:
|
||||
const: sck
|
||||
|
||||
VCC1-supply:
|
||||
description: 5V analog power supply
|
||||
|
||||
VCC2-supply:
|
||||
description: 5V analog power supply
|
||||
|
||||
VDD-supply:
|
||||
description: 3.3V digital power supply
|
||||
|
||||
"#sound-dai-cells":
|
||||
const: 0
|
||||
|
||||
|
|
|
|||
|
|
@ -219,9 +219,7 @@ allOf:
|
|||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- ti,tas2781
|
||||
const: ti,tas2781
|
||||
then:
|
||||
properties:
|
||||
reg:
|
||||
|
|
|
|||
|
|
@ -45,13 +45,13 @@ examples:
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
tas5805m: tas5805m@2c {
|
||||
reg = <0x2c>;
|
||||
compatible = "ti,tas5805m";
|
||||
reg = <0x2c>;
|
||||
compatible = "ti,tas5805m";
|
||||
|
||||
pvdd-supply = <&audiopwr>;
|
||||
pdn-gpios = <&tlmm 160 0>;
|
||||
pvdd-supply = <&audiopwr>;
|
||||
pdn-gpios = <&tlmm 160 0>;
|
||||
|
||||
ti,dsp-config-name = "mono_pbtl_48khz";
|
||||
ti,dsp-config-name = "mono_pbtl_48khz";
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
|
|||
|
|
@ -121,6 +121,6 @@ examples:
|
|||
AVDD-supply = <®ulator>;
|
||||
IOVDD-supply = <®ulator>;
|
||||
DVDD-supply = <®ulator>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,6 @@ examples:
|
|||
reg = <0x60>;
|
||||
Vdd-supply = <&vmmc2>;
|
||||
power-gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,39 +0,0 @@
|
|||
* MOP500 Audio Machine Driver
|
||||
|
||||
This node is responsible for linking together all ux500 Audio Driver components.
|
||||
|
||||
Required properties:
|
||||
- compatible : "stericsson,snd-soc-mop500"
|
||||
|
||||
Non-standard properties:
|
||||
- stericsson,cpu-dai : Phandle to the CPU-side DAI
|
||||
- stericsson,audio-codec : Phandle to the Audio CODEC
|
||||
- stericsson,card-name : Over-ride default card name
|
||||
|
||||
Example:
|
||||
|
||||
sound {
|
||||
compatible = "stericsson,snd-soc-mop500";
|
||||
|
||||
stericsson,cpu-dai = <&msp1 &msp3>;
|
||||
stericsson,audio-codec = <&codec>;
|
||||
};
|
||||
|
||||
msp1: msp@80124000 {
|
||||
compatible = "stericsson,ux500-msp-i2s";
|
||||
reg = <0x80124000 0x1000>;
|
||||
interrupts = <0 62 0x4>;
|
||||
v-ape-supply = <&db8500_vape_reg>;
|
||||
};
|
||||
|
||||
msp3: msp@80125000 {
|
||||
compatible = "stericsson,ux500-msp-i2s";
|
||||
reg = <0x80125000 0x1000>;
|
||||
interrupts = <0 62 0x4>;
|
||||
v-ape-supply = <&db8500_vape_reg>;
|
||||
};
|
||||
|
||||
codec: ab8500-codec {
|
||||
compatible = "stericsson,ab8500-codec";
|
||||
stericsson,earpeice-cmv = <950>; /* Units in mV. */
|
||||
};
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
* ux500 MSP (CPU-side Digital Audio Interface)
|
||||
|
||||
Required properties:
|
||||
- compatible :"stericsson,ux500-msp-i2s"
|
||||
- reg : Physical base address and length of the device's registers.
|
||||
|
||||
Optional properties:
|
||||
- interrupts : The interrupt output from the device.
|
||||
- <name>-supply : Phandle to the regulator <name> supply
|
||||
|
||||
Example:
|
||||
|
||||
sound {
|
||||
compatible = "stericsson,snd-soc-mop500";
|
||||
|
||||
stericsson,platform-pcm-dma = <&pcm>;
|
||||
stericsson,cpu-dai = <&msp1 &msp3>;
|
||||
stericsson,audio-codec = <&codec>;
|
||||
};
|
||||
|
||||
pcm: ux500-pcm {
|
||||
compatible = "stericsson,ux500-pcm";
|
||||
};
|
||||
|
||||
msp1: msp@80124000 {
|
||||
compatible = "stericsson,ux500-msp-i2s";
|
||||
reg = <0x80124000 0x1000>;
|
||||
interrupts = <0 62 0x4>;
|
||||
v-ape-supply = <&db8500_vape_reg>;
|
||||
};
|
||||
|
||||
msp3: msp@80125000 {
|
||||
compatible = "stericsson,ux500-msp-i2s";
|
||||
reg = <0x80125000 0x1000>;
|
||||
interrupts = <0 62 0x4>;
|
||||
v-ape-supply = <&db8500_vape_reg>;
|
||||
};
|
||||
|
||||
codec: ab8500-codec {
|
||||
compatible = "stericsson,ab8500-codec";
|
||||
stericsson,earpeice-cmv = <950>; /* Units in mV. */
|
||||
};
|
||||
|
|
@ -11,12 +11,11 @@ maintainers:
|
|||
- Xianwei Zhao <xianwei.zhao@amlogic.com>
|
||||
- Sunny Luo <sunny.luo@amlogic.com>
|
||||
|
||||
allOf:
|
||||
- $ref: spi-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: amlogic,a4-spisg
|
||||
enum:
|
||||
- amlogic,a4-spisg
|
||||
- amlogic,a9-spisg
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
|
@ -35,6 +34,16 @@ properties:
|
|||
resets:
|
||||
maxItems: 1
|
||||
|
||||
amlogic,mo-idle-output:
|
||||
description: |
|
||||
Controls the MOSI output level when the controller is idle.
|
||||
0 - Drive MOSI low
|
||||
1 - Drive MOSI high
|
||||
2 - Follow the last transmitted bit
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [0, 1, 2]
|
||||
default: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
@ -42,6 +51,19 @@ required:
|
|||
- clocks
|
||||
- clock-names
|
||||
|
||||
allOf:
|
||||
- $ref: spi-controller.yaml#
|
||||
- if:
|
||||
not:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- amlogic,a9-spisg
|
||||
then:
|
||||
properties:
|
||||
amlogic,mo-idle-output: false
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
|
|
|
|||
|
|
@ -16,10 +16,15 @@ description: |
|
|||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- amlogic,meson-gx-spicc # SPICC controller on Amlogic GX and compatible SoCs
|
||||
- amlogic,meson-axg-spicc # SPICC controller on Amlogic AXG and compatible SoCs
|
||||
- amlogic,meson-g12a-spicc # SPICC controller on Amlogic G12A and compatible SoCs
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- amlogic,t7-spicc
|
||||
- const: amlogic,meson-g12a-spicc
|
||||
- enum:
|
||||
- amlogic,meson-gx-spicc # SPICC controller on Amlogic GX and compatible SoCs
|
||||
- amlogic,meson-axg-spicc # SPICC controller on Amlogic AXG and compatible SoCs
|
||||
- amlogic,meson-g12a-spicc # SPICC controller on Amlogic G12A and compatible SoCs
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/spi/microchip,pic32mzda-spi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Microchip PIC32MZDA SPI Controller
|
||||
|
||||
maintainers:
|
||||
- Thomas Bogendoerfer <tsbogend@alpha.franken.de>
|
||||
|
||||
allOf:
|
||||
- $ref: spi-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: microchip,pic32mzda-spi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
items:
|
||||
- description: Fault interrupt
|
||||
- description: Receive interrupt
|
||||
- description: Transmit interrupt
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: fault
|
||||
- const: rx
|
||||
- const: tx
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: mck0
|
||||
|
||||
cs-gpios:
|
||||
maxItems: 1
|
||||
|
||||
dmas:
|
||||
items:
|
||||
- description: RX DMA channel
|
||||
- description: TX DMA channel
|
||||
|
||||
dma-names:
|
||||
items:
|
||||
- const: spi-rx
|
||||
- const: spi-tx
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
- clocks
|
||||
- clock-names
|
||||
- cs-gpios
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
spi@1f821000 {
|
||||
compatible = "microchip,pic32mzda-spi";
|
||||
reg = <0x1f821000 0x200>;
|
||||
interrupts = <109 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<110 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<111 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "fault", "rx", "tx";
|
||||
clocks = <&PBCLK2>;
|
||||
clock-names = "mck0";
|
||||
cs-gpios = <&gpio3 4 GPIO_ACTIVE_LOW>;
|
||||
dmas = <&dma 134>, <&dma 135>;
|
||||
dma-names = "spi-rx", "spi-tx";
|
||||
};
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
Microchip PIC32 SPI Master controller
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "microchip,pic32mzda-spi".
|
||||
- reg: Address and length of register space for the device.
|
||||
- interrupts: Should contain all three spi interrupts in sequence
|
||||
of <fault-irq>, <receive-irq>, <transmit-irq>.
|
||||
- interrupt-names: Should be "fault", "rx", "tx" in order.
|
||||
- clocks: Phandle of the clock generating SPI clock on the bus.
|
||||
- clock-names: Should be "mck0".
|
||||
- cs-gpios: Specifies the gpio pins to be used for chipselects.
|
||||
See: Documentation/devicetree/bindings/spi/spi-bus.txt
|
||||
|
||||
Optional properties:
|
||||
- dmas: Two or more DMA channel specifiers following the convention outlined
|
||||
in Documentation/devicetree/bindings/dma/dma.txt
|
||||
- dma-names: Names for the dma channels. There must be at least one channel
|
||||
named "spi-tx" for transmit and named "spi-rx" for receive.
|
||||
|
||||
Example:
|
||||
|
||||
spi1: spi@1f821000 {
|
||||
compatible = "microchip,pic32mzda-spi";
|
||||
reg = <0x1f821000 0x200>;
|
||||
interrupts = <109 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<110 IRQ_TYPE_LEVEL_HIGH>,
|
||||
<111 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "fault", "rx", "tx";
|
||||
clocks = <&PBCLK2>;
|
||||
clock-names = "mck0";
|
||||
cs-gpios = <&gpio3 4 GPIO_ACTIVE_LOW>;
|
||||
dmas = <&dma 134>, <&dma 135>;
|
||||
dma-names = "spi-rx", "spi-tx";
|
||||
};
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/spi/realtek,rtd1625-nor.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Realtek RTD1625 SPI NOR Flash Controller
|
||||
|
||||
maintainers:
|
||||
- Jyan Chou <jyanchou@realtek.com>
|
||||
- Yu-Chun Lin <eleanor.lin@realtek.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- realtek,rtd1625-nor
|
||||
|
||||
reg:
|
||||
maxItems: 3
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: ctrl
|
||||
- const: dma
|
||||
- const: dirmap
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- clocks
|
||||
- resets
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/spi/spi-controller.yaml#
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
spi@14b000 {
|
||||
compatible = "realtek,rtd1625-nor";
|
||||
reg = <0x14b000 0x50>, <0x14bf00 0x30>, <0x88100000 0x2000000>;
|
||||
reg-names = "ctrl", "dma", "dirmap";
|
||||
clocks = <&cc 18>;
|
||||
resets = <&cc 26>;
|
||||
pinctrl-0 = <&spi_pins>;
|
||||
pinctrl-names = "default";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
|
@ -54,6 +54,11 @@ properties:
|
|||
- renesas,msiof-r8a779h0 # R-Car V4M
|
||||
- const: renesas,rcar-gen4-msiof # generic R-Car Gen4
|
||||
# compatible device
|
||||
- items:
|
||||
- enum:
|
||||
- renesas,msiof-r8a78000 # R-Car X5H
|
||||
- const: renesas,rcar-gen5-msiof # generic R-Car Gen5
|
||||
# compatible device
|
||||
- items:
|
||||
- const: renesas,sh-msiof # deprecated
|
||||
|
||||
|
|
@ -100,11 +105,11 @@ properties:
|
|||
|
||||
dmas:
|
||||
minItems: 2
|
||||
maxItems: 4
|
||||
maxItems: 6
|
||||
|
||||
dma-names:
|
||||
minItems: 2
|
||||
maxItems: 4
|
||||
maxItems: 6
|
||||
items:
|
||||
enum: [ tx, rx ]
|
||||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,14 @@ properties:
|
|||
The delay from the default sample time before the actual
|
||||
sample of the rxd input signal occurs.
|
||||
|
||||
This describes the board rather than the peripheral, namely the extra
|
||||
delay this particular design needs, for example because of the flight time
|
||||
of the clock and data signals between controller and peripheral.
|
||||
|
||||
Timing parameters of the peripheral itself, such as its
|
||||
clock-to-output-valid time, are the same on every board using that chip
|
||||
and should be described with the chip.
|
||||
|
||||
spi-tx-bus-width:
|
||||
description:
|
||||
Bus width to the SPI bus used for write transfers.
|
||||
|
|
|
|||
|
|
@ -559,6 +559,8 @@ patternProperties:
|
|||
description: Seiko Epson Corp.
|
||||
"^esp,.*":
|
||||
description: Espressif Systems Co. Ltd.
|
||||
"^esstech,.*":
|
||||
description: ESS Technology, Inc.
|
||||
"^est,.*":
|
||||
description: ESTeem Wireless Modems
|
||||
"^eswin,.*":
|
||||
|
|
|
|||
|
|
@ -460,8 +460,6 @@ SPI
|
|||
devm_spi_alloc_target()
|
||||
devm_spi_optimize_message()
|
||||
devm_spi_register_controller()
|
||||
devm_spi_register_host()
|
||||
devm_spi_register_target()
|
||||
|
||||
WATCHDOG
|
||||
devm_watchdog_register_device()
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ field to indicate which mode they want to use for a given transfer.
|
|||
|
||||
The possible values for this field have the following semantics:
|
||||
|
||||
- :c:macro:`SPI_MULTI_BUS_MODE_SINGLE`: Only use the first lane. Other lanes are
|
||||
- :c:macro:`SPI_MULTI_LANE_MODE_SINGLE`: Only use the first lane. Other lanes are
|
||||
ignored. This means that it is operating just like a conventional SPI
|
||||
peripheral. This is the default, so it does not need to be explicitly set.
|
||||
|
||||
|
|
@ -149,7 +149,7 @@ The possible values for this field have the following semantics:
|
|||
---------- ---------------- ----------
|
||||
SDO 0 0-0-0-1-0-0-0-1 SDI 0
|
||||
|
||||
- :c:macro:`SPI_MULTI_BUS_MODE_MIRROR`: Send a single data word over all of the
|
||||
- :c:macro:`SPI_MULTI_LANE_MODE_MIRROR`: Send a single data word over all of the
|
||||
lanes at the same time. This only makes sense for writes and not
|
||||
for reads.
|
||||
|
||||
|
|
@ -160,7 +160,7 @@ The possible values for this field have the following semantics:
|
|||
struct spi_transfer xfer = {
|
||||
.tx_buf = tx_buf,
|
||||
.len = 1,
|
||||
.multi_lane_mode = SPI_MULTI_BUS_MODE_MIRROR,
|
||||
.multi_lane_mode = SPI_MULTI_LANE_MODE_MIRROR,
|
||||
};
|
||||
|
||||
spi_sync_transfer(spi, &xfer, 1);
|
||||
|
|
@ -172,7 +172,7 @@ The possible values for this field have the following semantics:
|
|||
SDO 0 0-0-0-1-0-0-0-1 SDI 0
|
||||
SDO 1 0-0-0-1-0-0-0-1 SDI 1
|
||||
|
||||
- :c:macro:`SPI_MULTI_BUS_MODE_STRIPE`: Send or receive two different data words
|
||||
- :c:macro:`SPI_MULTI_LANE_MODE_STRIPE`: Send or receive two different data words
|
||||
at the same time, one on each lane. This means that the buffer needs to be
|
||||
sized to hold data for all lanes. Data is interleaved in the buffer, with
|
||||
the first word corresponding to lane 0, the second to lane 1, and so on.
|
||||
|
|
@ -185,7 +185,7 @@ The possible values for this field have the following semantics:
|
|||
struct spi_transfer xfer = {
|
||||
.rx_buf = rx_buf,
|
||||
.len = 2,
|
||||
.multi_lane_mode = SPI_MULTI_BUS_MODE_STRIPE,
|
||||
.multi_lane_mode = SPI_MULTI_LANE_MODE_STRIPE,
|
||||
};
|
||||
|
||||
spi_sync_transfer(spi, &xfer, 1);
|
||||
|
|
|
|||
33
MAINTAINERS
33
MAINTAINERS
|
|
@ -767,6 +767,14 @@ F: Documentation/devicetree/bindings/phy/airoha,en7581-pcie-phy.yaml
|
|||
F: drivers/phy/phy-airoha-pcie-regs.h
|
||||
F: drivers/phy/phy-airoha-pcie.c
|
||||
|
||||
AIROHA SOUND DRIVER
|
||||
M: Christian Marangi <ansuelsmth@gmail.com>
|
||||
L: linux-sound@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/sound/airoha,an7581-afe.yaml
|
||||
F: Documentation/devicetree/bindings/sound/airoha,an7581-wm8960.yaml
|
||||
F: sound/soc/mediatek/an7581/*
|
||||
|
||||
AIROHA SPI SNFI DRIVER
|
||||
M: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
M: Ray Liu <ray.liu@airoha.com>
|
||||
|
|
@ -9715,6 +9723,13 @@ S: Maintained
|
|||
F: include/linux/errseq.h
|
||||
F: lib/errseq.c
|
||||
|
||||
ES9039Q2M AUDIO CODEC DRIVER
|
||||
M: Karl Asseily <karl@asseily.com>
|
||||
L: linux-sound@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/sound/esstech,es9039q2m.yaml
|
||||
F: sound/soc/codecs/es9039q2m.c
|
||||
|
||||
ESD CAN NETWORK DRIVERS
|
||||
M: Stefan Mätje <stefan.maetje@esd.eu>
|
||||
R: socketcan@esd.eu
|
||||
|
|
@ -22150,6 +22165,15 @@ F: sound/soc/codecs/wcd93*.*
|
|||
F: sound/soc/codecs/wsa88*.*
|
||||
F: sound/soc/qcom/
|
||||
|
||||
QCOM AUDIO INTERFACE (QAIF) DRIVER
|
||||
M: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
|
||||
M: Srinivas Kandagatla <srini@kernel.org>
|
||||
L: linux-sound@vger.kernel.org
|
||||
L: linux-arm-msm@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/sound/qcom,shikra-qaif-cpu.yaml
|
||||
F: sound/soc/qcom/qaif*
|
||||
|
||||
QCOM EMBEDDED USB DEBUGGER (EUD)
|
||||
M: Souradeep Chowdhury <quic_schowdhu@quicinc.com>
|
||||
L: linux-arm-msm@vger.kernel.org
|
||||
|
|
@ -23037,6 +23061,12 @@ S: Maintained
|
|||
F: Documentation/devicetree/bindings/spi/realtek,rtl9301-snand.yaml
|
||||
F: drivers/spi/spi-realtek-rtl-snand.c
|
||||
|
||||
REALTEK SPI-NOR
|
||||
M: Jyan Chou <jyanchou@realtek.com>
|
||||
M: Yu-Chun Lin <eleanor.lin@realtek.com>
|
||||
S: Supported
|
||||
F: drivers/spi/spi-rtk-nor.c
|
||||
|
||||
REALTEK SYSTIMER DRIVER
|
||||
M: Hao-Wen Ting <haowen.ting@realtek.com>
|
||||
S: Maintained
|
||||
|
|
@ -30218,9 +30248,12 @@ F: tools/testing/selftests/cgroup/test_zswap.c
|
|||
|
||||
SENARYTECH AUDIO CODEC DRIVER
|
||||
M: bo liu <bo.liu@senarytech.com>
|
||||
M: qianghua.wang <qianghua.wang@senarytech.com>
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
|
||||
F: sound/hda/codecs/senarytech.c
|
||||
F: sound/soc/codecs/sn624x*
|
||||
F: sound/soc/sdw_utils/soc_sdw_senary*
|
||||
|
||||
ZTE DINGHAI ETHERNET DRIVER
|
||||
M: Junyang Han <han.junyang@zte.com.cn>
|
||||
|
|
|
|||
|
|
@ -322,6 +322,7 @@ static inline unsigned int regcache_get_index_by_order(const struct regmap *map,
|
|||
}
|
||||
|
||||
struct regmap_ram_data {
|
||||
unsigned int base_reg;
|
||||
unsigned int *vals; /* Allocatd by caller */
|
||||
bool *read;
|
||||
bool *written;
|
||||
|
|
|
|||
|
|
@ -963,7 +963,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
|
|||
return 0;
|
||||
|
||||
err_domain:
|
||||
/* Should really dispose of the domain but... */
|
||||
irq_domain_remove(d->domain);
|
||||
err_mutex:
|
||||
mutex_destroy(&d->lock);
|
||||
lockdep_unregister_key(&d->lock_key);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#define BLOCK_TEST_SIZE 12
|
||||
|
||||
#define HIGH_BIT_REG ((UINT_MAX / 2) - 3)
|
||||
|
||||
KUNIT_DEFINE_ACTION_WRAPPER(regmap_exit_action, regmap_exit, struct regmap *);
|
||||
|
||||
struct regmap_test_priv {
|
||||
|
|
@ -23,6 +25,7 @@ struct regmap_test_param {
|
|||
enum regcache_type cache;
|
||||
enum regmap_endian val_endian;
|
||||
|
||||
unsigned int base_reg;
|
||||
unsigned int from_reg;
|
||||
bool fast_io;
|
||||
};
|
||||
|
|
@ -204,7 +207,8 @@ static struct regmap *gen_regmap(struct kunit *test,
|
|||
config->max_register += (BLOCK_TEST_SIZE * config->reg_stride);
|
||||
}
|
||||
|
||||
size = array_size(config->max_register + 1, sizeof(*buf));
|
||||
size = array_size(config->max_register - param->base_reg + 1,
|
||||
sizeof(*buf));
|
||||
buf = kmalloc(size, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
|
@ -215,6 +219,7 @@ static struct regmap *gen_regmap(struct kunit *test,
|
|||
if (!(*data))
|
||||
goto out_free;
|
||||
(*data)->vals = buf;
|
||||
(*data)->base_reg = param->base_reg;
|
||||
|
||||
if (config->num_reg_defaults) {
|
||||
defaults = kunit_kcalloc(test,
|
||||
|
|
@ -227,8 +232,8 @@ static struct regmap *gen_regmap(struct kunit *test,
|
|||
config->reg_defaults = defaults;
|
||||
|
||||
for (i = 0; i < config->num_reg_defaults; i++) {
|
||||
defaults[i].reg = param->from_reg + (i * config->reg_stride);
|
||||
defaults[i].def = buf[param->from_reg + (i * config->reg_stride)];
|
||||
defaults[i].reg = param->from_reg - param->base_reg + (i * config->reg_stride);
|
||||
defaults[i].def = buf[param->from_reg - param->base_reg + (i * config->reg_stride)];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1648,6 +1653,92 @@ static void cache_write_zero(struct kunit *test)
|
|||
KUNIT_ASSERT_FALSE(test, regcache_reg_cached(map, 1));
|
||||
}
|
||||
|
||||
static const struct regmap_test_param high_bit_cache_types_list[] = {
|
||||
{ .cache = REGCACHE_RBTREE, .from_reg = HIGH_BIT_REG,
|
||||
.base_reg = HIGH_BIT_REG },
|
||||
{ .cache = REGCACHE_MAPLE, .from_reg = HIGH_BIT_REG,
|
||||
.base_reg = HIGH_BIT_REG },
|
||||
};
|
||||
|
||||
KUNIT_ARRAY_PARAM(high_bit_cache_types, high_bit_cache_types_list, param_to_desc);
|
||||
|
||||
/*
|
||||
* Dynamically allocated cache types should support registers with the
|
||||
* high bit set, the backend will return an error for any operation on
|
||||
* a register below the expected window.
|
||||
*/
|
||||
static void cache_high_bit_reg(struct kunit *test)
|
||||
{
|
||||
const struct regmap_test_param *param = test->param_value;
|
||||
struct regmap_ram_data *data;
|
||||
struct regmap_config config;
|
||||
struct regmap *map;
|
||||
unsigned int val[BLOCK_TEST_SIZE], rval;
|
||||
int i;
|
||||
|
||||
config = test_regmap_config;
|
||||
|
||||
map = gen_regmap(test, &config, &data);
|
||||
KUNIT_ASSERT_FALSE(test, IS_ERR(map));
|
||||
if (IS_ERR(map))
|
||||
return;
|
||||
|
||||
get_random_bytes(&val, sizeof(val));
|
||||
|
||||
/* No defaults so no registers cached */
|
||||
for (i = 0; i < BLOCK_TEST_SIZE; i++)
|
||||
KUNIT_EXPECT_FALSE(test, regcache_reg_cached(map, param->from_reg + i));
|
||||
|
||||
/* Writes should reach the device */
|
||||
for (i = 0; i < BLOCK_TEST_SIZE; i++)
|
||||
KUNIT_EXPECT_EQ(test, 0, regmap_write(map, param->from_reg + i,
|
||||
val[i]));
|
||||
for (i = 0; i < BLOCK_TEST_SIZE; i++) {
|
||||
KUNIT_EXPECT_TRUE(test, data->written[i]);
|
||||
KUNIT_EXPECT_EQ(test, val[i], data->vals[i]);
|
||||
}
|
||||
|
||||
/* Reads should be satisfied from the cache */
|
||||
for (i = 0; i < BLOCK_TEST_SIZE; i++) {
|
||||
KUNIT_EXPECT_TRUE(test, regcache_reg_cached(map, param->from_reg + i));
|
||||
KUNIT_EXPECT_EQ(test, 0, regmap_read(map, param->from_reg + i,
|
||||
&rval));
|
||||
KUNIT_EXPECT_EQ(test, val[i], rval);
|
||||
KUNIT_EXPECT_FALSE(test, data->read[i]);
|
||||
}
|
||||
|
||||
/* Trash the data on the device then resync */
|
||||
regcache_mark_dirty(map);
|
||||
for (i = 0; i < BLOCK_TEST_SIZE; i++) {
|
||||
data->vals[i] = 0;
|
||||
data->written[i] = false;
|
||||
}
|
||||
KUNIT_EXPECT_EQ(test, 0, regcache_sync(map));
|
||||
|
||||
/* Did we just write the correct data out? */
|
||||
for (i = 0; i < BLOCK_TEST_SIZE; i++) {
|
||||
KUNIT_EXPECT_TRUE(test, data->written[i]);
|
||||
KUNIT_EXPECT_EQ(test, val[i], data->vals[i]);
|
||||
}
|
||||
|
||||
/* Drop some registers */
|
||||
KUNIT_EXPECT_EQ(test, 0, regcache_drop_region(map, param->from_reg + 3,
|
||||
param->from_reg + 5));
|
||||
for (i = 0; i < BLOCK_TEST_SIZE; i++)
|
||||
KUNIT_EXPECT_EQ(test, i < 3 || i > 5,
|
||||
regcache_reg_cached(map, param->from_reg + i));
|
||||
|
||||
/* Reread and check only the dropped registers hit the device */
|
||||
for (i = 0; i < BLOCK_TEST_SIZE; i++)
|
||||
data->read[i] = false;
|
||||
for (i = 0; i < BLOCK_TEST_SIZE; i++) {
|
||||
KUNIT_EXPECT_EQ(test, 0, regmap_read(map, param->from_reg + i,
|
||||
&rval));
|
||||
KUNIT_EXPECT_EQ(test, val[i], rval);
|
||||
KUNIT_EXPECT_EQ(test, i >= 3 && i <= 5, data->read[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that caching the window register works with sync */
|
||||
static void cache_range_window_reg(struct kunit *test)
|
||||
{
|
||||
|
|
@ -2168,6 +2259,7 @@ static struct kunit_case regmap_test_cases[] = {
|
|||
KUNIT_CASE_PARAM(cache_drop_all_and_sync_has_defaults, sparse_cache_types_gen_params),
|
||||
KUNIT_CASE_PARAM(cache_present, sparse_cache_types_gen_params),
|
||||
KUNIT_CASE_PARAM(cache_write_zero, sparse_cache_types_gen_params),
|
||||
KUNIT_CASE_PARAM(cache_high_bit_reg, high_bit_cache_types_gen_params),
|
||||
KUNIT_CASE_PARAM(cache_range_window_reg, real_cache_types_only_gen_params),
|
||||
|
||||
KUNIT_CASE_PARAM(raw_read_defaults_single, raw_test_types_gen_params),
|
||||
|
|
|
|||
|
|
@ -20,8 +20,11 @@ static int regmap_ram_write(void *context, unsigned int reg, unsigned int val)
|
|||
{
|
||||
struct regmap_ram_data *data = context;
|
||||
|
||||
data->vals[reg] = val;
|
||||
data->written[reg] = true;
|
||||
if (reg < data->base_reg)
|
||||
return -EINVAL;
|
||||
|
||||
data->vals[reg - data->base_reg] = val;
|
||||
data->written[reg - data->base_reg] = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -30,8 +33,11 @@ static int regmap_ram_read(void *context, unsigned int reg, unsigned int *val)
|
|||
{
|
||||
struct regmap_ram_data *data = context;
|
||||
|
||||
*val = data->vals[reg];
|
||||
data->read[reg] = true;
|
||||
if (reg < data->base_reg)
|
||||
return -EINVAL;
|
||||
|
||||
*val = data->vals[reg - data->base_reg];
|
||||
data->read[reg - data->base_reg] = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -60,17 +66,25 @@ struct regmap *__regmap_init_ram(struct device *dev,
|
|||
const char *lock_name)
|
||||
{
|
||||
struct regmap *map;
|
||||
unsigned int num_regs;
|
||||
|
||||
if (!config->max_register) {
|
||||
pr_crit("No max_register specified for RAM regmap\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
data->read = kzalloc_objs(bool, config->max_register + 1);
|
||||
if (data->base_reg > config->max_register) {
|
||||
pr_crit("base_reg above max_register for RAM regmap\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
num_regs = config->max_register - data->base_reg + 1;
|
||||
|
||||
data->read = kzalloc_objs(bool, num_regs);
|
||||
if (!data->read)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
data->written = kzalloc_objs(bool, config->max_register + 1);
|
||||
data->written = kzalloc_objs(bool, num_regs);
|
||||
if (!data->written) {
|
||||
kfree(data->read);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
|
|
|||
|
|
@ -16,14 +16,17 @@
|
|||
|
||||
#include "internal.h"
|
||||
|
||||
static unsigned int decode_reg(enum regmap_endian endian, const void *reg)
|
||||
static unsigned int decode_reg(struct regmap_ram_data *data, const void *reg)
|
||||
{
|
||||
const u16 *r = reg;
|
||||
unsigned int decode;
|
||||
|
||||
if (endian == REGMAP_ENDIAN_BIG)
|
||||
return be16_to_cpu(*r);
|
||||
if (data->reg_endian == REGMAP_ENDIAN_BIG)
|
||||
decode = be16_to_cpu(*r);
|
||||
else
|
||||
return le16_to_cpu(*r);
|
||||
decode = le16_to_cpu(*r);
|
||||
|
||||
return decode - data->base_reg;
|
||||
}
|
||||
|
||||
static int regmap_raw_ram_gather_write(void *context,
|
||||
|
|
@ -40,7 +43,7 @@ static int regmap_raw_ram_gather_write(void *context,
|
|||
if (val_len % 2)
|
||||
return -EINVAL;
|
||||
|
||||
r = decode_reg(data->reg_endian, reg);
|
||||
r = decode_reg(data, reg);
|
||||
if (data->noinc_reg && data->noinc_reg(data, r)) {
|
||||
memcpy(&our_buf[r], val + val_len - 2, 2);
|
||||
data->written[r] = true;
|
||||
|
|
@ -74,7 +77,7 @@ static int regmap_raw_ram_read(void *context,
|
|||
if (val_len % 2)
|
||||
return -EINVAL;
|
||||
|
||||
r = decode_reg(data->reg_endian, reg);
|
||||
r = decode_reg(data, reg);
|
||||
if (data->noinc_reg && data->noinc_reg(data, r)) {
|
||||
for (i = 0; i < val_len; i += 2)
|
||||
memcpy(val + i, &our_buf[r], 2);
|
||||
|
|
@ -114,6 +117,7 @@ struct regmap *__regmap_init_raw_ram(struct device *dev,
|
|||
const char *lock_name)
|
||||
{
|
||||
struct regmap *map;
|
||||
unsigned int regs;
|
||||
|
||||
if (config->reg_bits != 16)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
|
@ -123,11 +127,12 @@ struct regmap *__regmap_init_raw_ram(struct device *dev,
|
|||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
data->read = kzalloc_objs(bool, config->max_register + 1);
|
||||
regs = config->max_register - data->base_reg + 1;
|
||||
data->read = kzalloc_objs(bool, regs);
|
||||
if (!data->read)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
data->written = kzalloc_objs(bool, config->max_register + 1);
|
||||
data->written = kzalloc_objs(bool, regs);
|
||||
if (!data->written)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
|
|
|
|||
|
|
@ -2722,7 +2722,7 @@ EXPORT_SYMBOL_GPL(regmap_multi_reg_write_bypassed);
|
|||
* If supported by the underlying bus the write will be scheduled
|
||||
* asynchronously, helping maximise I/O speed on higher speed buses
|
||||
* like SPI. regmap_async_complete() can be called to ensure that all
|
||||
* asynchrnous writes have been completed.
|
||||
* asynchronous writes have been completed.
|
||||
*
|
||||
* A value of zero will be returned on success, a negative errno will
|
||||
* be returned in error cases.
|
||||
|
|
|
|||
|
|
@ -2960,6 +2960,8 @@ int cs_dsp_run(struct cs_dsp *dsp)
|
|||
return 0;
|
||||
|
||||
err:
|
||||
dsp->running = false;
|
||||
|
||||
if (dsp->ops->stop_core)
|
||||
dsp->ops->stop_core(dsp);
|
||||
if (dsp->ops->disable_core)
|
||||
|
|
@ -3505,7 +3507,7 @@ EXPORT_SYMBOL_NS_GPL(cs_dsp_chunk_write, "FW_CS_DSP");
|
|||
*
|
||||
* As cs_dsp_chunk_write only writes data when a whole DSP word is ready to
|
||||
* be written out it is possible that some data will remain in the cache, this
|
||||
* function will pad that data with zeros upto a whole DSP word and write out.
|
||||
* function will pad that data with zeros up to a whole DSP word and write out.
|
||||
*
|
||||
* Return: Zero for success, a negative number on error.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ struct cs_dsp_test_local {
|
|||
int num_post_stop;
|
||||
int num_watchdog_expired;
|
||||
|
||||
bool fail_post_run;
|
||||
|
||||
struct cs_dsp_coeff_ctl *passed_ctl[16];
|
||||
struct cs_dsp *passed_dsp;
|
||||
};
|
||||
|
|
@ -106,6 +108,9 @@ static int cs_dsp_test_post_run_callback(struct cs_dsp *dsp)
|
|||
local->passed_dsp = dsp;
|
||||
local->num_post_run++;
|
||||
|
||||
if (local->fail_post_run)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -198,6 +203,33 @@ static void cs_dsp_test_run_stop_callbacks(struct kunit *test)
|
|||
local->passed_dsp = NULL;
|
||||
}
|
||||
|
||||
static void cs_dsp_test_run_error_clears_running(struct kunit *test)
|
||||
{
|
||||
struct cs_dsp_test *priv = test->priv;
|
||||
struct cs_dsp_test_local *local = priv->local;
|
||||
struct firmware *wmfw;
|
||||
|
||||
wmfw = cs_dsp_mock_wmfw_get_firmware(local->wmfw_builder);
|
||||
|
||||
KUNIT_EXPECT_EQ(test,
|
||||
cs_dsp_power_up(priv->dsp, wmfw, "wmfw", NULL, NULL, "misc"),
|
||||
0);
|
||||
|
||||
/*
|
||||
* By the time the post_run hook runs, the core has been started. A
|
||||
* failure there stops and disables the core again, so the DSP must not
|
||||
* be left looking like it is running.
|
||||
*/
|
||||
local->fail_post_run = true;
|
||||
KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), -EIO);
|
||||
KUNIT_EXPECT_FALSE(test, priv->dsp->running);
|
||||
|
||||
/* and the next run must be able to start it again */
|
||||
local->fail_post_run = false;
|
||||
KUNIT_EXPECT_EQ(test, cs_dsp_run(priv->dsp), 0);
|
||||
KUNIT_EXPECT_TRUE(test, priv->dsp->running);
|
||||
}
|
||||
|
||||
static void cs_dsp_test_ctl_v1_callbacks(struct kunit *test)
|
||||
{
|
||||
struct cs_dsp_test *priv = test->priv;
|
||||
|
|
@ -609,6 +641,7 @@ KUNIT_ARRAY_PARAM(cs_dsp_no_callbacks,
|
|||
|
||||
static struct kunit_case cs_dsp_callbacks_adsp2_wmfwv1_test_cases[] = {
|
||||
KUNIT_CASE_PARAM(cs_dsp_test_run_stop_callbacks, cs_dsp_callbacks_ops_gen_params),
|
||||
KUNIT_CASE_PARAM(cs_dsp_test_run_error_clears_running, cs_dsp_callbacks_ops_gen_params),
|
||||
KUNIT_CASE_PARAM(cs_dsp_test_ctl_v1_callbacks, cs_dsp_callbacks_ops_gen_params),
|
||||
KUNIT_CASE_PARAM(cs_dsp_test_no_callbacks, cs_dsp_no_callbacks_gen_params),
|
||||
|
||||
|
|
@ -617,6 +650,7 @@ static struct kunit_case cs_dsp_callbacks_adsp2_wmfwv1_test_cases[] = {
|
|||
|
||||
static struct kunit_case cs_dsp_callbacks_adsp2_wmfwv2_test_cases[] = {
|
||||
KUNIT_CASE_PARAM(cs_dsp_test_run_stop_callbacks, cs_dsp_callbacks_ops_gen_params),
|
||||
KUNIT_CASE_PARAM(cs_dsp_test_run_error_clears_running, cs_dsp_callbacks_ops_gen_params),
|
||||
KUNIT_CASE_PARAM(cs_dsp_test_ctl_v2_callbacks, cs_dsp_callbacks_ops_gen_params),
|
||||
KUNIT_CASE_PARAM(cs_dsp_test_no_callbacks, cs_dsp_no_callbacks_gen_params),
|
||||
|
||||
|
|
@ -625,6 +659,7 @@ static struct kunit_case cs_dsp_callbacks_adsp2_wmfwv2_test_cases[] = {
|
|||
|
||||
static struct kunit_case cs_dsp_callbacks_halo_test_cases[] = {
|
||||
KUNIT_CASE_PARAM(cs_dsp_test_run_stop_callbacks, cs_dsp_callbacks_ops_gen_params),
|
||||
KUNIT_CASE_PARAM(cs_dsp_test_run_error_clears_running, cs_dsp_callbacks_ops_gen_params),
|
||||
KUNIT_CASE_PARAM(cs_dsp_test_ctl_v2_callbacks, cs_dsp_callbacks_ops_gen_params),
|
||||
KUNIT_CASE_PARAM(cs_dsp_test_no_callbacks, cs_dsp_no_callbacks_gen_params),
|
||||
|
||||
|
|
|
|||
|
|
@ -1458,11 +1458,15 @@ static int fmh_gpib_attach_impl(struct gpib_board *board, const struct gpib_boar
|
|||
e_priv->irq = irq;
|
||||
|
||||
if (acquire_dma) {
|
||||
e_priv->dma_channel = dma_request_slave_channel(board->dev, "rxtx");
|
||||
if (!e_priv->dma_channel) {
|
||||
struct dma_chan *tmp_chan;
|
||||
|
||||
tmp_chan = dma_request_chan(board->dev, "rxtx");
|
||||
retval = PTR_ERR_OR_ZERO(tmp_chan);
|
||||
if (retval) {
|
||||
dev_err(board->dev, "failed to acquire dma channel \"rxtx\".\n");
|
||||
return -EIO;
|
||||
return retval;
|
||||
}
|
||||
e_priv->dma_channel = tmp_chan;
|
||||
}
|
||||
/*
|
||||
* in the future we might want to know the half-fifo size
|
||||
|
|
|
|||
|
|
@ -63,7 +63,6 @@ comment "SPI Master Controller Drivers"
|
|||
config SPI_AIROHA_SNFI
|
||||
tristate "Airoha SPI NAND Flash Interface"
|
||||
depends on ARCH_AIROHA || COMPILE_TEST
|
||||
depends on SPI_MASTER
|
||||
select REGMAP_MMIO
|
||||
help
|
||||
This enables support for SPI-NAND mode on the Airoha NAND
|
||||
|
|
@ -92,6 +91,14 @@ config SPI_ALTERA_DFL
|
|||
Altera SPI master controller. The SPI master is connected
|
||||
to a SPI slave to Avalon bridge in a Intel MAX BMC.
|
||||
|
||||
config SPI_AMD
|
||||
tristate "AMD SPI controller"
|
||||
depends on PCI
|
||||
depends on X86 || COMPILE_TEST
|
||||
depends on SPI_MEM
|
||||
help
|
||||
Enables SPI controller driver for AMD SoC.
|
||||
|
||||
config SPI_AMLOGIC_SPIFC_A1
|
||||
tristate "Amlogic A1 SPIFC controller"
|
||||
depends on ARCH_MESON || COMPILE_TEST
|
||||
|
|
@ -136,6 +143,13 @@ config SPI_AR934X
|
|||
This enables support for the SPI controller present on the
|
||||
Qualcomm Atheros AR934X/QCA95XX SoCs.
|
||||
|
||||
config SPI_ARMADA_3700
|
||||
tristate "Marvell Armada 3700 SPI Controller"
|
||||
depends on (ARCH_MVEBU && OF) || COMPILE_TEST
|
||||
help
|
||||
This enables support for the SPI controller present on the
|
||||
Marvell Armada 3700 SoCs.
|
||||
|
||||
config SPI_ATCSPI200
|
||||
tristate "Andes ATCSPI200 SPI controller"
|
||||
depends on ARCH_ANDES || COMPILE_TEST
|
||||
|
|
@ -153,13 +167,6 @@ config SPI_ATH79
|
|||
This enables support for the SPI controller present on the
|
||||
Atheros AR71XX/AR724X/AR913X SoCs.
|
||||
|
||||
config SPI_ARMADA_3700
|
||||
tristate "Marvell Armada 3700 SPI Controller"
|
||||
depends on (ARCH_MVEBU && OF) || COMPILE_TEST
|
||||
help
|
||||
This enables support for the SPI controller present on the
|
||||
Marvell Armada 3700 SoCs.
|
||||
|
||||
config SPI_ASPEED_SMC
|
||||
tristate "Aspeed flash controllers in SPI mode"
|
||||
depends on ARCH_ASPEED || COMPILE_TEST
|
||||
|
|
@ -333,7 +340,7 @@ config SPI_CADENCE_XSPI
|
|||
|
||||
config SPI_CH341
|
||||
tristate "CH341 USB2SPI adapter"
|
||||
depends on SPI_MASTER && USB
|
||||
depends on USB
|
||||
help
|
||||
Enables the SPI controller on the CH341a USB to serial chip
|
||||
|
||||
|
|
@ -388,14 +395,14 @@ config SPI_DW_MMIO
|
|||
endif
|
||||
|
||||
config SPI_DLN2
|
||||
tristate "Diolan DLN-2 USB SPI adapter"
|
||||
depends on MFD_DLN2
|
||||
help
|
||||
If you say yes to this option, support will be included for Diolan
|
||||
DLN2, a USB to SPI interface.
|
||||
tristate "Diolan DLN-2 USB SPI adapter"
|
||||
depends on MFD_DLN2
|
||||
help
|
||||
If you say yes to this option, support will be included for Diolan
|
||||
DLN2, a USB to SPI interface.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called spi-dln2.
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called spi-dln2.
|
||||
|
||||
config SPI_EP93XX
|
||||
tristate "Cirrus Logic EP93xx SPI controller"
|
||||
|
|
@ -420,6 +427,22 @@ config SPI_FSI
|
|||
This enables support for the driver for FSI bus attached SPI
|
||||
controllers.
|
||||
|
||||
config SPI_FSL_DSPI
|
||||
tristate "Freescale DSPI controller"
|
||||
select REGMAP_MMIO
|
||||
depends on ARCH_MXC || ARCH_NXP || M5441x || COMPILE_TEST
|
||||
help
|
||||
This enables support for the Freescale DSPI controller in master
|
||||
mode. S32, VF610, LS1021A and ColdFire platforms uses the controller.
|
||||
|
||||
config SPI_FSL_ESPI
|
||||
tristate "Freescale eSPI controller"
|
||||
depends on FSL_SOC
|
||||
help
|
||||
This enables using the Freescale eSPI controllers in master mode.
|
||||
From MPC8536, 85xx platform uses the controller, and all P10xx,
|
||||
P20xx, P30xx,P40xx, P50xx uses this controller.
|
||||
|
||||
config SPI_FSL_LPSPI
|
||||
tristate "Freescale i.MX LPSPI controller"
|
||||
depends on ARCH_MXC || COMPILE_TEST
|
||||
|
|
@ -438,6 +461,26 @@ config SPI_FSL_QUADSPI
|
|||
This controller does not support generic SPI messages. It only
|
||||
supports the high-level SPI memory interface.
|
||||
|
||||
config SPI_FSL_LIB
|
||||
tristate
|
||||
depends on OF
|
||||
|
||||
config SPI_FSL_CPM
|
||||
tristate
|
||||
depends on FSL_SOC
|
||||
|
||||
config SPI_FSL_SPI
|
||||
tristate "Freescale SPI controller and Aeroflex Gaisler GRLIB SPI controller"
|
||||
depends on OF
|
||||
select SPI_FSL_LIB
|
||||
select SPI_FSL_CPM if FSL_SOC
|
||||
help
|
||||
This enables using the Freescale SPI controllers in master mode.
|
||||
MPC83xx platform uses the controller in cpu mode or CPM/QE mode.
|
||||
MPC8569 uses the controller in QE mode, MPC8610 in cpu mode.
|
||||
This also enables using the Aeroflex Gaisler GRLIB SPI controller in
|
||||
master mode.
|
||||
|
||||
config SPI_GXP
|
||||
tristate "GXP SPI driver"
|
||||
depends on ARCH_HPE || COMPILE_TEST
|
||||
|
|
@ -463,27 +506,6 @@ config SPI_HISI_SFC_V3XX
|
|||
This enables support for HiSilicon v3xx SPI NOR flash controller
|
||||
found in hi16xx chipsets.
|
||||
|
||||
config SPI_NXP_FLEXSPI
|
||||
tristate "NXP Flex SPI controller"
|
||||
depends on ARCH_LAYERSCAPE || ARCH_MXC || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
This enables support for the Flex SPI controller in master mode.
|
||||
Up to four slave devices can be connected on two buses with two
|
||||
chipselects each.
|
||||
This controller does not support generic SPI messages and only
|
||||
supports the high-level SPI memory interface.
|
||||
|
||||
config SPI_NXP_XSPI
|
||||
tristate "NXP xSPI controller"
|
||||
depends on ARCH_MXC || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
This enables support for the xSPI controller. Up to two devices
|
||||
can be connected to one host.
|
||||
This controller does not support generic SPI messages and only
|
||||
supports the high-level SPI memory interface.
|
||||
|
||||
config SPI_GPIO
|
||||
tristate "GPIO-based bitbanging SPI Master"
|
||||
depends on GPIOLIB || COMPILE_TEST
|
||||
|
|
@ -581,6 +603,25 @@ config SPI_KSPI2
|
|||
This driver can also be built as a module. If so, the module
|
||||
will be called spi-kspi2.
|
||||
|
||||
config SPI_LANTIQ_SSC
|
||||
tristate "Lantiq SSC SPI controller"
|
||||
depends on LANTIQ || X86 || COMPILE_TEST
|
||||
help
|
||||
This driver supports the Lantiq SSC SPI controller in master
|
||||
mode. This controller is found on Intel (former Lantiq) SoCs like
|
||||
the Danube, Falcon, xRX200, xRX300, Lightning Mountain.
|
||||
|
||||
config SPI_LJCA
|
||||
tristate "Intel La Jolla Cove Adapter SPI support"
|
||||
depends on USB_LJCA
|
||||
default USB_LJCA
|
||||
help
|
||||
Select this option to enable SPI driver for the Intel
|
||||
La Jolla Cove Adapter (LJCA) board.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called spi-ljca.
|
||||
|
||||
config SPI_LM70_LLP
|
||||
tristate "Parallel port adapter for LM70 eval board (DEVELOPMENT)"
|
||||
depends on PARPORT
|
||||
|
|
@ -626,74 +667,6 @@ config SPI_LP8841_RTC
|
|||
Say N here unless you plan to run the kernel on an ICP DAS
|
||||
LP-8x4x industrial computer.
|
||||
|
||||
config SPI_MPC52xx
|
||||
tristate "Freescale MPC52xx SPI (non-PSC) controller support"
|
||||
depends on PPC_MPC52xx
|
||||
help
|
||||
This drivers supports the MPC52xx SPI controller in master SPI
|
||||
mode.
|
||||
|
||||
config SPI_MPC52xx_PSC
|
||||
tristate "Freescale MPC52xx PSC SPI controller"
|
||||
depends on PPC_MPC52xx
|
||||
help
|
||||
This enables using the Freescale MPC52xx Programmable Serial
|
||||
Controller in master SPI mode.
|
||||
|
||||
config SPI_MPC512x_PSC
|
||||
tristate "Freescale MPC512x PSC SPI controller"
|
||||
depends on PPC_MPC512x
|
||||
help
|
||||
This enables using the Freescale MPC5121 Programmable Serial
|
||||
Controller in SPI master mode.
|
||||
|
||||
config SPI_FSL_LIB
|
||||
tristate
|
||||
depends on OF
|
||||
|
||||
config SPI_FSL_CPM
|
||||
tristate
|
||||
depends on FSL_SOC
|
||||
|
||||
config SPI_FSL_SPI
|
||||
tristate "Freescale SPI controller and Aeroflex Gaisler GRLIB SPI controller"
|
||||
depends on OF
|
||||
select SPI_FSL_LIB
|
||||
select SPI_FSL_CPM if FSL_SOC
|
||||
help
|
||||
This enables using the Freescale SPI controllers in master mode.
|
||||
MPC83xx platform uses the controller in cpu mode or CPM/QE mode.
|
||||
MPC8569 uses the controller in QE mode, MPC8610 in cpu mode.
|
||||
This also enables using the Aeroflex Gaisler GRLIB SPI controller in
|
||||
master mode.
|
||||
|
||||
config SPI_FSL_DSPI
|
||||
tristate "Freescale DSPI controller"
|
||||
select REGMAP_MMIO
|
||||
depends on ARCH_MXC || ARCH_NXP || M5441x || COMPILE_TEST
|
||||
help
|
||||
This enables support for the Freescale DSPI controller in master
|
||||
mode. S32, VF610, LS1021A and ColdFire platforms uses the controller.
|
||||
|
||||
config SPI_FSL_ESPI
|
||||
tristate "Freescale eSPI controller"
|
||||
depends on FSL_SOC
|
||||
help
|
||||
This enables using the Freescale eSPI controllers in master mode.
|
||||
From MPC8536, 85xx platform uses the controller, and all P10xx,
|
||||
P20xx, P30xx,P40xx, P50xx uses this controller.
|
||||
|
||||
config SPI_LJCA
|
||||
tristate "Intel La Jolla Cove Adapter SPI support"
|
||||
depends on USB_LJCA
|
||||
default USB_LJCA
|
||||
help
|
||||
Select this option to enable SPI driver for the Intel
|
||||
La Jolla Cove Adapter (LJCA) board.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called spi-ljca.
|
||||
|
||||
config SPI_MA35D1_QSPI
|
||||
tristate "Nuvoton MA35D1 QSPI controller"
|
||||
depends on ARCH_MA35 || COMPILE_TEST
|
||||
|
|
@ -722,7 +695,6 @@ config SPI_MESON_SPIFC
|
|||
|
||||
config SPI_MICROCHIP_CORE_QSPI
|
||||
tristate "Microchip FPGA QSPI controllers"
|
||||
depends on SPI_MASTER
|
||||
help
|
||||
This enables the QSPI driver for Microchip FPGA QSPI controllers.
|
||||
Say Y or M here if you want to use the QSPI controllers on
|
||||
|
|
@ -731,13 +703,33 @@ config SPI_MICROCHIP_CORE_QSPI
|
|||
|
||||
config SPI_MICROCHIP_CORE_SPI
|
||||
tristate "Microchip FPGA CoreSPI controller"
|
||||
depends on SPI_MASTER
|
||||
help
|
||||
This enables the SPI driver for Microchip FPGA CoreSPI controller.
|
||||
Say Y or M here if you want to use the "soft" controllers on
|
||||
PolarFire SoC.
|
||||
If built as a module, it will be called spi-microchip-core-spi.
|
||||
|
||||
config SPI_MPC52xx
|
||||
tristate "Freescale MPC52xx SPI (non-PSC) controller support"
|
||||
depends on PPC_MPC52xx
|
||||
help
|
||||
This drivers supports the MPC52xx SPI controller in master SPI
|
||||
mode.
|
||||
|
||||
config SPI_MPC52xx_PSC
|
||||
tristate "Freescale MPC52xx PSC SPI controller"
|
||||
depends on PPC_MPC52xx
|
||||
help
|
||||
This enables using the Freescale MPC52xx Programmable Serial
|
||||
Controller in master SPI mode.
|
||||
|
||||
config SPI_MPC512x_PSC
|
||||
tristate "Freescale MPC512x PSC SPI controller"
|
||||
depends on PPC_MPC512x
|
||||
help
|
||||
This enables using the Freescale MPC5121 Programmable Serial
|
||||
Controller in SPI master mode.
|
||||
|
||||
config SPI_MT65XX
|
||||
tristate "MediaTek SPI controller"
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
|
|
@ -773,6 +765,19 @@ config SPI_MTK_SNFI
|
|||
is implemented as a SPI-MEM controller with pipelined ECC
|
||||
capability.
|
||||
|
||||
config SPI_MXIC
|
||||
tristate "Macronix MX25F0A SPI controller"
|
||||
imply MTD_NAND_ECC_MXIC
|
||||
help
|
||||
This selects the Macronix MX25F0A SPI controller driver.
|
||||
|
||||
config SPI_MXS
|
||||
tristate "Freescale MXS SPI controller"
|
||||
depends on ARCH_MXS
|
||||
select STMP_DEVICE
|
||||
help
|
||||
SPI driver for Freescale MXS devices.
|
||||
|
||||
config SPI_WPCM_FIU
|
||||
tristate "Nuvoton WPCM450 Flash Interface Unit"
|
||||
depends on ARCH_NPCM || COMPILE_TEST
|
||||
|
|
@ -801,13 +806,26 @@ config SPI_NPCM_PSPI
|
|||
This driver provides support for Nuvoton NPCM BMC
|
||||
Peripheral SPI controller in master mode.
|
||||
|
||||
config SPI_LANTIQ_SSC
|
||||
tristate "Lantiq SSC SPI controller"
|
||||
depends on LANTIQ || X86 || COMPILE_TEST
|
||||
config SPI_NXP_FLEXSPI
|
||||
tristate "NXP Flex SPI controller"
|
||||
depends on ARCH_LAYERSCAPE || ARCH_MXC || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
This driver supports the Lantiq SSC SPI controller in master
|
||||
mode. This controller is found on Intel (former Lantiq) SoCs like
|
||||
the Danube, Falcon, xRX200, xRX300, Lightning Mountain.
|
||||
This enables support for the Flex SPI controller in master mode.
|
||||
Up to four slave devices can be connected on two buses with two
|
||||
chipselects each.
|
||||
This controller does not support generic SPI messages and only
|
||||
supports the high-level SPI memory interface.
|
||||
|
||||
config SPI_NXP_XSPI
|
||||
tristate "NXP xSPI controller"
|
||||
depends on ARCH_MXC || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
This enables support for the xSPI controller. Up to two devices
|
||||
can be connected to one host.
|
||||
This controller does not support generic SPI messages and only
|
||||
supports the high-level SPI memory interface.
|
||||
|
||||
config SPI_OC_TINY
|
||||
tristate "OpenCores tiny SPI"
|
||||
|
|
@ -838,14 +856,6 @@ config SPI_OMAP24XX
|
|||
SPI master controller for OMAP24XX and later Multichannel SPI
|
||||
(McSPI) modules.
|
||||
|
||||
config SPI_TI_QSPI
|
||||
tristate "DRA7xxx QSPI controller support"
|
||||
depends on ARCH_OMAP2PLUS || COMPILE_TEST
|
||||
help
|
||||
QSPI master controller for DRA7xxx used for flash devices.
|
||||
This device supports single, dual and quad read support, while
|
||||
it only supports single write mode.
|
||||
|
||||
config SPI_ORION
|
||||
tristate "Orion SPI master"
|
||||
depends on PLAT_ORION || ARCH_MVEBU || COMPILE_TEST
|
||||
|
|
@ -887,7 +897,6 @@ config SPI_PL022
|
|||
|
||||
config SPI_POLARFIRE_SOC
|
||||
tristate "Microchip FPGA SPI controllers"
|
||||
depends on SPI_MASTER
|
||||
depends on ARCH_MICROCHIP || COMPILE_TEST
|
||||
help
|
||||
This enables the SPI driver for Microchip FPGA SPI controllers.
|
||||
|
|
@ -950,7 +959,7 @@ config SPI_ROCKCHIP_SFC
|
|||
|
||||
config SPI_RB4XX
|
||||
tristate "Mikrotik RB4XX SPI master"
|
||||
depends on SPI_MASTER && (ATH79 || COMPILE_TEST)
|
||||
depends on ATH79 || COMPILE_TEST
|
||||
depends on OF
|
||||
help
|
||||
SPI controller driver for the Mikrotik RB4xx series boards.
|
||||
|
|
@ -967,6 +976,16 @@ config SPI_RSPI
|
|||
help
|
||||
SPI driver for Renesas RSPI and QSPI blocks.
|
||||
|
||||
config SPI_RTK_NOR
|
||||
tristate "Realtek SPI-NOR flash controller"
|
||||
depends on ARCH_REALTEK || COMPILE_TEST
|
||||
depends on SPI_MEM
|
||||
help
|
||||
This enables support for the SPI NOR Flash Controller found on
|
||||
Realtek DHC SoCs. The controller supports single and dual I/O
|
||||
transfers and offloads the payload to an integrated DMA engine.
|
||||
Say Y or M here if you are building a kernel for a Realtek DHC SoC
|
||||
|
||||
config SPI_RZV2H_RSPI
|
||||
tristate "Renesas RZ/V2H RSPI controller"
|
||||
depends on ARCH_RENESAS || COMPILE_TEST
|
||||
|
|
@ -1035,12 +1054,14 @@ config SPI_SC18IS602
|
|||
help
|
||||
SPI driver for NXP SC18IS602/602B/603 I2C to SPI bridge.
|
||||
|
||||
config SPI_SH_MSIOF
|
||||
tristate "SuperH MSIOF SPI controller"
|
||||
depends on HAVE_CLK
|
||||
depends on ARCH_SHMOBILE || ARCH_RENESAS || COMPILE_TEST
|
||||
config SPI_SG2044_NOR
|
||||
tristate "SG2044 SPI NOR Controller"
|
||||
depends on ARCH_SOPHGO || COMPILE_TEST
|
||||
help
|
||||
SPI driver for SuperH and SH Mobile MSIOF blocks.
|
||||
This enables support for the SG2044 SPI NOR controller,
|
||||
which supports Dual/Quad read and write operations while
|
||||
also supporting 3Byte address devices and 4Byte address
|
||||
devices.
|
||||
|
||||
config SPI_SH
|
||||
tristate "SuperH SPI controller"
|
||||
|
|
@ -1048,6 +1069,19 @@ config SPI_SH
|
|||
help
|
||||
SPI driver for SuperH SPI blocks.
|
||||
|
||||
config SPI_SH_HSPI
|
||||
tristate "SuperH HSPI controller"
|
||||
depends on ARCH_RENESAS || COMPILE_TEST
|
||||
help
|
||||
SPI driver for SuperH HSPI blocks.
|
||||
|
||||
config SPI_SH_MSIOF
|
||||
tristate "SuperH MSIOF SPI controller"
|
||||
depends on HAVE_CLK
|
||||
depends on ARCH_SHMOBILE || ARCH_RENESAS || COMPILE_TEST
|
||||
help
|
||||
SPI driver for SuperH and SH Mobile MSIOF blocks.
|
||||
|
||||
config SPI_SH_SCI
|
||||
tristate "SuperH SCI SPI controller"
|
||||
depends on SUPERH
|
||||
|
|
@ -1055,28 +1089,12 @@ config SPI_SH_SCI
|
|||
help
|
||||
SPI driver for SuperH SCI blocks.
|
||||
|
||||
config SPI_SH_HSPI
|
||||
tristate "SuperH HSPI controller"
|
||||
depends on ARCH_RENESAS || COMPILE_TEST
|
||||
help
|
||||
SPI driver for SuperH HSPI blocks.
|
||||
|
||||
config SPI_SIFIVE
|
||||
tristate "SiFive SPI controller"
|
||||
depends on HAS_IOMEM
|
||||
help
|
||||
This exposes the SPI controller IP from SiFive.
|
||||
|
||||
config SPI_SLAVE_MT27XX
|
||||
tristate "MediaTek SPI slave device"
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
depends on SPI_SLAVE
|
||||
help
|
||||
This selects the MediaTek(R) SPI slave device driver.
|
||||
If you want to use MediaTek(R) SPI slave interface,
|
||||
say Y or M here.If you are not sure, say N.
|
||||
SPI slave drivers for Mediatek MT27XX series ARM SoCs.
|
||||
|
||||
config SPI_SN_F_OSPI
|
||||
tristate "Socionext F_OSPI SPI flash controller"
|
||||
depends on OF && HAS_IOMEM
|
||||
|
|
@ -1086,15 +1104,6 @@ config SPI_SN_F_OSPI
|
|||
for connecting an SPI Flash memory over up to 8-bit wide bus.
|
||||
It supports indirect access mode only.
|
||||
|
||||
config SPI_SG2044_NOR
|
||||
tristate "SG2044 SPI NOR Controller"
|
||||
depends on ARCH_SOPHGO || COMPILE_TEST
|
||||
help
|
||||
This enables support for the SG2044 SPI NOR controller,
|
||||
which supports Dual/Quad read and write operations while
|
||||
also supporting 3Byte address devices and 4Byte address
|
||||
devices.
|
||||
|
||||
config SPI_SPACEMIT_K1
|
||||
tristate "K1 SPI Controller"
|
||||
depends on ARCH_SPACEMIT || COMPILE_TEST
|
||||
|
|
@ -1189,20 +1198,6 @@ config SPI_SYNQUACER
|
|||
|
||||
It also supports the new dual-bit and quad-bit SPI protocol.
|
||||
|
||||
config SPI_MXIC
|
||||
tristate "Macronix MX25F0A SPI controller"
|
||||
depends on SPI_MASTER
|
||||
imply MTD_NAND_ECC_MXIC
|
||||
help
|
||||
This selects the Macronix MX25F0A SPI controller driver.
|
||||
|
||||
config SPI_MXS
|
||||
tristate "Freescale MXS SPI controller"
|
||||
depends on ARCH_MXS
|
||||
select STMP_DEVICE
|
||||
help
|
||||
SPI driver for Freescale MXS devices.
|
||||
|
||||
config SPI_TEGRA210_QUAD
|
||||
tristate "NVIDIA Tegra QSPI Controller"
|
||||
depends on ARCH_TEGRA || COMPILE_TEST
|
||||
|
|
@ -1244,6 +1239,23 @@ config SPI_THUNDERX
|
|||
SPI host driver for the hardware found on Cavium ThunderX
|
||||
SOCs.
|
||||
|
||||
config SPI_TI_QSPI
|
||||
tristate "DRA7xxx QSPI controller support"
|
||||
depends on ARCH_OMAP2PLUS || COMPILE_TEST
|
||||
help
|
||||
QSPI master controller for DRA7xxx used for flash devices.
|
||||
This device supports single, dual and quad read support, while
|
||||
it only supports single write mode.
|
||||
|
||||
config SPI_TLE62X0
|
||||
tristate "Infineon TLE62X0 (for power switching)"
|
||||
depends on SYSFS
|
||||
help
|
||||
SPI driver for Infineon TLE62X0 series line driver chips,
|
||||
such as the TLE6220, TLE6230 and TLE6240. This provides a
|
||||
sysfs interface, with each line presented as a kind of GPIO
|
||||
exposing both switch control and diagnostic feedback.
|
||||
|
||||
config SPI_TOPCLIFF_PCH
|
||||
tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) SPI"
|
||||
depends on PCI && (X86_32 || MIPS || COMPILE_TEST)
|
||||
|
|
@ -1270,7 +1282,7 @@ config SPI_UNIPHIER
|
|||
|
||||
config SPI_VIRTIO
|
||||
tristate "Virtio SPI Controller"
|
||||
depends on SPI_MASTER && VIRTIO
|
||||
depends on VIRTIO
|
||||
help
|
||||
If you say yes to this option, support will be included for the virtio
|
||||
SPI controller driver. The hardware can be emulated by any device model
|
||||
|
|
@ -1336,14 +1348,6 @@ config SPI_ZYNQMP_GQSPI
|
|||
Enables Xilinx GQSPI controller driver for Zynq UltraScale+ MPSoC.
|
||||
This controller only supports SPI memory interface.
|
||||
|
||||
config SPI_AMD
|
||||
tristate "AMD SPI controller"
|
||||
depends on PCI
|
||||
depends on SPI_MASTER || X86 || COMPILE_TEST
|
||||
depends on SPI_MEM
|
||||
help
|
||||
Enables SPI controller driver for AMD SoC.
|
||||
|
||||
#
|
||||
# Add new SPI master controllers in alphabetical order above this line
|
||||
#
|
||||
|
|
@ -1392,15 +1396,6 @@ config SPI_LOOPBACK_TEST
|
|||
primarily used for development of spi_master drivers
|
||||
and to detect regressions
|
||||
|
||||
config SPI_TLE62X0
|
||||
tristate "Infineon TLE62X0 (for power switching)"
|
||||
depends on SYSFS
|
||||
help
|
||||
SPI driver for Infineon TLE62X0 series line driver chips,
|
||||
such as the TLE6220, TLE6230 and TLE6240. This provides a
|
||||
sysfs interface, with each line presented as a kind of GPIO
|
||||
exposing both switch control and diagnostic feedback.
|
||||
|
||||
#
|
||||
# Add new SPI protocol masters in alphabetical order above this line
|
||||
#
|
||||
|
|
@ -1431,6 +1426,15 @@ config SPI_SLAVE_SYSTEM_CONTROL
|
|||
SPI slave handler to allow remote control of system reboot, power
|
||||
off, halt, and suspend.
|
||||
|
||||
config SPI_SLAVE_MT27XX
|
||||
tristate "MediaTek SPI slave device"
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
help
|
||||
This selects the MediaTek(R) SPI slave device driver.
|
||||
If you want to use MediaTek(R) SPI slave interface,
|
||||
say Y or M here.If you are not sure, say N.
|
||||
SPI slave drivers for Mediatek MT27XX series ARM SoCs.
|
||||
|
||||
endif # SPI_SLAVE
|
||||
|
||||
config SPI_DYNAMIC
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@ obj-$(CONFIG_MACH_REALTEK_RTL) += spi-realtek-rtl.o
|
|||
obj-$(CONFIG_SPI_REALTEK_SNAND) += spi-realtek-rtl-snand.o
|
||||
obj-$(CONFIG_SPI_RPCIF) += spi-rpc-if.o
|
||||
obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
|
||||
obj-$(CONFIG_SPI_RTK_NOR) += spi-rtk-nor.o
|
||||
obj-$(CONFIG_SPI_RZV2H_RSPI) += spi-rzv2h-rspi.o
|
||||
obj-$(CONFIG_SPI_RZV2M_CSI) += spi-rzv2m-csi.o
|
||||
obj-$(CONFIG_SPI_S3C64XX) += spi-s3c64xx.o
|
||||
|
|
|
|||
|
|
@ -37,6 +37,12 @@
|
|||
#define CFG_HW_POS BIT(6)
|
||||
/* start on vsync falling */
|
||||
#define CFG_HW_NEG BIT(7)
|
||||
#define CFG_WORD_GAP GENMASK(9, 8)
|
||||
#define CFG_MO_IDLE_OUTPUT GENMASK(11, 10)
|
||||
/* cs hold time in pclk */
|
||||
#define CFG_CS_HOLD GENMASK(26, 12)
|
||||
/* high 4 bits of cs setup time in sclk */
|
||||
#define CFG_CS_SETUP_EXTEND GENMASK(30, 27)
|
||||
|
||||
#define SPISG_REG_CFG_START 0x08
|
||||
#define CFG_BLOCK_NUM GENMASK(19, 0)
|
||||
|
|
@ -95,7 +101,7 @@
|
|||
|
||||
#define SPISG_MAX_REG 0x40
|
||||
|
||||
#define SPISG_BLOCK_MAX 0x100000
|
||||
#define SPISG_BLOCK_MAX 0xFFFFF
|
||||
|
||||
#define SPISG_OP_MODE_WRITE_CMD 0
|
||||
#define SPISG_OP_MODE_READ_STS 1
|
||||
|
|
@ -143,6 +149,13 @@ struct spisg_descriptor_extra {
|
|||
int rx_ccsg_len;
|
||||
};
|
||||
|
||||
struct aml_spisg_data {
|
||||
bool mo_idle_output_ctrl;
|
||||
bool word_gap_ctrl;
|
||||
bool cs_hold_ctrl;
|
||||
bool cs_setup_extend_ctrl;
|
||||
};
|
||||
|
||||
struct spisg_device {
|
||||
struct spi_controller *controller;
|
||||
struct platform_device *pdev;
|
||||
|
|
@ -152,6 +165,7 @@ struct spisg_device {
|
|||
struct clk *sclk;
|
||||
struct clk_div_table *tbl;
|
||||
struct completion completion;
|
||||
const struct aml_spisg_data *data;
|
||||
u32 status;
|
||||
u32 speed_hz;
|
||||
u32 effective_speed_hz;
|
||||
|
|
@ -175,7 +189,7 @@ static int spi_delay_to_sclk(u32 slck_speed_hz, struct spi_delay *delay)
|
|||
if (ns < 0)
|
||||
return 0;
|
||||
|
||||
return DIV_ROUND_UP_ULL(slck_speed_hz * ns, NSEC_PER_SEC);
|
||||
return DIV_ROUND_UP_ULL((u64)slck_speed_hz * ns, NSEC_PER_SEC);
|
||||
}
|
||||
|
||||
static inline u32 aml_spisg_sem_down_read(struct spisg_device *spisg)
|
||||
|
|
@ -424,7 +438,8 @@ static void aml_spisg_setup_null_desc(struct spisg_device *spisg,
|
|||
static void aml_spisg_pending(struct spisg_device *spisg,
|
||||
dma_addr_t desc_paddr,
|
||||
bool trig,
|
||||
bool irq_en)
|
||||
bool irq_en,
|
||||
u32 delay)
|
||||
{
|
||||
u32 desc_l, desc_h, cfg_spi, irq_enable;
|
||||
|
||||
|
|
@ -437,6 +452,13 @@ static void aml_spisg_pending(struct spisg_device *spisg,
|
|||
#endif
|
||||
|
||||
cfg_spi = spisg->cfg_spi;
|
||||
|
||||
if (spisg->data && spisg->data->word_gap_ctrl) {
|
||||
if (delay > 3)
|
||||
delay = 3;
|
||||
cfg_spi |= FIELD_PREP(CFG_WORD_GAP, delay);
|
||||
}
|
||||
|
||||
if (trig)
|
||||
cfg_spi |= CFG_HW_POS;
|
||||
else
|
||||
|
|
@ -483,13 +505,16 @@ static int aml_spisg_transfer_one_message(struct spi_controller *ctlr,
|
|||
{
|
||||
struct spisg_device *spisg = spi_controller_get_devdata(ctlr);
|
||||
struct device *dev = &spisg->pdev->dev;
|
||||
const struct aml_spisg_data *data = spisg->data;
|
||||
unsigned long long ms = 0;
|
||||
struct spi_transfer *xfer;
|
||||
struct spisg_descriptor *descs, *desc;
|
||||
struct spisg_descriptor_extra *exdescs, *exdesc;
|
||||
dma_addr_t descs_paddr;
|
||||
int desc_num = 1, descs_len;
|
||||
bool last_xfer_keep_ss = false;
|
||||
u32 cs_hold_in_sclk = 0;
|
||||
u32 val, delay = 0;
|
||||
int ret = -EIO;
|
||||
|
||||
if (!aml_spisg_sem_down_read(spisg)) {
|
||||
|
|
@ -523,15 +548,27 @@ static int aml_spisg_transfer_one_message(struct spi_controller *ctlr,
|
|||
goto end;
|
||||
}
|
||||
|
||||
/* calculate cs-setup delay with the first xfer speed */
|
||||
if (list_is_first(&xfer->transfer_list, &msg->transfers))
|
||||
desc->cfg_bus |= FIELD_PREP(CFG_CS_SETUP,
|
||||
spi_delay_to_sclk(xfer->effective_speed_hz, &msg->spi->cs_setup));
|
||||
/* calculate cs-setup delay with the first xfer speed and word dealy*/
|
||||
if (list_is_first(&xfer->transfer_list, &msg->transfers)) {
|
||||
val = spi_delay_to_sclk(xfer->effective_speed_hz, &msg->spi->cs_setup);
|
||||
if (data && data->cs_setup_extend_ctrl) {
|
||||
val = min_t(u32, 0xFF, val);
|
||||
desc->cfg_bus |= FIELD_PREP(CFG_CS_SETUP, val & 0xF);
|
||||
FIELD_MODIFY(CFG_CS_SETUP_EXTEND, &spisg->cfg_spi, val >> 4);
|
||||
} else {
|
||||
val = min_t(u32, 0xF, val);
|
||||
desc->cfg_bus |= FIELD_PREP(CFG_CS_SETUP, val);
|
||||
}
|
||||
|
||||
delay = spi_delay_to_sclk(xfer->effective_speed_hz, &msg->spi->word_delay);
|
||||
}
|
||||
|
||||
/* calculate cs-hold delay with the last xfer speed */
|
||||
if (list_is_last(&xfer->transfer_list, &msg->transfers))
|
||||
if (list_is_last(&xfer->transfer_list, &msg->transfers)) {
|
||||
cs_hold_in_sclk =
|
||||
spi_delay_to_sclk(xfer->effective_speed_hz, &msg->spi->cs_hold);
|
||||
last_xfer_keep_ss = xfer->cs_change;
|
||||
}
|
||||
|
||||
desc++;
|
||||
exdesc++;
|
||||
|
|
@ -539,13 +576,23 @@ static int aml_spisg_transfer_one_message(struct spi_controller *ctlr,
|
|||
xfer->effective_speed_hz);
|
||||
}
|
||||
|
||||
if (cs_hold_in_sclk)
|
||||
if (data && data->cs_hold_ctrl) {
|
||||
cs_hold_in_sclk = cs_hold_in_sclk ? : 1;
|
||||
val = cs_hold_in_sclk * (FIELD_GET(CFG_CLK_DIV, spisg->cfg_bus) + 1);
|
||||
val = min_t(u32, 0x7FFF, val);
|
||||
FIELD_MODIFY(CFG_CS_HOLD, &spisg->cfg_spi, val);
|
||||
desc--;
|
||||
} else if (cs_hold_in_sclk) {
|
||||
/* additional null-descriptor to achieve the cs-hold delay */
|
||||
aml_spisg_setup_null_desc(spisg, desc, cs_hold_in_sclk);
|
||||
else
|
||||
desc--;
|
||||
desc->cfg_bus |= FIELD_PREP(CFG_KEEP_SS, 1);
|
||||
desc++;
|
||||
} else {
|
||||
desc--;
|
||||
}
|
||||
|
||||
desc->cfg_bus |= FIELD_PREP(CFG_KEEP_SS, 0);
|
||||
FIELD_MODIFY(CFG_KEEP_SS, &desc->cfg_bus, last_xfer_keep_ss);
|
||||
desc->cfg_start |= FIELD_PREP(CFG_EOC, 1);
|
||||
|
||||
/* some tolerances */
|
||||
|
|
@ -562,13 +609,16 @@ static int aml_spisg_transfer_one_message(struct spi_controller *ctlr,
|
|||
}
|
||||
|
||||
reinit_completion(&spisg->completion);
|
||||
aml_spisg_pending(spisg, descs_paddr, false, true);
|
||||
aml_spisg_pending(spisg, descs_paddr, false, true, delay);
|
||||
if (wait_for_completion_timeout(&spisg->completion,
|
||||
spi_controller_is_target(spisg->controller) ?
|
||||
MAX_SCHEDULE_TIMEOUT : msecs_to_jiffies(ms)))
|
||||
MAX_SCHEDULE_TIMEOUT : msecs_to_jiffies(ms))) {
|
||||
ret = spisg->status ? -EIO : 0;
|
||||
else
|
||||
} else {
|
||||
/* stop transfer */
|
||||
regmap_write(spisg->map, SPISG_REG_DESC_LIST_H, 0);
|
||||
ret = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
dma_unmap_single(dev, descs_paddr, descs_len, DMA_TO_DEVICE);
|
||||
end:
|
||||
|
|
@ -704,7 +754,9 @@ static int aml_spisg_clk_init(struct spisg_device *spisg, void __iomem *base)
|
|||
return PTR_ERR(spisg->sclk);
|
||||
}
|
||||
|
||||
clk_prepare_enable(spisg->sclk);
|
||||
ret = clk_prepare_enable(spisg->sclk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -715,6 +767,7 @@ static int aml_spisg_probe(struct platform_device *pdev)
|
|||
struct spisg_device *spisg;
|
||||
struct device *dev = &pdev->dev;
|
||||
void __iomem *base;
|
||||
u32 val = 0;
|
||||
int ret, irq;
|
||||
|
||||
const struct regmap_config aml_regmap_config = {
|
||||
|
|
@ -733,6 +786,7 @@ static int aml_spisg_probe(struct platform_device *pdev)
|
|||
|
||||
spisg = spi_controller_get_devdata(ctlr);
|
||||
spisg->controller = ctlr;
|
||||
spisg->data = (struct aml_spisg_data *)of_device_get_match_data(dev);
|
||||
|
||||
spisg->pdev = pdev;
|
||||
platform_set_drvdata(pdev, spisg);
|
||||
|
|
@ -763,6 +817,14 @@ static int aml_spisg_probe(struct platform_device *pdev)
|
|||
|
||||
spisg->cfg_spi = FIELD_PREP(CFG_SFLASH_WP, 1) |
|
||||
FIELD_PREP(CFG_SFLASH_HD, 1);
|
||||
|
||||
if (spisg->data && spisg->data->mo_idle_output_ctrl) {
|
||||
if (!of_property_read_u32(dev->of_node, "amlogic,mo-idle-output", &val))
|
||||
spisg->cfg_spi |= FIELD_PREP(CFG_MO_IDLE_OUTPUT, val);
|
||||
else
|
||||
spisg->cfg_spi |= FIELD_PREP(CFG_MO_IDLE_OUTPUT, 0);
|
||||
}
|
||||
|
||||
if (spi_controller_is_target(ctlr)) {
|
||||
spisg->cfg_spi |= FIELD_PREP(CFG_SLAVE_EN, 1);
|
||||
spisg->cfg_bus = FIELD_PREP(CFG_TX_TUNING, 0xf);
|
||||
|
|
@ -841,14 +903,30 @@ static int spisg_suspend_runtime(struct device *dev)
|
|||
static int spisg_resume_runtime(struct device *dev)
|
||||
{
|
||||
struct spisg_device *spisg = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(spisg->core);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(spisg->sclk);
|
||||
if (ret) {
|
||||
clk_disable_unprepare(spisg->core);
|
||||
return ret;
|
||||
}
|
||||
|
||||
clk_prepare_enable(spisg->core);
|
||||
clk_prepare_enable(spisg->sclk);
|
||||
pinctrl_pm_select_default_state(&spisg->pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct aml_spisg_data a9_spisg_data = {
|
||||
.mo_idle_output_ctrl = true,
|
||||
.word_gap_ctrl = true,
|
||||
.cs_hold_ctrl = true,
|
||||
.cs_setup_extend_ctrl = true,
|
||||
};
|
||||
|
||||
static const struct dev_pm_ops amlogic_spisg_pm_ops = {
|
||||
.runtime_suspend = spisg_suspend_runtime,
|
||||
.runtime_resume = spisg_resume_runtime,
|
||||
|
|
@ -858,6 +936,10 @@ static const struct of_device_id amlogic_spisg_of_match[] = {
|
|||
{
|
||||
.compatible = "amlogic,a4-spisg",
|
||||
},
|
||||
{
|
||||
.compatible = "amlogic,a9-spisg",
|
||||
.data = &a9_spisg_data,
|
||||
},
|
||||
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -197,23 +197,13 @@ static int ar934x_spi_probe(struct platform_device *pdev)
|
|||
SPI_BPW_MASK(16) | SPI_BPW_MASK(8);
|
||||
ctlr->num_chipselect = 3;
|
||||
|
||||
dev_set_drvdata(&pdev->dev, ctlr);
|
||||
|
||||
sp = spi_controller_get_devdata(ctlr);
|
||||
sp->base = base;
|
||||
sp->clk = clk;
|
||||
sp->clk_freq = clk_get_rate(clk);
|
||||
sp->ctlr = ctlr;
|
||||
|
||||
return spi_register_controller(ctlr);
|
||||
}
|
||||
|
||||
static void ar934x_spi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_controller *ctlr;
|
||||
|
||||
ctlr = dev_get_drvdata(&pdev->dev);
|
||||
spi_unregister_controller(ctlr);
|
||||
return devm_spi_register_controller(&pdev->dev, ctlr);
|
||||
}
|
||||
|
||||
static struct platform_driver ar934x_spi_driver = {
|
||||
|
|
@ -222,7 +212,6 @@ static struct platform_driver ar934x_spi_driver = {
|
|||
.of_match_table = ar934x_spi_match,
|
||||
},
|
||||
.probe = ar934x_spi_probe,
|
||||
.remove = ar934x_spi_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(ar934x_spi_driver);
|
||||
|
|
|
|||
|
|
@ -239,8 +239,8 @@ static int at91_usart_spi_dma_transfer(struct spi_controller *ctlr,
|
|||
if (dma_submit_error(cookie))
|
||||
goto at91_usart_spi_err_dma;
|
||||
|
||||
rxchan->device->device_issue_pending(rxchan);
|
||||
txchan->device->device_issue_pending(txchan);
|
||||
dma_async_issue_pending(rxchan);
|
||||
dma_async_issue_pending(txchan);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -877,8 +877,8 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_controller *host,
|
|||
cookie = txdesc->tx_submit(txdesc);
|
||||
if (dma_submit_error(cookie))
|
||||
goto err_dma;
|
||||
rxchan->device->device_issue_pending(rxchan);
|
||||
txchan->device->device_issue_pending(txchan);
|
||||
dma_async_issue_pending(rxchan);
|
||||
dma_async_issue_pending(txchan);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -527,7 +527,7 @@ static void bcm2835_spi_transfer_prologue(struct spi_controller *ctlr,
|
|||
| BCM2835_SPI_CS_CLEAR_TX
|
||||
| BCM2835_SPI_CS_DONE);
|
||||
|
||||
dma_sync_single_for_device(ctlr->dma_rx->device->dev,
|
||||
dma_sync_single_for_device(dmaengine_get_dma_device(ctlr->dma_rx),
|
||||
sg_dma_address(&tfr->rx_sg.sgl[0]),
|
||||
bs->rx_prologue, DMA_FROM_DEVICE);
|
||||
|
||||
|
|
@ -871,7 +871,7 @@ static void bcm2835_dma_release(struct spi_controller *ctlr,
|
|||
dmaengine_desc_free(bs->fill_tx_desc);
|
||||
|
||||
if (bs->fill_tx_addr)
|
||||
dma_unmap_page_attrs(ctlr->dma_tx->device->dev,
|
||||
dma_unmap_page_attrs(dmaengine_get_dma_device(ctlr->dma_tx),
|
||||
bs->fill_tx_addr, sizeof(u32),
|
||||
DMA_TO_DEVICE,
|
||||
DMA_ATTR_SKIP_CPU_SYNC);
|
||||
|
|
@ -891,6 +891,7 @@ static int bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev,
|
|||
struct bcm2835_spi *bs)
|
||||
{
|
||||
struct dma_slave_config slave_config;
|
||||
struct device *tx_dma_dev;
|
||||
const __be32 *addr;
|
||||
dma_addr_t dma_reg_base;
|
||||
int ret;
|
||||
|
|
@ -932,11 +933,13 @@ static int bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev,
|
|||
if (ret)
|
||||
goto err_config;
|
||||
|
||||
bs->fill_tx_addr = dma_map_page_attrs(ctlr->dma_tx->device->dev,
|
||||
tx_dma_dev = dmaengine_get_dma_device(ctlr->dma_tx);
|
||||
|
||||
bs->fill_tx_addr = dma_map_page_attrs(tx_dma_dev,
|
||||
ZERO_PAGE(0), 0, sizeof(u32),
|
||||
DMA_TO_DEVICE,
|
||||
DMA_ATTR_SKIP_CPU_SYNC);
|
||||
if (dma_mapping_error(ctlr->dma_tx->device->dev, bs->fill_tx_addr)) {
|
||||
if (dma_mapping_error(tx_dma_dev, bs->fill_tx_addr)) {
|
||||
dev_err(dev, "cannot map zero page - not using DMA mode\n");
|
||||
bs->fill_tx_addr = 0;
|
||||
ret = -ENOMEM;
|
||||
|
|
@ -1157,7 +1160,7 @@ static void bcm2835_spi_cleanup(struct spi_device *spi)
|
|||
dmaengine_desc_free(target->clear_rx_desc);
|
||||
|
||||
if (target->clear_rx_addr)
|
||||
dma_unmap_single(ctlr->dma_rx->device->dev,
|
||||
dma_unmap_single(dmaengine_get_dma_device(ctlr->dma_rx),
|
||||
target->clear_rx_addr,
|
||||
sizeof(u32),
|
||||
DMA_TO_DEVICE);
|
||||
|
|
@ -1174,16 +1177,16 @@ static int bcm2835_spi_setup_dma(struct spi_controller *ctlr,
|
|||
struct bcm2835_spi *bs,
|
||||
struct bcm2835_spidev *target)
|
||||
{
|
||||
struct device *rx_dev;
|
||||
int ret;
|
||||
|
||||
if (!ctlr->dma_rx)
|
||||
return 0;
|
||||
|
||||
target->clear_rx_addr = dma_map_single(ctlr->dma_rx->device->dev,
|
||||
&target->clear_rx_cs,
|
||||
sizeof(u32),
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(ctlr->dma_rx->device->dev, target->clear_rx_addr)) {
|
||||
rx_dev = dmaengine_get_dma_device(ctlr->dma_rx);
|
||||
target->clear_rx_addr = dma_map_single(rx_dev, &target->clear_rx_cs,
|
||||
sizeof(u32), DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(rx_dev, target->clear_rx_addr)) {
|
||||
dev_err(&spi->dev, "cannot map clear_rx_cs\n");
|
||||
target->clear_rx_addr = 0;
|
||||
return -ENOMEM;
|
||||
|
|
@ -1268,7 +1271,7 @@ static int bcm2835_spi_setup(struct spi_device *spi)
|
|||
target->clear_rx_cs = cs | BCM2835_SPI_CS_TA |
|
||||
BCM2835_SPI_CS_DMAEN |
|
||||
BCM2835_SPI_CS_CLEAR_RX;
|
||||
dma_sync_single_for_device(ctlr->dma_rx->device->dev,
|
||||
dma_sync_single_for_device(dmaengine_get_dma_device(ctlr->dma_rx),
|
||||
target->clear_rx_addr,
|
||||
sizeof(u32),
|
||||
DMA_TO_DEVICE);
|
||||
|
|
@ -1297,7 +1300,9 @@ static int bcm2835_spi_setup(struct spi_device *spi)
|
|||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(pinctrl_compats); i++) {
|
||||
if (of_find_compatible_node(NULL, NULL, pinctrl_compats[i]))
|
||||
struct device_node *np __free(device_node) =
|
||||
of_find_compatible_node(NULL, NULL, pinctrl_compats[i]);
|
||||
if (np)
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -413,7 +413,7 @@ static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id)
|
|||
struct bcm63xx_spi *bs = spi_controller_get_devdata(host);
|
||||
u8 intr;
|
||||
|
||||
/* Read interupts and clear them immediately */
|
||||
/* Read interrupts and clear them immediately */
|
||||
intr = bcm_spi_readb(bs, SPI_INT_STATUS);
|
||||
bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
|
||||
bcm_spi_writeb(bs, 0, SPI_INT_MASK);
|
||||
|
|
|
|||
|
|
@ -1381,7 +1381,7 @@ static int cqspi_direct_read_execute(struct cqspi_flash_pdata *f_pdata,
|
|||
return 0;
|
||||
}
|
||||
|
||||
ddev = cqspi->rx_chan->device->dev;
|
||||
ddev = dmaengine_get_dma_device(cqspi->rx_chan);
|
||||
dma_dst = dma_map_single(ddev, buf, len, DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(ddev, dma_dst)) {
|
||||
dev_err(dev, "dma mapping failed\n");
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ static irqreturn_t dw_spi_irq(int irq, void *dev_id)
|
|||
{
|
||||
struct spi_controller *ctlr = dev_id;
|
||||
struct dw_spi *dws = spi_controller_get_devdata(ctlr);
|
||||
u16 irq_status = dw_readl(dws, DW_SPI_ISR) & DW_SPI_INT_MASK;
|
||||
u16 irq_status = dw_readl(dws, DW_SPI_ISR);
|
||||
|
||||
if (!irq_status)
|
||||
return IRQ_NONE;
|
||||
|
|
@ -937,6 +937,15 @@ static void dw_spi_enh_write_cmd_addr(struct dw_spi *dws, const struct spi_mem_o
|
|||
|
||||
dw_spi_set_cs(mem->spi, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: The exact reason for this delay is not fully understood,
|
||||
* but empirical testing shows it significantly improves the stability
|
||||
* of read/write operations. Without this delay, occasional transfer
|
||||
* errors or timeouts may occur under certain conditions.
|
||||
* Keeping it as a safeguard based on practical validation.
|
||||
*/
|
||||
udelay(5);
|
||||
}
|
||||
|
||||
static int dw_spi_exec_enh_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||
|
|
@ -948,6 +957,8 @@ static int dw_spi_exec_enh_mem_op(struct spi_mem *mem, const struct spi_mem_op *
|
|||
unsigned long long ms;
|
||||
int ret;
|
||||
|
||||
dws->dma_mapped = false;
|
||||
|
||||
switch (op->data.buswidth) {
|
||||
case 0:
|
||||
case 1:
|
||||
|
|
@ -971,10 +982,13 @@ static int dw_spi_exec_enh_mem_op(struct spi_mem *mem, const struct spi_mem_op *
|
|||
cfg.dfs = 8;
|
||||
cfg.freq = clamp(op->max_freq, 0U, dws->max_mem_freq);
|
||||
cfg.ndf = op->data.nbytes;
|
||||
if (op->data.dir == SPI_MEM_DATA_IN)
|
||||
if (op->data.dir == SPI_MEM_DATA_IN) {
|
||||
cfg.tmode = DW_SPI_CTRLR0_TMOD_RO;
|
||||
else
|
||||
dws->tx_dir = false;
|
||||
} else {
|
||||
cfg.tmode = DW_SPI_CTRLR0_TMOD_TO;
|
||||
dws->tx_dir = true;
|
||||
}
|
||||
|
||||
if (op->data.buswidth == op->addr.buswidth &&
|
||||
op->data.buswidth == op->cmd.buswidth)
|
||||
|
|
@ -1010,47 +1024,61 @@ static int dw_spi_exec_enh_mem_op(struct spi_mem *mem, const struct spi_mem_op *
|
|||
}
|
||||
}
|
||||
|
||||
dw_spi_enh_write_cmd_addr(dws, op, mem);
|
||||
|
||||
/*
|
||||
* FIXME: The exact reason for this delay is not fully understood,
|
||||
* but empirical testing shows it significantly improves the stability
|
||||
* of read/write operations. Without this delay, occasional transfer
|
||||
* errors or timeouts may occur under certain conditions.
|
||||
* Keeping it as a safeguard based on practical validation.
|
||||
*/
|
||||
udelay(5);
|
||||
|
||||
dw_spi_enh_irq_setup(dws);
|
||||
|
||||
/* Use timeout calculation from spi_transfer_wait() */
|
||||
ms = 8LL * MSEC_PER_SEC * (dws->rx_len ? dws->rx_len : dws->tx_len);
|
||||
do_div(ms, dws->current_freq);
|
||||
|
||||
/*
|
||||
* Increase it twice and add 200 ms tolerance, use
|
||||
* predefined maximum in case of overflow.
|
||||
*/
|
||||
ms += ms + 200;
|
||||
if (ms > UINT_MAX)
|
||||
ms = UINT_MAX;
|
||||
|
||||
ms = wait_for_completion_timeout(&ctlr->xfer_completion,
|
||||
msecs_to_jiffies(ms));
|
||||
if (ms == 0) {
|
||||
dw_spi_mask_intr(dws, 0xff);
|
||||
synchronize_irq(dws->irq);
|
||||
dws->rx = NULL;
|
||||
dws->tx = NULL;
|
||||
dws->rx_len = 0;
|
||||
dws->tx_len = 0;
|
||||
dw_spi_stop_mem_op(dws, mem->spi);
|
||||
return -EIO;
|
||||
if (dws->dma_nr_chans && dws->dma_ops->dma_enh_mem_get_chan &&
|
||||
op->data.nbytes > dws->fifo_len) {
|
||||
ret = dws->dma_ops->dma_enh_mem_get_chan(ctlr->dev.parent, dws);
|
||||
if (ret) {
|
||||
/* fall back to the PIO/IRQ path */
|
||||
dev_dbg(&ctlr->dev, "DMA enh mem channel unavailable (%d)\n", ret);
|
||||
} else if (dws->dma_ops->can_dma_enh_mem(ctlr)) {
|
||||
ret = dws->dma_ops->dma_enh_mem_setup(dws);
|
||||
if (ret)
|
||||
dev_err(&ctlr->dev, "DMA enh mem setup failed (%d)\n", ret);
|
||||
else
|
||||
dws->dma_mapped = true;
|
||||
}
|
||||
}
|
||||
|
||||
ret = dw_spi_wait_mem_op_done(dws);
|
||||
if (dws->dma_mapped) {
|
||||
dw_spi_enh_write_cmd_addr(dws, op, mem);
|
||||
|
||||
dw_spi_stop_mem_op(dws, mem->spi);
|
||||
ret = dws->dma_ops->dma_enh_mem_transfer(mem, op);
|
||||
|
||||
dw_spi_stop_mem_op(dws, mem->spi);
|
||||
} else {
|
||||
dw_spi_enh_write_cmd_addr(dws, op, mem);
|
||||
|
||||
dw_spi_enh_irq_setup(dws);
|
||||
|
||||
/* Use timeout calculation from spi_transfer_wait() */
|
||||
ms = 8LL * MSEC_PER_SEC * (dws->rx_len ? dws->rx_len : dws->tx_len);
|
||||
do_div(ms, dws->current_freq);
|
||||
|
||||
/*
|
||||
* Increase it twice and add 200 ms tolerance, use
|
||||
* predefined maximum in case of overflow.
|
||||
*/
|
||||
ms += ms + 200;
|
||||
if (ms > UINT_MAX)
|
||||
ms = UINT_MAX;
|
||||
|
||||
ms = wait_for_completion_timeout(&ctlr->xfer_completion,
|
||||
msecs_to_jiffies(ms));
|
||||
if (ms == 0) {
|
||||
dw_spi_mask_intr(dws, 0xff);
|
||||
synchronize_irq(dws->irq);
|
||||
dws->rx = NULL;
|
||||
dws->tx = NULL;
|
||||
dws->rx_len = 0;
|
||||
dws->tx_len = 0;
|
||||
dw_spi_stop_mem_op(dws, mem->spi);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = dw_spi_wait_mem_op_done(dws);
|
||||
|
||||
dw_spi_stop_mem_op(dws, mem->spi);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1104,12 +1132,13 @@ static int dw_spi_setup(struct spi_device *spi)
|
|||
if (!chip)
|
||||
return -ENOMEM;
|
||||
spi_set_ctldata(spi, chip);
|
||||
/* Get specific / default rx-sample-delay */
|
||||
if (device_property_read_u32(&spi->dev,
|
||||
"rx-sample-delay-ns",
|
||||
&rx_sample_dly_ns) != 0)
|
||||
/* Use default controller value */
|
||||
rx_sample_dly_ns = dws->def_rx_sample_dly_ns;
|
||||
/*
|
||||
* Use the per-device value the core parsed from the peripheral
|
||||
* node, and fall back to the controller-wide default when the
|
||||
* device does not ask for a delay of its own.
|
||||
*/
|
||||
rx_sample_dly_ns = spi->rx_sample_delay_ns ?:
|
||||
dws->def_rx_sample_dly_ns;
|
||||
chip->rx_sample_dly = DIV_ROUND_CLOSEST(rx_sample_dly_ns,
|
||||
NSEC_PER_SEC /
|
||||
dws->max_freq);
|
||||
|
|
@ -1360,6 +1389,9 @@ int dw_spi_add_controller(struct device *dev, struct dw_spi *dws)
|
|||
goto err_free_irq;
|
||||
} else if (ret) {
|
||||
dev_warn(dev, "DMA init failed\n");
|
||||
} else if (dws->dma_nr_chans == 1) {
|
||||
/* Full-duplex DMA transfers need both channels */
|
||||
dev_info(dev, "Single DMA channel, full-duplex DMA disabled\n");
|
||||
} else {
|
||||
ctlr->can_dma = dws->dma_ops->can_dma;
|
||||
ctlr->flags |= SPI_CONTROLLER_MUST_TX;
|
||||
|
|
|
|||
|
|
@ -42,14 +42,19 @@ static void dw_spi_dma_maxburst_init(struct dw_spi *dws)
|
|||
|
||||
def_burst = dws->fifo_len / 2;
|
||||
|
||||
ret = dma_get_slave_caps(dws->rxchan, &caps);
|
||||
if (!ret && caps.max_burst)
|
||||
max_burst = caps.max_burst;
|
||||
else
|
||||
max_burst = DW_SPI_RX_BURST_LEVEL;
|
||||
if (dws->rxchan) {
|
||||
ret = dma_get_slave_caps(dws->rxchan, &caps);
|
||||
if (!ret && caps.max_burst)
|
||||
max_burst = caps.max_burst;
|
||||
else
|
||||
max_burst = DW_SPI_RX_BURST_LEVEL;
|
||||
|
||||
dws->rxburst = min(max_burst, def_burst);
|
||||
dw_writel(dws, DW_SPI_DMARDLR, dws->rxburst - 1);
|
||||
dws->rxburst = min(max_burst, def_burst);
|
||||
dw_writel(dws, DW_SPI_DMARDLR, dws->rxburst - 1);
|
||||
}
|
||||
|
||||
if (!dws->txchan)
|
||||
return;
|
||||
|
||||
ret = dma_get_slave_caps(dws->txchan, &caps);
|
||||
if (!ret && caps.max_burst)
|
||||
|
|
@ -74,20 +79,39 @@ static void dw_spi_dma_maxburst_init(struct dw_spi *dws)
|
|||
|
||||
static int dw_spi_dma_caps_init(struct dw_spi *dws)
|
||||
{
|
||||
struct dma_slave_caps tx, rx;
|
||||
struct dma_slave_caps tx = {}, rx = {};
|
||||
int ret;
|
||||
|
||||
ret = dma_get_slave_caps(dws->txchan, &tx);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (dws->txchan) {
|
||||
ret = dma_get_slave_caps(dws->txchan, &tx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = dma_get_slave_caps(dws->rxchan, &rx);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!(tx.directions & BIT(DMA_MEM_TO_DEV)))
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
if (!(tx.directions & BIT(DMA_MEM_TO_DEV) &&
|
||||
rx.directions & BIT(DMA_DEV_TO_MEM)))
|
||||
return -ENXIO;
|
||||
if (dws->rxchan) {
|
||||
ret = dma_get_slave_caps(dws->rxchan, &rx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!(rx.directions & BIT(DMA_DEV_TO_MEM)))
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/* With a single channel only one direction is available at a time */
|
||||
if (!dws->rxchan) {
|
||||
dws->dma_sg_burst = tx.max_sg_burst;
|
||||
dws->dma_addr_widths = tx.dst_addr_widths;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dws->txchan) {
|
||||
dws->dma_sg_burst = rx.max_sg_burst;
|
||||
dws->dma_addr_widths = rx.src_addr_widths;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tx.max_sg_burst > 0 && rx.max_sg_burst > 0)
|
||||
dws->dma_sg_burst = min(tx.max_sg_burst, rx.max_sg_burst);
|
||||
|
|
@ -169,40 +193,54 @@ static int dw_spi_dma_init_generic(struct device *dev, struct dw_spi *dws)
|
|||
{
|
||||
int ret;
|
||||
|
||||
dws->dma_nr_chans = 0;
|
||||
|
||||
dws->rxchan = dma_request_chan(dev, "rx");
|
||||
if (IS_ERR(dws->rxchan)) {
|
||||
ret = PTR_ERR(dws->rxchan);
|
||||
dws->rxchan = NULL;
|
||||
goto err_exit;
|
||||
}
|
||||
dws->dma_nr_chans++;
|
||||
|
||||
/*
|
||||
* Some platforms have only one DMA channel for the controller. Keep
|
||||
* the Rx channel in that case, it can still serve half-duplex
|
||||
* transfers.
|
||||
*/
|
||||
dws->txchan = dma_request_chan(dev, "tx");
|
||||
if (IS_ERR(dws->txchan)) {
|
||||
ret = PTR_ERR(dws->txchan);
|
||||
dws->txchan = NULL;
|
||||
goto free_rxchan;
|
||||
if (ret == -EPROBE_DEFER)
|
||||
goto free_rxchan;
|
||||
} else {
|
||||
dws->dma_nr_chans++;
|
||||
}
|
||||
|
||||
dws->ctlr->dma_rx = dws->rxchan;
|
||||
dws->ctlr->dma_tx = dws->txchan;
|
||||
|
||||
init_completion(&dws->dma_completion);
|
||||
|
||||
ret = dw_spi_dma_caps_init(dws);
|
||||
if (ret)
|
||||
goto free_txchan;
|
||||
|
||||
dw_spi_dma_maxburst_init(dws);
|
||||
|
||||
init_completion(&dws->dma_completion);
|
||||
|
||||
dws->ctlr->dma_rx = dws->rxchan;
|
||||
dws->ctlr->dma_tx = dws->txchan;
|
||||
|
||||
return 0;
|
||||
|
||||
free_txchan:
|
||||
dma_release_channel(dws->txchan);
|
||||
dws->txchan = NULL;
|
||||
if (dws->txchan) {
|
||||
dma_release_channel(dws->txchan);
|
||||
dws->txchan = NULL;
|
||||
}
|
||||
free_rxchan:
|
||||
dma_release_channel(dws->rxchan);
|
||||
dws->rxchan = NULL;
|
||||
err_exit:
|
||||
dws->dma_nr_chans = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -286,19 +324,27 @@ static inline bool dw_spi_dma_tx_busy(struct dw_spi *dws)
|
|||
(DW_SPI_SR_BUSY | DW_SPI_SR_TF_EMPT)) != DW_SPI_SR_TF_EMPT;
|
||||
}
|
||||
|
||||
static int dw_spi_dma_wait_tx_done(struct dw_spi *dws,
|
||||
struct spi_transfer *xfer)
|
||||
static int dw_spi_dma_wait_tx_done(struct dw_spi *dws, u32 speed_hz)
|
||||
{
|
||||
int retry = DW_SPI_WAIT_RETRIES;
|
||||
struct spi_delay delay;
|
||||
unsigned long ns, us;
|
||||
u32 nents;
|
||||
|
||||
nents = dw_readl(dws, DW_SPI_TXFLR);
|
||||
delay.unit = SPI_DELAY_UNIT_SCK;
|
||||
delay.value = nents * dws->n_bytes * BITS_PER_BYTE;
|
||||
ns = DIV_ROUND_UP(NSEC_PER_SEC, speed_hz) * nents *
|
||||
dws->n_bytes * BITS_PER_BYTE;
|
||||
if (ns <= NSEC_PER_USEC) {
|
||||
delay.unit = SPI_DELAY_UNIT_NSECS;
|
||||
delay.value = ns;
|
||||
} else {
|
||||
us = DIV_ROUND_UP(ns, NSEC_PER_USEC);
|
||||
delay.unit = SPI_DELAY_UNIT_USECS;
|
||||
delay.value = clamp_val(us, 0, USHRT_MAX);
|
||||
}
|
||||
|
||||
while (dw_spi_dma_tx_busy(dws) && retry--)
|
||||
spi_delay_exec(&delay, xfer);
|
||||
spi_delay_exec(&delay, NULL);
|
||||
|
||||
if (retry < 0) {
|
||||
dev_err(&dws->ctlr->dev, "Tx hanged up\n");
|
||||
|
|
@ -659,7 +705,7 @@ static int dw_spi_dma_transfer(struct dw_spi *dws, struct spi_transfer *xfer)
|
|||
return ret;
|
||||
|
||||
if (dws->ctlr->cur_msg->status == -EINPROGRESS) {
|
||||
ret = dw_spi_dma_wait_tx_done(dws, xfer);
|
||||
ret = dw_spi_dma_wait_tx_done(dws, xfer->effective_speed_hz);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -682,6 +728,183 @@ static void dw_spi_dma_stop(struct dw_spi *dws)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The enhanced SPI memory operations are half-duplex, so a single DMA channel
|
||||
* is enough for them. On a platform with only one channel, the channel is
|
||||
* bound to a direction by its "tx"/"rx" DMA specifier, and whichever channel
|
||||
* is currently held tells which direction it serves. Keep it across
|
||||
* operations and swap it only when the transfer direction changes.
|
||||
*/
|
||||
static int dw_spi_enh_mem_dma_get_chan(struct device *dev, struct dw_spi *dws)
|
||||
{
|
||||
struct dma_chan **chan, **other;
|
||||
const char *name;
|
||||
int ret;
|
||||
|
||||
if (dws->dma_nr_chans == 2)
|
||||
return 0;
|
||||
|
||||
if (dws->tx_dir) {
|
||||
chan = &dws->txchan;
|
||||
other = &dws->rxchan;
|
||||
name = "tx";
|
||||
} else {
|
||||
chan = &dws->rxchan;
|
||||
other = &dws->txchan;
|
||||
name = "rx";
|
||||
}
|
||||
|
||||
if (*chan)
|
||||
return 0;
|
||||
|
||||
dws->ctlr->dma_tx = NULL;
|
||||
dws->ctlr->dma_rx = NULL;
|
||||
|
||||
/*
|
||||
* With a single physical channel, the held channel must be released
|
||||
* before it can be requested again with the handshake of the other
|
||||
* direction. On failure both stay NULL, and the next operation
|
||||
* retries the request and falls back to PIO meanwhile.
|
||||
*/
|
||||
|
||||
if (*other) {
|
||||
dma_release_channel(*other);
|
||||
*other = NULL;
|
||||
}
|
||||
|
||||
*chan = dma_request_chan(dev, name);
|
||||
if (IS_ERR(*chan)) {
|
||||
ret = PTR_ERR(*chan);
|
||||
*chan = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dw_spi_dma_caps_init(dws);
|
||||
if (ret) {
|
||||
dma_release_channel(*chan);
|
||||
*chan = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
dw_spi_dma_maxburst_init(dws);
|
||||
|
||||
dws->ctlr->dma_tx = dws->txchan;
|
||||
dws->ctlr->dma_rx = dws->rxchan;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw_spi_enh_mem_dma_setup(struct dw_spi *dws)
|
||||
{
|
||||
u16 dma_ctrl, level;
|
||||
int ret;
|
||||
|
||||
/* Setup DMA channels */
|
||||
if (dws->tx_dir) {
|
||||
ret = dw_spi_dma_config_tx(dws);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dma_ctrl = DW_SPI_DMACR_TDMAE;
|
||||
} else {
|
||||
ret = dw_spi_dma_config_rx(dws);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dma_ctrl = DW_SPI_DMACR_RDMAE;
|
||||
}
|
||||
|
||||
dw_writel(dws, DW_SPI_DMACR, dma_ctrl);
|
||||
|
||||
/* Clear stale error status, it is checked after the transfer */
|
||||
dw_readl(dws, DW_SPI_ICR);
|
||||
|
||||
reinit_completion(&dws->dma_completion);
|
||||
|
||||
level = min_t(unsigned int, dws->fifo_len / 2, dws->tx_len);
|
||||
dw_writel(dws, DW_SPI_TXFTLR, level);
|
||||
|
||||
level = min_t(unsigned int, dws->fifo_len / 2, dws->rx_len);
|
||||
dw_writel(dws, DW_SPI_RXFTLR, level ? level - 1 : 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool dw_spi_enh_mem_can_dma(struct spi_controller *ctlr)
|
||||
{
|
||||
struct dw_spi *dws = spi_controller_get_devdata(ctlr);
|
||||
unsigned int len = dws->tx_dir ? dws->tx_len : dws->rx_len;
|
||||
enum dma_slave_buswidth dma_bus_width;
|
||||
|
||||
if (len <= dws->fifo_len)
|
||||
return false;
|
||||
|
||||
dma_bus_width = dw_spi_dma_convert_width(dws->n_bytes);
|
||||
|
||||
return dws->dma_addr_widths & BIT(dma_bus_width);
|
||||
}
|
||||
|
||||
static void dw_spi_enh_mem_dma_stop(struct dw_spi *dws)
|
||||
{
|
||||
if (dws->tx_dir) {
|
||||
if (test_bit(DW_SPI_TX_BUSY, &dws->dma_chan_busy)) {
|
||||
dmaengine_terminate_sync(dws->txchan);
|
||||
clear_bit(DW_SPI_TX_BUSY, &dws->dma_chan_busy);
|
||||
}
|
||||
} else {
|
||||
if (test_bit(DW_SPI_RX_BUSY, &dws->dma_chan_busy)) {
|
||||
dmaengine_terminate_sync(dws->rxchan);
|
||||
clear_bit(DW_SPI_RX_BUSY, &dws->dma_chan_busy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int dw_spi_enh_mem_dma_transfer(struct spi_mem *mem, const struct spi_mem_op *op)
|
||||
{
|
||||
struct spi_controller *ctlr = mem->spi->controller;
|
||||
struct dw_spi *dws = spi_controller_get_devdata(ctlr);
|
||||
struct sg_table sgt;
|
||||
int ret;
|
||||
|
||||
ret = spi_controller_dma_map_mem_op_data(ctlr, op, &sgt);
|
||||
if (ret)
|
||||
goto out_clear_dmac;
|
||||
|
||||
if (dws->tx_dir) {
|
||||
ret = dw_spi_dma_submit_tx(dws, sgt.sgl, sgt.nents);
|
||||
if (ret)
|
||||
goto out_unmap;
|
||||
|
||||
dma_async_issue_pending(dws->txchan);
|
||||
|
||||
ret = dw_spi_dma_wait(dws, dws->tx_len, dws->current_freq);
|
||||
if (!ret)
|
||||
ret = dw_spi_dma_wait_tx_done(dws, dws->current_freq);
|
||||
} else {
|
||||
ret = dw_spi_dma_submit_rx(dws, sgt.sgl, sgt.nents);
|
||||
if (ret)
|
||||
goto out_unmap;
|
||||
|
||||
dma_async_issue_pending(dws->rxchan);
|
||||
|
||||
ret = dw_spi_dma_wait(dws, dws->rx_len, dws->current_freq);
|
||||
if (!ret)
|
||||
ret = dw_spi_dma_wait_rx_done(dws);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
dw_spi_enh_mem_dma_stop(dws);
|
||||
else
|
||||
ret = dw_spi_check_status(dws, true);
|
||||
|
||||
out_unmap:
|
||||
spi_controller_dma_unmap_mem_op_data(ctlr, op, &sgt);
|
||||
out_clear_dmac:
|
||||
dw_writel(dws, DW_SPI_DMACR, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct dw_spi_dma_ops dw_spi_dma_mfld_ops = {
|
||||
.dma_init = dw_spi_dma_init_mfld,
|
||||
.dma_exit = dw_spi_dma_exit,
|
||||
|
|
@ -704,6 +927,11 @@ static const struct dw_spi_dma_ops dw_spi_dma_generic_ops = {
|
|||
.can_dma = dw_spi_can_dma,
|
||||
.dma_transfer = dw_spi_dma_transfer,
|
||||
.dma_stop = dw_spi_dma_stop,
|
||||
|
||||
.dma_enh_mem_get_chan = dw_spi_enh_mem_dma_get_chan,
|
||||
.dma_enh_mem_setup = dw_spi_enh_mem_dma_setup,
|
||||
.can_dma_enh_mem = dw_spi_enh_mem_can_dma,
|
||||
.dma_enh_mem_transfer = dw_spi_enh_mem_dma_transfer,
|
||||
};
|
||||
|
||||
void dw_spi_dma_setup_generic(struct dw_spi *dws)
|
||||
|
|
|
|||
|
|
@ -363,6 +363,8 @@ static int dw_spi_jhb100_init(struct platform_device *pdev,
|
|||
|
||||
dw_spi_jhb100_mask_intr(&dwsmmio->dws, 0xff);
|
||||
|
||||
dw_spi_dma_setup_generic(&dwsmmio->dws);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -183,6 +183,12 @@ struct dw_spi_dma_ops {
|
|||
struct spi_transfer *xfer);
|
||||
int (*dma_transfer)(struct dw_spi *dws, struct spi_transfer *xfer);
|
||||
void (*dma_stop)(struct dw_spi *dws);
|
||||
|
||||
/* enh mem dma ops */
|
||||
int (*dma_enh_mem_get_chan)(struct device *dev, struct dw_spi *dws);
|
||||
int (*dma_enh_mem_setup)(struct dw_spi *dws);
|
||||
bool (*can_dma_enh_mem)(struct spi_controller *ctlr);
|
||||
int (*dma_enh_mem_transfer)(struct spi_mem *mem, const struct spi_mem_op *op);
|
||||
};
|
||||
|
||||
struct dw_spi {
|
||||
|
|
@ -227,6 +233,8 @@ struct dw_spi {
|
|||
u32 txburst;
|
||||
struct dma_chan *rxchan;
|
||||
u32 rxburst;
|
||||
unsigned int dma_nr_chans;
|
||||
bool tx_dir;
|
||||
u32 dma_sg_burst;
|
||||
u32 dma_addr_widths;
|
||||
unsigned long dma_chan_busy;
|
||||
|
|
|
|||
|
|
@ -273,6 +273,7 @@ ep93xx_spi_dma_prepare(struct spi_controller *host,
|
|||
struct dma_async_tx_descriptor *txd;
|
||||
enum dma_slave_buswidth buswidth;
|
||||
struct dma_slave_config conf;
|
||||
struct device *dma_dev;
|
||||
struct scatterlist *sg;
|
||||
struct sg_table *sgt;
|
||||
struct dma_chan *chan;
|
||||
|
|
@ -348,14 +349,15 @@ ep93xx_spi_dma_prepare(struct spi_controller *host,
|
|||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
nents = dma_map_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
|
||||
dma_dev = dmaengine_get_dma_device(chan);
|
||||
nents = dma_map_sg(dma_dev, sgt->sgl, sgt->nents, dir);
|
||||
if (!nents)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
txd = dmaengine_prep_slave_sg(chan, sgt->sgl, nents, conf.direction,
|
||||
DMA_CTRL_ACK);
|
||||
if (!txd) {
|
||||
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
|
||||
dma_unmap_sg(dma_dev, sgt->sgl, sgt->nents, dir);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
return txd;
|
||||
|
|
@ -384,7 +386,7 @@ static void ep93xx_spi_dma_finish(struct spi_controller *host,
|
|||
sgt = &espi->tx_sgt;
|
||||
}
|
||||
|
||||
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
|
||||
dma_unmap_sg(dmaengine_get_dma_device(chan), sgt->sgl, sgt->nents, dir);
|
||||
}
|
||||
|
||||
static void ep93xx_spi_dma_callback(void *callback_param)
|
||||
|
|
|
|||
|
|
@ -670,6 +670,7 @@ static void dspi_dma_xfer(struct fsl_dspi *dspi)
|
|||
static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
|
||||
{
|
||||
struct device *dev = &dspi->pdev->dev;
|
||||
struct device *tx_dev, *rx_dev;
|
||||
struct dma_slave_config cfg;
|
||||
struct fsl_dspi_dma *dma;
|
||||
int ret;
|
||||
|
|
@ -688,20 +689,23 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
|
|||
goto err_tx_channel;
|
||||
}
|
||||
|
||||
tx_dev = dmaengine_get_dma_device(dma->chan_tx);
|
||||
rx_dev = dmaengine_get_dma_device(dma->chan_rx);
|
||||
|
||||
if (spi_controller_is_target(dspi->ctlr)) {
|
||||
/*
|
||||
* In target mode we have to be ready to receive the maximum
|
||||
* that can possibly be transferred at once by EDMA without any
|
||||
* FIFO underflows.
|
||||
*/
|
||||
dma->bufsize = min(dma_get_max_seg_size(dma->chan_rx->device->dev),
|
||||
dma_get_max_seg_size(dma->chan_tx->device->dev)) *
|
||||
dma->bufsize = min(dma_get_max_seg_size(rx_dev),
|
||||
dma_get_max_seg_size(tx_dev)) *
|
||||
DMA_SLAVE_BUSWIDTH_4_BYTES;
|
||||
} else {
|
||||
dma->bufsize = PAGE_SIZE;
|
||||
}
|
||||
|
||||
dma->tx_dma_buf = dma_alloc_noncoherent(dma->chan_tx->device->dev,
|
||||
dma->tx_dma_buf = dma_alloc_noncoherent(tx_dev,
|
||||
dma->bufsize, &dma->tx_dma_phys,
|
||||
DMA_TO_DEVICE, GFP_KERNEL);
|
||||
if (!dma->tx_dma_buf) {
|
||||
|
|
@ -709,7 +713,7 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
|
|||
goto err_tx_dma_buf;
|
||||
}
|
||||
|
||||
dma->rx_dma_buf = dma_alloc_noncoherent(dma->chan_rx->device->dev,
|
||||
dma->rx_dma_buf = dma_alloc_noncoherent(rx_dev,
|
||||
dma->bufsize, &dma->rx_dma_phys,
|
||||
DMA_FROM_DEVICE, GFP_KERNEL);
|
||||
if (!dma->rx_dma_buf) {
|
||||
|
|
@ -746,12 +750,11 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr)
|
|||
return 0;
|
||||
|
||||
err_slave_config:
|
||||
dma_free_noncoherent(dma->chan_rx->device->dev, dma->bufsize,
|
||||
dma->rx_dma_buf, dma->rx_dma_phys,
|
||||
DMA_FROM_DEVICE);
|
||||
dma_free_noncoherent(rx_dev, dma->bufsize, dma->rx_dma_buf,
|
||||
dma->rx_dma_phys, DMA_FROM_DEVICE);
|
||||
err_rx_dma_buf:
|
||||
dma_free_noncoherent(dma->chan_tx->device->dev, dma->bufsize,
|
||||
dma->tx_dma_buf, dma->tx_dma_phys, DMA_TO_DEVICE);
|
||||
dma_free_noncoherent(tx_dev, dma->bufsize, dma->tx_dma_buf,
|
||||
dma->tx_dma_phys, DMA_TO_DEVICE);
|
||||
err_tx_dma_buf:
|
||||
dma_release_channel(dma->chan_tx);
|
||||
err_tx_channel:
|
||||
|
|
@ -771,16 +774,18 @@ static void dspi_release_dma(struct fsl_dspi *dspi)
|
|||
return;
|
||||
|
||||
if (dma->chan_tx) {
|
||||
dma_free_noncoherent(dma->chan_tx->device->dev, dma->bufsize,
|
||||
dma->tx_dma_buf, dma->tx_dma_phys,
|
||||
DMA_TO_DEVICE);
|
||||
struct device *tx_dev = dmaengine_get_dma_device(dma->chan_tx);
|
||||
|
||||
dma_free_noncoherent(tx_dev, dma->bufsize, dma->tx_dma_buf,
|
||||
dma->tx_dma_phys, DMA_TO_DEVICE);
|
||||
dma_release_channel(dma->chan_tx);
|
||||
}
|
||||
|
||||
if (dma->chan_rx) {
|
||||
dma_free_noncoherent(dma->chan_rx->device->dev, dma->bufsize,
|
||||
dma->rx_dma_buf, dma->rx_dma_phys,
|
||||
DMA_FROM_DEVICE);
|
||||
struct device *rx_dev = dmaengine_get_dma_device(dma->chan_rx);
|
||||
|
||||
dma_free_noncoherent(rx_dev, dma->bufsize, dma->rx_dma_buf,
|
||||
dma->rx_dma_phys, DMA_FROM_DEVICE);
|
||||
dma_release_channel(dma->chan_rx);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,10 @@
|
|||
#include <linux/dma/qcom-gpi-dma.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/panic_notifier.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_opp.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
|
@ -115,6 +117,7 @@ struct spi_geni_master {
|
|||
struct dma_chan *rx;
|
||||
int cur_xfer_mode;
|
||||
const struct geni_spi_desc *dev_data;
|
||||
struct notifier_block panic_nb;
|
||||
};
|
||||
|
||||
static void spi_slv_setup(struct spi_geni_master *mas)
|
||||
|
|
@ -363,8 +366,8 @@ static int geni_spi_set_clock_and_bw(struct geni_se *se,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int setup_fifo_params(struct spi_device *spi_slv,
|
||||
struct spi_controller *spi)
|
||||
static void setup_spi_params(struct spi_device *spi_slv,
|
||||
struct spi_controller *spi)
|
||||
{
|
||||
struct spi_geni_master *mas = spi_controller_get_devdata(spi);
|
||||
struct geni_se *se = &mas->se;
|
||||
|
|
@ -390,8 +393,6 @@ static int setup_fifo_params(struct spi_device *spi_slv,
|
|||
|
||||
trace_geni_spi_setup_params(mas->dev, chipselect, spi_slv->mode,
|
||||
mode_changed, cs_changed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -554,17 +555,14 @@ static int spi_geni_prepare_message(struct spi_controller *spi,
|
|||
struct spi_message *spi_msg)
|
||||
{
|
||||
struct spi_geni_master *mas = spi_controller_get_devdata(spi);
|
||||
int ret;
|
||||
|
||||
switch (mas->cur_xfer_mode) {
|
||||
case GENI_SE_FIFO:
|
||||
case GENI_SE_DMA:
|
||||
if (spi_geni_is_abort_still_pending(mas))
|
||||
return -EBUSY;
|
||||
ret = setup_fifo_params(spi_msg->spi, spi);
|
||||
if (ret)
|
||||
dev_err(mas->dev, "Couldn't select mode %d\n", ret);
|
||||
return ret;
|
||||
setup_spi_params(spi_msg->spi, spi);
|
||||
return 0;
|
||||
|
||||
case GENI_GPI_DMA:
|
||||
/* nothing to do for GPI DMA */
|
||||
|
|
@ -700,7 +698,7 @@ static int spi_geni_init(struct spi_geni_master *mas)
|
|||
case 0:
|
||||
mas->cur_xfer_mode = GENI_SE_FIFO;
|
||||
geni_se_select_mode(se, GENI_SE_FIFO);
|
||||
/* setup_fifo_params assumes that these registers start with a zero value */
|
||||
/* setup_spi_params assumes that these registers start with a zero value */
|
||||
writel(0, se->base + SE_SPI_LOOPBACK);
|
||||
writel(0, se->base + SE_SPI_DEMUX_SEL);
|
||||
writel(0, se->base + SE_SPI_CPHA);
|
||||
|
|
@ -1066,6 +1064,69 @@ static int spi_geni_target_abort(struct spi_controller *spi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void spi_geni_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct spi_controller *spi = platform_get_drvdata(pdev);
|
||||
|
||||
spi_controller_suspend(spi);
|
||||
}
|
||||
|
||||
static int spi_geni_panic_notifier(struct notifier_block *nb,
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
struct spi_geni_master *mas = container_of(nb, struct spi_geni_master, panic_nb);
|
||||
struct spi_controller *spi = dev_get_drvdata(mas->dev);
|
||||
struct geni_se *se = &mas->se;
|
||||
u32 val;
|
||||
|
||||
if (!pm_runtime_active(mas->dev))
|
||||
return NOTIFY_OK;
|
||||
|
||||
if (mas->cur_xfer_mode == GENI_GPI_DMA) {
|
||||
dmaengine_terminate_async(mas->tx);
|
||||
dmaengine_terminate_async(mas->rx);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
if (!(readl_relaxed(se->base + SE_GENI_STATUS) & M_GENI_CMD_ACTIVE))
|
||||
return NOTIFY_OK;
|
||||
|
||||
if (!spi->target) {
|
||||
geni_se_cancel_m_cmd(se);
|
||||
if (!readl_poll_timeout_atomic(se->base + SE_GENI_M_IRQ_STATUS, val,
|
||||
val & M_CMD_CANCEL_EN, 10, 50000)) {
|
||||
writel_relaxed(M_CMD_CANCEL_EN, se->base + SE_GENI_M_IRQ_CLEAR);
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
}
|
||||
|
||||
geni_se_abort_m_cmd(se);
|
||||
if (!readl_poll_timeout_atomic(se->base + SE_GENI_M_IRQ_STATUS, val,
|
||||
val & M_CMD_ABORT_EN, 10, 50000))
|
||||
writel_relaxed(M_CMD_ABORT_EN, se->base + SE_GENI_M_IRQ_CLEAR);
|
||||
|
||||
if (mas->cur_xfer_mode == GENI_SE_DMA) {
|
||||
writel_relaxed(1, se->base + SE_DMA_TX_FSM_RST);
|
||||
readl_poll_timeout_atomic(se->base + SE_DMA_TX_IRQ_STAT, val,
|
||||
val & TX_RESET_DONE, 10, 50000);
|
||||
writel_relaxed(val, se->base + SE_DMA_TX_IRQ_CLR);
|
||||
|
||||
writel_relaxed(1, se->base + SE_DMA_RX_FSM_RST);
|
||||
readl_poll_timeout_atomic(se->base + SE_DMA_RX_IRQ_STAT, val,
|
||||
val & RX_RESET_DONE, 10, 50000);
|
||||
writel_relaxed(val, se->base + SE_DMA_RX_IRQ_CLR);
|
||||
}
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static void spi_geni_unregister_notifiers(void *data)
|
||||
{
|
||||
struct spi_geni_master *mas = data;
|
||||
|
||||
atomic_notifier_chain_unregister(&panic_notifier_list, &mas->panic_nb);
|
||||
}
|
||||
|
||||
static int spi_geni_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret, irq;
|
||||
|
|
@ -1154,6 +1215,15 @@ static int spi_geni_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
mas->panic_nb.notifier_call = spi_geni_panic_notifier;
|
||||
ret = atomic_notifier_chain_register(&panic_notifier_list, &mas->panic_nb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, spi_geni_unregister_notifiers, mas);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return devm_spi_register_controller(dev, spi);
|
||||
}
|
||||
|
||||
|
|
@ -1241,7 +1311,8 @@ static const struct of_device_id spi_geni_dt_match[] = {
|
|||
MODULE_DEVICE_TABLE(of, spi_geni_dt_match);
|
||||
|
||||
static struct platform_driver spi_geni_driver = {
|
||||
.probe = spi_geni_probe,
|
||||
.probe = spi_geni_probe,
|
||||
.shutdown = spi_geni_shutdown,
|
||||
.driver = {
|
||||
.name = "geni_spi",
|
||||
.pm = pm_ptr(&spi_geni_pm_ops),
|
||||
|
|
|
|||
|
|
@ -673,7 +673,7 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
|
|||
* propagate into the hardware. It takes exactly one tick of the
|
||||
* SCLK clock, but we will wait two SCLK clock just to be sure. The
|
||||
* effect of the delay it takes for the hardware to apply changes
|
||||
* is noticable if the SCLK clock run very slow. In such a case, if
|
||||
* is noticeable if the SCLK clock run very slow. In such a case, if
|
||||
* the polarity of SCLK should be inverted, the GPIO ChipSelect might
|
||||
* be asserted before the SCLK polarity changes, which would disrupt
|
||||
* the SPI communication as the device on the other end would consider
|
||||
|
|
@ -1467,8 +1467,8 @@ static int spi_imx_calculate_timeout(struct spi_imx_data *spi_imx, int size)
|
|||
static void spi_imx_dma_unmap(struct spi_imx_data *spi_imx,
|
||||
struct dma_data_package *dma_data)
|
||||
{
|
||||
struct device *tx_dev = spi_imx->controller->dma_tx->device->dev;
|
||||
struct device *rx_dev = spi_imx->controller->dma_rx->device->dev;
|
||||
struct device *tx_dev = dmaengine_get_dma_device(spi_imx->controller->dma_tx);
|
||||
struct device *rx_dev = dmaengine_get_dma_device(spi_imx->controller->dma_rx);
|
||||
|
||||
dma_unmap_single(tx_dev, dma_data->dma_tx_addr,
|
||||
DMA_CACHE_ALIGNED_LEN(dma_data->dma_len),
|
||||
|
|
@ -1526,8 +1526,8 @@ static int spi_imx_dma_map(struct spi_imx_data *spi_imx,
|
|||
struct dma_data_package *dma_data)
|
||||
{
|
||||
struct spi_controller *controller = spi_imx->controller;
|
||||
struct device *tx_dev = controller->dma_tx->device->dev;
|
||||
struct device *rx_dev = controller->dma_rx->device->dev;
|
||||
struct device *tx_dev = dmaengine_get_dma_device(controller->dma_tx);
|
||||
struct device *rx_dev = dmaengine_get_dma_device(controller->dma_rx);
|
||||
int ret;
|
||||
|
||||
dma_data->dma_tx_addr = dma_map_single(tx_dev, dma_data->dma_tx_buf,
|
||||
|
|
@ -1919,7 +1919,7 @@ static int spi_imx_dma_package_transfer(struct spi_imx_data *spi_imx,
|
|||
return ret;
|
||||
|
||||
/* Trim the DMA RX buffer and copy the actual data to rx_buf */
|
||||
dma_sync_single_for_cpu(controller->dma_rx->device->dev, dma_data->dma_rx_addr,
|
||||
dma_sync_single_for_cpu(dmaengine_get_dma_device(controller->dma_rx), dma_data->dma_rx_addr,
|
||||
dma_data->dma_len, DMA_FROM_DEVICE);
|
||||
spi_imx_dma_rx_data_handle(spi_imx, dma_data, transfer->rx_buf + spi_imx->rx_offset,
|
||||
word_delay);
|
||||
|
|
|
|||
|
|
@ -164,10 +164,8 @@ spi_ingenic_prepare_dma(struct spi_controller *ctlr, struct dma_chan *chan,
|
|||
cookie = dmaengine_submit(desc);
|
||||
|
||||
ret = dma_submit_error(cookie);
|
||||
if (ret) {
|
||||
dmaengine_desc_free(desc);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
|
@ -186,7 +184,6 @@ static int spi_ingenic_dma_tx(struct spi_controller *ctlr,
|
|||
&xfer->tx_sg, DMA_MEM_TO_DEV, bits);
|
||||
if (IS_ERR(tx_desc)) {
|
||||
dmaengine_terminate_async(ctlr->dma_rx);
|
||||
dmaengine_desc_free(rx_desc);
|
||||
return PTR_ERR(tx_desc);
|
||||
}
|
||||
|
||||
|
|
@ -354,8 +351,11 @@ static int spi_ingenic_request_dma(struct spi_controller *ctlr,
|
|||
ctlr->dma_tx = chan;
|
||||
|
||||
chan = dma_request_chan(dev, "rx");
|
||||
if (IS_ERR(chan))
|
||||
if (IS_ERR(chan)) {
|
||||
dma_release_channel(ctlr->dma_tx);
|
||||
ctlr->dma_tx = NULL;
|
||||
return PTR_ERR(chan);
|
||||
}
|
||||
ctlr->dma_rx = chan;
|
||||
|
||||
ctlr->can_dma = spi_ingenic_can_dma;
|
||||
|
|
|
|||
|
|
@ -633,18 +633,23 @@ static int nuvoton_qspi_probe(struct platform_device *pdev)
|
|||
return dev_err_probe(dev, ret, "failed to deassert reset\n");
|
||||
|
||||
ret = device_property_read_u32(dev, "num-cs", &num_cs);
|
||||
if (ret && ret != -EINVAL)
|
||||
return dev_err_probe(dev, ret, "failed to read num-cs\n");
|
||||
if (ret && ret != -EINVAL) {
|
||||
ret = dev_err_probe(dev, ret, "failed to read num-cs\n");
|
||||
goto err_assert;
|
||||
}
|
||||
|
||||
if (!num_cs || num_cs > NUVOTON_QSPI_MAX_NUM_CS)
|
||||
return dev_err_probe(dev, -EINVAL, "invalid num-cs %u\n",
|
||||
if (!num_cs || num_cs > NUVOTON_QSPI_MAX_NUM_CS) {
|
||||
ret = dev_err_probe(dev, -EINVAL, "invalid num-cs %u\n",
|
||||
num_cs);
|
||||
goto err_assert;
|
||||
}
|
||||
|
||||
ctlr->num_chipselect = num_cs;
|
||||
ctlr->max_transfer_size = nuvoton_qspi_max_transfer_size;
|
||||
ctlr->max_message_size = nuvoton_qspi_max_message_size;
|
||||
ctlr->mem_ops = &nuvoton_qspi_mem_ops;
|
||||
ctlr->mem_caps = &nuvoton_qspi_mem_caps;
|
||||
ctlr->dtr_caps = true;
|
||||
ctlr->set_cs = nuvoton_qspi_set_cs;
|
||||
ctlr->transfer_one = nuvoton_qspi_transfer_one;
|
||||
ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
|
|
@ -655,14 +660,20 @@ static int nuvoton_qspi_probe(struct platform_device *pdev)
|
|||
|
||||
ret = nuvoton_qspi_hw_init(qspi);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_assert;
|
||||
|
||||
ret = devm_spi_register_controller(dev, ctlr);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"failed to register spi controller\n");
|
||||
if (ret) {
|
||||
ret = dev_err_probe(dev, ret,
|
||||
"failed to register spi controller\n");
|
||||
goto err_assert;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_assert:
|
||||
reset_control_assert(rst);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id nuvoton_qspi_of_match[] = {
|
||||
|
|
|
|||
|
|
@ -46,9 +46,9 @@ int spi_controller_dma_map_mem_op_data(struct spi_controller *ctlr,
|
|||
return -EINVAL;
|
||||
|
||||
if (op->data.dir == SPI_MEM_DATA_OUT && ctlr->dma_tx)
|
||||
dmadev = ctlr->dma_tx->device->dev;
|
||||
dmadev = dmaengine_get_dma_device(ctlr->dma_tx);
|
||||
else if (op->data.dir == SPI_MEM_DATA_IN && ctlr->dma_rx)
|
||||
dmadev = ctlr->dma_rx->device->dev;
|
||||
dmadev = dmaengine_get_dma_device(ctlr->dma_rx);
|
||||
else
|
||||
dmadev = ctlr->dev.parent;
|
||||
|
||||
|
|
@ -92,9 +92,9 @@ void spi_controller_dma_unmap_mem_op_data(struct spi_controller *ctlr,
|
|||
return;
|
||||
|
||||
if (op->data.dir == SPI_MEM_DATA_OUT && ctlr->dma_tx)
|
||||
dmadev = ctlr->dma_tx->device->dev;
|
||||
dmadev = dmaengine_get_dma_device(ctlr->dma_tx);
|
||||
else if (op->data.dir == SPI_MEM_DATA_IN && ctlr->dma_rx)
|
||||
dmadev = ctlr->dma_rx->device->dev;
|
||||
dmadev = dmaengine_get_dma_device(ctlr->dma_rx);
|
||||
else
|
||||
dmadev = ctlr->dev.parent;
|
||||
|
||||
|
|
@ -172,7 +172,7 @@ bool spi_mem_default_supports_op(struct spi_mem *mem,
|
|||
op->cmd.dtr || op->addr.dtr || op->dummy.dtr || op->data.dtr;
|
||||
|
||||
if (op_is_dtr) {
|
||||
if (!spi_mem_controller_is_capable(ctlr, dtr))
|
||||
if (!spi_mem_controller_is_capable(ctlr, dtr) && !ctlr->dtr_caps)
|
||||
return false;
|
||||
|
||||
if (op->data.swap16 && !spi_mem_controller_is_capable(ctlr, swap16))
|
||||
|
|
@ -461,6 +461,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
|||
xfers[xferpos].len = op->cmd.nbytes;
|
||||
xfers[xferpos].tx_nbits = op->cmd.buswidth;
|
||||
xfers[xferpos].speed_hz = op->max_freq;
|
||||
xfers[xferpos].dtr_mode = op->cmd.dtr;
|
||||
spi_message_add_tail(&xfers[xferpos], &msg);
|
||||
xferpos++;
|
||||
totalxferlen++;
|
||||
|
|
@ -476,6 +477,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
|||
xfers[xferpos].len = op->addr.nbytes;
|
||||
xfers[xferpos].tx_nbits = op->addr.buswidth;
|
||||
xfers[xferpos].speed_hz = op->max_freq;
|
||||
xfers[xferpos].dtr_mode = op->addr.dtr;
|
||||
spi_message_add_tail(&xfers[xferpos], &msg);
|
||||
xferpos++;
|
||||
totalxferlen += op->addr.nbytes;
|
||||
|
|
@ -488,6 +490,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
|||
xfers[xferpos].tx_nbits = op->dummy.buswidth;
|
||||
xfers[xferpos].dummy_data = 1;
|
||||
xfers[xferpos].speed_hz = op->max_freq;
|
||||
xfers[xferpos].dtr_mode = op->dummy.dtr;
|
||||
spi_message_add_tail(&xfers[xferpos], &msg);
|
||||
xferpos++;
|
||||
totalxferlen += op->dummy.nbytes;
|
||||
|
|
@ -504,6 +507,7 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
|||
|
||||
xfers[xferpos].len = op->data.nbytes;
|
||||
xfers[xferpos].speed_hz = op->max_freq;
|
||||
xfers[xferpos].dtr_mode = op->data.dtr;
|
||||
spi_message_add_tail(&xfers[xferpos], &msg);
|
||||
xferpos++;
|
||||
totalxferlen += op->data.nbytes;
|
||||
|
|
|
|||
|
|
@ -929,6 +929,7 @@ static int mtk_nor_probe(struct platform_device *pdev)
|
|||
return 0;
|
||||
|
||||
err_probe:
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
pm_runtime_dont_use_autosuspend(&pdev->dev);
|
||||
|
|
|
|||
|
|
@ -744,7 +744,13 @@ static int mxic_spi_runtime_resume(struct device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
return mxic_spi_clk_enable(mxic);
|
||||
ret = mxic_spi_clk_enable(mxic);
|
||||
if (ret) {
|
||||
clk_disable_unprepare(mxic->ps_clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops mxic_spi_dev_pm_ops = {
|
||||
|
|
|
|||
|
|
@ -841,23 +841,23 @@ static int nxp_xspi_ahb_dma_read(struct nxp_xspi *xspi,
|
|||
{
|
||||
struct dma_async_tx_descriptor *desc;
|
||||
struct dma_chan *chan = xspi->dma_rx;
|
||||
struct device *dma_dev = dmaengine_get_dma_device(chan);
|
||||
unsigned long timeout;
|
||||
dma_addr_t src_addr, dst_addr;
|
||||
int ret = 0;
|
||||
|
||||
dst_addr = dma_map_single(chan->device->dev,
|
||||
op->data.buf.in, op->data.nbytes,
|
||||
dst_addr = dma_map_single(dma_dev, op->data.buf.in, op->data.nbytes,
|
||||
DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(chan->device->dev, dst_addr)) {
|
||||
if (dma_mapping_error(dma_dev, dst_addr)) {
|
||||
dev_err(xspi->dev, "failed to map DMA dst buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
src_addr = dma_map_resource(chan->device->dev,
|
||||
src_addr = dma_map_resource(dma_dev,
|
||||
(phys_addr_t)xspi->memmap_phy + op->addr.val,
|
||||
op->data.nbytes,
|
||||
DMA_TO_DEVICE, 0);
|
||||
if (dma_mapping_error(chan->device->dev, src_addr)) {
|
||||
if (dma_mapping_error(dma_dev, src_addr)) {
|
||||
dev_err(xspi->dev, "failed to map DMA src resource\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_unmap_dst;
|
||||
|
|
@ -886,12 +886,10 @@ static int nxp_xspi_ahb_dma_read(struct nxp_xspi *xspi,
|
|||
}
|
||||
|
||||
err_unmap_src:
|
||||
dma_unmap_resource(chan->device->dev, src_addr,
|
||||
op->data.nbytes, DMA_TO_DEVICE, 0);
|
||||
dma_unmap_resource(dma_dev, src_addr, op->data.nbytes, DMA_TO_DEVICE, 0);
|
||||
|
||||
err_unmap_dst:
|
||||
dma_unmap_single(chan->device->dev, dst_addr,
|
||||
op->data.nbytes, DMA_FROM_DEVICE);
|
||||
dma_unmap_single(dma_dev, dst_addr, op->data.nbytes, DMA_FROM_DEVICE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user