From patchwork Fri Nov 15 20:18:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 843780 Received: from mail-oo1-f49.google.com (mail-oo1-f49.google.com [209.85.161.49]) (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 005E61D5CF1 for ; Fri, 15 Nov 2024 20:18:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701933; cv=none; b=LjGedzHjtU0fg3SuyRs84ObKpIfDQ08Q77Oe+ycaBCFTh/ysZN4lUxZld0YBlC5EQM7KQ51EatVTqsuLmTecgL+GUzflVJzLQRjZ3Hjvl+p+A54sO2FyBNS9BwMGvp+3vZAb9wRYC4H/WS89zZLIndmTqzZwv2CbvpyvH3FCydE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701933; c=relaxed/simple; bh=TOgkx/m/6FrPpC7rnBHkuU0C5+5RkznAgqFoBKD3ESA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HmAVwtxK/iHYmFvOm04pgNyHmgVE1Kv1KXVJfJxi8l4o8KuikEUBIhQXsf06Sm1/vPCZ+JrwX6zUlems96fy+AfwJql107QMlbre+yTlHgcoWKbGQRtsJV8s4g3aWX+U/rfQkdKsgxGXoq23FH6C9D2nz2dJijkVBY/s+MyxTIw= 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=rtNuM5JR; arc=none smtp.client-ip=209.85.161.49 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="rtNuM5JR" Received: by mail-oo1-f49.google.com with SMTP id 006d021491bc7-5ee645cf74fso571913eaf.2 for ; Fri, 15 Nov 2024 12:18:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1731701930; x=1732306730; 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=A3CE0yheT4DVVry1IgtvS9L1hkM/iTvAih5hXhwRp+I=; b=rtNuM5JRgCZEpNamsauUYR59uY6Y0RXY6f4zloZYI2Mre+8Ks6LQQjz9bmQ1xp6r8c l8G6McpUKvu55X+HpzMDj5xITsF9KUGQRNRme9K0rAu/fpyf7m5oj1yI8z550br/uU1Z bWXTs+PvKWkQGnHyxMWe3ovyCcMeyqhVQ6LBTQUQsSIP3H7uTt80Z5/h2EWmWn2/mEIF uSRXniwKFumkJIBJ0uIMiJ/Tsvg+rNb+BlwRvKG3zTEztCLtKBA/QUaSy0SUEFuxYIjL PeAD9UDm7Oa8yP6g56FvDDjxI03g2YJe/r2uYxON39vJwspgxjNlWLjgf40A+9m+Sfh1 6KmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731701930; x=1732306730; 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=A3CE0yheT4DVVry1IgtvS9L1hkM/iTvAih5hXhwRp+I=; b=vba3vInTNcbCRyC41rXbyisENQTHIDtrMjy0O+KKZH01SK+D+SjTxV1Jrrmq2Eaydx MTtfU9ych5LZ62abgsjHoPFfFbf0n466hawODN7ZFN2sZWfXB9jK9OElY5uy8meBLv+O zXL6uLYRMtShyvpMVyTRMIURXrxbBgsIv4D9DI2ZnLbzzZ3H3uj8KzlqzmAlmYBa6WqL 7DoaFfhZkgGUHqn8fZr7W+ItclxWSdkC1hikqh25l0KlzfxMkMeyULWYPax6Esy1FDll GDjThFLii11aUwvUtXg47ZhdGdW7/Y9WEHbgw/ISA8HTNZLKMLd0it/Sk1q2chJzYf7e 3+4w== X-Forwarded-Encrypted: i=1; AJvYcCWrFfuipnynQajAexreMhlVtqb0ACfxMEyBmcA/piMmRNWahHHLqztOoBEdY+6XDPiit5Ctanket9Q=@vger.kernel.org X-Gm-Message-State: AOJu0YzNEHnSz328AwNAWtrCGIBuIdqzRrCM7j6S0KYjW42RFpk1SwZ1 +jr/f9TYcv3W9O1aRDI5+B/yYxIkzSCVtwHnRDN+ZgIvB+nvUAhu4511bEY78uU= X-Google-Smtp-Source: AGHT+IGYDEqISIJl9ctlQZb+4mYv7YJKqQHrlE6VL4Ec7aVtP9KKyc8lkY2pH9Td0Cs929GYSGBYnA== X-Received: by 2002:a05:6871:5292:b0:287:20ea:2db2 with SMTP id 586e51a60fabf-2962e0369a3mr4342642fac.25.1731701930037; Fri, 15 Nov 2024 12:18:50 -0800 (PST) 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 46e09a7af769-71a780ea62esm748978a34.5.2024.11.15.12.18.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Nov 2024 12:18:49 -0800 (PST) From: David Lechner Date: Fri, 15 Nov 2024 14:18:40 -0600 Subject: [PATCH v5 01/16] spi: add basic support for SPI offloading Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241115-dlech-mainline-spi-engine-offload-2-v5-1-bea815bd5ea5@baylibre.com> References: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> In-Reply-To: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , 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 Add the basic infrastructure to support SPI offload providers and consumers. SPI offloading is a feature that allows the SPI controller to perform transfers without any CPU intervention. This is useful, e.g. for high-speed data acquisition. SPI controllers with offload support need to implement the get_offload and put_offload callbacks and can use the devm_spi_offload_alloc() to allocate offload instances. SPI peripheral drivers will call devm_spi_offload_get() to get a reference to the matching offload instance. This offload instance can then be attached to a SPI message to request offloading that message. It is expected that SPI controllers with offload support will check for the offload instance in the SPI message in the ctlr->optimize_message() callback and handle it accordingly. CONFIG_SPI_OFFLOAD is intended to be a select-only option. Both consumer and provider drivers should `select SPI_OFFLOAD` in their Kconfig to ensure that the SPI core is built with offload support. Signed-off-by: David Lechner Reviewed-by: Jonathan Cameron --- v5 changes: * Don't include linux/property.h (moved to later patch). * Only allocate single offload instance instead of array. * Allocate *priv separately to avoid alignment issues. * Add put_offload() callback instead of assuming devm semantics. * Drop struct spi_offload::spi. It was only being used as a flag. * Don't get/put struct spi_offload::provider_dev. * Add MAINTAINERS entry for me as reviewer for anything related to SPI offload. v4 changes: * SPI offload functions moved to a separate file instead of spi.c (spi.c is already too long). * struct spi_offload and devm_spi_offload_get() are back, similar to but improved over v1. This avoids having to pass the function ID string to every function call and re-lookup the offload instance. * offload message prepare/unprepare functions are removed. Instead the existing optimize/unoptimize functions should be used. Setting spi_message::offload pointer is used as a flag to differentiate between an offloaded message and a regular message. v3 changes: * Minor changes to doc comments. * Changed to use phandle array for spi-offloads. * Changed id to string to make use of spi-offload-names. v2 changes: * This is a rework of "spi: add core support for controllers with offload capabilities" from v1. * The spi_offload_get() function that Nuno didn't like is gone. Instead, there is now a mapping callback that uses the new generic devicetree binding to request resources automatically when a SPI device is probed. * The spi_offload_enable/disable() functions for dealing with hardware triggers are deferred to a separate patch. * This leaves adding spi_offload_prepare/unprepare() which have been reworked to be a bit more robust. --- MAINTAINERS | 6 +++ drivers/spi/Kconfig | 3 ++ drivers/spi/Makefile | 1 + drivers/spi/spi-offload.c | 103 ++++++++++++++++++++++++++++++++++++++++ include/linux/spi/spi-offload.h | 60 +++++++++++++++++++++++ include/linux/spi/spi.h | 18 +++++++ 6 files changed, 191 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index bcc42036d635..75c8ca9a8584 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22019,6 +22019,12 @@ F: Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml F: drivers/mtd/spi-nor/ F: include/linux/mtd/spi-nor.h +SPI OFFLOAD +R: David Lechner +F: drivers/spi/spi-offload.c +F: include/linux/spi/spi-offload.h +K: spi_offload + SPI SUBSYSTEM M: Mark Brown L: linux-spi@vger.kernel.org diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index f51f9466e518..cdc483b0ec5c 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -55,6 +55,9 @@ config SPI_MEM This extension is meant to simplify interaction with SPI memories by providing a high-level interface to send memory-like commands. +config SPI_OFFLOAD + bool + comment "SPI Master Controller Drivers" config SPI_AIROHA_SNFI diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index aea5e54de195..39025ae5364d 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -10,6 +10,7 @@ ccflags-$(CONFIG_SPI_DEBUG) := -DDEBUG obj-$(CONFIG_SPI_MASTER) += spi.o obj-$(CONFIG_SPI_MEM) += spi-mem.o obj-$(CONFIG_SPI_MUX) += spi-mux.o +obj-$(CONFIG_SPI_OFFLOAD) += spi-offload.o obj-$(CONFIG_SPI_SPIDEV) += spidev.o obj-$(CONFIG_SPI_LOOPBACK_TEST) += spi-loopback-test.o diff --git a/drivers/spi/spi-offload.c b/drivers/spi/spi-offload.c new file mode 100644 index 000000000000..5ded7aecf9fc --- /dev/null +++ b/drivers/spi/spi-offload.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2024 Analog Devices Inc. + * Copyright (C) 2024 BayLibre, SAS + */ + +#define DEFAULT_SYMBOL_NAMESPACE SPI_OFFLOAD + +#include +#include +#include +#include +#include +#include +#include + +struct spi_controller_and_offload { + struct spi_controller *controller; + struct spi_offload *offload; +}; + +/** + * devm_spi_offload_alloc() - Allocate offload instance + * @dev: Device for devm purposes and assigned to &struct spi_offload.provider_dev + * @priv_size: Size of private data to allocate + * + * Offload providers should use this to allocate offload instances. + * + * Return: Pointer to new offload instance or error on failure. + */ +struct spi_offload *devm_spi_offload_alloc(struct device *dev, + size_t priv_size) +{ + struct spi_offload *offload; + void *priv; + + offload = devm_kzalloc(dev, sizeof(*offload), GFP_KERNEL); + if (!offload) + return ERR_PTR(-ENOMEM); + + priv = devm_kzalloc(dev, priv_size, GFP_KERNEL); + if (!priv) + return ERR_PTR(-ENOMEM); + + offload->provider_dev = dev; + offload->priv = priv; + + return offload; +} +EXPORT_SYMBOL_GPL(devm_spi_offload_alloc); + +static void spi_offload_put(void *data) +{ + struct spi_controller_and_offload *resource = data; + + resource->controller->put_offload(resource->offload); + kfree(resource); +} + +/** + * devm_spi_offload_get() - Get an offload instance + * @dev: Device for devm purposes + * @spi: SPI device to use for the transfers + * @config: Offload configuration + * + * Peripheral drivers call this function to get an offload instance that meets + * the requirements specified in @config. If no suitable offload instance is + * available, -ENODEV is returned. + * + * Return: Offload instance or error on failure. + */ +struct spi_offload *devm_spi_offload_get(struct device *dev, + struct spi_device *spi, + const struct spi_offload_config *config) +{ + struct spi_controller_and_offload *resource; + int ret; + + if (!spi || !config) + return ERR_PTR(-EINVAL); + + if (!spi->controller->get_offload) + return ERR_PTR(-ENODEV); + + resource = kzalloc(sizeof(*resource), GFP_KERNEL); + if (!resource) + return ERR_PTR(-ENOMEM); + + resource->controller = spi->controller; + resource->offload = spi->controller->get_offload(spi, config); + ret = PTR_ERR_OR_ZERO(resource->offload); + if (ret) { + kfree(resource); + return ERR_PTR(ret); + } + + ret = devm_add_action_or_reset(dev, spi_offload_put, resource); + if (ret) + return ERR_PTR(ret); + + return resource->offload; +} +EXPORT_SYMBOL_GPL(devm_spi_offload_get); diff --git a/include/linux/spi/spi-offload.h b/include/linux/spi/spi-offload.h new file mode 100644 index 000000000000..81b115fc89bf --- /dev/null +++ b/include/linux/spi/spi-offload.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2024 Analog Devices Inc. + * Copyright (C) 2024 BayLibre, SAS + */ + +/* + * SPI Offloading support. + * + * Some SPI controllers support offloading of SPI transfers. Essentially, this + * is the ability for a SPI controller to perform SPI transfers with minimal + * or even no CPU intervention, e.g. via a specialized SPI controller with a + * hardware trigger or via a conventional SPI controller using a non-Linux MCU + * processor core to offload the work. + */ + +#ifndef __LINUX_SPI_OFFLOAD_H +#define __LINUX_SPI_OFFLOAD_H + +#include + +MODULE_IMPORT_NS(SPI_OFFLOAD); + +struct device; +struct spi_device; + +/* 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. */ +#define SPI_OFFLOAD_CAP_TX_STATIC_DATA BIT(1) +/* Offload can get TX data from an external stream source. */ +#define SPI_OFFLOAD_CAP_TX_STREAM_DMA BIT(2) +/* Offload can send RX data to an external stream sink. */ +#define SPI_OFFLOAD_CAP_RX_STREAM_DMA BIT(3) + +/** + * struct spi_offload_config - offload configuration + * + * This is used to request an offload with specific configuration. + */ +struct spi_offload_config { + /** @capability_flags: required capabilities. See %SPI_OFFLOAD_CAP_* */ + u32 capability_flags; +}; + +/** + * struct spi_offload - offload instance + */ +struct spi_offload { + /** @provider_dev: for get/put reference counting */ + struct device *provider_dev; + /** @priv: provider driver private data */ + void *priv; +}; + +struct spi_offload *devm_spi_offload_alloc(struct device *dev, size_t priv_size); +struct spi_offload *devm_spi_offload_get(struct device *dev, struct spi_device *spi, + const struct spi_offload_config *config); + +#endif /* __LINUX_SPI_OFFLOAD_H */ diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 8497f4747e24..c2b24a0909ea 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -31,6 +31,9 @@ struct spi_transfer; struct spi_controller_mem_ops; struct spi_controller_mem_caps; struct spi_message; +struct spi_controller_offload_ops; +struct spi_offload; +struct spi_offload_config; /* * INTERFACES between SPI master-side drivers and SPI slave protocol handlers, @@ -496,6 +499,10 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch * @mem_ops: optimized/dedicated operations for interactions with SPI memory. * This field is optional and should only be implemented if the * controller has native support for memory like operations. + * @get_offload: callback for controllers with offload support to get matching + * offload instance. Implementations should return -ENODEV if no match is + * found. + * @put_offload: release the offload instance acquired by @get_offload. * @mem_caps: controller capabilities for the handling of memory operations. * @unprepare_message: undo any work done by prepare_message(). * @target_abort: abort the ongoing transfer request on an SPI target controller @@ -740,6 +747,10 @@ struct spi_controller { const struct spi_controller_mem_ops *mem_ops; const struct spi_controller_mem_caps *mem_caps; + struct spi_offload *(*get_offload)(struct spi_device *spi, + const struct spi_offload_config *config); + void (*put_offload)(struct spi_offload *offload); + /* GPIO chip select */ struct gpio_desc **cs_gpiods; bool use_gpio_descriptors; @@ -1108,6 +1119,7 @@ struct spi_transfer { * @state: for use by whichever driver currently owns the message * @opt_state: for use by whichever driver currently owns the message * @resources: for resource management when the SPI message is processed + * @offload: (optional) offload instance used by this message * * A @spi_message is used to execute an atomic sequence of data transfers, * each represented by a struct spi_transfer. The sequence is "atomic" @@ -1168,6 +1180,12 @@ struct spi_message { */ void *opt_state; + /* + * Optional offload instance used by this message. This must be set + * by the peripheral driver before calling spi_optimize_message(). + */ + struct spi_offload *offload; + /* List of spi_res resources when the SPI message is processed */ struct list_head resources; }; From patchwork Fri Nov 15 20:18:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 844886 Received: from mail-oo1-f51.google.com (mail-oo1-f51.google.com [209.85.161.51]) (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 07AD71E2821 for ; Fri, 15 Nov 2024 20:18:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701934; cv=none; b=uNKLYDo8tLlLkYpwONI1Q9qYDTimBrAkBmE0EdMRNcXrnDbj/CZc7kGhwf3PYr0OzId684PbuUO5kIB7MXkfEitkXg+tnvPBI4lmj325yGNlmKQfET3NDqoILCp+bKEatl0bzCFg4a3P0jNAWJ5hof7eJVf4X+VeJ5lXwV2bC3w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701934; c=relaxed/simple; bh=8QeWRFnBbPtiaZcfm19ZRxMBBZD3hN5n0PvnMAvk3oo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=edlY87RgU9DDNQShNubnUGC6dMBfQ2k/USO2Xd7ezqjXvF1dyeKnddBVjovegOccIXrOfgZfskqlcIiLCq6ERPc0LxGe/is0jpQlAtj2JQ3SMrnS5QqDI8DyuaIT0B73s8JrS58cH+lWz8BxQ4QvCu84mzXcTKlrYNfT46glsXE= 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=BQhVvQMF; arc=none smtp.client-ip=209.85.161.51 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="BQhVvQMF" Received: by mail-oo1-f51.google.com with SMTP id 006d021491bc7-5edf76cd843so1104322eaf.1 for ; Fri, 15 Nov 2024 12:18:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1731701931; x=1732306731; 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=cVmZptNuU1vXGigJJVK41C6i2cznUItpweQh61SG6wc=; b=BQhVvQMFCEnK9l4/PNHKEB7va/QXpFoyAWp8Azp6+4wZ2Sh3AMfqx9aoo2uXiNZhXf NmNFitpazX/69HKb/EF/+MBUtGuwDLUrQ8OEzIfYTdIf422tUxvPbTtATvYnyYxkwx8C DhfSL4tYS7H1s0u9f33wS27tB64mJUm+GrtJX0kOfBy6M3rKqGoWBRphvxAWCq7RdY0g ECdApofAV7SF81mbYau7oC1D+jY1i8/+wseUew5Qkrlv6H560USN36AHst9recmbv36I Er7TyBzDd6FoDJCX86yDHWqqYvvLPZaW9v/fo7dzhZqozjCYlYd831sFNijL56VYQg/i K9RA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731701931; x=1732306731; 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=cVmZptNuU1vXGigJJVK41C6i2cznUItpweQh61SG6wc=; b=LUlQwV/FO73BkO1ZQ0p7Y/zgGAcDMsBi2iPa8X7ngHvH07XH6hadp2QEjlCEbTi894 VvIif3K+fBXclUmNW3/givqjEwSV7CYoMNrXUnBMe41vAvuqGO7qnq54NvLUr9zq7jbo oj/xvw9EINM6mg8h+vxQBsF8/SKFAlaTP5m8BclLTr/yXAJTTpEWeNY6jK3XFlmVDNMl z5TWmiANsqVPzNlFa+aU3h3eJxEu/iEJ2KXDakGVcvWFB4WVmu1MWYXmgsfJjbmB396d RiPcxhOb411/XDGjCzmTvp1gB74CzAWUPd+hxcnGdEqSBkJPxwy3V1MTfxUfK9mVpHYU j9YA== X-Forwarded-Encrypted: i=1; AJvYcCXcUK1NcAmV2khN7EgV1ICnt8OcbgI2GqDCKIrsq715L4fBMzgiHiVW3b/VtN/Vs7ZYYtPSUoUL07k=@vger.kernel.org X-Gm-Message-State: AOJu0YwsMFeQM9/vs1FfsUVtGPiSMidE864WWeRJKAV0TC3U/BInPko6 o7EuYysJA1euDyCvY1qMObcADRxfMl1xxY96qzMY3KkgPNPHYQ9gBH61UcV/VVM= X-Google-Smtp-Source: AGHT+IE4fv6WbmHXgZUCDI/5mC+GQKuO54T2G3DEtL6XpRdxY0xjsMx28lO/JWAAA5f1H5azUtlOSA== X-Received: by 2002:a05:6820:a07:b0:5eb:6c26:1ca0 with SMTP id 006d021491bc7-5eeab2cc1c4mr3148345eaf.1.1731701930963; Fri, 15 Nov 2024 12:18:50 -0800 (PST) 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 46e09a7af769-71a780ea62esm748978a34.5.2024.11.15.12.18.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Nov 2024 12:18:50 -0800 (PST) From: David Lechner Date: Fri, 15 Nov 2024 14:18:41 -0600 Subject: [PATCH v5 02/16] spi: offload: add support for hardware triggers Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241115-dlech-mainline-spi-engine-offload-2-v5-2-bea815bd5ea5@baylibre.com> References: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> In-Reply-To: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , 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 Extend SPI offloading to support hardware triggers. This allows an arbitrary hardware trigger to be used to start a SPI transfer that was previously set up with spi_optimize_message(). A new struct spi_offload_trigger is introduced that can be used to configure any type of trigger. It has a type discriminator and a union to allow it to be extended in the future. Two trigger types are defined to start with. One is a trigger that indicates that the SPI peripheral is ready to read or write data. The other is a periodic trigger to repeat a SPI message at a fixed rate. There is also a spi_offload_hw_trigger_validate() function that works similar to clk_round_rate(). It basically asks the question of if we enabled the hardware trigger what would the actual parameters be. This can be used to test if the requested trigger type is actually supported by the hardware and for periodic triggers, it can be used to find the actual rate that the hardware is capable of. Signed-off-by: David Lechner Reviewed-by: Jonathan Cameron --- v5 changes: * Use struct kref instead of struct dev for trigger lifetime management. * Don't use __free() for args.fwnode. * Pass *trigger instead of *priv to all callbacks. * Add new *spi_offload_trigger_get_priv() function. * Use ops instead of priv for "provider is gone" flag. * Combine devm_spi_offload_trigger_alloc() and devm_spi_offload_trigger_register() into one function. * Add kernel-doc comments for public functions. v4 changes: * Added new struct spi_offload_trigger that is a generic struct for any hardware trigger rather than returning a struct clk. * Added new spi_offload_hw_trigger_validate() function. * Dropped extra locking since it was too restrictive. v3 changes: * renamed enable/disable functions to spi_offload_hw_trigger_*mode*_... * added spi_offload_hw_trigger_get_clk() function * fixed missing EXPORT_SYMBOL_GPL v2 changes: * This is split out from "spi: add core support for controllers with offload capabilities". * Added locking for offload trigger to claim exclusive use of the SPI bus. --- drivers/spi/spi-offload.c | 279 ++++++++++++++++++++++++++++++++++++++++ include/linux/spi/spi-offload.h | 80 ++++++++++++ 2 files changed, 359 insertions(+) diff --git a/drivers/spi/spi-offload.c b/drivers/spi/spi-offload.c index 5ded7aecf9fc..01d7b632d109 100644 --- a/drivers/spi/spi-offload.c +++ b/drivers/spi/spi-offload.c @@ -9,7 +9,11 @@ #include #include #include +#include +#include #include +#include +#include #include #include #include @@ -19,6 +23,23 @@ struct spi_controller_and_offload { struct spi_offload *offload; }; +struct spi_offload_trigger { + struct list_head list; + struct kref ref; + struct fwnode_handle *fwnode; + /* synchronizes calling ops and driver registration */ + struct mutex lock; + /* + * If the provider goes away while the consumer still has a reference, + * ops and priv will be set to NULL and all calls will fail with -ENODEV. + */ + const struct spi_offload_trigger_ops *ops; + void *priv; +}; + +static LIST_HEAD(spi_offload_triggers); +static DEFINE_MUTEX(spi_offload_triggers_lock); + /** * devm_spi_offload_alloc() - Allocate offload instance * @dev: Device for devm purposes and assigned to &struct spi_offload.provider_dev @@ -101,3 +122,261 @@ struct spi_offload *devm_spi_offload_get(struct device *dev, return resource->offload; } EXPORT_SYMBOL_GPL(devm_spi_offload_get); + +static void spi_offload_trigger_free(struct kref *ref) +{ + struct spi_offload_trigger *trigger = + container_of(ref, struct spi_offload_trigger, ref); + + mutex_destroy(&trigger->lock); + fwnode_handle_put(trigger->fwnode); + kfree(trigger); +} + +static void spi_offload_trigger_put(void *data) +{ + struct spi_offload_trigger *trigger = data; + + scoped_guard(mutex, &trigger->lock) + if (trigger->ops && trigger->ops->release) + trigger->ops->release(trigger); + + kref_put(&trigger->ref, spi_offload_trigger_free); +} + +static struct spi_offload_trigger +*spi_offload_trigger_get(enum spi_offload_trigger_type type, + struct fwnode_reference_args *args) +{ + struct spi_offload_trigger *trigger; + bool match = false; + int ret; + + guard(mutex)(&spi_offload_triggers_lock); + + list_for_each_entry(trigger, &spi_offload_triggers, list) { + if (trigger->fwnode != args->fwnode) + continue; + + match = trigger->ops->match(trigger, type, args->args, args->nargs); + if (match) + break; + } + + if (!match) + return ERR_PTR(-EPROBE_DEFER); + + guard(mutex)(&trigger->lock); + + if (!trigger->ops) + return ERR_PTR(-ENODEV); + + if (trigger->ops->request) { + ret = trigger->ops->request(trigger, type, args->args, args->nargs); + if (ret) + return ERR_PTR(ret); + } + + kref_get(&trigger->ref); + + return trigger; +} + +/** + * devm_spi_offload_trigger_get() - Get an offload trigger instance + * @dev: Device for devm purposes. + * @offload: Offload instance connected to a trigger. + * @type: Trigger type to get. + * + * Return: Offload trigger instance or error on failure. + */ +struct spi_offload_trigger +*devm_spi_offload_trigger_get(struct device *dev, + struct spi_offload *offload, + enum spi_offload_trigger_type type) +{ + struct spi_offload_trigger *trigger; + struct fwnode_reference_args args; + int ret; + + ret = fwnode_property_get_reference_args(dev_fwnode(offload->provider_dev), + "trigger-sources", + "#trigger-source-cells", 0, 0, + &args); + if (ret) + return ERR_PTR(ret); + + trigger = spi_offload_trigger_get(type, &args); + fwnode_handle_put(args.fwnode); + if (IS_ERR(trigger)) + return trigger; + + ret = devm_add_action_or_reset(dev, spi_offload_trigger_put, trigger); + if (ret) + return ERR_PTR(ret); + + return trigger; +} +EXPORT_SYMBOL_GPL(devm_spi_offload_trigger_get); + +/** + * spi_offload_trigger_validate - Validate the requested trigger + * @trigger: Offload trigger instance + * @config: Trigger config to validate + * + * On success, @config may be modifed to reflect what the hardware can do. + * For example, the frequency of a periodic trigger may be adjusted to the + * nearest supported value. + * + * Callers will likely need to do additional validation of the modified trigger + * parameters. + * + * Return: 0 on success, negative error code on failure. + */ +int spi_offload_trigger_validate(struct spi_offload_trigger *trigger, + struct spi_offload_trigger_config *config) +{ + guard(mutex)(&trigger->lock); + + if (!trigger->ops) + return -ENODEV; + + if (!trigger->ops->validate) + return -EOPNOTSUPP; + + return trigger->ops->validate(trigger, config); +} +EXPORT_SYMBOL_GPL(spi_offload_trigger_validate); + +/** + * spi_offload_trigger_enable - enables trigger for offload + * @trigger: Offload trigger instance + * @config: Trigger config to validate + * + * There must be a prepared offload instance with the specified ID (i.e. + * spi_optimize_message() was called with the same offload assigned to the + * message). This will also reserve the bus for exclusive use by the offload + * instance until the trigger is disabled. Any other attempts to send a + * transfer or lock the bus will fail with -EBUSY during this time. + * + * Calls must be balanced with spi_offload_trigger_disable(). + * + * Context: can sleep + * Return: 0 on success, else a negative error code. + */ +int spi_offload_trigger_enable(struct spi_offload *offload, + struct spi_offload_trigger *trigger, + struct spi_offload_trigger_config *config) +{ + int ret; + + guard(mutex)(&trigger->lock); + + if (!trigger->ops) + return -ENODEV; + + if (offload->ops && offload->ops->trigger_enable) { + ret = offload->ops->trigger_enable(offload); + if (ret) + return ret; + } + + if (trigger->ops->enable) { + ret = trigger->ops->enable(trigger, config); + if (ret) { + if (offload->ops->trigger_disable) + offload->ops->trigger_disable(offload); + return ret; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(spi_offload_trigger_enable); + +/** + * spi_offload_trigger_disable - disables hardware trigger for offload + * @offload: Offload instance + * + * Disables the hardware trigger for the offload instance with the specified ID + * and releases the bus for use by other clients. + * + * Context: can sleep + */ +void spi_offload_trigger_disable(struct spi_offload *offload, + struct spi_offload_trigger *trigger) +{ + if (offload->ops && offload->ops->trigger_disable) + offload->ops->trigger_disable(offload); + + guard(mutex)(&trigger->lock); + + if (!trigger->ops) + return; + + if (trigger->ops->disable) + trigger->ops->disable(trigger); +} +EXPORT_SYMBOL_GPL(spi_offload_trigger_disable); + +/* Triggers providers */ + +static void spi_offload_trigger_unregister(void *data) +{ + struct spi_offload_trigger *trigger = data; + + scoped_guard(mutex, &spi_offload_triggers_lock) + list_del(&trigger->list); + + scoped_guard(mutex, &trigger->lock) { + trigger->priv = NULL; + trigger->ops = NULL; + } + + kref_put(&trigger->ref, spi_offload_trigger_free); +} + +/** + * devm_spi_offload_trigger_register() - Allocate and register an offload trigger + * @dev: Device for devm purposes. + * @info: Provider-specific trigger info. + * + * Return: 0 on success, else a negative error code. + */ +int devm_spi_offload_trigger_register(struct device *dev, + struct spi_offload_trigger_info *info) +{ + struct spi_offload_trigger *trigger; + + if (!info->fwnode || !info->ops) + return -EINVAL; + + trigger = kzalloc(sizeof(*trigger), GFP_KERNEL); + if (!trigger) + return -ENOMEM; + + kref_init(&trigger->ref); + mutex_init(&trigger->lock); + trigger->fwnode = fwnode_handle_get(info->fwnode); + trigger->ops = info->ops; + trigger->priv = info->priv; + + scoped_guard(mutex, &spi_offload_triggers_lock) + list_add_tail(&trigger->list, &spi_offload_triggers); + + return devm_add_action_or_reset(dev, spi_offload_trigger_unregister, trigger); +} +EXPORT_SYMBOL_GPL(devm_spi_offload_trigger_register); + +/** + * spi_offload_trigger_get_priv() - Get the private data for the trigger + * + * @trigger: Offload trigger instance. + * + * Return: Private data for the trigger. + */ +void *spi_offload_trigger_get_priv(struct spi_offload_trigger *trigger) +{ + return trigger->priv; +} +EXPORT_SYMBOL_GPL(spi_offload_trigger_get_priv); diff --git a/include/linux/spi/spi-offload.h b/include/linux/spi/spi-offload.h index 81b115fc89bf..c8c673784e99 100644 --- a/include/linux/spi/spi-offload.h +++ b/include/linux/spi/spi-offload.h @@ -22,6 +22,7 @@ MODULE_IMPORT_NS(SPI_OFFLOAD); struct device; +struct fwnode_handle; struct spi_device; /* Offload can be triggered by external hardware event. */ @@ -51,10 +52,89 @@ struct spi_offload { struct device *provider_dev; /** @priv: provider driver private data */ void *priv; + /** @ops: callbacks for offload support */ + const struct spi_offload_ops *ops; +}; + +enum spi_offload_trigger_type { + /* Indication from SPI peripheral that data is read to read. */ + SPI_OFFLOAD_TRIGGER_DATA_READY, + /* Trigger comes from a periodic source such as a clock. */ + SPI_OFFLOAD_TRIGGER_PERIODIC, +}; + +struct spi_offload_trigger_periodic { + u64 frequency_hz; +}; + +struct spi_offload_trigger_config { + /** @type: type discriminator for union */ + enum spi_offload_trigger_type type; + union { + struct spi_offload_trigger_periodic periodic; + }; +}; + +/** + * struct spi_offload_ops - callbacks implemented by offload providers + */ +struct spi_offload_ops { + /** + * @trigger_enable: Optional callback to enable the trigger for the + * given offload instance. + */ + int (*trigger_enable)(struct spi_offload *offload); + /** + * @trigger_disable: Optional callback to disable the trigger for the + * given offload instance. + */ + void (*trigger_disable)(struct spi_offload *offload); }; struct spi_offload *devm_spi_offload_alloc(struct device *dev, size_t priv_size); struct spi_offload *devm_spi_offload_get(struct device *dev, struct spi_device *spi, const struct spi_offload_config *config); +struct spi_offload_trigger +*devm_spi_offload_trigger_get(struct device *dev, + struct spi_offload *offload, + enum spi_offload_trigger_type type); +int spi_offload_trigger_validate(struct spi_offload_trigger *trigger, + struct spi_offload_trigger_config *config); +int spi_offload_trigger_enable(struct spi_offload *offload, + struct spi_offload_trigger *trigger, + struct spi_offload_trigger_config *config); +void spi_offload_trigger_disable(struct spi_offload *offload, + struct spi_offload_trigger *trigger); + +/* Trigger providers */ + +struct spi_offload_trigger; + +struct spi_offload_trigger_ops { + bool (*match)(struct spi_offload_trigger *trigger, + enum spi_offload_trigger_type type, u64 *args, u32 nargs); + int (*request)(struct spi_offload_trigger *trigger, + enum spi_offload_trigger_type type, u64 *args, u32 nargs); + void (*release)(struct spi_offload_trigger *trigger); + int (*validate)(struct spi_offload_trigger *trigger, + struct spi_offload_trigger_config *config); + int (*enable)(struct spi_offload_trigger *trigger, + struct spi_offload_trigger_config *config); + void (*disable)(struct spi_offload_trigger *trigger); +}; + +struct spi_offload_trigger_info { + /** @fwnode: Provider fwnode, used to match to consumer. */ + struct fwnode_handle *fwnode; + /** @ops: Provider-specific callbacks. */ + const struct spi_offload_trigger_ops *ops; + /** Provider-specific state to be used in callbacks. */ + void *priv; +}; + +int devm_spi_offload_trigger_register(struct device *dev, + struct spi_offload_trigger_info *info); +void *spi_offload_trigger_get_priv(struct spi_offload_trigger *trigger); + #endif /* __LINUX_SPI_OFFLOAD_H */ From patchwork Fri Nov 15 20:18:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 843779 Received: from mail-oa1-f47.google.com (mail-oa1-f47.google.com [209.85.160.47]) (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 BF9321E2846 for ; Fri, 15 Nov 2024 20:18:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701935; cv=none; b=sxEyNWf4vcEi5zrxXyi0/KpQqinHgVWXPdHCgvN/dxrE5QGweOA7q5Y9FE4F5UAWiiSSwLViI9lMo2mkKQY625nPykSX8lbRouWujBtZaTXeSQMUddXNoQrRjcDa7zlZ+xu2GdZNJupDYXntIpI7N1rPQlFT/eqAq8h60/afknI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701935; c=relaxed/simple; bh=/brcg85kbnd2G8W/XlwOERT7c14hy3w6WyG/qyK3teM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=P73hO2F2ZVfTGUE9zfCJUadsHd3XjtjXR0u/lqRKbXpx9cH86sz8Ly0aiBVWSqGrw/2vJIzBUWzJqHao8Qv1Bg5B8uMZr2TJwvP55srfRPhpXrnr6/DFBY/q1cGTrZAj5YR98PcV0Ud351sIS/NdYoII0sUTtsw9R/k0Z8gd1g4= 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=hleUTxoT; arc=none smtp.client-ip=209.85.160.47 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="hleUTxoT" Received: by mail-oa1-f47.google.com with SMTP id 586e51a60fabf-290ff24354dso13282fac.0 for ; Fri, 15 Nov 2024 12:18:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1731701933; x=1732306733; 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=mRU4AU2p10ANc+DkhnwT4CXPMLQZx70yMguYOCpfFSY=; b=hleUTxoT1VZU4cAgMHLKRXPdHPg2xv04kUBAv51NpVmEObB8PM0ApWZ4NZZ4kz1tX5 Wm67MnmAiJYgZVLkrcrrUkEiIM0XrfeRm0HYii9qRUYiNHWOzm7RfJcVx2ijoK4dEyNW 9DnLfERBZ56Lr20mMv0izH8om2eSTbU+W+e/Y9nWFSFAnhy6IVDcfl0v/Y6twqBBNjhJ aFdBu3U7d/jiollqz+W5nP9L89N1RcbJEvOqhgOBQELrU4gSaOu3h3Ves0C2wWW3b1P1 kVENjuDeG8dgjXcCfMKq+VOPLskrpX6yq4ZcWi9Lzpge6NltfGnLahseieiSrlYs3jSP 0urA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731701933; x=1732306733; 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=mRU4AU2p10ANc+DkhnwT4CXPMLQZx70yMguYOCpfFSY=; b=bzGnVyuW7BYGCZYjICFSxdLdEo3IDjgvS3pFnShRWf9V8vMq/Fi8RszECF9v6U0l6K ayhDiRUTEdRcpRYW7+LUHwnJcwR1wtRB6Cr4RMxXPtPaqRAAYk5IJpZsu6MLb6UMqwLQ czcHyg5MeNFuKl1HbDZryH4cjudHAzNVHagk9S0hHdDC/INsj3HQr2fIjClCxjSUmG/u vYFW1UrZfL2mimhFjiGQoNt1sBtFFwe+JOZ5+61LQ9o6GpCPXlPBlnf/2EB1qtbLzXur 4VcP9ptt1URSHXS5820Is+m9Hy0aDXEDwXlHwzWgmB9P6zEV3L4TPZga7XT4YyIAYgH7 RN/w== X-Forwarded-Encrypted: i=1; AJvYcCX7w+RqVep/9jnfxtbnApfr+2MVGHF1NMTFN6Du7lowjQAjqfZjOJoazjF2YzFbLaeMvLs7WarwgYc=@vger.kernel.org X-Gm-Message-State: AOJu0YyYjDiPQ/SF8UcK2Se1PvAW+/46u7RnObKKMbxyaH8RJKAdadm4 uhTcyyOcPUdzZ+eQE97clzcxRapWVxznHAvAmtnzw8xk34JxwwE1Pv7G196QnPU= X-Google-Smtp-Source: AGHT+IEq4dvxzsxFEL++1N4Levf1DEfOWHAxo1ifVYZbayZTOwOVP2E9GaVwjZAe8BvQjJvrahEhEQ== X-Received: by 2002:a05:6870:96a2:b0:287:0:9ecc with SMTP id 586e51a60fabf-2962dfe8e32mr4184189fac.33.1731701932849; Fri, 15 Nov 2024 12:18:52 -0800 (PST) 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 46e09a7af769-71a780ea62esm748978a34.5.2024.11.15.12.18.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Nov 2024 12:18:52 -0800 (PST) From: David Lechner Date: Fri, 15 Nov 2024 14:18:42 -0600 Subject: [PATCH v5 03/16] spi: dt-bindings: add trigger-source.yaml Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241115-dlech-mainline-spi-engine-offload-2-v5-3-bea815bd5ea5@baylibre.com> References: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> In-Reply-To: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , 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 Add a new binding for SPI offload trigger sources. Signed-off-by: David Lechner --- v5 changes: * Add MAINTAINERS entry. v4 changes: new patch in v4. FWIW, this is essentially identical to the leds trigger-source binding. --- .../devicetree/bindings/spi/trigger-source.yaml | 28 ++++++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 29 insertions(+) diff --git a/Documentation/devicetree/bindings/spi/trigger-source.yaml b/Documentation/devicetree/bindings/spi/trigger-source.yaml new file mode 100644 index 000000000000..d64367726af2 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/trigger-source.yaml @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/trigger-source.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Trigger source providers for SPI offloads + +maintainers: + - David Lechner + +description: + Each trigger source provider should be represented by a device tree node. It + may be e.g. a SPI peripheral chip or a clock source. + +properties: + '#trigger-source-cells': + description: + Number of cells in a source trigger. Typically 0 for nodes of simple + trigger sources. For nodes with more than one output signal, the first + cell be used to specify which output signal to use. If the same signal is + available on more than one pin, the second cell can be used to specify + which pin to use. + enum: [ 0, 1, 2 ] + +additionalProperties: true + +... diff --git a/MAINTAINERS b/MAINTAINERS index 75c8ca9a8584..91a4a7eb6194 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22021,6 +22021,7 @@ F: include/linux/mtd/spi-nor.h SPI OFFLOAD R: David Lechner +F: Documentation/devicetree/bindings/spi/trigger-source.yaml F: drivers/spi/spi-offload.c F: include/linux/spi/spi-offload.h K: spi_offload From patchwork Fri Nov 15 20:18:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 844885 Received: from mail-oa1-f42.google.com (mail-oa1-f42.google.com [209.85.160.42]) (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 A069C1E3DCE for ; Fri, 15 Nov 2024 20:18:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701938; cv=none; b=NvewW5lv2nuCVnCu4fgjjjJaMxMQFwqhx6RT3irOOyKKBypKTnO9tvmJRq1FrLltbDAjpAvp4zpFFglnI2h3MmpbZSjZu1xDwONCNk6BYrX1McdXBc5LSLgDBw8srd+Ae40cWM8HdLTEsGq2R7RqmmAyXrIay9qa/J0ff4rUyQ8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701938; c=relaxed/simple; bh=wsgGx84cWBUtGa7G4wtbH/BWpIo6zEAdmqzXQ6w3/1c=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=nq2sM5ML+Czh4TyXeVR7I3MNzaXH3XS+VZ4Icbl6CVKvIm4CDYE3R6p5x5H1K/AGCLvwsivuitk8/YG3rG9WULX+obli/IzRPyNmjz/oAmb4XRY2h/4+rXKuPAwztcLqZhKDOwBfJHw38Xlz0dgh1+6cIvwawwoPkDIKYzP8JCw= 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=Hc2TLK+W; arc=none smtp.client-ip=209.85.160.42 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="Hc2TLK+W" Received: by mail-oa1-f42.google.com with SMTP id 586e51a60fabf-288a90e4394so1074948fac.0 for ; Fri, 15 Nov 2024 12:18:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1731701936; x=1732306736; 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=3err676nsDhVRmrJ3FZsk1bPZcnOqEf2IqEsHND5yQ8=; b=Hc2TLK+WCyNylftJ1Ghnqidab30k6a4FIErC/STwtwJSYhYIlLKpCKr8YkU0qS25By CGd5WXUj26ThVrYTDKN39NTX3AA4AFT0DwzE7Y+i4O+XgFBJyCyJHl6JdRlMaYfunjgI kAkeN4NWU3T7DXmjHTV+sKA73+RjCFKhoy/oDliAOHuTBpqjuD4RsRKEOANE3079kGdc 14Kb5dJb6MkeZ38pimvMKEvbTal92aisGTNF8FLms533xxtKW+iJfbDtw1CiS5E73MvP 8yohe8hrel29Kd3ArwbUku/q9CFyK2pVfzAbxjNfCYwMCzUGLLVfCf3f6o44gKxdgvcO MDmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731701936; x=1732306736; 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=3err676nsDhVRmrJ3FZsk1bPZcnOqEf2IqEsHND5yQ8=; b=wLq/XGbR1qyBMfyvXHX4Zw3dInWUde5IIKWBGHq9wmFHaNS1lmdCnD3iVoJB7VO8GB Wzib0DtnVcxBJ7LZ9KAT2Jp8dgfikZOD90G9k/uQhg0ukZLgsLH2TgtqHMxdeudlISXh EjhaDIU8Wqy3g/ABxJnxiXsWyuTimHRCfcBAgDBFvtBmsO+Yxe9JmV907RuxScam07oN 8msTO+H9ipJYeq0MzWXnz0IFW1ARdjyoBCWcHWE4AEQlbu4VidSuWlp8qT5eYLurnSOb eOGq1ibYdIKRjCp7BMbetwOQIjhCVOY+A4KRs33F5uTmEUkfLsXIfY0BUM+lOSxl0fEV A77g== X-Forwarded-Encrypted: i=1; AJvYcCWaOxj8nOsGIU5XALAOOPhA1nRtFIqJ4eb+7NeBicrT4psb8WFMz/EKigU4sYA/lMerQjuuZP8tb/8=@vger.kernel.org X-Gm-Message-State: AOJu0YyPmaHFcWZ7X95eGyyDRGY1ZVr2JMj5XDNlgLDTMQdb9oxnBRZz VsU0BsZVK50J/ZmfqnS9tr/sfVnIxKob87ESnJdljgOTuKq42MYc0t9pLlXNmbo= X-Google-Smtp-Source: AGHT+IFslhtXy2tcMW9lG2cdKDAvgBpEw3gZ1sN7XsFjpAzVktIDpcBrd6KtQD9GxRg2iyWZ/5Xb+g== X-Received: by 2002:a05:6870:7028:b0:287:b9:349 with SMTP id 586e51a60fabf-2962e20d981mr3793513fac.36.1731701935768; Fri, 15 Nov 2024 12:18:55 -0800 (PST) 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 46e09a7af769-71a780ea62esm748978a34.5.2024.11.15.12.18.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Nov 2024 12:18:54 -0800 (PST) From: David Lechner Date: Fri, 15 Nov 2024 14:18:43 -0600 Subject: [PATCH v5 04/16] spi: dt-bindings: add PWM SPI offload trigger Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241115-dlech-mainline-spi-engine-offload-2-v5-4-bea815bd5ea5@baylibre.com> References: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> In-Reply-To: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , 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 Add a new binding for using a PWM signal as a trigger for SPI offloads. Signed-off-by: David Lechner --- v5 changes: * Add MAINTAINERS entry v4 changes: new patch in v4 --- .../devicetree/bindings/spi/trigger-pwm.yaml | 39 ++++++++++++++++++++++ MAINTAINERS | 1 + 2 files changed, 40 insertions(+) diff --git a/Documentation/devicetree/bindings/spi/trigger-pwm.yaml b/Documentation/devicetree/bindings/spi/trigger-pwm.yaml new file mode 100644 index 000000000000..987638aa4732 --- /dev/null +++ b/Documentation/devicetree/bindings/spi/trigger-pwm.yaml @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spi/trigger-pwm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Generic SPI offload trigger using PWM + +description: Remaps a PWM channel as a trigger source. + +maintainers: + - David Lechner + +$ref: /schemas/spi/trigger-source.yaml# + +properties: + compatible: + const: trigger-pwm + + '#trigger-source-cells': + const: 0 + + pwms: + maxItems: 1 + +required: + - compatible + - '#trigger-source-cells' + - pwms + +additionalProperties: false + +examples: + - | + trigger { + compatible = "trigger-pwm"; + #trigger-source-cells = <0>; + pwms = <&pwm 0 1000000 0>; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 91a4a7eb6194..a43532a1edde 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22021,6 +22021,7 @@ F: include/linux/mtd/spi-nor.h SPI OFFLOAD R: David Lechner +F: Documentation/devicetree/bindings/spi/trigger-pwm.yaml F: Documentation/devicetree/bindings/spi/trigger-source.yaml F: drivers/spi/spi-offload.c F: include/linux/spi/spi-offload.h From patchwork Fri Nov 15 20:18:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 843778 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 99FFF1E5733 for ; Fri, 15 Nov 2024 20:18:58 +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=1731701941; cv=none; b=Qo8zzeg5EQg2+bi3QFjHlIu24Mh7e+7C+DcEvwdeQIMEpiOQknl6CcrJoYZfIY1Otr+WJgvoqsCTEUvlmhvOxF7qqn10G1u4/01gJqw4cwgCAUX7h1nwVz0zs+30EG/9sk3uVBw3Kb8rc66oVqN7+oxrCLkctwysRZ4aSVnxCYo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701941; c=relaxed/simple; bh=EOrNOpVWi5EnXRP0UHniNwzvlTT9ETmHZWZMFC0dRL4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=oaFajRRWlsjd1lTPJ7HPTfUH9lTqN30fqS1ok6MzVXwGMxEEa+lU2rAcsBC0y6cijyOB8ClnOoFtQ2FZ9bsl/S6zzkKmN9W5vHolx8zYzKEHSlwFntqSIQAeXoiZMnFpbtlGf7IMY9oer7RUmD3jAY2yGIY5bC5I0htr9/CkuNI= 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=k1rg/IUX; 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="k1rg/IUX" Received: by mail-oo1-f45.google.com with SMTP id 006d021491bc7-5ee645cf763so1181051eaf.2 for ; Fri, 15 Nov 2024 12:18:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1731701938; x=1732306738; 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=t7IS98DAXMrAPkmBeqmORVUNuKNfq4F6AMKjYOvJmjo=; b=k1rg/IUXPQIFLvPDLcEDyAKj8U007qJy/DfuA26fiGdk5FD0ZVt8Po4OtNm8udWu7E II1dY03Zu548P0r62f8RGgt8nzKZCA/ehTpcBRr1k6Ae66YUCv3PLRTV89Fuk6cdGNBN r9IDf7v5rOkh4Y95oPRdx8PfnGpMtZG/sCvNTAcLCUJxLxHxLltAu/5Az8Gq8QwxnXg0 MbHsc+O8Il3A0K2lZ99iSZnG9dSKv51Jxt+S61fM7CgjocGp94G3xU3VxUr1RJLyYm3I x8HXN1BJ5AMZYijdfB2xJxNtgxUvZAOXpSIukuUmqpAZZw7AeZX9Md1wx/zL0hKcqlhH FgoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731701938; x=1732306738; 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=t7IS98DAXMrAPkmBeqmORVUNuKNfq4F6AMKjYOvJmjo=; b=c4DoxvVkrN/LfED8zN3s/6OOYVNaedqcogDu1n5yvnmvLnJj86+HFwcY+06H8e/6jC ooou6ZtN6ir50iWTUTuxigz425jS4ySRqbNOPOYWLGXSF2Da+PJ80p8Sht0EjJYNe76N yV1koLg2QksgA82wFeusJNenchG6Ea5DATLnMwwU2L+tlfLhUsJpZtJlAGgDjmAzY8h1 YZ+s/kJpSbs0cKiJ7yKYAgjOR/EbQ9IRzi82UhAhFTSTDE3vMpK0YKBVeUgg4RY7gE1F VeKUr4m7hZmho8m+EX6knavKtvGeDNEG2yFCYThp1ONzVkDXgMx3sRXP7QxoIbnIPJwc Kq8g== X-Forwarded-Encrypted: i=1; AJvYcCVjSZ8/0+y+ioxKg8udQA4mBj15GENvbXU0lDvaQwAcJCXNnnPK3ecC8RCmwiSZQjIogWJPnsmdps4=@vger.kernel.org X-Gm-Message-State: AOJu0YyP1h8bXy0lHVHvC3T9joyCbr7qs1kl9/RMu+QIwCHOngEdjavw ShWS1HpIsVzR2KDfEcdw23vzJZdHWgSTQI/B0hZBuli3vhiDkzRzgerkd8gThRI= X-Google-Smtp-Source: AGHT+IFHeOlL2szpnhn4w4uUrf+kcWOlOBXXrP/zlahKkvyGqcUo6Oac5nm5vBqKn+mlHYLrAPqrcQ== X-Received: by 2002:a05:6820:4c88:b0:5eb:c6ba:783b with SMTP id 006d021491bc7-5eeab29d4a5mr3913047eaf.1.1731701937692; Fri, 15 Nov 2024 12:18:57 -0800 (PST) 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 46e09a7af769-71a780ea62esm748978a34.5.2024.11.15.12.18.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Nov 2024 12:18:57 -0800 (PST) From: David Lechner Date: Fri, 15 Nov 2024 14:18:44 -0600 Subject: [PATCH v5 05/16] spi: offload-trigger: add PWM trigger driver Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241115-dlech-mainline-spi-engine-offload-2-v5-5-bea815bd5ea5@baylibre.com> References: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> In-Reply-To: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , 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 Add a new driver for a generic PWM trigger for SPI offloads. Signed-off-by: David Lechner Reviewed-by: Jonathan Cameron --- v5 changes: * Updated to accommodate changes in other patches in this series. * Add MAINTAINERS entry. v4 changes: new patch in v4 --- MAINTAINERS | 1 + drivers/spi/Kconfig | 12 +++ drivers/spi/Makefile | 3 + drivers/spi/spi-offload-trigger-pwm.c | 162 ++++++++++++++++++++++++++++++++++ 4 files changed, 178 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index a43532a1edde..36a40aaa026a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22023,6 +22023,7 @@ SPI OFFLOAD R: David Lechner F: Documentation/devicetree/bindings/spi/trigger-pwm.yaml F: Documentation/devicetree/bindings/spi/trigger-source.yaml +F: drivers/spi/spi-offload-trigger-pwm.c F: drivers/spi/spi-offload.c F: include/linux/spi/spi-offload.h K: spi_offload diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index cdc483b0ec5c..867d4b55bef9 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -1308,4 +1308,16 @@ endif # SPI_SLAVE config SPI_DYNAMIC def_bool ACPI || OF_DYNAMIC || SPI_SLAVE +if SPI_OFFLOAD + +comment "SPI Offload triggers" + +config SPI_OFFLOAD_TRIGGER_PWM + tristate "SPI offload trigger using PWM" + depends on PWM + help + Generic SPI offload trigger implemented using PWM output. + +endif # SPI_OFFLOAD + endif # SPI diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 39025ae5364d..9396d32e1994 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -163,3 +163,6 @@ obj-$(CONFIG_SPI_AMD) += spi-amd.o # SPI slave protocol handlers obj-$(CONFIG_SPI_SLAVE_TIME) += spi-slave-time.o obj-$(CONFIG_SPI_SLAVE_SYSTEM_CONTROL) += spi-slave-system-control.o + +# SPI offload triggers +obj-$(CONFIG_SPI_OFFLOAD_TRIGGER_PWM) += spi-offload-trigger-pwm.o diff --git a/drivers/spi/spi-offload-trigger-pwm.c b/drivers/spi/spi-offload-trigger-pwm.c new file mode 100644 index 000000000000..7e1b4a80becc --- /dev/null +++ b/drivers/spi/spi-offload-trigger-pwm.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2024 Analog Devices Inc. + * Copyright (C) 2024 BayLibre, SAS + * + * Generic PWM trigger for SPI offload. + */ + +#include +#include +#include +#include +#include + +struct spi_offload_trigger_pwm_state { + struct device *dev; + struct pwm_device *pwm; +}; + +static bool spi_offload_trigger_pwm_match(struct spi_offload_trigger *trigger, + enum spi_offload_trigger_type type, + u64 *args, u32 nargs) +{ + if (nargs) + return false; + + return type == SPI_OFFLOAD_TRIGGER_PERIODIC; +} + +static int spi_offload_trigger_pwm_validate(struct spi_offload_trigger *trigger, + struct spi_offload_trigger_config *config) +{ + struct spi_offload_trigger_pwm_state *st = spi_offload_trigger_get_priv(trigger); + struct spi_offload_trigger_periodic *periodic = &config->periodic; + struct pwm_waveform wf = { }; + int ret; + + if (config->type != SPI_OFFLOAD_TRIGGER_PERIODIC) + return -EINVAL; + + if (!periodic->frequency_hz) + return -EINVAL; + + wf.period_length_ns = DIV_ROUND_UP_ULL(NSEC_PER_SEC, periodic->frequency_hz); + /* REVISIT: 50% duty-cycle for now - may add config parameter later */ + wf.duty_length_ns = wf.period_length_ns / 2; + + ret = pwm_round_waveform_might_sleep(st->pwm, &wf); + if (ret < 0) + return ret; + + periodic->frequency_hz = DIV_ROUND_UP_ULL(NSEC_PER_SEC, wf.period_length_ns); + + return 0; +} + +static int spi_offload_trigger_pwm_enable(struct spi_offload_trigger *trigger, + struct spi_offload_trigger_config *config) +{ + struct spi_offload_trigger_pwm_state *st = spi_offload_trigger_get_priv(trigger); + struct spi_offload_trigger_periodic *periodic = &config->periodic; + struct pwm_waveform wf = { }; + + if (config->type != SPI_OFFLOAD_TRIGGER_PERIODIC) + return -EINVAL; + + if (!periodic->frequency_hz) + return -EINVAL; + + wf.period_length_ns = DIV_ROUND_UP_ULL(NSEC_PER_SEC, periodic->frequency_hz); + /* REVISIT: 50% duty-cycle for now - may add config parameter later */ + wf.duty_length_ns = wf.period_length_ns / 2; + + return pwm_set_waveform_might_sleep(st->pwm, &wf, false); +} + +static void spi_offload_trigger_pwm_disable(struct spi_offload_trigger *trigger) +{ + struct spi_offload_trigger_pwm_state *st = spi_offload_trigger_get_priv(trigger); + struct pwm_waveform wf; + int ret; + + ret = pwm_get_waveform_might_sleep(st->pwm, &wf); + if (ret < 0) { + dev_err(st->dev, "failed to get waveform: %d\n", ret); + return; + } + + wf.duty_length_ns = 0; + + ret = pwm_set_waveform_might_sleep(st->pwm, &wf, false); + if (ret < 0) + dev_err(st->dev, "failed to disable PWM: %d\n", ret); +} + +static const struct spi_offload_trigger_ops spi_offload_trigger_pwm_ops = { + .match = spi_offload_trigger_pwm_match, + .validate = spi_offload_trigger_pwm_validate, + .enable = spi_offload_trigger_pwm_enable, + .disable = spi_offload_trigger_pwm_disable, +}; + +static void spi_offload_trigger_pwm_release(void *data) +{ + pwm_disable(data); +} + +static int spi_offload_trigger_pwm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct spi_offload_trigger_info info = { + .fwnode = dev_fwnode(dev), + .ops = &spi_offload_trigger_pwm_ops, + }; + struct spi_offload_trigger_pwm_state *st; + struct pwm_state state; + int ret; + + st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL); + if (!st) + return -ENOMEM; + + info.priv = st; + st->dev = dev; + + st->pwm = devm_pwm_get(&pdev->dev, NULL); + if (IS_ERR(st->pwm)) + return dev_err_probe(dev, PTR_ERR(st->pwm), "failed to get PWM\n"); + + /* init with duty_cycle = 0, output enabled to ensure trigger off */ + pwm_init_state(st->pwm, &state); + state.enabled = true; + + ret = pwm_apply_might_sleep(st->pwm, &state); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to apply PWM state\n"); + + ret = devm_add_action_or_reset(dev, spi_offload_trigger_pwm_release, st->pwm); + if (ret) + return ret; + + return devm_spi_offload_trigger_register(dev, &info); +} + +static const struct of_device_id spi_offload_trigger_pwm_of_match_table[] = { + { .compatible = "trigger-pwm" }, + { } +}; +MODULE_DEVICE_TABLE(of, spi_offload_trigger_pwm_of_match_table); + +static struct platform_driver spi_offload_trigger_pwm_driver = { + .driver = { + .name = "trigger-pwm", + .of_match_table = spi_offload_trigger_pwm_of_match_table, + }, + .probe = spi_offload_trigger_pwm_probe, +}; +module_platform_driver(spi_offload_trigger_pwm_driver); + +MODULE_AUTHOR("David Lechner "); +MODULE_DESCRIPTION("Generic PWM trigger"); +MODULE_LICENSE("GPL"); From patchwork Fri Nov 15 20:18:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 844884 Received: from mail-oa1-f41.google.com (mail-oa1-f41.google.com [209.85.160.41]) (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 76F5E1E7641 for ; Fri, 15 Nov 2024 20:18:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701942; cv=none; b=kyJYsQfYBpuTGWFJkrHxkR506nJN47qBGKgJq9OhiB6uDBEW2xP1ZbIf8mJaE6zQTGxZOykNKve2yZNTQKvj1lqVtSCvfIqk6QektJB69OHwonr3Hw3FTGxnEp9WdNskfw6Rh24cTmsymxBGJU7wobDvp1jbWrozWFbf4fh9PS0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701942; c=relaxed/simple; bh=lHDQPMwP/f0vQi/LB7g/3w7zJV7pZTr+cdbnP18cpFk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=bQ2vEpj+GTItxQZJVISnXzv9O25YOaa2O1a19qopJU6B3RHNkCJ82+l9RosIES3nKO7qOJy57bpAstTqPqQmwoxGIfSnN0n0SHm2Ovjh8SXfGb75lKWfA13m1wOqIEdY42ltn8wFUzdpCMDy3U1O4rZWbAEhb+QLaRoUM3cg1mo= 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=R6c6CIeV; arc=none smtp.client-ip=209.85.160.41 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="R6c6CIeV" Received: by mail-oa1-f41.google.com with SMTP id 586e51a60fabf-295cee3a962so1303905fac.3 for ; Fri, 15 Nov 2024 12:18:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1731701938; x=1732306738; 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=OPVL9IOUqvtFQfEuJrra9pvdj030MVfb0lKKNV1PGXo=; b=R6c6CIeVHIWKx2lZs8e3l40s1sKmmBa+b2zU599WLI44U8VzWhVqIBOB4tgOM1v+DM APKXGewytHdX2zQJJQ+q+ccyl4xchUciapzkO1J3+lU892XlB1gv0Q+qBj1DF8eUBBXW J8DdWsPPNbc2H3Q7MN56cOfNYzkJ4mmnDlufgW7noNBqKL/KkMZdbnRZA00jqGsivKtd Ivw/igXsaBQXsvvS8dGGmzxyK0NxIAO6YyMkqnLnSx7e7ynzXXcVqTZfegYOawoQpc7W 9F6TIfHlpqqMehkAn46yHMEM8RVwfy0DS3+GRL2ygzdF7JB0Qwecf4AvP5T/ohjTuwqh fD6A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731701938; x=1732306738; 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=OPVL9IOUqvtFQfEuJrra9pvdj030MVfb0lKKNV1PGXo=; b=CuUS3GtFmHI5aIXQDKMJjQBQpP+GdzyPdqNy9ElfcfbCGOcFj6Ik2OZuQCoVCCNBs/ I5a+0E2unCU2eNMx1dJ0e9XEUZ2hfMJ1sX9okkasavjEIuTegjb0lcNriLlIlg57sDYg U1qjljpib9wWDOJrX0+AQl3t7JJleI6RJwzSzcmh64KwXptd5OszKeQFqbX2OdnSL4xp nnOTVEOsyTYY1WuuvZ5aKoVHu/UVJqftF/2GOkh9vK/ZAV2QdcQCvzVbuBKnOW6eJUMQ uut+R/L5WvGHc6cLEm0yp8ky2aQKTc4Yd9bepW6eikBfpOjucPoPOYBeuBQfnUEtQ2Ne 3nJA== X-Forwarded-Encrypted: i=1; AJvYcCV0UnibNv0q8U6t2c9zthn0EI5vnLuWvuf0r140eIPY/ZoGq8z+i6pwHRiR445Oh7zVB1y9es8+JPo=@vger.kernel.org X-Gm-Message-State: AOJu0YxhOrpCLCrQ29eRkmA3uejOBGZS5gTTgmYCqpuN1COGQVA+oAMR AtGTTJwzkaNZfeXfMgjR2KrvM7sa6PWLVF/DpfcBzyHG+fAQaAyvt+DRFpcldAo= X-Google-Smtp-Source: AGHT+IFKWlC4vrCp05d3/1c9UNzH+kf3T3fxbtPXzPVlfEhklc/TU9XpmmRHVZeejKXSJzbZd/jR9w== X-Received: by 2002:a05:6870:3923:b0:288:2906:6882 with SMTP id 586e51a60fabf-2962dfeec01mr4621330fac.29.1731701938603; Fri, 15 Nov 2024 12:18:58 -0800 (PST) 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 46e09a7af769-71a780ea62esm748978a34.5.2024.11.15.12.18.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Nov 2024 12:18:58 -0800 (PST) From: David Lechner Date: Fri, 15 Nov 2024 14:18:45 -0600 Subject: [PATCH v5 06/16] spi: add offload TX/RX streaming APIs Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241115-dlech-mainline-spi-engine-offload-2-v5-6-bea815bd5ea5@baylibre.com> References: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> In-Reply-To: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , 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 --- v5 change: * Remove incorrect comment about caller needing to release DMA channels. 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 | 70 +++++++++++++++++++++++++++++++++++++++++ drivers/spi/spi.c | 10 ++++++ include/linux/spi/spi-offload.h | 24 ++++++++++++++ include/linux/spi/spi.h | 3 ++ 4 files changed, 107 insertions(+) diff --git a/drivers/spi/spi-offload.c b/drivers/spi/spi-offload.c index 01d7b632d109..7b3e20ad9e4f 100644 --- a/drivers/spi/spi-offload.c +++ b/drivers/spi/spi-offload.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -319,6 +320,75 @@ void spi_offload_trigger_disable(struct spi_offload *offload, } EXPORT_SYMBOL_GPL(spi_offload_trigger_disable); +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. + * + * 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 = offload->ops->tx_stream_request_dma_chan(offload); + if (IS_ERR(chan)) + return chan; + + ret = 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. + * + * 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 = offload->ops->rx_stream_request_dma_chan(offload); + if (IS_ERR(chan)) + return chan; + + ret = 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 */ static void spi_offload_trigger_unregister(void *data) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 74e04a4b0f19..47020bd033bd 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, struct spi_message *message) 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; + } } message->status = -EINPROGRESS; diff --git a/include/linux/spi/spi-offload.h b/include/linux/spi/spi-offload.h index c8c673784e99..132b2f819b91 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; +/* 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. */ @@ -54,6 +59,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; }; enum spi_offload_trigger_type { @@ -89,6 +96,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 *offload); + /** + * @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 *offload); }; struct spi_offload *devm_spi_offload_alloc(struct device *dev, size_t priv_size); @@ -107,6 +126,11 @@ int spi_offload_trigger_enable(struct spi_offload *offload, void spi_offload_trigger_disable(struct spi_offload *offload, struct spi_offload_trigger *trigger); +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 */ struct spi_offload_trigger; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index c2b24a0909ea..e7e612e30a2f 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -1094,6 +1094,9 @@ struct spi_transfer { u32 effective_speed_hz; + /* Use %SPI_OFFLOAD_XFER_* from spi-offload.h */ + unsigned int offload_flags; + unsigned int ptp_sts_word_pre; unsigned int ptp_sts_word_post; From patchwork Fri Nov 15 20:18:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 843777 Received: from mail-oo1-f51.google.com (mail-oo1-f51.google.com [209.85.161.51]) (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 6AD291E7671 for ; Fri, 15 Nov 2024 20:19:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701942; cv=none; b=SXyNRUrLY+dHislxSVpFVfxXBIWF2cIHctooLcseHjC7pW+rlUOVjPPHBdtyNCggm3BryypenHsqB6TBz3nKLO0KL5vafBo6qt5xq6kIt//ckMmPEgFyqiQbtonsNWCgldaU+cGLfN7avnSkX/OkiAAkrOOteIrzKb6lTxe0DuQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701942; c=relaxed/simple; bh=n3gvwTh1zq8LlUg6hocRmmA4Ouflzb8V3XorZLtL5w4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=V+PUziwN2jvl6fiVhNKnnXpkdrjW9ZKRSXLJnSpIBvMUiLTQbw+CFAWjOkmPpl1wkpkjACI7hRKUmXprlQyZb88oM5CS3rD5kXyRHGNnWDzK1lhWG8SZUgpKs1nPoVjoeYrDmFQTapehrjyF6eDAnjAttoCsA8hezS3aLgadDFQ= 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=EGIhGVzr; arc=none smtp.client-ip=209.85.161.51 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="EGIhGVzr" Received: by mail-oo1-f51.google.com with SMTP id 006d021491bc7-5ebc349204cso1155074eaf.3 for ; Fri, 15 Nov 2024 12:19:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1731701939; x=1732306739; 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=unmeYdeBn+D1ZmpuSEm58bDvDpLySt7nxP95EdRhLZ8=; b=EGIhGVzrPnCQqFzGqlEBlsPSFk2yk6HjE8FrCX7NpXMjF/X4qu3rwygcOVjNR+m2k9 SWU73rXaSRVJ4zC4imZuBukk/aLKZLsY5EjXmOHRbCEmacq6pDRBneVzmpAfXm/D6Do6 grgBZlAJuktmg/mBOhesZOEBvimhZpdxSHtrslhvAc4yP1DOALdtr/BXRu23gGAGPf2P wtLRO3pFcNpA+ct3K7V3G71KmMwPuC8spJpfRMSQF3PbM2RPZ7V/6EVQMlpPhD+0R/ot gvaNFfQx8L/1pltZ4QGGsBJ27yDC0sLzk3AoyFGFVuVCORCIuRNeccqC+lfVRcp1ac51 vJIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731701939; x=1732306739; 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=unmeYdeBn+D1ZmpuSEm58bDvDpLySt7nxP95EdRhLZ8=; b=qB0s6u3W+DdawI1FqFRaI9VI1u1ZVmYqGi5zMHva/0ScPWb8CJ8n4UHAU4PqU/MX7K 6Z3fYZKyQPVymWFzQMxJn7ATxP6auNnr9aYPe1xcRDMQwykb7Vl7E1Vw9MhiLba1tHZQ RHVOcLLSbfPSE1On6JRT4Jr/yP/C8wFP32Fjg0q8ZXQrZ1GeZGsbtUR3bLOTIt6u4f1r NEO4f8YViDz12jtIkLsTSoeK8v7eDAgFoKYGfr2ZNq1b4/ZXY108qt/CDl7f0zWFpWJW ATs5BRg5AV9NlEFjlQOGHRplx+toTl0+K7k2Uk1t+nwbLFBFUrNBI7ENWc1fA0PIGEFs G9Lg== X-Forwarded-Encrypted: i=1; AJvYcCVHisZxz/SfSv6spdQ5MjmOQQPeENUSiX7Ak+yLwVRzopXGb4XD/0j8OKV3TFw34sKjyQbT1EN6xrs=@vger.kernel.org X-Gm-Message-State: AOJu0YwMZKiOWhr7GtYycBQib+un8N+iYAupfLb/XYzcV+v097hO34bn FpW5iyawZHy0DhfFHd8kQjqeVhj2u32cuHy+qL9PXWHv92YhwoEIM6nOz2hva3Q= X-Google-Smtp-Source: AGHT+IHeF5FoHsWnd/xYfNXHiRj6XV96twgJUsRypMRtTcUzak6K6jO+tc0oO8DmmLcbRnoHfwfN1Q== X-Received: by 2002:a05:6820:983:b0:5eb:6a67:6255 with SMTP id 006d021491bc7-5eeab2c11ffmr3502045eaf.1.1731701939465; Fri, 15 Nov 2024 12:18:59 -0800 (PST) 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 46e09a7af769-71a780ea62esm748978a34.5.2024.11.15.12.18.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Nov 2024 12:18:59 -0800 (PST) From: David Lechner Date: Fri, 15 Nov 2024 14:18:46 -0600 Subject: [PATCH v5 07/16] spi: dt-bindings: axi-spi-engine: add SPI offload properties Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241115-dlech-mainline-spi-engine-offload-2-v5-7-bea815bd5ea5@baylibre.com> References: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> In-Reply-To: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , 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 The AXI SPI Engine has support for hardware offloading capabilities. This includes a connection to a DMA controller for streaming RX data and a trigger input for starting execution of the SPI message programmed in the offload. Each SPI Engine may have up to 1 offload. The spec actually says that it could support up to 32, so we are using an index number in the dma-names (e.g. offload0-rx) to allow for this possibility in the future. Signed-off-by: David Lechner --- v5 changes: * Also document offload0-tx DMA names since the hardware can support that now. * Limit the number of offloads to 1 for now since it would require significant hardware changes to actually support more than that. v4 changes: * Dropped #spi-offload-cells property. * Changed subject line. v3 changes: * Added #spi-offload-cells property. * Added properties for triggers and RX data stream connected to DMA. v2 changes: * This is basically a new patch. It partially replaces "dt-bindings: iio: offload: add binding for PWM/DMA triggered buffer". * The controller no longer has an offloads object node and the spi-offloads property is now a standard SPI peripheral property. --- .../bindings/spi/adi,axi-spi-engine.yaml | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Documentation/devicetree/bindings/spi/adi,axi-spi-engine.yaml b/Documentation/devicetree/bindings/spi/adi,axi-spi-engine.yaml index d48faa42d025..d703b47eb498 100644 --- a/Documentation/devicetree/bindings/spi/adi,axi-spi-engine.yaml +++ b/Documentation/devicetree/bindings/spi/adi,axi-spi-engine.yaml @@ -41,6 +41,26 @@ properties: - const: s_axi_aclk - const: spi_clk + trigger-sources: + description: + An array of trigger source phandles for offload instances. The index in + the array corresponds to the offload instance number. + $ref: /schemas/types.yaml#/definitions/phandle-array + maxItems: 1 + + dmas: + description: + DMA channels connected to the input or output stream interface of an + offload instance. + minItems: 1 + maxItems: 2 + + dma-names: + items: + pattern: "^offload0-[tr]x$" + minItems: 1 + maxItems: 2 + required: - compatible - reg @@ -59,6 +79,10 @@ examples: clocks = <&clkc 15>, <&clkc 15>; clock-names = "s_axi_aclk", "spi_clk"; + trigger-sources = <&trigger_clock>; + dmas = <&dma 0>; + dma-names = "offload0-rx"; + #address-cells = <1>; #size-cells = <0>; From patchwork Fri Nov 15 20:18:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 844883 Received: from mail-ot1-f48.google.com (mail-ot1-f48.google.com [209.85.210.48]) (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 7C1781E9073 for ; Fri, 15 Nov 2024 20:19:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701944; cv=none; b=QHLb8x+nCrUNJfArqh7n7yx0D1nRddDTbuSmmbnh2sUB0j/pumdrC38qqkGEVdaePGde4PbQZMEGNxeGuCMRf+pe/S+BlBerXzZ4OiuFHGSIymKr1naKMLnvhNQrS3crp9nrArLg/qziqvLJkc4dfe3ShDKgaSOsbJb0AcM8XOo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701944; c=relaxed/simple; bh=erKKZRVUn7IwrRaCIDy7XYkV9HY0K/mNJSiRh3VE4VY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HVaVLELD03372XAM2VO4fDayZ7JEeTi6A9mILk4u38hk00Oh3r0TaTxFPbCOumD5AbjCalO2wFglPBDvrrgGURK+GaF8HqWz0Q4tR8yThUOKKpf+9hDCwpYKEzkAJSS3G19KjY6Jvz7krEdNsC5efvi8mSBvgLaylXju2VMU5NY= 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=C3AZV1W1; arc=none smtp.client-ip=209.85.210.48 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="C3AZV1W1" Received: by mail-ot1-f48.google.com with SMTP id 46e09a7af769-7180f2f5fb0so536642a34.1 for ; Fri, 15 Nov 2024 12:19:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1731701940; x=1732306740; 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=PYPeRBi9nrELQs979W4XEUoH02dIXOt6zRUj5jB314E=; b=C3AZV1W1hdpBM8tiRrVtqK/uBkExgv3KzBjnOAN4pLnnuox9gnNklYc+b/tCw/t/DC 5csUhT4R9rOzQoX7Kh2r3NDSKwNVAhHSvdx8gux67BF62MFxteSw7nrk2als6INVnyaY goBzkCMc6tHwZA7Yh3mefemai5eISk/AH6jHzhzH3yMIz/eydC6iVh/S2FNoo+Pce5NZ Mk4KSZqhR895FZWGBjzWsjfg6IbJW6kDV7meBlsfmTtpTlygOw6OJhL5LKrD2Ei7B11t bDBIcg/6ucAjdjKXBzemZHnixVD9e5t6l7uWvqyUr6tL5IVHI0G3eHRvgsqdJH2knbzX lr1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731701940; x=1732306740; 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=PYPeRBi9nrELQs979W4XEUoH02dIXOt6zRUj5jB314E=; b=R9vY/tnQN+67z5jdH2rkk8mTzLRi/1Yts23riXyL4wQAA24VC4FkMakYEvjtK/zs+G XZG36iqdarsug8TuwNamR5Mf11U6jjL6sDZHKzlLZPIQfmvSGy95ETT472o3Pe+Ml0j6 Wr/u3V14gElg59/zu3+F98+eSJM76Pux8bx16KRMyxKC9j84ZRVvFXsFi3BiINjkzaCe YrSNNBaJVi9A4Kff8QeJV5jqPzz70i8wo1Lp+/w9xlCHv+tMehqi9HLwAdobWXH8b5Yo hGnko8P3+GQyq+YpQ5kaKnZCiVYE2dIUy+1WpnlFRmrQNldSFjL3mTxjv4MPgl65HLsc a/mQ== X-Forwarded-Encrypted: i=1; AJvYcCVxFF/Mn3EvlX0fe2+RxCxyDH7wPRqw7n9+OexgWZfiairUrcIuNk2fV2DufjFE7JcY/VbnpWfA9OU=@vger.kernel.org X-Gm-Message-State: AOJu0YwlFBOu2iMlslrKODO31Ehgt9eVMcJ1qoVNeVXNjCITmrIjEWbj D7ql5FDB2esg+8JfsY7AMaOODhtyzXoew5V9mbSwz3KpKzDLi6KkcXIeiTW2m0M= X-Google-Smtp-Source: AGHT+IHMGVKi0FqsBN5EszNDDL8jXkOP8TayUeRcOI/MUXnbSEj5fQ0Os+LSjCLYDsLnL8MyGGdFWw== X-Received: by 2002:a05:6830:600a:b0:719:cd05:c7fe with SMTP id 46e09a7af769-71a7798f130mr4876373a34.17.1731701940414; Fri, 15 Nov 2024 12:19:00 -0800 (PST) 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 46e09a7af769-71a780ea62esm748978a34.5.2024.11.15.12.18.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Nov 2024 12:19:00 -0800 (PST) From: David Lechner Date: Fri, 15 Nov 2024 14:18:47 -0600 Subject: [PATCH v5 08/16] spi: axi-spi-engine: implement offload support Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241115-dlech-mainline-spi-engine-offload-2-v5-8-bea815bd5ea5@baylibre.com> References: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> In-Reply-To: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , 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 Implement SPI offload support for the AXI SPI Engine. Currently, the hardware only supports triggering offload transfers with a hardware trigger so attempting to use an offload message in the regular SPI message queue will fail. Also, only allows streaming rx data to an external sink, so attempts to use a rx_buf in the offload message will fail. Signed-off-by: David Lechner Reviewed-by: Jonathan Cameron --- v5 changes: * Set offload capability flags based on DT properties. * Add support for TX DMA since the hardware supports that now. * Update for changes in other patches in the series. v4 changes: * Adapted to changes in other patches in the series. * Moved trigger enable/disable to same function as offload enable/disable. v3 changes: * Added clk and dma_chan getter callbacks. * Fixed some bugs. v2 changes: This patch has been reworked to accommodate the changes described in all of the other patches. --- drivers/spi/Kconfig | 1 + drivers/spi/spi-axi-spi-engine.c | 314 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 308 insertions(+), 7 deletions(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 867d4b55bef9..b7bbead647eb 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -179,6 +179,7 @@ config SPI_AU1550 config SPI_AXI_SPI_ENGINE tristate "Analog Devices AXI SPI Engine controller" depends on HAS_IOMEM + select SPI_OFFLOAD help This enables support for the Analog Devices AXI SPI Engine SPI controller. It is part of the SPI Engine framework that is used in some Analog Devices diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index 9386ddc4714e..172a9f1f1ead 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -2,11 +2,14 @@ /* * SPI-Engine SPI controller driver * Copyright 2015 Analog Devices Inc. + * Copyright 2024 BayLibre, SAS * Author: Lars-Peter Clausen */ +#include #include #include +#include #include #include #include @@ -14,9 +17,11 @@ #include #include #include +#include #include #include +#define SPI_ENGINE_REG_OFFLOAD_MEM_ADDR_WIDTH 0x10 #define SPI_ENGINE_REG_RESET 0x40 #define SPI_ENGINE_REG_INT_ENABLE 0x80 @@ -24,6 +29,7 @@ #define SPI_ENGINE_REG_INT_SOURCE 0x88 #define SPI_ENGINE_REG_SYNC_ID 0xc0 +#define SPI_ENGINE_REG_OFFLOAD_SYNC_ID 0xc4 #define SPI_ENGINE_REG_CMD_FIFO_ROOM 0xd0 #define SPI_ENGINE_REG_SDO_FIFO_ROOM 0xd4 @@ -34,10 +40,24 @@ #define SPI_ENGINE_REG_SDI_DATA_FIFO 0xe8 #define SPI_ENGINE_REG_SDI_DATA_FIFO_PEEK 0xec +#define SPI_ENGINE_MAX_NUM_OFFLOADS 32 + +#define SPI_ENGINE_REG_OFFLOAD_CTRL(x) (0x100 + SPI_ENGINE_MAX_NUM_OFFLOADS * (x)) +#define SPI_ENGINE_REG_OFFLOAD_STATUS(x) (0x104 + SPI_ENGINE_MAX_NUM_OFFLOADS * (x)) +#define SPI_ENGINE_REG_OFFLOAD_RESET(x) (0x108 + SPI_ENGINE_MAX_NUM_OFFLOADS * (x)) +#define SPI_ENGINE_REG_OFFLOAD_CMD_FIFO(x) (0x110 + SPI_ENGINE_MAX_NUM_OFFLOADS * (x)) +#define SPI_ENGINE_REG_OFFLOAD_SDO_FIFO(x) (0x114 + SPI_ENGINE_MAX_NUM_OFFLOADS * (x)) + +#define SPI_ENGINE_SPI_OFFLOAD_MEM_WIDTH_SDO GENMASK(15, 8) +#define SPI_ENGINE_SPI_OFFLOAD_MEM_WIDTH_CMD GENMASK(7, 0) + #define SPI_ENGINE_INT_CMD_ALMOST_EMPTY BIT(0) #define SPI_ENGINE_INT_SDO_ALMOST_EMPTY BIT(1) #define SPI_ENGINE_INT_SDI_ALMOST_FULL BIT(2) #define SPI_ENGINE_INT_SYNC BIT(3) +#define SPI_ENGINE_INT_OFFLOAD_SYNC BIT(4) + +#define SPI_ENGINE_OFFLOAD_CTRL_ENABLE BIT(0) #define SPI_ENGINE_CONFIG_CPHA BIT(0) #define SPI_ENGINE_CONFIG_CPOL BIT(1) @@ -79,6 +99,10 @@ #define SPI_ENGINE_CMD_CS_INV(flags) \ SPI_ENGINE_CMD(SPI_ENGINE_INST_CS_INV, 0, (flags)) +/* default sizes - can be changed when SPI Engine firmware is compiled */ +#define SPI_ENGINE_OFFLOAD_CMD_FIFO_SIZE 16 +#define SPI_ENGINE_OFFLOAD_SDO_FIFO_SIZE 16 + struct spi_engine_program { unsigned int length; uint16_t instructions[] __counted_by(length); @@ -106,6 +130,17 @@ struct spi_engine_message_state { uint8_t *rx_buf; }; +enum { + SPI_ENGINE_OFFLOAD_FLAG_ASSIGNED, + SPI_ENGINE_OFFLOAD_FLAG_PREPARED, +}; + +struct spi_engine_offload { + struct spi_engine *spi_engine; + unsigned long flags; + unsigned int offload_num; +}; + struct spi_engine { struct clk *clk; struct clk *ref_clk; @@ -118,6 +153,11 @@ struct spi_engine { unsigned int int_enable; /* shadows hardware CS inversion flag state */ u8 cs_inv; + + unsigned int offload_ctrl_mem_size; + unsigned int offload_sdo_mem_size; + struct spi_offload *offload; + u32 offload_caps; }; static void spi_engine_program_add_cmd(struct spi_engine_program *p, @@ -163,9 +203,9 @@ static void spi_engine_gen_xfer(struct spi_engine_program *p, bool dry, unsigned int n = min(len, 256U); unsigned int flags = 0; - if (xfer->tx_buf) + if (xfer->tx_buf || (xfer->offload_flags & SPI_OFFLOAD_XFER_TX_STREAM)) flags |= SPI_ENGINE_TRANSFER_WRITE; - if (xfer->rx_buf) + if (xfer->rx_buf || (xfer->offload_flags & SPI_OFFLOAD_XFER_RX_STREAM)) flags |= SPI_ENGINE_TRANSFER_READ; spi_engine_program_add_cmd(p, dry, @@ -221,16 +261,24 @@ static void spi_engine_gen_cs(struct spi_engine_program *p, bool dry, * * NB: This is separate from spi_engine_compile_message() because the latter * is called twice and would otherwise result in double-evaluation. + * + * Returns 0 on success, -EINVAL on failure. */ -static void spi_engine_precompile_message(struct spi_message *msg) +static int spi_engine_precompile_message(struct spi_message *msg) { unsigned int clk_div, max_hz = msg->spi->controller->max_speed_hz; struct spi_transfer *xfer; list_for_each_entry(xfer, &msg->transfers, transfer_list) { + /* If we have an offload transfer, we can't rx to buffer */ + if (msg->offload && xfer->rx_buf) + return -EINVAL; + clk_div = DIV_ROUND_UP(max_hz, xfer->speed_hz); xfer->effective_speed_hz = max_hz / min(clk_div, 256U); } + + return 0; } static void spi_engine_compile_message(struct spi_message *msg, bool dry, @@ -545,11 +593,105 @@ static irqreturn_t spi_engine_irq(int irq, void *devid) return IRQ_HANDLED; } +static int spi_engine_offload_prepare(struct spi_message *msg) +{ + struct spi_controller *host = msg->spi->controller; + struct spi_engine *spi_engine = spi_controller_get_devdata(host); + struct spi_engine_program *p = msg->opt_state; + struct spi_engine_offload *priv = msg->offload->priv; + struct spi_transfer *xfer; + void __iomem *cmd_addr; + void __iomem *sdo_addr; + size_t tx_word_count = 0; + unsigned int i; + + if (p->length > spi_engine->offload_ctrl_mem_size) + return -EINVAL; + + /* count total number of tx words in message */ + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + /* no support for reading to rx_buf */ + if (xfer->rx_buf) + return -EINVAL; + + if (!xfer->tx_buf) + continue; + + if (xfer->bits_per_word <= 8) + tx_word_count += xfer->len; + else if (xfer->bits_per_word <= 16) + tx_word_count += xfer->len / 2; + else + tx_word_count += xfer->len / 4; + } + + if (tx_word_count && !(spi_engine->offload_caps & SPI_OFFLOAD_CAP_TX_STATIC_DATA)) + return -EINVAL; + + if (tx_word_count > spi_engine->offload_sdo_mem_size) + return -EINVAL; + + /* + * This protects against calling spi_optimize_message() with an offload + * that has already been prepared with a different message. + */ + if (test_and_set_bit_lock(SPI_ENGINE_OFFLOAD_FLAG_PREPARED, &priv->flags)) + return -EBUSY; + + cmd_addr = spi_engine->base + + SPI_ENGINE_REG_OFFLOAD_CMD_FIFO(priv->offload_num); + sdo_addr = spi_engine->base + + SPI_ENGINE_REG_OFFLOAD_SDO_FIFO(priv->offload_num); + + list_for_each_entry(xfer, &msg->transfers, transfer_list) { + if (!xfer->tx_buf) + continue; + + if (xfer->bits_per_word <= 8) { + const u8 *buf = xfer->tx_buf; + + for (i = 0; i < xfer->len; i++) + writel_relaxed(buf[i], sdo_addr); + } else if (xfer->bits_per_word <= 16) { + const u16 *buf = xfer->tx_buf; + + for (i = 0; i < xfer->len / 2; i++) + writel_relaxed(buf[i], sdo_addr); + } else { + const u32 *buf = xfer->tx_buf; + + for (i = 0; i < xfer->len / 4; i++) + writel_relaxed(buf[i], sdo_addr); + } + } + + for (i = 0; i < p->length; i++) + writel_relaxed(p->instructions[i], cmd_addr); + + return 0; +} + +static void spi_engine_offload_unprepare(struct spi_offload *offload) +{ + struct spi_engine_offload *priv = offload->priv; + struct spi_engine *spi_engine = priv->spi_engine; + + writel_relaxed(1, spi_engine->base + + SPI_ENGINE_REG_OFFLOAD_RESET(priv->offload_num)); + writel_relaxed(0, spi_engine->base + + SPI_ENGINE_REG_OFFLOAD_RESET(priv->offload_num)); + + clear_bit_unlock(SPI_ENGINE_OFFLOAD_FLAG_PREPARED, &priv->flags); +} + static int spi_engine_optimize_message(struct spi_message *msg) { struct spi_engine_program p_dry, *p; + int ret; - spi_engine_precompile_message(msg); + ret = spi_engine_precompile_message(msg); + if (ret) + return ret; p_dry.length = 0; spi_engine_compile_message(msg, true, &p_dry); @@ -561,20 +703,61 @@ static int spi_engine_optimize_message(struct spi_message *msg) spi_engine_compile_message(msg, false, p); spi_engine_program_add_cmd(p, false, SPI_ENGINE_CMD_SYNC( - AXI_SPI_ENGINE_CUR_MSG_SYNC_ID)); + msg->offload ? 0 : AXI_SPI_ENGINE_CUR_MSG_SYNC_ID)); msg->opt_state = p; + if (msg->offload) { + ret = spi_engine_offload_prepare(msg); + if (ret) { + msg->opt_state = NULL; + kfree(p); + return ret; + } + } + return 0; } static int spi_engine_unoptimize_message(struct spi_message *msg) { + if (msg->offload) + spi_engine_offload_unprepare(msg->offload); + kfree(msg->opt_state); return 0; } +static struct spi_offload +*spi_engine_get_offload(struct spi_device *spi, + const struct spi_offload_config *config) +{ + struct spi_controller *host = spi->controller; + struct spi_engine *spi_engine = spi_controller_get_devdata(host); + struct spi_engine_offload *priv; + + if (!spi_engine->offload) + return ERR_PTR(-ENODEV); + + if (config->capability_flags & ~spi_engine->offload_caps) + return ERR_PTR(-EINVAL); + + priv = spi_engine->offload->priv; + + if (test_and_set_bit_lock(SPI_ENGINE_OFFLOAD_FLAG_ASSIGNED, &priv->flags)) + return ERR_PTR(-EBUSY); + + return spi_engine->offload; +} + +static void spi_engine_put_offload(struct spi_offload *offload) +{ + struct spi_engine_offload *priv = offload->priv; + + clear_bit_unlock(SPI_ENGINE_OFFLOAD_FLAG_ASSIGNED, &priv->flags); +} + static int spi_engine_setup(struct spi_device *device) { struct spi_controller *host = device->controller; @@ -607,6 +790,12 @@ static int spi_engine_transfer_one_message(struct spi_controller *host, unsigned int int_enable = 0; unsigned long flags; + if (msg->offload) { + dev_err(&host->dev, "Single transfer offload not supported\n"); + msg->status = -EOPNOTSUPP; + goto out; + } + /* reinitialize message state for this transfer */ memset(st, 0, sizeof(*st)); st->cmd_buf = p->instructions; @@ -656,11 +845,68 @@ static int spi_engine_transfer_one_message(struct spi_controller *host, trace_spi_transfer_stop(msg, xfer); } +out: spi_finalize_current_message(host); return msg->status; } +static int spi_engine_trigger_enable(struct spi_offload *offload) +{ + struct spi_engine_offload *priv = offload->priv; + struct spi_engine *spi_engine = priv->spi_engine; + unsigned int reg; + + reg = readl_relaxed(spi_engine->base + + SPI_ENGINE_REG_OFFLOAD_CTRL(priv->offload_num)); + reg |= SPI_ENGINE_OFFLOAD_CTRL_ENABLE; + writel_relaxed(reg, spi_engine->base + + SPI_ENGINE_REG_OFFLOAD_CTRL(priv->offload_num)); + return 0; +} + +static void spi_engine_trigger_disable(struct spi_offload *offload) +{ + struct spi_engine_offload *priv = offload->priv; + struct spi_engine *spi_engine = priv->spi_engine; + unsigned int reg; + + reg = readl_relaxed(spi_engine->base + + SPI_ENGINE_REG_OFFLOAD_CTRL(priv->offload_num)); + reg &= ~SPI_ENGINE_OFFLOAD_CTRL_ENABLE; + writel_relaxed(reg, spi_engine->base + + SPI_ENGINE_REG_OFFLOAD_CTRL(priv->offload_num)); +} + +static struct dma_chan +*spi_engine_tx_stream_request_dma_chan(struct spi_offload *offload) +{ + struct spi_engine_offload *priv = offload->priv; + char name[16]; + + snprintf(name, sizeof(name), "offload%u-tx", priv->offload_num); + + return dma_request_chan(offload->provider_dev, name); +} + +static struct dma_chan +*spi_engine_rx_stream_request_dma_chan(struct spi_offload *offload) +{ + struct spi_engine_offload *priv = offload->priv; + char name[16]; + + snprintf(name, sizeof(name), "offload%u-rx", priv->offload_num); + + return dma_request_chan(offload->provider_dev, name); +} + +static const struct spi_offload_ops spi_engine_offload_ops = { + .trigger_enable = spi_engine_trigger_enable, + .trigger_disable = spi_engine_trigger_disable, + .tx_stream_request_dma_chan = spi_engine_tx_stream_request_dma_chan, + .rx_stream_request_dma_chan = spi_engine_rx_stream_request_dma_chan, +}; + static void spi_engine_release_hw(void *p) { struct spi_engine *spi_engine = p; @@ -675,8 +921,7 @@ static int spi_engine_probe(struct platform_device *pdev) struct spi_engine *spi_engine; struct spi_controller *host; unsigned int version; - int irq; - int ret; + int irq, ret; irq = platform_get_irq(pdev, 0); if (irq < 0) @@ -691,6 +936,46 @@ static int spi_engine_probe(struct platform_device *pdev) spin_lock_init(&spi_engine->lock); init_completion(&spi_engine->msg_complete); + /* + * REVISIT: for now, all SPI Engines only have one offload. In the + * future, this should be read from a memory mapped register to + * determine the number of offloads enabled at HDL compile time. For + * now, we can tell if an offload is present if there is a trigger + * source wired up to it. + */ + if (device_property_present(&pdev->dev, "trigger-sources")) { + struct spi_engine_offload *priv; + + spi_engine->offload = + devm_spi_offload_alloc(&pdev->dev, + sizeof(struct spi_engine_offload)); + if (IS_ERR(spi_engine->offload)) + return PTR_ERR(spi_engine->offload); + + priv = spi_engine->offload->priv; + priv->spi_engine = spi_engine; + priv->offload_num = 0; + + spi_engine->offload->ops = &spi_engine_offload_ops; + spi_engine->offload_caps = SPI_OFFLOAD_CAP_TRIGGER; + + if (device_property_match_string(&pdev->dev, "dma-names", "offload0-rx") >= 0) { + spi_engine->offload_caps |= SPI_OFFLOAD_CAP_RX_STREAM_DMA; + spi_engine->offload->xfer_flags |= SPI_OFFLOAD_XFER_RX_STREAM; + } + + if (device_property_match_string(&pdev->dev, "dma-names", "offload0-tx") >= 0) { + spi_engine->offload_caps |= SPI_OFFLOAD_CAP_TX_STREAM_DMA; + spi_engine->offload->xfer_flags |= SPI_OFFLOAD_XFER_TX_STREAM; + } else { + /* + * HDL compile option to enable TX DMA stream also disables + * the SDO memory, so can't do both at the same time. + */ + spi_engine->offload_caps |= SPI_OFFLOAD_CAP_TX_STATIC_DATA; + } + } + spi_engine->clk = devm_clk_get_enabled(&pdev->dev, "s_axi_aclk"); if (IS_ERR(spi_engine->clk)) return PTR_ERR(spi_engine->clk); @@ -712,6 +997,19 @@ static int spi_engine_probe(struct platform_device *pdev) return -ENODEV; } + if (ADI_AXI_PCORE_VER_MINOR(version) >= 1) { + unsigned int sizes = readl(spi_engine->base + + SPI_ENGINE_REG_OFFLOAD_MEM_ADDR_WIDTH); + + spi_engine->offload_ctrl_mem_size = 1 << + FIELD_GET(SPI_ENGINE_SPI_OFFLOAD_MEM_WIDTH_CMD, sizes); + spi_engine->offload_sdo_mem_size = 1 << + FIELD_GET(SPI_ENGINE_SPI_OFFLOAD_MEM_WIDTH_SDO, sizes); + } else { + spi_engine->offload_ctrl_mem_size = SPI_ENGINE_OFFLOAD_CMD_FIFO_SIZE; + spi_engine->offload_sdo_mem_size = SPI_ENGINE_OFFLOAD_SDO_FIFO_SIZE; + } + writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_RESET); writel_relaxed(0xff, spi_engine->base + SPI_ENGINE_REG_INT_PENDING); writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_INT_ENABLE); @@ -733,6 +1031,8 @@ static int spi_engine_probe(struct platform_device *pdev) host->transfer_one_message = spi_engine_transfer_one_message; host->optimize_message = spi_engine_optimize_message; host->unoptimize_message = spi_engine_unoptimize_message; + host->get_offload = spi_engine_get_offload; + host->put_offload = spi_engine_put_offload; host->num_chipselect = 8; /* Some features depend of the IP core version. */ From patchwork Fri Nov 15 20:18:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 843776 Received: from mail-ot1-f52.google.com (mail-ot1-f52.google.com [209.85.210.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 51E431EF951 for ; Fri, 15 Nov 2024 20:19:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701945; cv=none; b=IIumdLHzPx2nwTS05zI7wSstjfXizLvKY9wbAQeNhPJlXGR5G9nxOV85ut+Ol2B/AWILs04bNpNCvC8xchvnfBdngHFsO0h5/8EpPdhQDvUPaQFZNw+2WpKBXyKndL9LpUR31hG/0Q6cNGb2mu9C/+hGsCde2Ah4dhfvhOHeiKg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701945; c=relaxed/simple; bh=liN7b/KYzKtzeNSL+5oMImxJ6lcQk3gX9Kb2jv+h/ro=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=SACDLo3QWwqh2JkC6tk6/egc53qbYPByF+gVpjw16hjZaJ42AxS1SUwL0mYn2L50tO4qkyrEBZu6vyqHgCXRl1EZpIejXbVgvwyFK4r9Mh26jqpLtW+RI6Prvu22MwkELlW1LqAPnXuETMJavomtE7dkbG2UuDg9mZjBAvvBsn0= 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=hVHA84Dw; arc=none smtp.client-ip=209.85.210.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="hVHA84Dw" Received: by mail-ot1-f52.google.com with SMTP id 46e09a7af769-7180e07185bso913894a34.3 for ; Fri, 15 Nov 2024 12:19:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1731701942; x=1732306742; 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=0V8K9STxeMmBsbxzTyK1zNzGuxIPVz8nmTjFT2BLRT4=; b=hVHA84DwKhpRjhy76VpaVoC8S++0uxCpadJArbTlAPX6/fh99tkkusWCsN/ZEYEZTp uO5Cb9HUcb02/nvSK/Ej4vIptodo1oUCBwdqEwIxDkmVHaEAnOI+Ccc+i8TyNkv7Vzdn YSXqyaQxtDb2up4x1syImbvUO1g6Jrigz2CmXS7kpSPrvIDmqXlXM+1e276cYqO2l3bM YlUlVyQ8UPkyjGEIprGgUBaOLA5VzCFHnm5mWn/izdOIE8dnf8FrBi47/hbqiEg3IODO PfIVWJrkwYbo0eOa6cWTJWDJeApf8L3lNSvCs1VFqxB0nsQbJsoPSixrnnIvCN0um5N1 ZHCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731701942; x=1732306742; 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=0V8K9STxeMmBsbxzTyK1zNzGuxIPVz8nmTjFT2BLRT4=; b=ZPmnWj+sORvGPGgO9MJ+u9Qx91vzG7xINImAYEXGaiYsQdXLosR31Y/gs0BfVhne2F yw/85vG8e6ACPo5QSdkBkK9yS9lxP7heGxzO9Bb7lyMoPuzkEgfYSVnVNsa/ufaz89U5 inIl5J/Z6FDEwoMghvHB1waFVhnppr6nfInvNXy8FZEiQ+njNwitIVQBcOcwXhBSmzig L/zsVPUHn5Mx2UyIfLT3hwstREmZjqqSwps2Hk/WAU4aCz0BQNrYfW63CMXGPSfTcsN8 E9/mlhxObAS6R9Bfhd9cLk7r5lWBTnGV7Yt/9Ppxwa3AverAYpvxc+7DbocKR3Cva/AS NfGA== X-Forwarded-Encrypted: i=1; AJvYcCXpbuUI3LDMnbxD8bJV16cxaGOS059zATb5fWr2cTqXDJ3PMo2CPuu4QYhpa7cCqLaO6Qs724kUvkg=@vger.kernel.org X-Gm-Message-State: AOJu0Yyi27+b+3MHist5HzXUaispI9d72ecp1a0FNXEBhCJCePHb+kTL mz27AX2/yCa7RnvutxE6RgOtChHfMl+6qYs9+0yAAuGKMC76jkzoViFIB1RPppk= X-Google-Smtp-Source: AGHT+IE09WFChQ+/hR2mVDvjYMehhUE2fePG8D9Jb1Cbzj66rlCOErUZI2AFvqUCBNYs2zx0h1rLDQ== X-Received: by 2002:a05:6830:6c0f:b0:71a:7603:d2d2 with SMTP id 46e09a7af769-71a7797c309mr4591306a34.18.1731701942374; Fri, 15 Nov 2024 12:19:02 -0800 (PST) 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 46e09a7af769-71a780ea62esm748978a34.5.2024.11.15.12.19.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Nov 2024 12:19:01 -0800 (PST) From: David Lechner Date: Fri, 15 Nov 2024 14:18:48 -0600 Subject: [PATCH v5 09/16] iio: buffer-dmaengine: document iio_dmaengine_buffer_setup_ext Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241115-dlech-mainline-spi-engine-offload-2-v5-9-bea815bd5ea5@baylibre.com> References: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> In-Reply-To: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , 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 The iio_dmaengine_buffer_setup_ext() function is public and should be documented. Also, while touching this, fix the description of @dev in related functions. @dev does not strictly have to be the parent of the IIO device. It is only passed to dma_request_chan() so strictly speaking, it can be any device that is a valid DMA channel consumer. Signed-off-by: David Lechner --- v5 changes: none v4 changes: * This patch is new in v4. Jonathan, I think this patch stands on its own if you want to take it earlier than the rest of this series. --- drivers/iio/buffer/industrialio-buffer-dmaengine.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c index 19af1caf14cd..054af21dfa65 100644 --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c @@ -206,7 +206,7 @@ static const struct iio_dev_attr *iio_dmaengine_buffer_attrs[] = { /** * iio_dmaengine_buffer_alloc() - Allocate new buffer which uses DMAengine - * @dev: Parent device for the buffer + * @dev: DMA channel consumer device * @channel: DMA channel name, typically "rx". * * This allocates a new IIO buffer which internally uses the DMAengine framework @@ -288,6 +288,21 @@ void iio_dmaengine_buffer_free(struct iio_buffer *buffer) } EXPORT_SYMBOL_NS_GPL(iio_dmaengine_buffer_free, IIO_DMAENGINE_BUFFER); +/** + * iio_dmaengine_buffer_setup_ext() - Setup a DMA buffer for an IIO device + * @dev: DMA channel consumer device + * @indio_dev: IIO device to which to attach this buffer. + * @channel: DMA channel name, typically "rx". + * @dir: Direction of buffer (in or out) + * + * This allocates a new IIO buffer with devm_iio_dmaengine_buffer_alloc() + * and attaches it to an IIO device with iio_device_attach_buffer(). + * It also appends the INDIO_BUFFER_HARDWARE mode to the supported modes of the + * IIO device. + * + * Once done using the buffer iio_dmaengine_buffer_free() should be used to + * release it. + */ struct iio_buffer *iio_dmaengine_buffer_setup_ext(struct device *dev, struct iio_dev *indio_dev, const char *channel, @@ -321,7 +336,7 @@ static void __devm_iio_dmaengine_buffer_free(void *buffer) /** * devm_iio_dmaengine_buffer_setup_ext() - Setup a DMA buffer for an IIO device - * @dev: Parent device for the buffer + * @dev: Device for devm ownership and DMA channel consumer device * @indio_dev: IIO device to which to attach this buffer. * @channel: DMA channel name, typically "rx". * @dir: Direction of buffer (in or out) From patchwork Fri Nov 15 20:18:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 843775 Received: from mail-ot1-f46.google.com (mail-ot1-f46.google.com [209.85.210.46]) (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 362771F706F for ; Fri, 15 Nov 2024 20:19:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701948; cv=none; b=gn7NOGjh9CZ3GgaLdEgYJyBGuwL7KyyiEcGeoNSwVKcbCiyb1IA5wCfB6HScygISIasvlQsbpra/ZYZ2yp8F8aTfAxl4SX1PYdGvdW6ILGeP8y8NSkUt42hLN59xedhWDsvJTXtJUltZWo8FGA9CrBVVDjMjrynFz05Gi1eUwoY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701948; c=relaxed/simple; bh=nByoFKUVSmX22QOrB5tKOE6hy2vdogrk8IlWYmMb7iA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Tcyq0PUQMTYdSCnNY+Ezwk1f3Ut55cXcS9szT1WBWdrA8e9KLUcSYWfLEroIMEn6SBkMvCo+RugLUeigm7z8DzqBN5VTgA9S3n3e3ZLgwg1Ebzuqy4chaVDQb89+KEvp/Bn7Rk8o1T4PbK4tGOobjsodK9f9XFfAhC5dGOdFdmY= 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=sJ8yRa/U; arc=none smtp.client-ip=209.85.210.46 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="sJ8yRa/U" Received: by mail-ot1-f46.google.com with SMTP id 46e09a7af769-7181c0730ddso782375a34.2 for ; Fri, 15 Nov 2024 12:19:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1731701944; x=1732306744; 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=hQ9TBdpHxWzvzSyVZJpMzkKE9PvbJoCuWgBYWs06guk=; b=sJ8yRa/Utq4US7mqGjtp09jKg2wwKGJuVrHGEesX5c7N7HAPjhNBipsa+NlrX0nL8K wL/UOwxJgIG81dqzE+jo36b+szK8oGAuvBEtXkTUtGWyr6tiJfwbXAysivb81Hy8ut8l lc0W3Jz6fJsEgrko/e/H+JTKL/a9HFFvdxrv27SJqZicxZQ1VBVEi/IPcqz7xxsLtwlP ge3wSeHSbVaZK8AB+xSfZyR/Ox+xhj3i/hxisdhISUs05k6Xu3i7KW1S81qMaOfj1d1o 2bL6gICF0X0osl8nrPnUSC1E0mBul9Q2Y9fM4ged6EMHZ4ad1zZKI/3gp7pMwtm5z+cn FlCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731701944; x=1732306744; 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=hQ9TBdpHxWzvzSyVZJpMzkKE9PvbJoCuWgBYWs06guk=; b=dw6vH7ayUt01vCMvB2LJoeBsjCkVQ1TLmdaXm91mnZbkCvhi0W23yc2DssNk9vweEi fBtpfXom1y8gVaIntuP32GxosJ1Wvnhly+7/+Y38EKEjGz6hmetIKZeSVi69W/ZAGOLl TfLR1eEahauZu7I2MEfN7FfGOn8+ZwIjZeyfBgXO02CYB4ykVPS71Is46B809jANw4q4 dnaaxRnWf4JKbpgGkpKzFjaSInM2H8KSZnx1Pp5tmBZYqLRQQ7xhr1cN3ZyyOjy7WjdA zuZHi6/0m1uU4Qn2d0wQDyraRvgGk/zt7Ntx+LMnjM+3AL5iFfMd13SkvQbpeCpZ/sJe uyiw== X-Forwarded-Encrypted: i=1; AJvYcCXFlNhTQwXzuFrb5hhdnu1cBA77CSJyOPqEETJ55Iuy9TZgNiDiS6p04ZsrR2uimyW5GhtBvbqBCwM=@vger.kernel.org X-Gm-Message-State: AOJu0YysFbNpnchoqpNyENQoCQjgSkE7uSnZ9SYd/tJ7XzbCcoQUUSAH 2RtH9DPT6eVNQR1Vw9wg4sTdJZ0cUPQ456Bels2e8xptOBFsfdEOaGRHFwriWN0= X-Google-Smtp-Source: AGHT+IFpIObwug+gjtaFB8EYgLYodh+d7CpNa3uZrjGmbI+QPIYY+qYFAjZ6xzpN4D9Z/f4yyjISHA== X-Received: by 2002:a05:6830:64ca:b0:718:194d:8ab with SMTP id 46e09a7af769-71a77a55f3cmr4663542a34.27.1731701944380; Fri, 15 Nov 2024 12:19:04 -0800 (PST) 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 46e09a7af769-71a780ea62esm748978a34.5.2024.11.15.12.19.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Nov 2024 12:19:03 -0800 (PST) From: David Lechner Date: Fri, 15 Nov 2024 14:18:49 -0600 Subject: [PATCH v5 10/16] iio: buffer-dmaengine: add devm_iio_dmaengine_buffer_setup_ext2() Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241115-dlech-mainline-spi-engine-offload-2-v5-10-bea815bd5ea5@baylibre.com> References: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> In-Reply-To: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , 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 Add a new devm_iio_dmaengine_buffer_setup_ext2() function to handle cases where the DMA channel is managed by the caller rather than being requested and released by the iio_dmaengine module. Signed-off-by: David Lechner --- v5 changes: none v4 changes: * This replaces "iio: buffer-dmaengine: generalize requesting DMA channel" --- drivers/iio/buffer/industrialio-buffer-dmaengine.c | 107 +++++++++++++++------ include/linux/iio/buffer-dmaengine.h | 5 + 2 files changed, 81 insertions(+), 31 deletions(-) diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c index 054af21dfa65..602cb2e147a6 100644 --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c @@ -33,6 +33,7 @@ struct dmaengine_buffer { struct iio_dma_buffer_queue queue; struct dma_chan *chan; + bool owns_chan; struct list_head active; size_t align; @@ -216,28 +217,23 @@ static const struct iio_dev_attr *iio_dmaengine_buffer_attrs[] = { * Once done using the buffer iio_dmaengine_buffer_free() should be used to * release it. */ -static struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev, - const char *channel) +static struct iio_buffer *iio_dmaengine_buffer_alloc(struct dma_chan *chan, + bool owns_chan) { struct dmaengine_buffer *dmaengine_buffer; unsigned int width, src_width, dest_width; struct dma_slave_caps caps; - struct dma_chan *chan; int ret; dmaengine_buffer = kzalloc(sizeof(*dmaengine_buffer), GFP_KERNEL); - if (!dmaengine_buffer) - return ERR_PTR(-ENOMEM); - - chan = dma_request_chan(dev, channel); - if (IS_ERR(chan)) { - ret = PTR_ERR(chan); - goto err_free; + if (!dmaengine_buffer) { + ret = -ENOMEM; + goto err_release; } ret = dma_get_slave_caps(chan, &caps); if (ret < 0) - goto err_release; + goto err_free; /* Needs to be aligned to the maximum of the minimums */ if (caps.src_addr_widths) @@ -252,6 +248,7 @@ static struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev, INIT_LIST_HEAD(&dmaengine_buffer->active); dmaengine_buffer->chan = chan; + dmaengine_buffer->owns_chan = owns_chan; dmaengine_buffer->align = width; dmaengine_buffer->max_size = dma_get_max_seg_size(chan->device->dev); @@ -263,10 +260,12 @@ static struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev, return &dmaengine_buffer->queue.buffer; -err_release: - dma_release_channel(chan); err_free: kfree(dmaengine_buffer); +err_release: + if (owns_chan) + dma_release_channel(chan); + return ERR_PTR(ret); } @@ -282,12 +281,38 @@ void iio_dmaengine_buffer_free(struct iio_buffer *buffer) iio_buffer_to_dmaengine_buffer(buffer); iio_dma_buffer_exit(&dmaengine_buffer->queue); - dma_release_channel(dmaengine_buffer->chan); - iio_buffer_put(buffer); + + if (dmaengine_buffer->owns_chan) + dma_release_channel(dmaengine_buffer->chan); } EXPORT_SYMBOL_NS_GPL(iio_dmaengine_buffer_free, IIO_DMAENGINE_BUFFER); +static struct iio_buffer +*__iio_dmaengine_buffer_setup_ext(struct iio_dev *indio_dev, + struct dma_chan *chan, bool owns_chan, + enum iio_buffer_direction dir) +{ + struct iio_buffer *buffer; + int ret; + + buffer = iio_dmaengine_buffer_alloc(chan, owns_chan); + if (IS_ERR(buffer)) + return ERR_CAST(buffer); + + indio_dev->modes |= INDIO_BUFFER_HARDWARE; + + buffer->direction = dir; + + ret = iio_device_attach_buffer(indio_dev, buffer); + if (ret) { + iio_dmaengine_buffer_free(buffer); + return ERR_PTR(ret); + } + + return buffer; +} + /** * iio_dmaengine_buffer_setup_ext() - Setup a DMA buffer for an IIO device * @dev: DMA channel consumer device @@ -308,24 +333,13 @@ struct iio_buffer *iio_dmaengine_buffer_setup_ext(struct device *dev, const char *channel, enum iio_buffer_direction dir) { - struct iio_buffer *buffer; - int ret; - - buffer = iio_dmaengine_buffer_alloc(dev, channel); - if (IS_ERR(buffer)) - return ERR_CAST(buffer); - - indio_dev->modes |= INDIO_BUFFER_HARDWARE; - - buffer->direction = dir; + struct dma_chan *chan; - ret = iio_device_attach_buffer(indio_dev, buffer); - if (ret) { - iio_dmaengine_buffer_free(buffer); - return ERR_PTR(ret); - } + chan = dma_request_chan(dev, channel); + if (IS_ERR(chan)) + return ERR_CAST(chan); - return buffer; + return __iio_dmaengine_buffer_setup_ext(indio_dev, chan, true, dir); } EXPORT_SYMBOL_NS_GPL(iio_dmaengine_buffer_setup_ext, IIO_DMAENGINE_BUFFER); @@ -362,6 +376,37 @@ int devm_iio_dmaengine_buffer_setup_ext(struct device *dev, } EXPORT_SYMBOL_NS_GPL(devm_iio_dmaengine_buffer_setup_ext, IIO_DMAENGINE_BUFFER); +/** + * devm_iio_dmaengine_buffer_setup_ext2() - Setup a DMA buffer for an IIO device + * @dev: Device for devm ownership + * @indio_dev: IIO device to which to attach this buffer. + * @chan: DMA channel + * @dir: Direction of buffer (in or out) + * + * This allocates a new IIO buffer with devm_iio_dmaengine_buffer_alloc() + * and attaches it to an IIO device with iio_device_attach_buffer(). + * It also appends the INDIO_BUFFER_HARDWARE mode to the supported modes of the + * IIO device. + * + * This is the same as devm_iio_dmaengine_buffer_setup_ext() except that the + * caller manages requesting and releasing the DMA channel. + */ +int devm_iio_dmaengine_buffer_setup_ext2(struct device *dev, + struct iio_dev *indio_dev, + struct dma_chan *chan, + enum iio_buffer_direction dir) +{ + struct iio_buffer *buffer; + + buffer = __iio_dmaengine_buffer_setup_ext(indio_dev, chan, false, dir); + if (IS_ERR(buffer)) + return PTR_ERR(buffer); + + return devm_add_action_or_reset(dev, __devm_iio_dmaengine_buffer_free, + buffer); +} +EXPORT_SYMBOL_NS_GPL(devm_iio_dmaengine_buffer_setup_ext2, IIO_DMAENGINE_BUFFER); + MODULE_AUTHOR("Lars-Peter Clausen "); MODULE_DESCRIPTION("DMA buffer for the IIO framework"); MODULE_LICENSE("GPL"); diff --git a/include/linux/iio/buffer-dmaengine.h b/include/linux/iio/buffer-dmaengine.h index 81d9a19aeb91..7bdb979b59f2 100644 --- a/include/linux/iio/buffer-dmaengine.h +++ b/include/linux/iio/buffer-dmaengine.h @@ -11,6 +11,7 @@ struct iio_dev; struct device; +struct dma_chan; void iio_dmaengine_buffer_free(struct iio_buffer *buffer); struct iio_buffer *iio_dmaengine_buffer_setup_ext(struct device *dev, @@ -26,6 +27,10 @@ int devm_iio_dmaengine_buffer_setup_ext(struct device *dev, struct iio_dev *indio_dev, const char *channel, enum iio_buffer_direction dir); +int devm_iio_dmaengine_buffer_setup_ext2(struct device *dev, + struct iio_dev *indio_dev, + struct dma_chan *chan, + enum iio_buffer_direction dir); #define devm_iio_dmaengine_buffer_setup(dev, indio_dev, channel) \ devm_iio_dmaengine_buffer_setup_ext(dev, indio_dev, channel, \ From patchwork Fri Nov 15 20:18:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 844882 Received: from mail-oo1-f48.google.com (mail-oo1-f48.google.com [209.85.161.48]) (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 4B0291F6685 for ; Fri, 15 Nov 2024 20:19:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701948; cv=none; b=tV0bMi7jnKtNa7beeSCuIIJ0z5RAkrTWKTu3095SKTuDmqJqzNhKSUNixllJK7lJ8tz5oV1+HOdHI5jZB+OeNOZR3Z4IKAebhxGo81PqE79CbSWPBxLjl4Hj70egJ+I5LlelM6nUQ3mLH8sHrJd+ts1DAihyPwo5JKHr8KwB3lM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701948; c=relaxed/simple; bh=kKFzcQWwxfRZslAvb5mFTNlEqtJH2JETnWxcZJ5iPUk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=K9rgtxvkLwQTdZhoUDqiy+4kJ5IUGbEIaGrDJJThgIEyIAEqTuiBlOrR4eKBCSR153BRMLFm3lV2llC8ovdNeC9sH5hIyoddjDQzBxLXVEUS8pxRfX02M0HX7ckbbAIl3FPGD/10/FXFSSg0FPPn+gyvCsVS7VeD0kGk1u7Z4rI= 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=ldfS99y/; arc=none smtp.client-ip=209.85.161.48 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="ldfS99y/" Received: by mail-oo1-f48.google.com with SMTP id 006d021491bc7-5ee58c5c2e3so541741eaf.2 for ; Fri, 15 Nov 2024 12:19:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1731701945; x=1732306745; 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=+vpBdskAj4GrGKxQ9kXlXTxFK22DsgbpucNoSRiceYI=; b=ldfS99y/O3tuXbMZdfeFAVfDiYdZh03qVDkjHx40pWUqnTN2+9eBEKghX838Ijcb6t 4NdJXyV9tO9Sa2PNEa8genbwt24WgxLIGmDxxsHIIsitudHM9UX2GNv3EKHxzPGbhgcc zvKwvLeq4nQhYTu4s1CQnfKtCnaT4oVhXlS4X/xGJB1CuoUPUuOjKFtXOxQTdT7A78nM +ohjSpB9+SAUf25PvxBeyLA5PkVBqEP3hp3ahBWOFgOVlCRFc2EiEh/LgEL9csUkBMgf hRlPHG9rKSp/J09BmDZIYCwg8U0depZPtyirUNFVZrxy+tU5ikoZPu1/c89akTGstSqp VXKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731701945; x=1732306745; 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=+vpBdskAj4GrGKxQ9kXlXTxFK22DsgbpucNoSRiceYI=; b=QNspUBZxT8OV35fxmOiJeS7QKM4JhcUpMZlDqw28HkmV2mOofqnwwjoPy+0yiaAi4j qHKuUwqetjVH5T5vjVk7V6girOuUtKRGNOMdug0sw/5lkpvEfa/rJOKaDG7kDj9AUi0E P+8EOSZA5IYWJGxqxggf1jv0TdRwT574n9Of9QpmQiNH71Yy4HEn4HfY7qIRbdE31043 iSRIfRd3tkw7T74Gghj7NdPzeHcCc/Gd98INZOIj3cCV4e3t7Ndf1Xir0G/8CZbRdvfL DroDfMj7L4/D4uD76s4FhT7zIOK1W1RjfbLuNFQbhVTzjDF2zJXh5yTiPTQwAfNszRzc BgjQ== X-Forwarded-Encrypted: i=1; AJvYcCX+o43nC3mcYljPbicdg5CXnb0Mx5UInGCpTBonh7J/BebHy9rp5edpwKNEPSZWx2m2Tff/pPh6nZo=@vger.kernel.org X-Gm-Message-State: AOJu0YyvRJunsdExcq/+WxdjI9SLMHo2nni9AYF5lY7+Xk1Iz1EMZ1iH o2gpDY+ofdLdDtlAEb2ncHwDRwwZ4bVfsrLwexePdACmuBwEMWd8W0Dt8KQoOkY= X-Google-Smtp-Source: AGHT+IEZV3/LjtJ7YJvC8Nl7cg9HoNWJp3fP6XrApsH5OzhF03yxaGbNgop8uGTjsrTSl9FpER7avg== X-Received: by 2002:a05:6820:260e:b0:5e5:7086:ebe8 with SMTP id 006d021491bc7-5eeab0fbd99mr3753008eaf.0.1731701945295; Fri, 15 Nov 2024 12:19:05 -0800 (PST) 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 46e09a7af769-71a780ea62esm748978a34.5.2024.11.15.12.19.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Nov 2024 12:19:04 -0800 (PST) From: David Lechner Date: Fri, 15 Nov 2024 14:18:50 -0600 Subject: [PATCH v5 11/16] iio: adc: ad7944: don't use storagebits for sizing Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241115-dlech-mainline-spi-engine-offload-2-v5-11-bea815bd5ea5@baylibre.com> References: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> In-Reply-To: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , 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 Replace use of storagebits with realbits for determining the number of bytes needed for SPI transfers. When adding SPI offload support, storagebits will no longer be guaranteed to be the "best fit" for 16-bit chips so we can no longer rely on storagebits being the correct size expected by the SPI framework. Instead, derive the correct size from realbits since it will always be correct even when SPI offloads are used. Signed-off-by: David Lechner --- v5 changes: none v4 changes: new patch in v4 --- drivers/iio/adc/ad7944.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/iio/adc/ad7944.c b/drivers/iio/adc/ad7944.c index a5aea4e9f1a7..6d1202bd55a0 100644 --- a/drivers/iio/adc/ad7944.c +++ b/drivers/iio/adc/ad7944.c @@ -98,6 +98,9 @@ struct ad7944_chip_info { const struct iio_chan_spec channels[2]; }; +/* get number of bytes for SPI xfer */ +#define AD7944_SPI_BYTES(scan_type) ((scan_type).realbits > 16 ? 4 : 2) + /* * AD7944_DEFINE_CHIP_INFO - Define a chip info structure for a specific chip * @_name: The name of the chip @@ -164,7 +167,7 @@ static int ad7944_3wire_cs_mode_init_msg(struct device *dev, struct ad7944_adc * /* Then we can read the data during the acquisition phase */ xfers[2].rx_buf = &adc->sample.raw; - xfers[2].len = BITS_TO_BYTES(chan->scan_type.storagebits); + xfers[2].len = AD7944_SPI_BYTES(chan->scan_type); xfers[2].bits_per_word = chan->scan_type.realbits; spi_message_init_with_transfers(&adc->msg, xfers, 3); @@ -193,7 +196,7 @@ static int ad7944_4wire_mode_init_msg(struct device *dev, struct ad7944_adc *adc xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS; xfers[1].rx_buf = &adc->sample.raw; - xfers[1].len = BITS_TO_BYTES(chan->scan_type.storagebits); + xfers[1].len = AD7944_SPI_BYTES(chan->scan_type); xfers[1].bits_per_word = chan->scan_type.realbits; spi_message_init_with_transfers(&adc->msg, xfers, 2); @@ -228,7 +231,7 @@ static int ad7944_chain_mode_init_msg(struct device *dev, struct ad7944_adc *adc xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS; xfers[1].rx_buf = adc->chain_mode_buf; - xfers[1].len = BITS_TO_BYTES(chan->scan_type.storagebits) * n_chain_dev; + xfers[1].len = AD7944_SPI_BYTES(chan->scan_type) * n_chain_dev; xfers[1].bits_per_word = chan->scan_type.realbits; spi_message_init_with_transfers(&adc->msg, xfers, 2); @@ -274,12 +277,12 @@ static int ad7944_single_conversion(struct ad7944_adc *adc, return ret; if (adc->spi_mode == AD7944_SPI_MODE_CHAIN) { - if (chan->scan_type.storagebits > 16) + if (chan->scan_type.realbits > 16) *val = ((u32 *)adc->chain_mode_buf)[chan->scan_index]; else *val = ((u16 *)adc->chain_mode_buf)[chan->scan_index]; } else { - if (chan->scan_type.storagebits > 16) + if (chan->scan_type.realbits > 16) *val = adc->sample.raw.u32; else *val = adc->sample.raw.u16; @@ -409,8 +412,7 @@ static int ad7944_chain_mode_alloc(struct device *dev, /* 1 word for each voltage channel + aligned u64 for timestamp */ chain_mode_buf_size = ALIGN(n_chain_dev * - BITS_TO_BYTES(chan[0].scan_type.storagebits), sizeof(u64)) - + sizeof(u64); + AD7944_SPI_BYTES(chan[0].scan_type), sizeof(u64)) + sizeof(u64); buf = devm_kzalloc(dev, chain_mode_buf_size, GFP_KERNEL); if (!buf) return -ENOMEM; From patchwork Fri Nov 15 20:18:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 844881 Received: from mail-oa1-f44.google.com (mail-oa1-f44.google.com [209.85.160.44]) (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 5F1FC1F80B6 for ; Fri, 15 Nov 2024 20:19:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701949; cv=none; b=paCeJyLq6axMbfNyTzpqYNhXh+vnVYEzV7EaK6ziRi9pUsamDT3lQlvjlrBweuouoLZA/rpCK0vxmhLTDmn6RARaWBVAVkGOFDmS4WTH262sqEKmGqRivaUpw5M8Ao8zEtFbFbUAJMk+Pr+QkyDI5HxNk/6IQ04nnqXb8GGZ8UQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701949; c=relaxed/simple; bh=K1HoU/1E/QUQRe3UVXF/+K4ECGHjub1lJwvbHWp9jQc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=QBMNhs1RQ2f7L49kJEQAr9Ax4WT0heVOSO8Fzy8ENg1yWbdpd+QjlCzutbnArUArYK7MZM8y/jmcD1oBBhbLaRw869VuEGfaPF4ulRRAkGqt9hJ0j0RLGrd5alxtNH2PP2nPSrxeQmZrnsDj5onQTa1EXLdvqUH8uoWmO/OP3VE= 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=Xajit6dE; arc=none smtp.client-ip=209.85.160.44 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="Xajit6dE" Received: by mail-oa1-f44.google.com with SMTP id 586e51a60fabf-296252514c2so1028217fac.3 for ; Fri, 15 Nov 2024 12:19:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1731701946; x=1732306746; 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=L3Uuz3QqVS6gHnYak4A3GWg09WNjnuXwNWm39DAev2Y=; b=Xajit6dE9krQf9FCU3AeSVxnpFHLJDo37RsZjPC0dqDcA9aSeW2N+WOuYhWNWsaLs0 s8j0kv5Ilp49IzZTNFCJ8j76rZYUv8yfFyaASbrx5sfzNDMEhnwDQjrI6FT9TBBxpwRA mB7hVrE8TeYHq+sgJGtBJCKjJpolZSy/twX43wxPybtEYR3Ag/9Hst1dz1MEczdbM1Rc niIPo/RRXcpPqVUgrmcMngPr9rnrZuQaUUEBJo5VT2zj28+5EPvOCbBQF2zaBrYbE05k O6M/VogMX2EmDi8lb/EuBHMCQ4JhBXX74dvXSJNHoYDoiAgQ/9OdYIip3tYcxR3VkfMg 8qIQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731701946; x=1732306746; 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=L3Uuz3QqVS6gHnYak4A3GWg09WNjnuXwNWm39DAev2Y=; b=qYE+PzFEomatVixnAZRfxayR1b3Ej8TaRc/DU8C6CzwlSanEBSOLFzQqNEXDpdhSqN szJty458ObcK/w/csWsqOIY6sYOPKc5hso2wG+1NevnKEr1f4uS21P7bVA+pK+Gpq2JD MDAPFjqQT2eAPxEaPXz927mKzn73ov8JZ96UXFUIF3M9cs3PkSxQvy5M+ZhQSMBmx+ns pCL5sIPvkbl++pVxFEOtk/8DyfoTGhy+4Nl9MutQ+hOHRzefr2nL08uUY1V+4OlEwzbq CRth0AgF1+4F0BuOxSAVAmhLAuvaJ25K7nhwFtfsQSe3ZLVNxkXfyK/Qyp/R69g7/WMF +lPQ== X-Forwarded-Encrypted: i=1; AJvYcCXVrwOjTwuK3263OfwuLfGdM8zHwWR6EvTr0sFTaScAPkAaAxYaqzimj812XayyrlAW4yKJipCHUuo=@vger.kernel.org X-Gm-Message-State: AOJu0YwPqhvPyHTH8nUaqFSlyObOvVObppIjT2UCFZOg79rHNHWjGQ1F HOYlQ9jbC+60Ni9WNVf24Wp79+FWT0LuY6ojA9WK307nHWXHXyL/wI+rOXKbXKs= X-Google-Smtp-Source: AGHT+IGilfQALzlUaRjQKAeJdDuhDXJ/hfaTiTpgfDtaWkXIRakHM2UbjucZmhQBeuZED8qGnKiPZA== X-Received: by 2002:a05:6870:1d1a:b0:288:559d:5b5c with SMTP id 586e51a60fabf-2962e01d26emr3417404fac.34.1731701946232; Fri, 15 Nov 2024 12:19:06 -0800 (PST) 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 46e09a7af769-71a780ea62esm748978a34.5.2024.11.15.12.19.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Nov 2024 12:19:05 -0800 (PST) From: David Lechner Date: Fri, 15 Nov 2024 14:18:51 -0600 Subject: [PATCH v5 12/16] iio: adc: ad7944: add support for SPI offload Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241115-dlech-mainline-spi-engine-offload-2-v5-12-bea815bd5ea5@baylibre.com> References: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> In-Reply-To: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , 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 This adds support for SPI offload to the ad7944 driver. This allows reading data at the max sample rate of 2.5 MSPS. Signed-off-by: David Lechner Reviewed-by: Jonathan Cameron --- v5 changes: * Remove dev_info() message. * Implement sampling_frequency_available attribute. * Limit max sample rate to chip-specific value. v4 changes: * Adapted to changes in other patches. * Add new separate channel spec for when using SPI offload. * Fixed some nitpicks. v3 changes: * Finished TODOs. * Adapted to changes in other patches. v2 changes: In the previous version, there was a new separate driver for the PWM trigger and DMA hardware buffer. This was deemed too complex so they are moved into the ad7944 driver. It has also been reworked to accommodate for the changes described in the other patches. --- drivers/iio/adc/Kconfig | 1 + drivers/iio/adc/ad7944.c | 281 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 266 insertions(+), 16 deletions(-) diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index a3e8ac569ce4..995b9cacbaa9 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -360,6 +360,7 @@ config AD7923 config AD7944 tristate "Analog Devices AD7944 and similar ADCs driver" depends on SPI + select SPI_OFFLOAD select IIO_BUFFER select IIO_TRIGGERED_BUFFER help diff --git a/drivers/iio/adc/ad7944.c b/drivers/iio/adc/ad7944.c index 6d1202bd55a0..f5237db06b1e 100644 --- a/drivers/iio/adc/ad7944.c +++ b/drivers/iio/adc/ad7944.c @@ -16,11 +16,14 @@ #include #include #include +#include #include #include +#include #include #include +#include #include #include @@ -54,6 +57,12 @@ struct ad7944_adc { enum ad7944_spi_mode spi_mode; struct spi_transfer xfers[3]; struct spi_message msg; + struct spi_transfer offload_xfers[2]; + struct spi_message offload_msg; + struct spi_offload *offload; + struct spi_offload_trigger *offload_trigger; + unsigned long offload_trigger_hz; + int sample_freq_range[3]; void *chain_mode_buf; /* Chip-specific timing specifications. */ const struct ad7944_timing_spec *timing_spec; @@ -81,6 +90,8 @@ struct ad7944_adc { /* quite time before CNV rising edge */ #define AD7944_T_QUIET_NS 20 +/* minimum CNV high time to trigger conversion */ +#define AD7944_T_CNVH_NS 10 static const struct ad7944_timing_spec ad7944_timing_spec = { .conv_ns = 420, @@ -95,7 +106,9 @@ static const struct ad7944_timing_spec ad7986_timing_spec = { struct ad7944_chip_info { const char *name; const struct ad7944_timing_spec *timing_spec; + u32 max_sample_rate_hz; const struct iio_chan_spec channels[2]; + const struct iio_chan_spec offload_channels[1]; }; /* get number of bytes for SPI xfer */ @@ -105,13 +118,15 @@ struct ad7944_chip_info { * AD7944_DEFINE_CHIP_INFO - Define a chip info structure for a specific chip * @_name: The name of the chip * @_ts: The timing specification for the chip + * @_max: The maximum sample rate in Hz * @_bits: The number of bits in the conversion result * @_diff: Whether the chip is true differential or not */ -#define AD7944_DEFINE_CHIP_INFO(_name, _ts, _bits, _diff) \ +#define AD7944_DEFINE_CHIP_INFO(_name, _ts, _max, _bits, _diff) \ static const struct ad7944_chip_info _name##_chip_info = { \ .name = #_name, \ .timing_spec = &_ts##_timing_spec, \ + .max_sample_rate_hz = _max, \ .channels = { \ { \ .type = IIO_VOLTAGE, \ @@ -129,13 +144,33 @@ static const struct ad7944_chip_info _name##_chip_info = { \ }, \ IIO_CHAN_SOFT_TIMESTAMP(1), \ }, \ + /* basically the same minus soft timestamp plus sampling freq */\ + .offload_channels = { \ + { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .differential = _diff, \ + .channel = 0, \ + .channel2 = _diff ? 1 : 0, \ + .scan_index = 0, \ + .scan_type.sign = _diff ? 's' : 'u', \ + .scan_type.realbits = _bits, \ + .scan_type.storagebits = 32, \ + .scan_type.endianness = IIO_CPU, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \ + | BIT(IIO_CHAN_INFO_SCALE) \ + | BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_separate_available = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + }, \ + }, \ } /* pseudo-differential with ground sense */ -AD7944_DEFINE_CHIP_INFO(ad7944, ad7944, 14, 0); -AD7944_DEFINE_CHIP_INFO(ad7985, ad7944, 16, 0); +AD7944_DEFINE_CHIP_INFO(ad7944, ad7944, 2.5 * MEGA, 14, 0); +AD7944_DEFINE_CHIP_INFO(ad7985, ad7944, 2.5 * MEGA, 16, 0); /* fully differential */ -AD7944_DEFINE_CHIP_INFO(ad7986, ad7986, 18, 1); +AD7944_DEFINE_CHIP_INFO(ad7986, ad7986, 2 * MEGA, 18, 1); static int ad7944_3wire_cs_mode_init_msg(struct device *dev, struct ad7944_adc *adc, const struct iio_chan_spec *chan) @@ -239,6 +274,48 @@ static int ad7944_chain_mode_init_msg(struct device *dev, struct ad7944_adc *adc return devm_spi_optimize_message(dev, adc->spi, &adc->msg); } +/* + * Unlike ad7944_3wire_cs_mode_init_msg(), this creates a message that reads + * during the conversion phase instead of the acquisition phase when reading + * a sample from the ADC. This is needed to be able to read at the maximum + * sample rate. It requires the SPI controller to have offload support and a + * high enough SCLK rate to read the sample during the conversion phase. + */ +static int ad7944_3wire_cs_mode_init_offload_msg(struct device *dev, + struct ad7944_adc *adc, + const struct iio_chan_spec *chan) +{ + struct spi_transfer *xfers = adc->offload_xfers; + int ret; + + /* + * CS is tied to CNV and we need a low to high transition to start the + * conversion, so place CNV low for t_QUIET to prepare for this. + */ + xfers[0].delay.value = AD7944_T_QUIET_NS; + xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS; + /* CNV has to be high for a minimum time to trigger conversion. */ + xfers[0].cs_change = 1; + xfers[0].cs_change_delay.value = AD7944_T_CNVH_NS; + xfers[0].cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; + + /* Then we can read the previous sample during the conversion phase */ + xfers[1].offload_flags = SPI_OFFLOAD_XFER_RX_STREAM; + xfers[1].len = AD7944_SPI_BYTES(chan->scan_type); + xfers[1].bits_per_word = chan->scan_type.realbits; + + spi_message_init_with_transfers(&adc->offload_msg, xfers, + ARRAY_SIZE(adc->offload_xfers)); + + adc->offload_msg.offload = adc->offload; + + ret = devm_spi_optimize_message(dev, adc->spi, &adc->offload_msg); + if (ret) + return dev_err_probe(dev, ret, "failed to prepare offload msg\n"); + + return 0; +} + /** * ad7944_convert_and_acquire - Perform a single conversion and acquisition * @adc: The ADC device structure @@ -294,6 +371,23 @@ static int ad7944_single_conversion(struct ad7944_adc *adc, return IIO_VAL_INT; } +static int ad7944_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + struct ad7944_adc *adc = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + *vals = adc->sample_freq_range; + *type = IIO_VAL_INT; + return IIO_AVAIL_RANGE; + default: + return -EINVAL; + } +} + static int ad7944_read_raw(struct iio_dev *indio_dev, const struct iio_chan_spec *chan, int *val, int *val2, long info) @@ -326,13 +420,104 @@ static int ad7944_read_raw(struct iio_dev *indio_dev, return -EINVAL; } + case IIO_CHAN_INFO_SAMP_FREQ: + *val = adc->offload_trigger_hz; + return IIO_VAL_INT; + default: return -EINVAL; } } +static int ad7944_set_sample_freq(struct ad7944_adc *adc, int val) +{ + struct spi_offload_trigger_config config = { + .type = SPI_OFFLOAD_TRIGGER_PERIODIC, + .periodic = { + .frequency_hz = val, + }, + }; + int ret; + + ret = spi_offload_trigger_validate(adc->offload_trigger, &config); + if (ret) + return ret; + + adc->offload_trigger_hz = config.periodic.frequency_hz; + + return 0; +} + +static int ad7944_write_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + int val, int val2, long info) +{ + struct ad7944_adc *adc = iio_priv(indio_dev); + + switch (info) { + case IIO_CHAN_INFO_SAMP_FREQ: + if (val < 1 || val > adc->sample_freq_range[2]) + return -EINVAL; + + return ad7944_set_sample_freq(adc, val); + default: + return -EINVAL; + } +} + +static int ad7944_write_raw_get_fmt(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + return IIO_VAL_INT; + default: + return IIO_VAL_INT_PLUS_MICRO; + } +} + static const struct iio_info ad7944_iio_info = { + .read_avail = &ad7944_read_avail, .read_raw = &ad7944_read_raw, + .write_raw = &ad7944_write_raw, + .write_raw_get_fmt = &ad7944_write_raw_get_fmt, +}; + +static int ad7944_offload_buffer_postenable(struct iio_dev *indio_dev) +{ + struct ad7944_adc *adc = iio_priv(indio_dev); + struct spi_offload_trigger_config config = { + .type = SPI_OFFLOAD_TRIGGER_PERIODIC, + .periodic = { + .frequency_hz = adc->offload_trigger_hz, + }, + }; + int ret; + + gpiod_set_value_cansleep(adc->turbo, 1); + + ret = spi_offload_trigger_enable(adc->offload, adc->offload_trigger, + &config); + if (ret) + gpiod_set_value_cansleep(adc->turbo, 0); + + return ret; +} + +static int ad7944_offload_buffer_predisable(struct iio_dev *indio_dev) +{ + struct ad7944_adc *adc = iio_priv(indio_dev); + + spi_offload_trigger_disable(adc->offload, adc->offload_trigger); + gpiod_set_value_cansleep(adc->turbo, 0); + + return 0; +} + +static const struct iio_buffer_setup_ops ad7944_offload_buffer_setup_ops = { + .postenable = &ad7944_offload_buffer_postenable, + .predisable = &ad7944_offload_buffer_predisable, }; static irqreturn_t ad7944_trigger_handler(int irq, void *p) @@ -446,6 +631,11 @@ static const char * const ad7944_power_supplies[] = { "avdd", "dvdd", "bvdd", "vio" }; +static const struct spi_offload_config ad7944_offload_config = { + .capability_flags = SPI_OFFLOAD_CAP_TRIGGER | + SPI_OFFLOAD_CAP_RX_STREAM_DMA, +}; + static int ad7944_probe(struct spi_device *spi) { const struct ad7944_chip_info *chip_info; @@ -471,6 +661,10 @@ static int ad7944_probe(struct spi_device *spi) adc->timing_spec = chip_info->timing_spec; + adc->sample_freq_range[0] = 1; /* min */ + adc->sample_freq_range[1] = 1; /* step */ + adc->sample_freq_range[2] = chip_info->max_sample_rate_hz; /* max */ + ret = device_property_match_property_string(dev, "adi,spi-mode", ad7944_spi_modes, ARRAY_SIZE(ad7944_spi_modes)); @@ -590,20 +784,74 @@ static int ad7944_probe(struct spi_device *spi) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &ad7944_iio_info; - if (adc->spi_mode == AD7944_SPI_MODE_CHAIN) { - indio_dev->available_scan_masks = chain_scan_masks; - indio_dev->channels = chain_chan; - indio_dev->num_channels = n_chain_dev + 1; + adc->offload = devm_spi_offload_get(dev, spi, &ad7944_offload_config); + ret = PTR_ERR_OR_ZERO(adc->offload); + if (ret && ret != -ENODEV) + return dev_err_probe(dev, ret, "failed to get offload\n"); + + /* Fall back to low speed usage when no SPI offload available. */ + if (ret == -ENODEV) { + if (adc->spi_mode == AD7944_SPI_MODE_CHAIN) { + indio_dev->available_scan_masks = chain_scan_masks; + indio_dev->channels = chain_chan; + indio_dev->num_channels = n_chain_dev + 1; + } else { + indio_dev->channels = chip_info->channels; + indio_dev->num_channels = ARRAY_SIZE(chip_info->channels); + } + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, + iio_pollfunc_store_time, + ad7944_trigger_handler, + NULL); + if (ret) + return ret; } else { - indio_dev->channels = chip_info->channels; - indio_dev->num_channels = ARRAY_SIZE(chip_info->channels); - } + struct dma_chan *rx_dma; - ret = devm_iio_triggered_buffer_setup(dev, indio_dev, - iio_pollfunc_store_time, - ad7944_trigger_handler, NULL); - if (ret) - return ret; + if (adc->spi_mode != AD7944_SPI_MODE_SINGLE) + return dev_err_probe(dev, -EINVAL, + "offload only supported in single mode\n"); + + indio_dev->setup_ops = &ad7944_offload_buffer_setup_ops; + indio_dev->channels = chip_info->offload_channels; + indio_dev->num_channels = ARRAY_SIZE(chip_info->offload_channels); + + adc->offload_trigger = devm_spi_offload_trigger_get(dev, + adc->offload, SPI_OFFLOAD_TRIGGER_PERIODIC); + if (IS_ERR(adc->offload_trigger)) + return dev_err_probe(dev, PTR_ERR(adc->offload_trigger), + "failed to get offload trigger\n"); + + ret = ad7944_set_sample_freq(adc, 2 * MEGA); + if (ret) + return dev_err_probe(dev, ret, + "failed to init sample rate\n"); + + rx_dma = devm_spi_offload_rx_stream_request_dma_chan(dev, + adc->offload); + if (IS_ERR(rx_dma)) + return dev_err_probe(dev, PTR_ERR(rx_dma), + "failed to get offload RX DMA\n"); + + /* + * REVISIT: ideally, we would confirm that the offload RX DMA + * buffer layout is the same as what is hard-coded in + * offload_channels. Right now, the only supported offload + * is the pulsar_adc project which always uses 32-bit word + * size for data values, regardless of the SPI bits per word. + */ + + ret = devm_iio_dmaengine_buffer_setup_ext2( + dev, indio_dev, rx_dma, IIO_BUFFER_DIRECTION_IN); + if (ret) + return ret; + + ret = ad7944_3wire_cs_mode_init_offload_msg(dev, adc, + &chip_info->offload_channels[0]); + if (ret) + return ret; + } return devm_iio_device_register(dev, indio_dev); } @@ -638,3 +886,4 @@ module_spi_driver(ad7944_driver); MODULE_AUTHOR("David Lechner "); MODULE_DESCRIPTION("Analog Devices AD7944 PulSAR ADC family driver"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(IIO_DMAENGINE_BUFFER); From patchwork Fri Nov 15 20:18:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 843774 Received: from mail-oa1-f45.google.com (mail-oa1-f45.google.com [209.85.160.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 6C3251F8934 for ; Fri, 15 Nov 2024 20:19:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701951; cv=none; b=gzcEuOEmLyD9012U4yn/xZLOeVbX1vSrkG4mWGL6uic+fIBzZfL2J6v3tRq6Ch+oZoZxpAv3+oZc2eJgrjewfdBSBQ697DoVHZO9BTyHsnicY1mRxuyNVqv/i8rqvQHmrCu/BOfP/lR27Dv2BOIktilIoyCSdOAXzeMPfZg0tL0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701951; c=relaxed/simple; bh=K0ELSxsB5ewnDfByel6azG1qzhpSdfFUlrceHRoZqqY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gkqqk5YB0wP2XxKvQPqz4WhIorKyJHn3Ve3KlDZmujUrl7IPpb6gk+K1cw0Y4NYuBd3m2Qc79WhyCNfC9K54z4yFI91lPAq5togLLX9KicLKO/XeItkTnmk9i0gn6GbBTvwx0zuN9ems8d7/o7ff4UFQLdKeO3FN1oRNotdXmeA= 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=iLOt5OkK; arc=none smtp.client-ip=209.85.160.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="iLOt5OkK" Received: by mail-oa1-f45.google.com with SMTP id 586e51a60fabf-28c7f207806so984296fac.3 for ; Fri, 15 Nov 2024 12:19:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1731701948; x=1732306748; 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=gHWSp9g71dav0wBB3RsBnAwDxMnAi0+sYhD4RSgE92s=; b=iLOt5OkKff+H5qnAg29jnxdMSADjMWv2Sf9Mj0EybfejW3UveERNNhVF1EfBKL/QqY /cWsP4VzVQq6+dc/jkUd/wrmWOD+riSMQ4COkYHemH4zcDe/fWa798zioVavY0Ed0TWa dQ6wx329dxa1F8jhbx7rIUPaZGyA4Cwps7+E/3CKkjRpKmcvgapykEieeMwjY08vAOPl u8l0HFef/L10UTUNRKfE/4hRlpd2S1HKumYvcVh1dPVdBfxvgU0+/SXJ08BiItKXr8LP 34CKDIcKbNdaHLLOnIz+Zgvk2ERupSs3ooqKJ1ucFJXCiNDvkXDYoiFOB/X4oRzDxqa4 iLqQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731701948; x=1732306748; 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=gHWSp9g71dav0wBB3RsBnAwDxMnAi0+sYhD4RSgE92s=; b=rOHDQh0kG6jsL+JVphvrkK9ldjPwbFBhCx9UwUPNXHmcadyflbpzhWjv9Og9l+3Dhe +5+pLXn8OEhANjE3nzRdkkwAj17TXqaSW7paPOBEeu1SS4eu+2u11RnXQC8PTvY952NR ZjN+3zsXJ96w4MZ1vDOecrmbmgaPf2dELIZmSW8cSn6xPKzmS9MFapgX5vNJEOrrXmML BuZbpxN16oFF8HniskSqWvDz5bClt2y41o2IWsiKjDhGs4RsWhN2g0SzWqsXLeoKQyjR O0ROECTlbTw2zp7lIN1ulPyLTv4sH1LHHJJmYJ1xc1dJAuRXzGs0fsBeY7pnI2w0QOt5 jvnw== X-Forwarded-Encrypted: i=1; AJvYcCXLvpy2GWwhJ/1MrBfinhoQZbNyfVTrub8ZLjJqBPy+eURMAli6WhEY2ZMvnPfX5Y7i2B3TgR6gIoo=@vger.kernel.org X-Gm-Message-State: AOJu0YyziDUsUocMU0omj8MTImM5iK+fESpAAEFgVju+zWkO9QmrFArS g5Q7mD97zYpga5lW8mBiuD9BhVf/FZ9UNVWy15hSL0C1GW1kD+KBk9g7qb/sCTc= X-Google-Smtp-Source: AGHT+IGWBHYcdZrBR+Etr+tBdm3Lz7gnqd+0QTKy8x+5SgSS97gRVwEjKew7vBfdhv9QAdngjnHbCA== X-Received: by 2002:a05:6870:32d4:b0:27c:df1d:85c6 with SMTP id 586e51a60fabf-2962dd3a1c0mr3912680fac.8.1731701948269; Fri, 15 Nov 2024 12:19:08 -0800 (PST) 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 46e09a7af769-71a780ea62esm748978a34.5.2024.11.15.12.19.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Nov 2024 12:19:06 -0800 (PST) From: David Lechner Date: Fri, 15 Nov 2024 14:18:52 -0600 Subject: [PATCH v5 13/16] doc: iio: ad7944: describe offload support Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241115-dlech-mainline-spi-engine-offload-2-v5-13-bea815bd5ea5@baylibre.com> References: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> In-Reply-To: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , 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 Add a section to the ad7944 documentation describing how to use the driver with SPI offloading. Signed-off-by: David Lechner Reviewed-by: Jonathan Cameron --- v5 changes: new patch in v5 --- Documentation/iio/ad7944.rst | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Documentation/iio/ad7944.rst b/Documentation/iio/ad7944.rst index 0d26e56aba88..e6dbe4d7f58c 100644 --- a/Documentation/iio/ad7944.rst +++ b/Documentation/iio/ad7944.rst @@ -46,6 +46,8 @@ CS mode, 3-wire, without busy indicator To select this mode in the device tree, set the ``adi,spi-mode`` property to ``"single"`` and omit the ``cnv-gpios`` property. +This is the only wiring configuration supported when using `SPI offload support`_. + CS mode, 4-wire, without busy indicator ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -106,7 +108,6 @@ Unimplemented features ---------------------- - ``BUSY`` indication -- ``TURBO`` mode Device attributes @@ -147,6 +148,27 @@ AD7986 is a fully-differential ADC and has the following attributes: In "chain" mode, additional chips will appear as additional voltage input channels, e.g. ``in_voltage2-voltage3_raw``. +SPI offload support +=================== + +To be able to achieve the maximum sample rate, the driver can be used with the +`AXI SPI Engine`_ to provide SPI offload support. + +.. _AXI SPI Engine: http://analogdevicesinc.github.io/hdl/projects/pulsar_adc/index.html + +When SPI offload is being used, some attributes will be different. + +* ``trigger`` directory is removed. +* ``in_voltage0_sampling_frequency`` attribute is added for setting the sample + rate. +* ``in_voltage0_sampling_frequency_available`` attribute is added for querying + the max sample rate. +* ``timestamp`` channel is removed. +* Buffer data format may be different compared to when offload is not used, + e.g. the ``in_voltage0_type`` attribute. + +If the ``turbo-gpios`` property is present in the device tree, the driver will +turn on TURBO during buffered reads and turn it off otherwise. Device buffers ============== From patchwork Fri Nov 15 20:18:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 844880 Received: from mail-oa1-f50.google.com (mail-oa1-f50.google.com [209.85.160.50]) (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 113EE1F9411 for ; Fri, 15 Nov 2024 20:19:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701952; cv=none; b=uVOmaSoKqx1I4zfTn4VFlOw+DrlEDE5fD7aArJnDf8F9Jn0nCoEI2rvhnUJ/TrOrAAVTkrmwGakXKuyd/q4nmNiQv/3hbJMnYojbLd+QK8zsTGPZrxII1MpzR/jjSIpdkwFMP70PyPedM1bc8Pk3GAVD5QK1EWjHfyA8X5EQ+S4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701952; c=relaxed/simple; bh=S/ZB5G447JrD+Sj23MWpY7n93070DqnmYQOxfSZ5VDw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jdfeUGUf0wJyCM9OawkBxKYuGbitDygdlnCrWHjJNLhxeUGRK/X4HF4wCtu0ba5EOtf6CEIROxpCjgLlUYUnIx9CKz+zSad8vV7FKBgwareHtY8w7xUqQ90XcAHXlM+ZjXWFQ5COC8f0BQWQJOdwFhEmJy+19IuUluTbBnP4wV4= 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=2qOSNTK+; arc=none smtp.client-ip=209.85.160.50 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="2qOSNTK+" Received: by mail-oa1-f50.google.com with SMTP id 586e51a60fabf-295d27f9fc9so23285fac.0 for ; Fri, 15 Nov 2024 12:19:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1731701949; x=1732306749; 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=hZDnLi74GMbcbXDL9gHZvGllU4Iq2w9PER/wlLwda4Y=; b=2qOSNTK+ZdWud8H4mHw9PaZ+HHyD6VIedYFPEMmTh/h+bdW24SxtzUNkoCCAy7l1cR DkN9bdW8PIezIyDxHzG6L7oCaaJpQ3d28KvAwhQ8tZ7Wg7pFySN9W8ujAbUjfVxGNRTU HtblVt/burP9cVxHWDwvmdJGYSGw786hwPnXbV1f+El0+qgJBbs/Km0psT9ZF9hshpnP 9h7QnhLlcGUVCfeXhE6xlCRwPGcKdQGnExFPLXuuKFZ12vYY1Z9VNHfYITG+G6zoL2Vb 77iTLnFW/FTOXORJx+FGJiHa8uL/YJEYpcuXnbbbbsDvSm/b8xml8TOqG0AK5xCNNXiF XJeA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731701949; x=1732306749; 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=hZDnLi74GMbcbXDL9gHZvGllU4Iq2w9PER/wlLwda4Y=; b=KLBZDPm9J2awbY33BPO4mmVFxWpEOvJmgwFVz+R5Nc9RUEzhPtdhzZLS/J5YbOJDKD RklC2JdxAkyo5O2AdZs0J/obNwJapXXzPYs4yK1dhjJf0WAbzc9ClEo9bekrFz8jJDLS joF9De+BI2Vu+rPvyBqIQu3+wKLsre76Suvu5OtNL8xUL8ET2sGMKwnxIA+ksL8bgfBS VnZ0JwNG91rZh+10mJamDglo+q6A4aoHgRjleF939A2YL3uSTwXgZziiIpi/oduBwKnP Ui66lv/YSYdMjG+vhLtCsZLURlde86M9xBo4QcYSHId2mhOyP2CTwMhs3nX7Z7oUweuy 05Fg== X-Forwarded-Encrypted: i=1; AJvYcCXXdqpcNX15qqjnYrKwW3j965o6/9/duVvj66BTZAkSAv0RnoIIGFa1Ve4iMefBceVyYnnQwa4gNRk=@vger.kernel.org X-Gm-Message-State: AOJu0Yxg93SDDOYejmzBJYmm5QL/uKGxEBaztoX8isZr7pHOsphk0sny ewxNIfQ0WB7XBFrCOHfKO/idaqId7+jdeB4lYjbUXf6EjtgYT8QIA1sSnFunKOA= X-Google-Smtp-Source: AGHT+IEAilK2ZOpQfbXmxKo0iagU/D0Z/JRkDI6Rf6wF0ylOLjKlbR82USKYPG9tkrONhOjTLTEPXA== X-Received: by 2002:a05:6870:7a08:b0:26f:ddfa:3564 with SMTP id 586e51a60fabf-2962dcca0d7mr4563036fac.6.1731701949133; Fri, 15 Nov 2024 12:19:09 -0800 (PST) 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 46e09a7af769-71a780ea62esm748978a34.5.2024.11.15.12.19.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Nov 2024 12:19:08 -0800 (PST) From: David Lechner Date: Fri, 15 Nov 2024 14:18:53 -0600 Subject: [PATCH v5 14/16] dt-bindings: iio: adc: adi,ad4695: add SPI offload properties Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241115-dlech-mainline-spi-engine-offload-2-v5-14-bea815bd5ea5@baylibre.com> References: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> In-Reply-To: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , 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 Add a pwms property to the adi,ad4695 binding to specify an optional PWM output connected to the CNV pin on the ADC. Also add #trigger-source-cells property to allow the BUSY output to be used as a SPI offload trigger source to indicate when a sample is ready to be read. Macros are added to adi,ad4695.h for the cell values to help with readability since they are arbitrary values. The $ref for spi-peripheral-props.yaml is moved to keep similar $refs grouped together. Signed-off-by: David Lechner --- v5 changes: * Added macros for cell values v4 changes: new patch in v4 --- .../devicetree/bindings/iio/adc/adi,ad4695.yaml | 16 ++++++++++++++-- include/dt-bindings/iio/adc/adi,ad4695.h | 7 +++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad4695.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad4695.yaml index 7d2229dee444..c0d4e4ff62a4 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad4695.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad4695.yaml @@ -18,8 +18,6 @@ description: | * https://www.analog.com/en/products/ad4697.html * https://www.analog.com/en/products/ad4698.html -$ref: /schemas/spi/spi-peripheral-props.yaml# - properties: compatible: enum: @@ -84,6 +82,9 @@ properties: description: The Reset Input (RESET). Should be configured GPIO_ACTIVE_LOW. maxItems: 1 + pwms: + description: PWM signal connected to the CNV pin. + interrupts: minItems: 1 items: @@ -106,6 +107,15 @@ properties: The first cell is the GPn number: 0 to 3. The second cell takes standard GPIO flags. + '#trigger-source-cells': + description: | + First cell indicates the output signal: 0 = BUSY, 1 = ALERT. + Second cell indicates which GPn pin is used: 0, 2 or 3. + + For convenience, macros for these values are available in + dt-bindings/iio/adc/adi,ad4695.h. + const: 2 + "#address-cells": const: 1 @@ -166,6 +176,8 @@ required: - vio-supply allOf: + - $ref: /schemas/spi/spi-peripheral-props.yaml# + - $ref: /schemas/spi/trigger-source.yaml# - oneOf: - required: - ldo-in-supply diff --git a/include/dt-bindings/iio/adc/adi,ad4695.h b/include/dt-bindings/iio/adc/adi,ad4695.h index 9fbef542bf67..fea4525d2710 100644 --- a/include/dt-bindings/iio/adc/adi,ad4695.h +++ b/include/dt-bindings/iio/adc/adi,ad4695.h @@ -6,4 +6,11 @@ #define AD4695_COMMON_MODE_REFGND 0xFF #define AD4695_COMMON_MODE_COM 0xFE +#define AD4695_TRIGGER_EVENT_BUSY 0 +#define AD4695_TRIGGER_EVENT_ALERT 1 + +#define AD4695_TRIGGER_PIN_GP0 0 +#define AD4695_TRIGGER_PIN_GP2 2 +#define AD4695_TRIGGER_PIN_GP3 3 + #endif /* _DT_BINDINGS_ADI_AD4695_H */ From patchwork Fri Nov 15 20:18:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 843773 Received: from mail-oo1-f50.google.com (mail-oo1-f50.google.com [209.85.161.50]) (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 012081FAC38 for ; Fri, 15 Nov 2024 20:19:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701955; cv=none; b=EBDVxTsneUS4dr3Kl7XAwlmC4HI5Nlp8Gxh3CX3oTDuiTn1VGil2ZrCRF95V4ZM850Q9lMcCtflNtlbDWo3pNYLA9cpbwuxbUKPE8DoGu2ZCK2II5iDku3s2EiMgZoz9jLrxN0fIBlI0Gn5jRePPf0dW9vz3KZraL7nda4sCRtk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701955; c=relaxed/simple; bh=lAGm0BfqgiNcIcjLhq96l0xwQMzn10PfebZ1OkujxZY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=afxJNKmErv/1NofgQzEwe1/WazYzqAa84vvTcMyWyZHsp16QGhgE3Ux6NxLNogQnWpM+d+TMXNQEv7h0WN0fXRP9qE4AJzwu4ddpU/5ni1wOUtr8ghJ6v2NgAyk4E193bSUDi4hIvTI0HTRg9nysH+gCwobgATtEzTJ0Oko48/o= 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=y2PppCwh; arc=none smtp.client-ip=209.85.161.50 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="y2PppCwh" Received: by mail-oo1-f50.google.com with SMTP id 006d021491bc7-5ee55fa4b31so1226702eaf.0 for ; Fri, 15 Nov 2024 12:19:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1731701952; x=1732306752; 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=+8s25RYMi+zlyRDlUm0JExPlZPMjT1HBFf4tYIofzew=; b=y2PppCwhMF68/W9cV0d37bUh48J1V2i/bz+69x752BvQIPWXO7JJG80uPa3M/bWNAA cCEGFqOKBD3JmgBIUJ+AR3xsr846QjbJr71EYnmJeoudd1QtTHfss0eo05knaorC4bZD jeyvpaWI7tbQR5HdvAqEt1qwgGUhZUcOG8K3cXrXHXYwarq7KqFMMyoDKx4OV5SbK5ss pU5w7oncMjw2d8R9d/YFM+f57WgiZbyyPbVaaEZQgn+lJSXSmq0kI7Kh2Kn9VOAFag4G U9Vdmlw9OvyHLMh2TOfRNFZ+ZsjMI5jUVlC7A2rA+C1RAP4Hl3DCh/ghCENB5A6xmWIA T6qQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731701952; x=1732306752; 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=+8s25RYMi+zlyRDlUm0JExPlZPMjT1HBFf4tYIofzew=; b=ZlvBO7novfzGzQgs5dMvGsonEByKKAdyrDhWTctpMYgvyo2zwL69JjvwcBn2UIhK5S 3UcQY/IJmwE2HdCfMy0/J1/DPjp3O+zORHzux2jrCYwTg2cy3ct8Vhazz1x+vf0KsdoV jRXAQr9Ojc5KbEOLNWWCnkgcWW9aibUkCWgJvHOV2RrMiEVdqtBGUNEAykZWkK7PGnil O75EoqWaNl5NgD/OoTLTtNKCe2dEB5doObNRmR/ttTonz3hAY6U4S3c6PP7fO05iLZ1A A3zfzNH6YWKezjCjQQIY+Np6hoRXq6G0Fp7kLBRRr4F5JefhSSQpEAOkKY+rjeb8hOlQ YB/g== X-Forwarded-Encrypted: i=1; AJvYcCWPAo6N53QW7QEnZlGLHBjwMfaQLIlxwg3fYgWrGJQj/NhigYOq1POgu2c/X7leM4OlgDzPkHndhW0=@vger.kernel.org X-Gm-Message-State: AOJu0Yx0P5syQP3HLwoxtgs1rbutx/3ECDxC/6vJWEOJnbhn8ucxy/Y1 eLRvmi3Tu21yzTp5fNU7on/r5c4fQKiCNXoRBbWjsilGQd/TyHoPsD/i4uSYNHk= X-Google-Smtp-Source: AGHT+IF+lv4w+8HYxFzmk7lngOHQjR5NRVDb+KEp2Ni5zx2ZGPOp/A07V9v7MCv0sDwNk76D0Q1dow== X-Received: by 2002:a05:6820:2d0c:b0:5ed:feae:d5bd with SMTP id 006d021491bc7-5eeab410f02mr4409964eaf.3.1731701952105; Fri, 15 Nov 2024 12:19:12 -0800 (PST) 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 46e09a7af769-71a780ea62esm748978a34.5.2024.11.15.12.19.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Nov 2024 12:19:10 -0800 (PST) From: David Lechner Date: Fri, 15 Nov 2024 14:18:54 -0600 Subject: [PATCH v5 15/16] iio: adc: ad4695: Add support for SPI offload Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241115-dlech-mainline-spi-engine-offload-2-v5-15-bea815bd5ea5@baylibre.com> References: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> In-Reply-To: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , 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 Add support for SPI offload to the ad4695 driver. SPI offload allows sampling data at the max sample rate (500kSPS or 1MSPS). This is developed and tested against the ADI example FPGA design for this family of ADCs [1]. [1]: http://analogdevicesinc.github.io/hdl/projects/ad469x_fmc/index.html Signed-off-by: David Lechner Reviewed-by: Jonathan Cameron --- v5 changes: * Register SCLK speed handling has been split out into a separate series. * Add sampling_frequency_available attribute. * Limit max allowed sampling frequency based on chip info. * Expand explanations of offload enable/disable ordering requirements. * Finish TODO to use macros for phandle arg values. * Don't use dev_info() when falling back to non-offload operation. * Update to accommodate changes in other patches in this series. v4 changes: new patch in v4 --- drivers/iio/adc/Kconfig | 1 + drivers/iio/adc/ad4695.c | 438 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 422 insertions(+), 17 deletions(-) diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 995b9cacbaa9..ec60b64c46e1 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -52,6 +52,7 @@ config AD4695 tristate "Analog Device AD4695 ADC Driver" depends on SPI select IIO_BUFFER + select IIO_BUFFER_DMAENGINE select IIO_TRIGGERED_BUFFER select REGMAP help diff --git a/drivers/iio/adc/ad4695.c b/drivers/iio/adc/ad4695.c index 10f61290e2c1..02880d1ef31b 100644 --- a/drivers/iio/adc/ad4695.c +++ b/drivers/iio/adc/ad4695.c @@ -19,14 +19,18 @@ #include #include #include +#include #include #include #include #include #include +#include #include +#include #include #include +#include #include #include @@ -66,6 +70,8 @@ #define AD4695_REG_STD_SEQ_CONFIG 0x0024 #define AD4695_REG_GPIO_CTRL 0x0026 #define AD4695_REG_GP_MODE 0x0027 +#define AD4695_REG_GP_MODE_BUSY_GP_SEL BIT(5) +#define AD4695_REG_GP_MODE_BUSY_GP_EN BIT(1) #define AD4695_REG_TEMP_CTRL 0x0029 #define AD4695_REG_TEMP_CTRL_TEMP_EN BIT(0) #define AD4695_REG_CONFIG_IN(n) (0x0030 | (n)) @@ -124,13 +130,22 @@ struct ad4695_channel_config { struct ad4695_state { struct spi_device *spi; + struct spi_offload *offload; + struct spi_offload_trigger *offload_trigger; struct regmap *regmap; struct regmap *regmap16; struct gpio_desc *reset_gpio; + /* currently PWM CNV only supported with SPI offload use */ + struct pwm_device *cnv_pwm; + /* protects against concurrent use of cnv_pwm */ + struct mutex cnv_pwm_lock; + /* offload also requires separate gpio to manually control CNV */ + struct gpio_desc *cnv_gpio; /* voltages channels plus temperature and timestamp */ struct iio_chan_spec iio_chan[AD4695_MAX_CHANNELS + 2]; struct ad4695_channel_config channels_cfg[AD4695_MAX_CHANNELS]; const struct ad4695_chip_info *chip_info; + int sample_freq_range[3]; /* Reference voltage. */ unsigned int vref_mv; /* Common mode input pin voltage. */ @@ -355,6 +370,13 @@ static const struct ad4695_chip_info ad4698_chip_info = { .num_voltage_inputs = 8, }; +static void ad4695_cnv_manual_trigger(struct ad4695_state *st) +{ + gpiod_set_value_cansleep(st->cnv_gpio, 1); + ndelay(10); + gpiod_set_value_cansleep(st->cnv_gpio, 0); +} + /** * ad4695_set_single_cycle_mode - Set the device in single cycle mode * @st: The AD4695 state @@ -460,6 +482,17 @@ static int ad4695_exit_conversion_mode(struct ad4695_state *st) */ st->cnv_cmd2 = AD4695_CMD_EXIT_CNV_MODE << 3; + if (st->cnv_gpio) { + ad4695_cnv_manual_trigger(st); + + /* + * In this case, CNV is not connected to CS, so we don't need + * the extra CS toggle to trigger the conversion and toggling + * CS would have no effect. + */ + return spi_sync_transfer(st->spi, &xfers[1], 1); + } + return spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); } @@ -687,6 +720,159 @@ static irqreturn_t ad4695_trigger_handler(int irq, void *p) return IRQ_HANDLED; } +static int ad4695_offload_buffer_postenable(struct iio_dev *indio_dev) +{ + struct ad4695_state *st = iio_priv(indio_dev); + struct spi_offload_trigger_config config = { + .type = SPI_OFFLOAD_TRIGGER_DATA_READY, + }; + struct spi_transfer *xfer = &st->buf_read_xfer[0]; + struct pwm_state state; + u8 temp_chan_bit = st->chip_info->num_voltage_inputs; + u8 num_slots = 0; + u8 temp_en = 0; + unsigned int bit; + int ret; + + iio_for_each_active_channel(indio_dev, bit) { + if (bit == temp_chan_bit) { + temp_en = 1; + continue; + } + + ret = regmap_write(st->regmap, AD4695_REG_AS_SLOT(num_slots), + FIELD_PREP(AD4695_REG_AS_SLOT_INX, bit)); + if (ret) + return ret; + + num_slots++; + } + + /* + * For non-offload, we could discard data to work around this + * restriction, but with offload, that is not possible. + */ + if (num_slots < 2) { + dev_err(&st->spi->dev, + "At least two voltage channels must be enabled.\n"); + return -EINVAL; + } + + ret = regmap_update_bits(st->regmap, AD4695_REG_TEMP_CTRL, + AD4695_REG_TEMP_CTRL_TEMP_EN, + FIELD_PREP(AD4695_REG_TEMP_CTRL_TEMP_EN, + temp_en)); + if (ret) + return ret; + + /* Each BUSY event means just one sample for one channel is ready. */ + memset(xfer, 0, sizeof(*xfer)); + xfer->offload_flags = SPI_OFFLOAD_XFER_RX_STREAM; + xfer->bits_per_word = 16; + xfer->len = 2; + + spi_message_init_with_transfers(&st->buf_read_msg, xfer, 1); + st->buf_read_msg.offload = st->offload; + + ret = spi_optimize_message(st->spi, &st->buf_read_msg); + if (ret) + return ret; + + /* + * NB: technically, this is part the SPI offload trigger enable, but it + * doesn't work to call it from the offload trigger enable callback + * because it requires accessing the SPI bus. Calling it from the + * trigger enable callback could cause a deadlock. + */ + ret = regmap_set_bits(st->regmap, AD4695_REG_GP_MODE, + AD4695_REG_GP_MODE_BUSY_GP_EN); + if (ret) + goto err_unoptimize_message; + + ret = spi_offload_trigger_enable(st->offload, st->offload_trigger, + &config); + if (ret) + goto err_disable_busy_output; + + ret = ad4695_enter_advanced_sequencer_mode(st, num_slots); + if (ret) + goto err_offload_trigger_disable; + + guard(mutex)(&st->cnv_pwm_lock); + pwm_get_state(st->cnv_pwm, &state); + /* + * PWM subsystem generally rounds down, so requesting 2x minimum high + * time ensures that we meet the minimum high time in any case. + */ + state.duty_cycle = AD4695_T_CNVH_NS * 2; + ret = pwm_apply_might_sleep(st->cnv_pwm, &state); + if (ret) + goto err_offload_exit_conversion_mode; + + return 0; + +err_offload_exit_conversion_mode: + /* + * We have to unwind in a different order to avoid triggering offload. + * ad4695_exit_conversion_mode() triggers a conversion, so it has to be + * done after spi_offload_trigger_disable(). + */ + spi_offload_trigger_disable(st->offload, st->offload_trigger); + ad4695_exit_conversion_mode(st); + goto err_disable_busy_output; + +err_offload_trigger_disable: + spi_offload_trigger_disable(st->offload, st->offload_trigger); + +err_disable_busy_output: + regmap_clear_bits(st->regmap, AD4695_REG_GP_MODE, + AD4695_REG_GP_MODE_BUSY_GP_EN); + +err_unoptimize_message: + spi_unoptimize_message(&st->buf_read_msg); + + return ret; +} + +static int ad4695_offload_buffer_predisable(struct iio_dev *indio_dev) +{ + struct ad4695_state *st = iio_priv(indio_dev); + struct pwm_state state; + int ret; + + scoped_guard(mutex, &st->cnv_pwm_lock) { + pwm_get_state(st->cnv_pwm, &state); + state.duty_cycle = 0; + ret = pwm_apply_might_sleep(st->cnv_pwm, &state); + if (ret) + return ret; + } + + spi_offload_trigger_disable(st->offload, st->offload_trigger); + + /* + * ad4695_exit_conversion_mode() triggers a conversion, so it has to be + * done after spi_offload_trigger_disable(). + */ + ret = ad4695_exit_conversion_mode(st); + if (ret) + return ret; + + ret = regmap_clear_bits(st->regmap, AD4695_REG_GP_MODE, + AD4695_REG_GP_MODE_BUSY_GP_EN); + if (ret) + return ret; + + spi_unoptimize_message(&st->buf_read_msg); + + return 0; +} + +static const struct iio_buffer_setup_ops ad4695_offload_buffer_setup_ops = { + .postenable = ad4695_offload_buffer_postenable, + .predisable = ad4695_offload_buffer_predisable, +}; + /** * ad4695_read_one_sample - Read a single sample using single-cycle mode * @st: The AD4695 state @@ -718,6 +904,13 @@ static int ad4695_read_one_sample(struct ad4695_state *st, unsigned int address) if (ret) return ret; + /* + * If CNV is connected to CS, the previous function will have triggered + * the conversion, otherwise, we do it manually. + */ + if (st->cnv_gpio) + ad4695_cnv_manual_trigger(st); + /* * Setting the first channel to the temperature channel isn't supported * in single-cycle mode, so we have to do an extra conversion to read @@ -729,6 +922,13 @@ static int ad4695_read_one_sample(struct ad4695_state *st, unsigned int address) ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); if (ret) return ret; + + /* + * If CNV is connected to CS, the previous function will have + * triggered the conversion, otherwise, we do it manually. + */ + if (st->cnv_gpio) + ad4695_cnv_manual_trigger(st); } /* Then read the result and exit conversion mode. */ @@ -842,11 +1042,34 @@ static int ad4695_read_raw(struct iio_dev *indio_dev, default: return -EINVAL; } + case IIO_CHAN_INFO_SAMP_FREQ: { + struct pwm_state state; + + ret = pwm_get_state_hw(st->cnv_pwm, &state); + if (ret) + return ret; + + *val = DIV_ROUND_UP_ULL(NSEC_PER_SEC, state.period); + + return IIO_VAL_INT; + } default: return -EINVAL; } } +static int ad4695_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + return IIO_VAL_INT; + default: + return IIO_VAL_INT_PLUS_MICRO; + } +} + static int ad4695_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int val, int val2, long mask) @@ -900,6 +1123,17 @@ static int ad4695_write_raw(struct iio_dev *indio_dev, default: return -EINVAL; } + case IIO_CHAN_INFO_SAMP_FREQ: { + struct pwm_state state; + + if (val <= 0 || val > st->chip_info->max_sample_rate) + return -EINVAL; + + guard(mutex)(&st->cnv_pwm_lock); + pwm_get_state(st->cnv_pwm, &state); + state.period = DIV_ROUND_UP_ULL(NSEC_PER_SEC, val); + return pwm_apply_might_sleep(st->cnv_pwm, &state); + } default: return -EINVAL; } @@ -923,6 +1157,7 @@ static int ad4695_read_avail(struct iio_dev *indio_dev, */ S16_MIN / 4, 0, 0, MICRO / 4, S16_MAX / 4, S16_MAX % 4 * MICRO / 4 }; + struct ad4695_state *st = iio_priv(indio_dev); switch (mask) { case IIO_CHAN_INFO_CALIBSCALE: @@ -943,6 +1178,10 @@ static int ad4695_read_avail(struct iio_dev *indio_dev, default: return -EINVAL; } + case IIO_CHAN_INFO_SAMP_FREQ: + *vals = st->sample_freq_range; + *type = IIO_VAL_INT; + return IIO_AVAIL_RANGE; default: return -EINVAL; } @@ -978,6 +1217,7 @@ static int ad4695_debugfs_reg_access(struct iio_dev *indio_dev, static const struct iio_info ad4695_info = { .read_raw = &ad4695_read_raw, + .write_raw_get_fmt = &ad4695_write_raw_get_fmt, .write_raw = &ad4695_write_raw, .read_avail = &ad4695_read_avail, .debugfs_reg_access = &ad4695_debugfs_reg_access, @@ -1091,26 +1331,156 @@ static int ad4695_parse_channel_cfg(struct ad4695_state *st) return 0; } +static bool ad4695_offload_trigger_match(struct spi_offload_trigger *trigger, + enum spi_offload_trigger_type type, + u64 *args, u32 nargs) +{ + if (type != SPI_OFFLOAD_TRIGGER_DATA_READY) + return false; + + // args[0] is the trigger event. + // args[1] is the GPIO pin number. + if (nargs != 2 || args[0] != AD4695_TRIGGER_EVENT_BUSY) + return false; + + return true; +} + +static int ad4695_offload_trigger_request(struct spi_offload_trigger *trigger, + enum spi_offload_trigger_type type, + u64 *args, u32 nargs) +{ + struct ad4695_state *st = spi_offload_trigger_get_priv(trigger); + + /* Should already be validated by match, but just in case. */ + if (nargs != 2) + return -EINVAL; + + /* DT tells us if BUSY event uses GP0 or GP3. */ + if (args[1] == AD4695_TRIGGER_PIN_GP3) + return regmap_set_bits(st->regmap, AD4695_REG_GP_MODE, + AD4695_REG_GP_MODE_BUSY_GP_SEL); + + return regmap_clear_bits(st->regmap, AD4695_REG_GPIO_CTRL, + AD4695_REG_GP_MODE_BUSY_GP_SEL); +} + +static int +ad4695_offload_trigger_validate(struct spi_offload_trigger *trigger, + struct spi_offload_trigger_config *config) +{ + if (config->type != SPI_OFFLOAD_TRIGGER_DATA_READY) + return -EINVAL; + + return 0; +} + +/* + * NB: There are no enable/disable callbacks here due to requiring a SPI + * message to enable or disable the BUSY output on the ADC. + */ +static const struct spi_offload_trigger_ops ad4695_offload_trigger_ops = { + .match = ad4695_offload_trigger_match, + .request = ad4695_offload_trigger_request, + .validate = ad4695_offload_trigger_validate, +}; + +static void ad4695_pwm_disable(void *pwm) +{ + pwm_disable(pwm); +} + +static int ad4695_probe_spi_offload(struct iio_dev *indio_dev, + struct ad4695_state *st) +{ + struct device *dev = &st->spi->dev; + struct spi_offload_trigger_info trigger_info = { + .fwnode = dev_fwnode(dev), + .ops = &ad4695_offload_trigger_ops, + .priv = st, + }; + struct pwm_state pwm_state; + struct dma_chan *rx_dma; + int ret, i; + + indio_dev->num_channels = st->chip_info->num_voltage_inputs + 1; + indio_dev->setup_ops = &ad4695_offload_buffer_setup_ops; + + if (!st->cnv_gpio) + return dev_err_probe(dev, -ENODEV, + "CNV GPIO is required for SPI offload\n"); + + ret = devm_spi_offload_trigger_register(dev, &trigger_info); + if (ret) + return dev_err_probe(dev, ret, + "failed to register offload trigger\n"); + + st->offload_trigger = devm_spi_offload_trigger_get(dev, st->offload, + SPI_OFFLOAD_TRIGGER_DATA_READY); + if (IS_ERR(st->offload_trigger)) + return dev_err_probe(dev, PTR_ERR(st->offload_trigger), + "failed to get offload trigger\n"); + + ret = devm_mutex_init(dev, &st->cnv_pwm_lock); + if (ret) + return ret; + + st->cnv_pwm = devm_pwm_get(dev, NULL); + if (IS_ERR(st->cnv_pwm)) + return dev_err_probe(dev, PTR_ERR(st->cnv_pwm), + "failed to get CNV PWM\n"); + + pwm_init_state(st->cnv_pwm, &pwm_state); + + /* If firmware didn't provide default rate, use 10kHz (arbitrary). */ + if (pwm_state.period == 0) + pwm_state.period = 100 * MILLI; + + pwm_state.enabled = true; + + ret = pwm_apply_might_sleep(st->cnv_pwm, &pwm_state); + if (ret) + return dev_err_probe(dev, ret, "failed to apply CNV PWM\n"); + + ret = devm_add_action_or_reset(dev, ad4695_pwm_disable, st->cnv_pwm); + if (ret) + return ret; + + rx_dma = devm_spi_offload_rx_stream_request_dma_chan(dev, st->offload); + if (IS_ERR(rx_dma)) + return dev_err_probe(dev, PTR_ERR(rx_dma), + "failed to get offload RX DMA\n"); + + /* + * REVISIT: ideally, we would ask the RX DMA stream what the + * buffer layout is. Right now, the only supported offload is + * the ADI ad469x HDL project which always uses 32-bit word + * size for data values, regardless of the SPI bits per word. + */ + + for (i = 0; i < indio_dev->num_channels; i++) { + struct iio_chan_spec *chan = &st->iio_chan[i]; + + /* update storagebits to match offload capabilities */ + chan->scan_type.storagebits = 32; + /* add sample frequency for PWM CNV trigger */ + chan->info_mask_separate |= BIT(IIO_CHAN_INFO_SAMP_FREQ); + chan->info_mask_separate_available |= BIT(IIO_CHAN_INFO_SAMP_FREQ); + } + + return devm_iio_dmaengine_buffer_setup_ext2(dev, indio_dev, rx_dma, + IIO_BUFFER_DIRECTION_IN); +} + static int ad4695_probe(struct spi_device *spi) { struct device *dev = &spi->dev; struct ad4695_state *st; struct iio_dev *indio_dev; - struct gpio_desc *cnv_gpio; bool use_internal_ldo_supply; bool use_internal_ref_buffer; int ret; - cnv_gpio = devm_gpiod_get_optional(dev, "cnv", GPIOD_OUT_LOW); - if (IS_ERR(cnv_gpio)) - return dev_err_probe(dev, PTR_ERR(cnv_gpio), - "Failed to get CNV GPIO\n"); - - /* Driver currently requires CNV pin to be connected to SPI CS */ - if (cnv_gpio) - return dev_err_probe(dev, -ENODEV, - "CNV GPIO is not supported\n"); - indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); if (!indio_dev) return -ENOMEM; @@ -1122,6 +1492,10 @@ static int ad4695_probe(struct spi_device *spi) if (!st->chip_info) return -EINVAL; + st->sample_freq_range[0] = 1; /* min */ + st->sample_freq_range[1] = 1; /* step */ + st->sample_freq_range[2] = st->chip_info->max_sample_rate; /* max */ + st->regmap = devm_regmap_init(dev, &ad4695_regmap_bus, st, &ad4695_regmap_config); if (IS_ERR(st->regmap)) @@ -1134,6 +1508,11 @@ static int ad4695_probe(struct spi_device *spi) return dev_err_probe(dev, PTR_ERR(st->regmap16), "Failed to initialize regmap16\n"); + st->cnv_gpio = devm_gpiod_get_optional(dev, "cnv", GPIOD_OUT_LOW); + if (IS_ERR(st->cnv_gpio)) + return dev_err_probe(dev, PTR_ERR(st->cnv_gpio), + "Failed to get CNV GPIO\n"); + ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(ad4695_power_supplies), ad4695_power_supplies); @@ -1260,12 +1639,36 @@ static int ad4695_probe(struct spi_device *spi) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = st->iio_chan; - ret = devm_iio_triggered_buffer_setup(dev, indio_dev, - iio_pollfunc_store_time, - ad4695_trigger_handler, - &ad4695_buffer_setup_ops); - if (ret) - return ret; + static const struct spi_offload_config ad4695_offload_config = { + .capability_flags = SPI_OFFLOAD_CAP_TRIGGER + | SPI_OFFLOAD_CAP_RX_STREAM_DMA, + }; + + st->offload = devm_spi_offload_get(dev, spi, &ad4695_offload_config); + ret = PTR_ERR_OR_ZERO(st->offload); + if (ret && ret != -ENODEV) + return dev_err_probe(dev, ret, "failed to get SPI offload\n"); + + /* If no SPI offload, fall back to low speed usage. */ + if (ret == -ENODEV) { + /* Driver currently requires CNV pin to be connected to SPI CS */ + if (st->cnv_gpio) + return dev_err_probe(dev, -EINVAL, + "CNV GPIO is not supported\n"); + + indio_dev->num_channels = st->chip_info->num_voltage_inputs + 2; + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, + iio_pollfunc_store_time, + ad4695_trigger_handler, + &ad4695_buffer_setup_ops); + if (ret) + return ret; + } else { + ret = ad4695_probe_spi_offload(indio_dev, st); + if (ret) + return ret; + } return devm_iio_device_register(dev, indio_dev); } @@ -1302,3 +1705,4 @@ MODULE_AUTHOR("Ramona Gradinariu "); MODULE_AUTHOR("David Lechner "); MODULE_DESCRIPTION("Analog Devices AD4695 ADC driver"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(IIO_DMAENGINE_BUFFER); From patchwork Fri Nov 15 20:18:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 844879 Received: from mail-oo1-f42.google.com (mail-oo1-f42.google.com [209.85.161.42]) (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 C91B31FAC5B for ; Fri, 15 Nov 2024 20:19:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701956; cv=none; b=AtwF4SGx5QRQckgmWzzfqDAEOJeIFnrN0E7EfEHbsUHi6sOyzRVGgy1jEI7gC00egckSa+xmAL/49aKvO6UNkBYJtsIyJIaTLCF8pcxM5MImIz/mF4JcBVZxXs+aCoYBMks/jE6tqwLF7q0QHleYOnVVd+jfl9ci8dPjBAQ270I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731701956; c=relaxed/simple; bh=Hk8RC/iufxLD2a+ydJA5dpksupb3CS/GNCxUZjKmAHU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VOICcg+0FRxxGDiA+PF2Ea0UhTuE+5tncJ++xVPsQRF/K94VMuCmrUHC6J+AszuC5dtBU7gYgrqrtHLK/D3M9vH3tZFNDQiIVDgJVbnefcTG6YtNAUgwsL4rw0cVjUJc6JMfTiXsP6wUfo8KPlgYHAJD42KKV44nSkQWeQqug2I= 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=xOyyUJxh; arc=none smtp.client-ip=209.85.161.42 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="xOyyUJxh" Received: by mail-oo1-f42.google.com with SMTP id 006d021491bc7-5ee645cf763so1181212eaf.2 for ; Fri, 15 Nov 2024 12:19:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1731701953; x=1732306753; 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=6w6V24uqzrq77Vph3I2ahD02yEXC9JX57Vqpm9P42UI=; b=xOyyUJxhxgZd6Q6GZohN9F1v2IpE+n7woi4+cr95f24s7g/EWkYF8JM/S0bxg+2ies 79ZL8dz3MXx00RbAemQ72Y4RjR6HwA5lfB94HkHIq9HpMaEjmMNV4OKGXhAgfaRTi25p 7i0SW3A0U7hA1rVuT+JiLW1lHGq03mbL9dpTcGP7HD8TEhcRpojFnVDohP3HDNSarHhJ 8DphJpHaXd1+7DRvomaxOjAyU7HhU/PJh2glFcdu8KvMi1U27lHZyrWXqfzIOGZsYHHl X/BSBct/TCGBTimZDIABQ3TN3uYQ+tityGl0N65no+iEqzH4wncG/QpCXXrTdu/XGbQ0 H2rw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731701953; x=1732306753; 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=6w6V24uqzrq77Vph3I2ahD02yEXC9JX57Vqpm9P42UI=; b=F7invbq1LZB5uzRHmoTMLpmCPLHgDVxCq5v8oLURRah9y+iYXD9vibPfkrXgn9sz7F 42lex4OXVvgZIvP8ZiiJUYoSHcqKy2wlAINpDCRPrhtRVzS/fl0qPsa4HzLRSeihEXQL fJHxPEocRHbhvAc6LHtWN2++uCKr/47MWtthCwexHKLkry3SEpc+qIIZsAa/IPquJYaj 7d9p/K+zps6WcDv4vWNiyQ5F9HGJOJ2oUApvoVv9yWY2lLNX7o3u4eNgtp9sVkMA/b3T wV5YYG6ZATTVMAomAhnpw5Epv/FtjuRg000AopZL6ozN21FDscQmKhxI+/N/tnSBbt8W aGmA== X-Forwarded-Encrypted: i=1; AJvYcCVzmTPPyGvb3fw4XyHE4zS03mMGuyY5ksFerf7uiAQFLzur+REbiDovCW0kOXb2mGbIXvcNkaSZwFk=@vger.kernel.org X-Gm-Message-State: AOJu0YwDtEFJ+30KgBjHl97i33sZgLTN/cgZTMBFcMiO/moFy149lirn n8dVwdaSq7Wd/vkcUgBVfuP4mTJ70LUOkv+ncOAGZVGKYiPqzM1eXF/7SsxpJqc= X-Google-Smtp-Source: AGHT+IFO2Tmuu3SXBwdN6noWGmFoRzGeGSqPwhckywErQbXZsu+Ra0D/gCw1hGXbt0rPUVfh6B5vqg== X-Received: by 2002:a05:6820:1a0a:b0:5ec:c22c:72db with SMTP id 006d021491bc7-5eeab29e337mr4710916eaf.2.1731701953013; Fri, 15 Nov 2024 12:19:13 -0800 (PST) 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 46e09a7af769-71a780ea62esm748978a34.5.2024.11.15.12.19.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 Nov 2024 12:19:12 -0800 (PST) From: David Lechner Date: Fri, 15 Nov 2024 14:18:55 -0600 Subject: [PATCH v5 16/16] doc: iio: ad4695: add SPI offload support Precedence: bulk X-Mailing-List: linux-spi@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20241115-dlech-mainline-spi-engine-offload-2-v5-16-bea815bd5ea5@baylibre.com> References: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> In-Reply-To: <20241115-dlech-mainline-spi-engine-offload-2-v5-0-bea815bd5ea5@baylibre.com> To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , 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 Document SPI offload support for the ad4695 driver. Signed-off-by: David Lechner --- v5 changes: new patch in v5 --- Documentation/iio/ad4695.rst | 68 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/Documentation/iio/ad4695.rst b/Documentation/iio/ad4695.rst index 9ec8bf466c15..8009a0c272bc 100644 --- a/Documentation/iio/ad4695.rst +++ b/Documentation/iio/ad4695.rst @@ -47,6 +47,36 @@ In this mode, CNV and CS are tied together and there is a single SDO line. To use this mode, in the device tree, omit the ``cnv-gpios`` and ``spi-rx-bus-width`` properties. +SPI offload wiring +^^^^^^^^^^^^^^^^^^ + +When used with a SPI offload, the supported wiring configuration is: + +.. code-block:: + + +-------------+ +-------------+ + | GP0/BUSY |-------->| TRIGGER | + | CS |<--------| CS | + | | | | + | ADC | | SPI | + | | | | + | SDI |<--------| SDO | + | SDO |-------->| SDI | + | SCLK |<--------| SCLK | + | | | | + | | +-------------+ + | CNV |<-----+--| PWM | + | | +--| GPIO | + +-------------+ +-------------+ + +In this case, both the ``cnv-gpios`` and ``pwms`` properties are required. +The ``#trigger-source-cells = <2>`` property is also required to connect back +to the SPI offload. The SPI offload will have ``trigger-sources`` property +with cells to indicate the busy signal and which GPx pin is used, e.g +``<&ad4695 AD4695_TRIGGER_EVENT_BUSY AD4695_TRIGGER_PIN_GP0>``. + +.. seealso:: `SPI offload support`_ + Channel configuration --------------------- @@ -158,6 +188,27 @@ Unimplemented features - GPIO support - CRC support +SPI offload support +=================== + +To be able to achieve the maximum sample rate, the driver can be used with the +`AXI SPI Engine`_ to provide SPI offload support. + +.. _AXI SPI Engine: http://analogdevicesinc.github.io/hdl/projects/ad469x_fmc/index.html + +.. seealso:: `SPI offload wiring`_ + +When SPI offload is being used, some attributes will be different. + +* ``trigger`` directory is removed. +* ``in_voltage0_sampling_frequency`` attributes are added for setting the sample + rate. +* ``in_voltage0_sampling_frequency_available`` attributes are added for querying + the max sample rate. +* ``timestamp`` channel is removed. +* Buffer data format may be different compared to when offload is not used, + e.g. the ``in_voltage0_type`` attribute. + Device buffers ============== @@ -165,3 +216,20 @@ This driver supports hardware triggered buffers. This uses the "advanced sequencer" feature of the chip to trigger a burst of conversions. Also see :doc:`iio_devbuf` for more general information. + +Effective sample rate for buffered reads +---------------------------------------- + +When SPI offload is not used, the sample rate is determined by the trigger that +is manually configured in userspace. All enabled channels will be read in a +burst when the trigger is received. + +When SPI offload is used, the sample rate is configured per channel. All +all channels will have the same rate, so only one ``sampling_frequency`` +attribute needs to be set. Since this rate determines the delay between each +individual conversion, the effective sample rate for each sample is actually +the sum of the periods of each enabled channel in a buffered read. In other +words, it is the value of the ``sampling_frequency`` attribute divided by the +number of enabled channels. So if 4 channels are enabled, with the +``sampling_frequency`` attributes set to 1 MHz, the effective sample rate is +250 kHz.