From nobody Tue Nov 26 00:56:16 2024 Received: from mail-oo1-f45.google.com (mail-oo1-f45.google.com [209.85.161.45]) (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 AF2A91FF7AE for ; Wed, 23 Oct 2024 20:59:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729717179; cv=none; b=UtgozoHG6v3xxkNPBMqTOBtpVBSJloAzcqwc00N1A261pTkHqvbMoAZJKML+5zHCA0ZJuMsjwPGc4//XJ0jcoRQKfatLT0uDo6LoimPiVf04E0fLR75c3vTJT78JEofBfhynmShQfWxjzrQyS8B9BXkH//Cxd0t1otLu8qsxwPI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729717179; c=relaxed/simple; bh=9Uoi/lsx5lDzmesX/dTqmB11w7iIVMU2MC+rAN+Xo0o=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=EcpZf07SJeEAOuFeI9hTvI40k93pp/wF+tbswKe3BmHUYy9+zjXPrHoMHTzITsbfGaHq8A6726eoMCV6KsSlg9JJ5SRRoHRzhoR8ecE0disS0oC660AjNbJzl7WlS43hno0eOtLj+hFO3N9/4ZHOVWD8MYB7+I2O+/NutGS7sfk= 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=hvptctuZ; arc=none smtp.client-ip=209.85.161.45 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="hvptctuZ" Received: by mail-oo1-f45.google.com with SMTP id 006d021491bc7-5eb67d926c4so139974eaf.0 for ; Wed, 23 Oct 2024 13:59:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1729717177; x=1730321977; 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=MJpBAkzSSYPV4RvQhjaw2/1DFd2kkl7hVgMR3+qjlgE=; b=hvptctuZQ5a5qjfBFSAo2mQX4Dubo1Q1glMKG2CfM3Y6QPqO8RZulJVrHr1fvWu7aj oqWvuydKGganITgmZoH+ssSdHVvszZ6xGtCQpAZ0P+tpoe/LlwvtR3zufBE6aat3GPAO vHoD3hCzUYLx1CfnlYZQKmKafxyFQC3ZfMiGQUkFVcWKxZZhGlfC5AP69LTa+bK0x3A4 HiyMmkZf/GDBWWnwAt33PvLKY0KaZ9ZF3K4U6WGU3Gqwzrh3jb2D4+ijjZuRL/nVNLtB ux77Pc2/7OS5VT9v6/WdY8j+Wno/8MJ2D+kicx8WkJts4iJQAf3EzsStXR4ErjqmVcot 1UkQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1729717177; x=1730321977; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=MJpBAkzSSYPV4RvQhjaw2/1DFd2kkl7hVgMR3+qjlgE=; b=uYfmYqWDgTnflT8L0Rztodc/PElWcNxUwitl6YdbznC2lWMA5iPzK8BqDUg45wT1Tf VOgw+RnvUP5ObYcx4aAfic+uFSi3/uezwkj93kZ2PaVi2lqcaDHfwMSxF9j5/MTFw9J8 +ogqac+qiDEYACt+4cuz5Nm1hkuglpcvlyJwfAQe/Dq+X7w/zsx0ENRKiij43w6A9/cs /icoZsm3Qwn4dL8IpBCvSW2nLNN4gfTCWJjcC8BI4Zg79BFuAwE15+OJ6Ou653/sTA5k mDuPRdQ+oKEgEFJ4bIBT5iF2/Qz4n8KOKeTWe0dbCPwq6H67FGVJtg1EJyhvJxbV5tOF pSEw== X-Forwarded-Encrypted: i=1; AJvYcCV0mToDf6H7+75AxTsOBCa9Wgl2ACRedJbl6Jg4jIj9c7HVSDt4SZB6xgM6Ucy0wcAr+dFHEESQ/CfGITs=@vger.kernel.org X-Gm-Message-State: AOJu0Yx01tKBr2KtxzqB0pwtkyRUw3Ipf7y2JlWUoyouzU9wtPbNMHiv TMMj4ywtMzvaIEo+YIE/OUEw7KryWO4kg6wQthFwnyzXBVddmZ+ea5qLoAdtccI= X-Google-Smtp-Source: AGHT+IHhgz4z/pNzeGgfxd28esWvpBib5iH9I1o0u1Snz5WDz9JUClIdWIVkcf1KuO2G++R03tqq+Q== X-Received: by 2002:a05:6820:608:b0:5eb:c72e:e29f with SMTP id 006d021491bc7-5ebee0753aemr2275209eaf.1.1729717176874; Wed, 23 Oct 2024 13:59:36 -0700 (PDT) Received: from [127.0.1.1] (ip98-183-112-25.ok.ok.cox.net. [98.183.112.25]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-5ec02c2c157sm52730eaf.44.2024.10.23.13.59.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 23 Oct 2024 13:59:35 -0700 (PDT) From: David Lechner Date: Wed, 23 Oct 2024 15:59:14 -0500 Subject: [PATCH RFC v4 07/15] spi: add offload TX/RX streaming APIs 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: <20241023-dlech-mainline-spi-engine-offload-2-v4-7-f8125b99f5a1@baylibre.com> References: <20241023-dlech-mainline-spi-engine-offload-2-v4-0-f8125b99f5a1@baylibre.com> In-Reply-To: <20241023-dlech-mainline-spi-engine-offload-2-v4-0-f8125b99f5a1@baylibre.com> To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= , =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= Cc: Michael Hennerich , Lars-Peter Clausen , David Jander , Martin Sperl , linux-spi@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org, linux-pwm@vger.kernel.org, David Lechner X-Mailer: b4 0.14.1 Most configuration of SPI offloads is handled opaquely using the offload pointer that is passed to the various offload functions. However, there are some offload features that need to be controlled on a per transfer basis. This patch adds a flag field to struct spi_transfer to allow specifying such features. The first feature to be added is the ability to stream data to/from a hardware sink/source rather than using a tx or rx buffer. Additional flags can be added in the future as needed. A flags field is also added to the offload struct for providers to indicate which flags are supported. This allows for generic checking of offload capabilities during __spi_validate() so that each offload provider doesn't have to implement their own validation. As a first users of this streaming capability, getter functions are added to get a DMA channel that is directly connected to the offload. Peripheral drivers will use this to get a DMA channel and configure it to suit their needs. Signed-off-by: David Lechner --- v4 changes: * DMA API's now automatically release DMA channels instead of leaving it up to the caller. v3 changes: * Added spi_offload_{tx,rx}_stream_get_dma_chan() functions. v2 changes: * This is also split out from "spi: add core support for controllers with offload capabilities". * In the previous version, we were using (void *)-1 as a sentinel value that could be assigned, e.g. to rx_buf. But this was naive since there is core code that would try to dereference this pointer. So instead, we've added a new flags field to the spi_transfer structure for this sort of thing. This also has the advantage of being able to be used in the future for other arbitrary features. --- drivers/spi/spi-offload.c | 76 +++++++++++++++++++++++++++++++++++++= ++++ drivers/spi/spi.c | 10 ++++++ include/linux/spi/spi-offload.h | 24 +++++++++++++ include/linux/spi/spi.h | 3 ++ 4 files changed, 113 insertions(+) diff --git a/drivers/spi/spi-offload.c b/drivers/spi/spi-offload.c index 2a1f9587f27a..dd4cb3c2e985 100644 --- a/drivers/spi/spi-offload.c +++ b/drivers/spi/spi-offload.c @@ -8,6 +8,7 @@ =20 #include #include +#include #include #include #include @@ -282,6 +283,81 @@ void spi_offload_trigger_disable(struct spi_offload *o= ffload, } EXPORT_SYMBOL_GPL(spi_offload_trigger_disable); =20 +static void spi_offload_release_dma_chan(void *chan) +{ + dma_release_channel(chan); +} + +/** + * spi_offload_tx_stream_request_dma_chan_info - Get the DMA channel info = for the TX stream + * @spi: SPI device + * @id: Function ID if SPI device uses more than one offload or NULL. + * + * This is the DMA channel that will provide data to transfers that use the + * %SPI_OFFLOAD_XFER_TX_STREAM offload flag. + * + * The caller is responsible for calling spi_offload_free_dma_chan_info() = on the + * returned pointer. + * + * Return: Pointer to DMA channel info, or negative error code + */ +struct dma_chan +*devm_spi_offload_tx_stream_request_dma_chan(struct device *dev, + struct spi_offload *offload) +{ + struct dma_chan *chan; + int ret; + + if (!offload->ops || !offload->ops->tx_stream_request_dma_chan) + return ERR_PTR(-EOPNOTSUPP); + + chan =3D offload->ops->tx_stream_request_dma_chan(offload); + if (IS_ERR(chan)) + return chan; + + ret =3D devm_add_action_or_reset(dev, spi_offload_release_dma_chan, chan); + if (ret) + return ERR_PTR(ret); + + return chan; +} +EXPORT_SYMBOL_GPL(devm_spi_offload_tx_stream_request_dma_chan); + +/** + * spi_offload_rx_stream_request_dma_chan_info - Get the DMA channel info = for the RX stream + * @spi: SPI device + * @id: Function ID if SPI device uses more than one offload or NULL. + * + * This is the DMA channel that will receive data from transfers that use = the + * %SPI_OFFLOAD_XFER_RX_STREAM offload flag. + * + * The caller is responsible for calling spi_offload_free_dma_chan_info() = on the + * returned pointer. + * + * Return: Pointer to DMA channel info, or negative error code + */ +struct dma_chan +*devm_spi_offload_rx_stream_request_dma_chan(struct device *dev, + struct spi_offload *offload) +{ + struct dma_chan *chan; + int ret; + + if (!offload->ops || !offload->ops->rx_stream_request_dma_chan) + return ERR_PTR(-EOPNOTSUPP); + + chan =3D offload->ops->rx_stream_request_dma_chan(offload); + if (IS_ERR(chan)) + return chan; + + ret =3D devm_add_action_or_reset(dev, spi_offload_release_dma_chan, chan); + if (ret) + return ERR_PTR(ret); + + return chan; +} +EXPORT_SYMBOL_GPL(devm_spi_offload_rx_stream_request_dma_chan); + /* Triggers providers */ =20 static void spi_offload_trigger_dev_release(struct device *dev) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 7c5e76b15421..cb6184c0ae03 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -4159,6 +4160,15 @@ static int __spi_validate(struct spi_device *spi, st= ruct spi_message *message) =20 if (_spi_xfer_word_delay_update(xfer, spi)) return -EINVAL; + + /* make sure controller supports required offload features */ + if (xfer->offload_flags) { + if (!message->offload) + return -EINVAL; + + if (xfer->offload_flags & ~message->offload->xfer_flags) + return -EINVAL; + } } =20 message->status =3D -EINPROGRESS; diff --git a/include/linux/spi/spi-offload.h b/include/linux/spi/spi-offloa= d.h index 561cc1fb6f35..5d0e29b25977 100644 --- a/include/linux/spi/spi-offload.h +++ b/include/linux/spi/spi-offload.h @@ -25,6 +25,11 @@ struct device; struct fwnode_handle; struct spi_device; =20 +/* This is write xfer but TX uses external data stream rather than tx_buf.= */ +#define SPI_OFFLOAD_XFER_TX_STREAM BIT(0) +/* This is read xfer but RX uses external data stream rather than rx_buf. = */ +#define SPI_OFFLOAD_XFER_RX_STREAM BIT(1) + /* Offload can be triggered by external hardware event. */ #define SPI_OFFLOAD_CAP_TRIGGER BIT(0) /* Offload can record and then play back TX data when triggered. */ @@ -56,6 +61,8 @@ struct spi_offload { void *priv; /** @ops: callbacks for offload support */ const struct spi_offload_ops *ops; + /** @xfer_flags: %SPI_OFFLOAD_XFER_* flags supported by provider */ + u32 xfer_flags; }; =20 enum spi_offload_trigger_type { @@ -91,6 +98,18 @@ struct spi_offload_ops { * given offload instance. */ void (*trigger_disable)(struct spi_offload *offload); + /** + * @tx_stream_request_dma_chan: Optional callback for controllers that + * have an offload where the TX data stream is connected directly to a + * DMA channel. + */ + struct dma_chan *(*tx_stream_request_dma_chan)(struct spi_offload *offloa= d); + /** + * @rx_stream_request_dma_chan: Optional callback for controllers that + * have an offload where the RX data stream is connected directly to a + * DMA channel. + */ + struct dma_chan *(*rx_stream_request_dma_chan)(struct spi_offload *offloa= d); }; =20 struct spi_offload *devm_spi_offload_alloc(struct device *dev, @@ -111,6 +130,11 @@ int spi_offload_trigger_enable(struct spi_offload *off= load, void spi_offload_trigger_disable(struct spi_offload *offload, struct spi_offload_trigger *trigger); =20 +struct dma_chan *devm_spi_offload_tx_stream_request_dma_chan(struct device= *dev, + struct spi_offload *offload); +struct dma_chan *devm_spi_offload_rx_stream_request_dma_chan(struct device= *dev, + struct spi_offload *offload); + /* Trigger providers */ =20 struct spi_offload_trigger; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index c230d6a209ee..fbb8b2d0b5ea 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -1092,6 +1092,9 @@ struct spi_transfer { =20 u32 effective_speed_hz; =20 + /* Use %SPI_OFFLOAD_XFER_* from spi-offload.h */ + unsigned int offload_flags; + unsigned int ptp_sts_word_pre; unsigned int ptp_sts_word_post; =20 --=20 2.43.0