From nobody Tue Feb 10 01:19:19 2026 Received: from mail-oa1-f52.google.com (mail-oa1-f52.google.com [209.85.160.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8D1CB37E318 for ; Mon, 12 Jan 2026 17:46:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768240004; cv=none; b=YLvuxBA/Oxt+Q0FQqpNNHLN2zzCDhN3x8WwSd9VyYIKyD2EFJD4MCuQqcHHLX3u+pZBYWL13Ib+QzdZ9Iw5CwJrbJ+3HaQSUBgdWOL8qUQ/PZNVKKw+clVE422+dQG+0KE613jVnxN2E9VzvdMXEySUHg2LnFSj0IVag+3SMZO8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768240004; c=relaxed/simple; bh=MVsDQFH2OsHI6nzdX0cat5az8qPnbZtSXWv8CsLqz2E=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hniamr6KNP5N7pFbRwa3mlGvWpfRVj9pXhtktBmcy2kqKzsCh8psEZLaM9pJHUmQHZMgcVIOv4QXzDKicTInc69uwZn7Q0kPJ5G9hOf0SS3P58GI+eHpNz+K9azp2DQWSqy9HuVyQo4yfkUABeW8fioKRxT9ytAw5xc/I1lFe/4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=zNRLtCMz; arc=none smtp.client-ip=209.85.160.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="zNRLtCMz" Received: by mail-oa1-f52.google.com with SMTP id 586e51a60fabf-3f4f9ea26aaso5073382fac.0 for ; Mon, 12 Jan 2026 09:46:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1768239997; x=1768844797; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=HmKXsoki/VhflIbyQc4ST4EE0k/E3vaHih8A+QqR2LE=; b=zNRLtCMzKZgJ1NmlLuQhvd10NpdkITFdoEFujSwHxVstoxm8Pvlgj0kotJrwamy3bJ eStdOquSasyta5Dl7z6KFRrM949Enmozt+oG3dQONg8hse3KzbPdtmwCC1gJOMEN41rU CVzzx1f9SrOb8uL3eKFIAoP7PpudZ2oG1BFYH8updvaHjLq96OzUmut54XSapqHbg2Dh dCe2Y4ClPHBXm8fR4GIkCKT0czx4I4udeMOeMzoQZAhZtbnJGc2FGqnPABIJXpvmX59z sxtDlR4q+m14aURkF3kpqulsziSCs3+KlOtaoa64nsxGkuv4iYtElA/ANBrQD6HfyeEj lQuQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768239997; x=1768844797; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=HmKXsoki/VhflIbyQc4ST4EE0k/E3vaHih8A+QqR2LE=; b=V4JSj9L67Zh08/zluvFoPN0ZJyKVCIe4plJVmtfrRqLc+uv78+hgFIDS0nk+Zz5OWp /C/WXz3r8//rLZAEoZtl1AOexbUAz7pZ5i9+DxAhRDr6eFPXkJYihMwiNRkSEFe+ULoo Y8YQ+5fqZlj9GfnUx2X+HAPkUY6Em9bdMVQ5FC7LqjzTtSVy2ubJxz2R1CHryrsO0uMe Xgv+RYibnIEH4JRqz0Z9jxiX64YSkF+l6XrzcH7GZshlnBXkhoZndDa5OTfgDx6IsvW9 IrCqMqAb3j1lobzRa3lG5XFFf+clQNYU8YkFX6Q1VNYU8G5Htco5PlLINk5NrRcPM0+i 9QxQ== X-Forwarded-Encrypted: i=1; AJvYcCWzyE+cvtH9c9TbcsbR/++MsXPQNbagZ+X5v2Vgh+8fDv+C5UQdIRHoFm19XEk9QMkn7CiEYgrM3OeHF5g=@vger.kernel.org X-Gm-Message-State: AOJu0YyDQKTIbZOHdW9S6pFYstwUwvdQJrPU7mqNLATp/+GN3LsjOqYC +U521wdCDYc0p5RJrDZCPxQsGLKq8/10KMXB4nPgnlT2HM0NZef/CnEM1KO2+Wf9eN8= X-Gm-Gg: AY/fxX6J1/+4vEMFyCW5X0/vEXY4hT9AkEm0elVQwQ0f6ejs5bmO2COueknA7mrzMGq uJungtw1udrVHC2zrk0QuiIgym9FSAwptQ383y88NDVrKrA7t7kuYnXky1bP5hiV9Y+1RnDtIEC ZPoS5W3DeVM6wPCrh79OU1hp0lEMQMYUYB6rZe5bDrHObadxEbjnvZYYmgwZqwSyeTReEoDUI4u I6yyh+aA6c8cKPPDjW7OGc6+zUecjZt2R72UqkcFiDmC/k3g+MXqi7KoT2O9SA2Yq1mWQ1pL0Yz wheSZW2IjhxbrDTtEISJMHfihZA/eLRVMCz4q9iQqT18VkzhHMWkJImogd58UOS/KptuYJ90w6o jP6K6DtzRFwDAXtt4vUwrT+MuIvl++VHVQxQ07P9HcSa+iAMvLNVipbImzQU1fidwpqoy7ZUKyD Ep/Xj3VpbDRhYDbs4= X-Google-Smtp-Source: AGHT+IHDAluGdahbvyLPZLvCK4N93Hgdp1InyurG6jyBTL+3ZHFyvo0Ik+mB3pEu8hHs/Ff2X+K6aQ== X-Received: by 2002:a05:6871:2ea5:b0:3ec:3437:e395 with SMTP id 586e51a60fabf-3ffc09515e6mr9188063fac.17.1768239997384; Mon, 12 Jan 2026 09:46:37 -0800 (PST) Received: from [127.0.1.1] ([2600:8803:e7e4:500:6b4b:49b3:cce5:b58f]) by smtp.gmail.com with ESMTPSA id 586e51a60fabf-3ffa4de40bfsm12126941fac.5.2026.01.12.09.46.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 12 Jan 2026 09:46:37 -0800 (PST) From: David Lechner Date: Mon, 12 Jan 2026 11:45:25 -0600 Subject: [PATCH v5 7/9] spi: axi-spi-engine: support SPI_MULTI_LANE_MODE_STRIPE Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260112-spi-add-multi-bus-support-v5-7-295f4f09f6ba@baylibre.com> References: <20260112-spi-add-multi-bus-support-v5-0-295f4f09f6ba@baylibre.com> In-Reply-To: <20260112-spi-add-multi-bus-support-v5-0-295f4f09f6ba@baylibre.com> To: Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Marcelo Schmitt , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , Jonathan Cameron , Andy Shevchenko Cc: Sean Anderson , linux-spi@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, David Lechner X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=12127; i=dlechner@baylibre.com; h=from:subject:message-id; bh=MVsDQFH2OsHI6nzdX0cat5az8qPnbZtSXWv8CsLqz2E=; b=owEBbQGS/pANAwAKAcLMIAH/AY/AAcsmYgBpZTNfWnPyjZQpLULSfA2Mt8nAud3GUtKxnHbq5 Df1OxHFp36JATMEAAEKAB0WIQTsGNmeYg6D1pzYaJjCzCAB/wGPwAUCaWUzXwAKCRDCzCAB/wGP wLe+CACDQk0ctEIjRuGKOGuiJwS8rgn6HNWOrMZAsM2EOc4Pd+zibbWGzspuqVPQlW2Vjh2cKkn n4HaVZPzXplr9vH4OJy980dY7OjKknclBHzYyhLV92CkNcxGiQuhHEJzxk6t6rkOz4b3BHqdeh5 zzTV5kGgRndjrawldLUQfpzeXs5izIrMDrb4iZ1++EIOMYU9Y2yg+H1XNxHmt6+FZp9IaomsmI+ ijvzDD0FqiLo/JERPJuYUSG07lRbmn7cyHDvPDe2CNik75Ea53Jq79ZUxQHow2BQccXp3Q1KvOw 74Qj3OCh0B2+DCUtkNkEok2ulVO9q8SuyLID5DcAD0TNhFQd X-Developer-Key: i=dlechner@baylibre.com; a=openpgp; fpr=8A73D82A6A1F509907F373881F8AF88C82F77C03 Add support for SPI_MULTI_LANE_MODE_STRIPE to the AXI SPI engine driver. The v2.0.0 version of the AXI SPI Engine IP core supports multiple lanes. This can be used with SPI_MULTI_LANE_MODE_STRIPE to support reading from simultaneous sampling ADCs that have a separate SDO line for each analog channel. This allows reading all channels at the same time to increase throughput. Reviewed-by: Marcelo Schmitt Signed-off-by: David Lechner Reviewed-by: Jonathan Cameron --- v4 changes: * Update for core SPI API changes. v3 changes: * Renamed "buses" to "lanes" to reflect devicetree property name change. v2 changes: * Fixed off-by-one in SPI_ENGINE_REG_DATA_WIDTH_NUM_OF_SDIO_MASK GENMASK --- drivers/spi/spi-axi-spi-engine.c | 145 +++++++++++++++++++++++++++++++++++= ++-- 1 file changed, 141 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-eng= ine.c index e06f412190fd..3028e6112909 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -23,6 +23,9 @@ #include #include =20 +#define SPI_ENGINE_REG_DATA_WIDTH 0x0C +#define SPI_ENGINE_REG_DATA_WIDTH_NUM_OF_SDIO_MASK GENMASK(23, 16) +#define SPI_ENGINE_REG_DATA_WIDTH_MASK GENMASK(15, 0) #define SPI_ENGINE_REG_OFFLOAD_MEM_ADDR_WIDTH 0x10 #define SPI_ENGINE_REG_RESET 0x40 =20 @@ -75,6 +78,8 @@ #define SPI_ENGINE_CMD_REG_CLK_DIV 0x0 #define SPI_ENGINE_CMD_REG_CONFIG 0x1 #define SPI_ENGINE_CMD_REG_XFER_BITS 0x2 +#define SPI_ENGINE_CMD_REG_SDI_MASK 0x3 +#define SPI_ENGINE_CMD_REG_SDO_MASK 0x4 =20 #define SPI_ENGINE_MISC_SYNC 0x0 #define SPI_ENGINE_MISC_SLEEP 0x1 @@ -105,6 +110,10 @@ #define SPI_ENGINE_OFFLOAD_CMD_FIFO_SIZE 16 #define SPI_ENGINE_OFFLOAD_SDO_FIFO_SIZE 16 =20 +/* Extending SPI_MULTI_LANE_MODE values for optimizing messages. */ +#define SPI_ENGINE_MULTI_BUS_MODE_UNKNOWN -1 +#define SPI_ENGINE_MULTI_BUS_MODE_CONFLICTING -2 + struct spi_engine_program { unsigned int length; uint16_t instructions[] __counted_by(length); @@ -142,6 +151,11 @@ struct spi_engine_offload { unsigned long flags; unsigned int offload_num; unsigned int spi_mode_config; + unsigned int multi_lane_mode; + u8 rx_primary_lane_mask; + u8 tx_primary_lane_mask; + u8 rx_all_lanes_mask; + u8 tx_all_lanes_mask; u8 bits_per_word; }; =20 @@ -165,6 +179,25 @@ struct spi_engine { bool offload_requires_sync; }; =20 +static void spi_engine_primary_lane_flag(struct spi_device *spi, + u8 *rx_lane_flags, u8 *tx_lane_flags) +{ + *rx_lane_flags =3D BIT(spi->rx_lane_map[0]); + *tx_lane_flags =3D BIT(spi->tx_lane_map[0]); +} + +static void spi_engine_all_lanes_flags(struct spi_device *spi, + u8 *rx_lane_flags, u8 *tx_lane_flags) +{ + int i; + + for (i =3D 0; i < spi->num_rx_lanes; i++) + *rx_lane_flags |=3D BIT(spi->rx_lane_map[i]); + + for (i =3D 0; i < spi->num_tx_lanes; i++) + *tx_lane_flags |=3D BIT(spi->tx_lane_map[i]); +} + static void spi_engine_program_add_cmd(struct spi_engine_program *p, bool dry, uint16_t cmd) { @@ -193,7 +226,7 @@ static unsigned int spi_engine_get_config(struct spi_de= vice *spi) } =20 static void spi_engine_gen_xfer(struct spi_engine_program *p, bool dry, - struct spi_transfer *xfer) + struct spi_transfer *xfer, u32 num_lanes) { unsigned int len; =20 @@ -204,6 +237,9 @@ static void spi_engine_gen_xfer(struct spi_engine_progr= am *p, bool dry, else len =3D xfer->len / 4; =20 + if (xfer->multi_lane_mode =3D=3D SPI_MULTI_LANE_MODE_STRIPE) + len /=3D num_lanes; + while (len) { unsigned int n =3D min(len, 256U); unsigned int flags =3D 0; @@ -269,6 +305,7 @@ static int spi_engine_precompile_message(struct spi_mes= sage *msg) { unsigned int clk_div, max_hz =3D msg->spi->controller->max_speed_hz; struct spi_transfer *xfer; + int multi_lane_mode =3D SPI_ENGINE_MULTI_BUS_MODE_UNKNOWN; u8 min_bits_per_word =3D U8_MAX; u8 max_bits_per_word =3D 0; =20 @@ -284,6 +321,24 @@ static int spi_engine_precompile_message(struct spi_me= ssage *msg) min_bits_per_word =3D min(min_bits_per_word, xfer->bits_per_word); max_bits_per_word =3D max(max_bits_per_word, xfer->bits_per_word); } + + if (xfer->rx_buf || xfer->offload_flags & SPI_OFFLOAD_XFER_RX_STREAM || + xfer->tx_buf || xfer->offload_flags & SPI_OFFLOAD_XFER_TX_STREAM) { + switch (xfer->multi_lane_mode) { + case SPI_MULTI_LANE_MODE_SINGLE: + case SPI_MULTI_LANE_MODE_STRIPE: + break; + default: + /* Other modes, like mirror not supported */ + return -EINVAL; + } + + /* If all xfers have the same multi-lane mode, we can optimize. */ + if (multi_lane_mode =3D=3D SPI_ENGINE_MULTI_BUS_MODE_UNKNOWN) + multi_lane_mode =3D xfer->multi_lane_mode; + else if (multi_lane_mode !=3D xfer->multi_lane_mode) + multi_lane_mode =3D SPI_ENGINE_MULTI_BUS_MODE_CONFLICTING; + } } =20 /* @@ -297,6 +352,14 @@ static int spi_engine_precompile_message(struct spi_me= ssage *msg) priv->bits_per_word =3D min_bits_per_word; else priv->bits_per_word =3D 0; + + priv->multi_lane_mode =3D multi_lane_mode; + spi_engine_primary_lane_flag(msg->spi, + &priv->rx_primary_lane_mask, + &priv->tx_primary_lane_mask); + spi_engine_all_lanes_flags(msg->spi, + &priv->rx_all_lanes_mask, + &priv->tx_all_lanes_mask); } =20 return 0; @@ -310,6 +373,7 @@ static void spi_engine_compile_message(struct spi_messa= ge *msg, bool dry, struct spi_engine_offload *priv; struct spi_transfer *xfer; int clk_div, new_clk_div, inst_ns; + int prev_multi_lane_mode =3D SPI_MULTI_LANE_MODE_SINGLE; bool keep_cs =3D false; u8 bits_per_word =3D 0; =20 @@ -334,6 +398,7 @@ static void spi_engine_compile_message(struct spi_messa= ge *msg, bool dry, * in the same way. */ bits_per_word =3D priv->bits_per_word; + prev_multi_lane_mode =3D priv->multi_lane_mode; } else { spi_engine_program_add_cmd(p, dry, SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_CONFIG, @@ -344,6 +409,28 @@ static void spi_engine_compile_message(struct spi_mess= age *msg, bool dry, spi_engine_gen_cs(p, dry, spi, !xfer->cs_off); =20 list_for_each_entry(xfer, &msg->transfers, transfer_list) { + if (xfer->rx_buf || xfer->offload_flags & SPI_OFFLOAD_XFER_RX_STREAM || + xfer->tx_buf || xfer->offload_flags & SPI_OFFLOAD_XFER_TX_STREAM) { + if (xfer->multi_lane_mode !=3D prev_multi_lane_mode) { + u8 tx_lane_flags, rx_lane_flags; + + if (xfer->multi_lane_mode =3D=3D SPI_MULTI_LANE_MODE_STRIPE) + spi_engine_all_lanes_flags(spi, &rx_lane_flags, + &tx_lane_flags); + else + spi_engine_primary_lane_flag(spi, &rx_lane_flags, + &tx_lane_flags); + + spi_engine_program_add_cmd(p, dry, + SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDI_MASK, + rx_lane_flags)); + spi_engine_program_add_cmd(p, dry, + SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDO_MASK, + tx_lane_flags)); + } + prev_multi_lane_mode =3D xfer->multi_lane_mode; + } + new_clk_div =3D host->max_speed_hz / xfer->effective_speed_hz; if (new_clk_div !=3D clk_div) { clk_div =3D new_clk_div; @@ -360,7 +447,7 @@ static void spi_engine_compile_message(struct spi_messa= ge *msg, bool dry, bits_per_word)); } =20 - spi_engine_gen_xfer(p, dry, xfer); + spi_engine_gen_xfer(p, dry, xfer, spi->num_rx_lanes); spi_engine_gen_sleep(p, dry, spi_delay_to_ns(&xfer->delay, xfer), inst_ns, xfer->effective_speed_hz); =20 @@ -394,6 +481,19 @@ static void spi_engine_compile_message(struct spi_mess= age *msg, bool dry, if (clk_div !=3D 1) spi_engine_program_add_cmd(p, dry, SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_CLK_DIV, 0)); + + /* Restore single lane mode unless offload disable will restore it later.= */ + if (prev_multi_lane_mode =3D=3D SPI_MULTI_LANE_MODE_STRIPE && + (!msg->offload || priv->multi_lane_mode !=3D SPI_MULTI_LANE_MODE_STRI= PE)) { + u8 rx_lane_flags, tx_lane_flags; + + spi_engine_primary_lane_flag(spi, &rx_lane_flags, &tx_lane_flags); + + spi_engine_program_add_cmd(p, dry, + SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDI_MASK, rx_lane_flags)); + spi_engine_program_add_cmd(p, dry, + SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDO_MASK, tx_lane_flags)); + } } =20 static void spi_engine_xfer_next(struct spi_message *msg, @@ -799,6 +899,19 @@ static int spi_engine_setup(struct spi_device *device) writel_relaxed(SPI_ENGINE_CMD_CS_INV(spi_engine->cs_inv), spi_engine->base + SPI_ENGINE_REG_CMD_FIFO); =20 + if (host->num_data_lanes > 1) { + u8 rx_lane_flags, tx_lane_flags; + + spi_engine_primary_lane_flag(device, &rx_lane_flags, &tx_lane_flags); + + writel_relaxed(SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDI_MASK, + rx_lane_flags), + spi_engine->base + SPI_ENGINE_REG_CMD_FIFO); + writel_relaxed(SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDO_MASK, + tx_lane_flags), + spi_engine->base + SPI_ENGINE_REG_CMD_FIFO); + } + /* * In addition to setting the flags, we have to do a CS assert command * to make the new setting actually take effect. @@ -902,6 +1015,15 @@ static int spi_engine_trigger_enable(struct spi_offlo= ad *offload) priv->bits_per_word), spi_engine->base + SPI_ENGINE_REG_CMD_FIFO); =20 + if (priv->multi_lane_mode =3D=3D SPI_MULTI_LANE_MODE_STRIPE) { + writel_relaxed(SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDI_MASK, + priv->rx_all_lanes_mask), + spi_engine->base + SPI_ENGINE_REG_CMD_FIFO); + writel_relaxed(SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDO_MASK, + priv->tx_all_lanes_mask), + spi_engine->base + SPI_ENGINE_REG_CMD_FIFO); + } + writel_relaxed(SPI_ENGINE_CMD_SYNC(1), spi_engine->base + SPI_ENGINE_REG_CMD_FIFO); =20 @@ -929,6 +1051,16 @@ static void spi_engine_trigger_disable(struct spi_off= load *offload) reg &=3D ~SPI_ENGINE_OFFLOAD_CTRL_ENABLE; writel_relaxed(reg, spi_engine->base + SPI_ENGINE_REG_OFFLOAD_CTRL(priv->offload_num)); + + /* Restore single-lane mode. */ + if (priv->multi_lane_mode =3D=3D SPI_MULTI_LANE_MODE_STRIPE) { + writel_relaxed(SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDI_MASK, + priv->rx_primary_lane_mask), + spi_engine->base + SPI_ENGINE_REG_CMD_FIFO); + writel_relaxed(SPI_ENGINE_CMD_WRITE(SPI_ENGINE_CMD_REG_SDO_MASK, + priv->tx_primary_lane_mask), + spi_engine->base + SPI_ENGINE_REG_CMD_FIFO); + } } =20 static struct dma_chan @@ -973,7 +1105,7 @@ static int spi_engine_probe(struct platform_device *pd= ev) { struct spi_engine *spi_engine; struct spi_controller *host; - unsigned int version; + unsigned int version, data_width_reg_val; int irq, ret; =20 irq =3D platform_get_irq(pdev, 0); @@ -1042,7 +1174,7 @@ static int spi_engine_probe(struct platform_device *p= dev) return PTR_ERR(spi_engine->base); =20 version =3D readl(spi_engine->base + ADI_AXI_REG_VERSION); - if (ADI_AXI_PCORE_VER_MAJOR(version) !=3D 1) { + if (ADI_AXI_PCORE_VER_MAJOR(version) > 2) { dev_err(&pdev->dev, "Unsupported peripheral version %u.%u.%u\n", ADI_AXI_PCORE_VER_MAJOR(version), ADI_AXI_PCORE_VER_MINOR(version), @@ -1050,6 +1182,8 @@ static int spi_engine_probe(struct platform_device *p= dev) return -ENODEV; } =20 + data_width_reg_val =3D readl(spi_engine->base + SPI_ENGINE_REG_DATA_WIDTH= ); + if (adi_axi_pcore_ver_gteq(version, 1, 1)) { unsigned int sizes =3D readl(spi_engine->base + SPI_ENGINE_REG_OFFLOAD_MEM_ADDR_WIDTH); @@ -1097,6 +1231,9 @@ static int spi_engine_probe(struct platform_device *p= dev) } if (adi_axi_pcore_ver_gteq(version, 1, 3)) host->mode_bits |=3D SPI_MOSI_IDLE_LOW | SPI_MOSI_IDLE_HIGH; + if (adi_axi_pcore_ver_gteq(version, 2, 0)) + host->num_data_lanes =3D FIELD_GET(SPI_ENGINE_REG_DATA_WIDTH_NUM_OF_SDIO= _MASK, + data_width_reg_val); =20 if (host->max_speed_hz =3D=3D 0) return dev_err_probe(&pdev->dev, -EINVAL, "spi_clk rate is 0"); --=20 2.43.0