From patchwork Mon Jul 22 21:57:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 13739151 Received: from mail-ot1-f53.google.com (mail-ot1-f53.google.com [209.85.210.53]) (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 B16631849 for ; Mon, 22 Jul 2024 22:01:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721685690; cv=none; b=U1cLyZwmzSPUX/zMeP3Vz4BTdnLdYUPY9TquTr6ynJo9lkx6GzYvewqtF9Cb3QWTcqS7bhbPp+1xrO+daK8A3ppmQNmkwdMbdZaFl+G6WButWEpR3NIzumvgLddcABjw2C9oE9RlkenzbjZEet+DtBy1YiUDhRoloY2YqEzCHPI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721685690; c=relaxed/simple; bh=wulqRuubMrgRAM7cMPkpHvYollCniUKOOXs7X5dxBfI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=MVM2vH9KNVyH41IwV0lhjJHD+H6KHJzQvZVIb5fjjAT/T7Zr9iN/Rfjdi66Psz6U/EJ8fdvo9DzV/WuJ+m4kf6MhvxRBRFJa5ZziyNpm32TMK218rpZdLTRARyQW8DShWXX/y5za8a2bhRKEbS1I1yFYiMCz9GS5JKhOjQQmnzg= 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=MKnS9PXz; arc=none smtp.client-ip=209.85.210.53 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="MKnS9PXz" Received: by mail-ot1-f53.google.com with SMTP id 46e09a7af769-7037a208ff5so2753868a34.0 for ; Mon, 22 Jul 2024 15:01:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1721685687; x=1722290487; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Ja5JNhTBrJAtUikvnEnwKbaUm2FfY83ptA2bQUTuqEw=; b=MKnS9PXzhioTmGHpkDNWAw8tFQA+5qLpn1Kjz6XRFIPRWrMxKyfGugbzWGu95JtTcK fkmD89klXmOD+aN/s4fBEEIqCjtaKqCvCb+I8HUb0WhkPeHgDGiesUNHA6u2jYwk/aXM 0uuHwUvVUQ1yi9BV3lDHL1atL+kIcZh9wrWpvzIxfen8nav8Py6Mdcp1ggTleCiS5RuJ chaslxdIcS7xrQFliFSpFb7uCuPojalrIH3boIyn2pilFbwpbFtQDfaVbfIOINkHV53g C5PwOFqQl+H/SDnPGqY0ziVxnIr/nca0fKG3IqMC2VB31K3HmWMaBZ2mXCSk7E80rFt4 KASA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721685687; x=1722290487; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Ja5JNhTBrJAtUikvnEnwKbaUm2FfY83ptA2bQUTuqEw=; b=cK0MYesOrnLEYC4izka6lc7L0XS+wD90IN+gFgWgxrRlRlyy5O7LB4NDQXRvG0So3d C4PQ2MYybWRUC7FvyaAN9cB71MmjFgqNcQ4JwmXzbng790myH1bab6RkNwbYKLI7mwLM 8IEPB/LSVl6nYgZQMBaIAlNmKYMew0QyehzUKRw0L/7vah0BXcGGmiYxQYfZIoZt3I92 VE9JT7yxnWMCuTF9kDrUU0sxW5ZtOcaPp7HVAuYYqsSqfMIB1kE5dMHC93h6X+WN1wHn IdKrbmYETNTgZrNdENhFn/p12nhQ/zD27i1n2+j1/HlJSxApDky7qBGVt1Kbq7KAEJdS Gbpg== X-Forwarded-Encrypted: i=1; AJvYcCVnJ4hZ8IKU0evnyPPVjRwtLxir34aQPJW+hskkUeafgagvV0k8xQ4OV+JPKrs9klyr27jBx+GfVC2F+a8z99N0pV4jd9pHcFTI X-Gm-Message-State: AOJu0Yx+kLP81cmGqZXTFUBhtKxNrr9W/OPa6x5o4tI5ck9pMVvlAJGu o53XEeegZCRu64uh/8junbW5wSZ/x0iMBUX7vxqKTkazo1ao3m2ch45ZqGJ6TUw= X-Google-Smtp-Source: AGHT+IG+ELjG5K5NexgQuh6kX11Z7bpUaRB99zGM4WXSrAFQFtdiLR6aW3LuDQ0CxXhP8HJIaai2rA== X-Received: by 2002:a05:6830:6f4b:b0:703:ba24:7320 with SMTP id 46e09a7af769-708fdb0c45cmr11516484a34.10.1721685686745; Mon, 22 Jul 2024 15:01:26 -0700 (PDT) Received: from freyr.lechnology.com (ip98-183-112-25.ok.ok.cox.net. [98.183.112.25]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-708f60a55e1sm1719911a34.11.2024.07.22.15.01.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Jul 2024 15:01:26 -0700 (PDT) From: David Lechner To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: David Lechner , 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 Subject: [PATCH RFC v3 1/9] spi: dt-bindings: add spi-offload properties Date: Mon, 22 Jul 2024 16:57:08 -0500 Message-ID: <20240722-dlech-mainline-spi-engine-offload-2-v3-1-7420e45df69b@baylibre.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240722-dlech-mainline-spi-engine-offload-2-v3-0-7420e45df69b@baylibre.com> References: <20240722-dlech-mainline-spi-engine-offload-2-v3-0-7420e45df69b@baylibre.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Mailer: b4 0.14.0 This adds a new provider/consumer property pair to the generic SPI bindings for use with peripherals connected to controllers that support offloading. Here, offloading means that the controller has the ability to perform SPI transactions without any CPU intervention in some shape or form. The spi-offloads property will be used to assign controller offload resources to each peripheral that needs them. What these resources are will be defined by each specific controller binding by specifying the value of the #spi-offload-cells property. SPI peripherals that use multiple offload instances at the same time for different functions can describe the functions using the spi-offload-names property, for example, for a SPI flash memory, this might be "read", "erase" and "write" functions. Signed-off-by: David Lechner --- v3 changes: * Added #spi-offload-cells property to the controller binding. * Changed spi-offloads to phandle-array. * Added spi-offload-names property. v2 changes: In v1, instead of generic SPI bindings, there were only controller- specific bindings, so this is a new patch. --- Documentation/devicetree/bindings/spi/spi-controller.yaml | 5 +++++ .../devicetree/bindings/spi/spi-peripheral-props.yaml | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/Documentation/devicetree/bindings/spi/spi-controller.yaml b/Documentation/devicetree/bindings/spi/spi-controller.yaml index 093150c0cb87..0af9cce80be9 100644 --- a/Documentation/devicetree/bindings/spi/spi-controller.yaml +++ b/Documentation/devicetree/bindings/spi/spi-controller.yaml @@ -105,6 +105,11 @@ properties: required: - compatible + '#spi-offload-cells': + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Number of cells in a SPI offload specifier. + patternProperties: "^.*@[0-9a-f]+$": type: object diff --git a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml index 0bb443b8decd..e27577bdae48 100644 --- a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml +++ b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml @@ -113,6 +113,17 @@ properties: minItems: 2 maxItems: 4 + spi-offloads: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: + Array of SPI offload instances that are used by the peripheral. + + spi-offload-names: + $ref: /schemas/types.yaml#/definitions/string-array + description: + Describes the function of each offload instance. Can be omitted if there + is only one item allowed in the spi-offloads array. + st,spi-midi-ns: description: | Only for STM32H7, (Master Inter-Data Idleness) minimum time From patchwork Mon Jul 22 21:57:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 13739152 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 A3A2B4597F for ; Mon, 22 Jul 2024 22:01:28 +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=1721685690; cv=none; b=F8KpQ67QvG/fq/U6dImkwbYmyzINWWgX8ojRMuxCyyXSJdWvi/uxbWtT6BgKhYzCdfpgF9l5mOQ51M2kwau6GaVJ1hPTd+FtatnSPi8Rx/hAnrr0AOKvPv+OT0WOK/8fOhdQX4GgVAXV2LvSWKlQWqcye18jozPSeNyRK4eJbhk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721685690; c=relaxed/simple; bh=1B09Jui1kz07R/7PfI7iAgF3gynzk4/nQZkjsJp+2XU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=TkXw5yVycMW4hEPaaFDWyYU7GCWv9mNORlKgTwPC86xcOrR/6MP9un7rIGOq3WvOcz3ZUjFQN5+CVICJf+BDxJ+YJdryu0k/YP+B30fRKPyA/OQ7DJE4ahLGzIVbipT2epWQqAj6YELknbyz03zZnb7P8zSaKU5P3GwgNrbBLj8= 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=0PCVOU+K; 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="0PCVOU+K" Received: by mail-ot1-f46.google.com with SMTP id 46e09a7af769-7044bda722fso2822918a34.2 for ; Mon, 22 Jul 2024 15:01:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1721685688; x=1722290488; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=GZOa0K1V/Ey7BU+5ST8W2wQBmjXJNycuVFCgasaNz1A=; b=0PCVOU+KxNLEFZl631kP1zaD0OwKvE+Em958h0KVfIiS3DmhzZ4XdGgVVV/hSFxOYa rVFNwovE/9tFwaVEItN5gih0vziAH0T430HpZPK3NzWct8wu5JL9Zefqt15PQKXZQ3+O PJEP+JYXKN+lr2X4f7gJGfE1dJVeP9yPaeYJkylaE6kundlX2/5aLGxsEJmJxryKeURZ bSoL7GZ0RsBeLhj06zcwe3WRlwIVp4vuoehJlnijsGS/sEZXcdvfkfpthoFuvOlZf8tz db8jMJa4d+DOBlZC3sQWq2/SCbQTwv8UxrpcR3vhHwR5sa7pPzKEwhll/NZ7l3TNqhV1 69Rg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721685688; x=1722290488; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=GZOa0K1V/Ey7BU+5ST8W2wQBmjXJNycuVFCgasaNz1A=; b=Z/xYDGlhkAVDRqjgn9bAYIT5D2fG6EAUfvb621LHSk957M2bV2VTnsUJ3GP0n9GJhX X1qWBIbMqxfUGs6LSstcdlBu4pAocl0a8WOlfY/IzAcznDaAy+YLHrKFl6Fabf6w/24Q ps9GTo+e0BJAoTsEJLWjYm6cm1FcLLgnJli263mc2h0A9yp+pT4yY+KTnxX4qQFZ8uRu XdKH7UqqU1h+M0CAIrK9YyhK30/RYbaUz7w6Qfie3AAYceMcu2nvZxUcJVY8+r5A6kOH c3MnYmZUU0xXnazcWnNeK10TiCv7VW1UxYa9H6/jlFwwopv2CLs2D6uQdKMR464F9Jhe IB1A== X-Forwarded-Encrypted: i=1; AJvYcCXEguR0CJ7CGhseuBbE7ESvAkdDSvy4ZWPL+6/3RiN9Enl3UD2OvO2odnQkSQLDBSmTbbRZFTOmrbqoe2lst8JkRclu2xDxQNJU X-Gm-Message-State: AOJu0YzZLOvphBOunSdJYaQdtV+yZYUlJLTR1STeFMeBncuJZPEaTDRu YjCVLRneLtdcjcsjIKQKSc/JJTj4i1n4JqvDlGi7QeDk2LQdCsbh6YTADLccuR0= X-Google-Smtp-Source: AGHT+IFo70BHNM9xbD19IHbLstor6jVOhrw5/iz2IMYdO2fmxYUL8cwptC+z293AWKKBiO8ujc4HOg== X-Received: by 2002:a05:6830:488c:b0:708:b46d:5c76 with SMTP id 46e09a7af769-709008dd3abmr9920745a34.17.1721685687669; Mon, 22 Jul 2024 15:01:27 -0700 (PDT) Received: from freyr.lechnology.com (ip98-183-112-25.ok.ok.cox.net. [98.183.112.25]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-708f60a55e1sm1719911a34.11.2024.07.22.15.01.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Jul 2024 15:01:27 -0700 (PDT) From: David Lechner To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: David Lechner , 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 Subject: [PATCH RFC v3 2/9] spi: add basic support for SPI offloading Date: Mon, 22 Jul 2024 16:57:09 -0500 Message-ID: <20240722-dlech-mainline-spi-engine-offload-2-v3-2-7420e45df69b@baylibre.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240722-dlech-mainline-spi-engine-offload-2-v3-0-7420e45df69b@baylibre.com> References: <20240722-dlech-mainline-spi-engine-offload-2-v3-0-7420e45df69b@baylibre.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Mailer: b4 0.14.0 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. This patch adds the basic infrastructure to support SPI offloading. It introduces new callbacks that are to be implemented by controllers with offload capabilities. On SPI device probe, the standard spi-offloads devicetree property is parsed and passed to the controller driver to reserve the resources requested by the peripheral via the map_channel() callback. The peripheral driver can then use spi_offload_prepare() to load a SPI message into the offload hardware. If the controller supports it, this message can then be passed to the SPI message queue as if it was a normal message. Future patches will will also implement a way to use a hardware trigger to start the message transfers rather than going through the message queue. Signed-off-by: David Lechner --- 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. In the previous review, Mark suggested that these functions should not be separate from the spi_[un]optimize() functions. I understand the reasoning behind that. However, it seems like there are two different kinds of things going on here. Currently, spi_optimize() only performs operations on the message data structures and doesn't poke any hardware. This makes it free to be use by any peripheral without worrying about tying up any hardware resources while the message is "optimized". On the other hand, spi_offload_prepare() is poking hardware, so we need to be more careful about how it is used. And in these cases, we need a way to specify exactly which hardware resources it should use, which it is currently doing with the extra ID parameter. --- drivers/spi/spi.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/spi/spi.h | 57 ++++++++++++++++++++++ 2 files changed, 180 insertions(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index d4da5464dbd0..d01b2e5c8c44 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2477,6 +2477,51 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, of_spi_parse_dt_cs_delay(nc, &spi->cs_hold, "spi-cs-hold-delay-ns"); of_spi_parse_dt_cs_delay(nc, &spi->cs_inactive, "spi-cs-inactive-delay-ns"); + /* Offloads */ + rc = of_count_phandle_with_args(nc, "spi-offloads", "#spi-offload-cells"); + if (rc > 0) { + int num_offload = rc; + + if (!ctlr->offload_ops) { + dev_err(&ctlr->dev, "SPI controller doesn't support offloading\n"); + return -EINVAL; + } + + for (idx = 0; idx < num_offload; idx++) { + struct of_phandle_args args; + const char *offload_name = NULL; + + rc = of_parse_phandle_with_args(nc, "spi-offloads", + "#spi-offload-cells", + idx, &args); + if (rc) { + dev_err(&spi->dev, "Failed to parse offload phandle %d: %d\n", + idx, rc); + return rc; + } + + if (args.np != ctlr->dev.of_node) { + dev_err(&spi->dev, "Offload phandle %d is not for this SPI controller\n", + idx); + of_node_put(args.np); + return -EINVAL; + } + + of_property_read_string_index(nc, "spi-offload-names", + idx, &offload_name); + + rc = ctlr->offload_ops->map_channel(spi, offload_name, + args.args, + args.args_count); + of_node_put(args.np); + if (rc) { + dev_err(&spi->dev, "Failed to map offload channel %d: %d\n", + value, rc); + return rc; + } + } + } + return 0; } @@ -3231,6 +3276,11 @@ static int spi_controller_check_ops(struct spi_controller *ctlr) } } + if (ctlr->offload_ops && !(ctlr->offload_ops->map_channel && + ctlr->offload_ops->prepare && + ctlr->offload_ops->unprepare)) + return -EINVAL; + return 0; } @@ -4751,6 +4801,79 @@ int spi_write_then_read(struct spi_device *spi, } EXPORT_SYMBOL_GPL(spi_write_then_read); +/** + * spi_offload_prepare - prepare offload hardware for a transfer + * @spi: The spi device to use for the transfers. + * @id: Function ID if SPI device uses more than one offload or NULL. + * @msg: The SPI message to use for the offload operation. + * + * Requests an offload instance with the specified ID and programs it with the + * provided message. + * + * The message must not be pre-optimized (do not call spi_optimize_message() on + * the message). + * + * Calls must be balanced with spi_offload_unprepare(). + * + * Return: 0 on success, else a negative error code. + */ +int spi_offload_prepare(struct spi_device *spi, const char *id, + struct spi_message *msg) +{ + struct spi_controller *ctlr = spi->controller; + int ret; + + if (!ctlr->offload_ops) + return -EOPNOTSUPP; + + msg->offload = true; + + ret = spi_optimize_message(spi, msg); + if (ret) + return ret; + + mutex_lock(&ctlr->io_mutex); + ret = ctlr->offload_ops->prepare(spi, id, msg); + mutex_unlock(&ctlr->io_mutex); + + if (ret) { + spi_unoptimize_message(msg); + msg->offload = false; + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(spi_offload_prepare); + +/** + * spi_offload_unprepare - releases any resources used by spi_offload_prepare() + * @spi: The same SPI device passed to spi_offload_prepare() + * @id: The same ID device passed to spi_offload_prepare() + * @msg: The same SPI message passed to spi_offload_prepare() + * + * Callers must ensure that the offload is no longer in use before calling this + * function, e.g. no in-progress transfers. + */ +void spi_offload_unprepare(struct spi_device *spi, const char *id, + struct spi_message *msg) +{ + struct spi_controller *ctlr = spi->controller; + + if (!ctlr->offload_ops) + return; + + mutex_lock(&ctlr->io_mutex); + ctlr->offload_ops->unprepare(spi, id); + mutex_unlock(&ctlr->io_mutex); + + msg->offload = false; + msg->offload_state = NULL; + + spi_unoptimize_message(msg); +} +EXPORT_SYMBOL_GPL(spi_offload_unprepare); + /*-------------------------------------------------------------------------*/ #if IS_ENABLED(CONFIG_OF_DYNAMIC) diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index d7a16e0adf44..4998b48ea7fd 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -31,6 +31,7 @@ struct spi_transfer; struct spi_controller_mem_ops; struct spi_controller_mem_caps; struct spi_message; +struct spi_controller_offload_ops; /* * INTERFACES between SPI master-side drivers and SPI slave protocol handlers, @@ -499,6 +500,7 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch * This field is optional and should only be implemented if the * controller has native support for memory like operations. * @mem_caps: controller capabilities for the handling of memory operations. + * @offload_ops: operations for controllers with offload support. * @unprepare_message: undo any work done by prepare_message(). * @slave_abort: abort the ongoing transfer request on an SPI slave controller * @target_abort: abort the ongoing transfer request on an SPI target controller @@ -746,6 +748,9 @@ struct spi_controller { const struct spi_controller_mem_ops *mem_ops; const struct spi_controller_mem_caps *mem_caps; + /* Operations for controllers with offload support. */ + const struct spi_controller_offload_ops *offload_ops; + /* GPIO chip select */ struct gpio_desc **cs_gpiods; bool use_gpio_descriptors; @@ -1122,6 +1127,7 @@ struct spi_transfer { * @pre_optimized: peripheral driver pre-optimized the message * @optimized: the message is in the optimized state * @prepared: spi_prepare_message was called for the this message + * @offload: message is to be used with offload hardware * @status: zero for success, else negative errno * @complete: called to report transaction completions * @context: the argument to complete() when it's called @@ -1131,6 +1137,7 @@ struct spi_transfer { * @queue: for use by whichever driver currently owns the message * @state: for use by whichever driver currently owns the message * @opt_state: for use by whichever driver currently owns the message + * @offload_state: for use by whichever driver currently owns the message * @resources: for resource management when the SPI message is processed * * A @spi_message is used to execute an atomic sequence of data transfers, @@ -1159,6 +1166,8 @@ struct spi_message { /* spi_prepare_message() was called for this message */ bool prepared; + /* spi_offload_prepare() was called on this message */ + bool offload; /* * REVISIT: we might want a flag affecting the behavior of the @@ -1191,6 +1200,11 @@ struct spi_message { * __spi_optimize_message() and __spi_unoptimize_message(). */ void *opt_state; + /* + * Optional state for use by controller driver between calls to + * offload_ops->prepare() and offload_ops->unprepare(). + */ + void *offload_state; /* List of spi_res resources when the SPI message is processed */ struct list_head resources; @@ -1556,6 +1570,49 @@ static inline ssize_t spi_w8r16be(struct spi_device *spi, u8 cmd) /*---------------------------------------------------------------------------*/ +/* + * Offloading support. + * + * Some SPI controllers support offloading of SPI transfers. Essentially, + * this allows the SPI controller to record SPI transfers and then play them + * back later in one go via a single trigger. + */ + +/** + * struct spi_controller_offload_ops - callbacks for offload support + * + * Drivers for hardware with offload support need to implement all of these + * callbacks. + */ +struct spi_controller_offload_ops { + /** + * @map_channel: Required callback to reserve an offload instance for + * the given SPI device. If a SPI device requires more than one instance, + * then @id is used to differentiate between them. Channels must be + * unmapped in the struct spi_controller::cleanup() callback. + */ + int (*map_channel)(struct spi_device *spi, const char *id, + const unsigned int *args, unsigned int num_args); + /** + * @prepare: Required callback to prepare the offload for the given SPI + * message. @msg and any of its members (including any xfer->tx_buf) is + * not guaranteed to be valid beyond the lifetime of this call. + */ + int (*prepare)(struct spi_device *spi, const char *id, + struct spi_message *msg); + /** + * @unprepare: Required callback to release any resources used by prepare(). + */ + void (*unprepare)(struct spi_device *spi, const char *id); +}; + +extern int spi_offload_prepare(struct spi_device *spi, const char *id, + struct spi_message *msg); +extern void spi_offload_unprepare(struct spi_device *spi, const char *id, + struct spi_message *msg); + +/*---------------------------------------------------------------------------*/ + /* * INTERFACE between board init code and SPI infrastructure. * From patchwork Mon Jul 22 21:57:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 13739153 Received: from mail-oa1-f46.google.com (mail-oa1-f46.google.com [209.85.160.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 C0CF347F69 for ; Mon, 22 Jul 2024 22:01:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721685692; cv=none; b=peWB2vHkG7R26gCArS6TUIs1UmXRQsaarptgKDNuHUMKnD0k4bSji7p9ELxxxUeZGd0/GBPgmqUFKZQEGJLSFKDoKOdH7FU0k0zXWGonM1W74/qtVZvip4eamzCDbIIqbFTpD11nJ3Ur2ISvkuvsrdng1WJlSzsCg/78l7rtO9E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721685692; c=relaxed/simple; bh=zGfSzq6+NZYNsIg6gm+v9kAPsniNOtWpWcNSLGE6Ezw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=bOWeJQd2Qp3xz57rmfWmDacTmpKnegP/mvga+RKJu4vEqsiVdJnQwCFEg3rA/KRU0jDkkZ7UabYLZnv3UgCPF05t4ZiyLEyxScpMtqEqW2pbIqTHYEsbfkoGA8i4kw3U7qw3pLIJAGNGFqFcoujI4EJEZCKzcKXErVpv0Qeys4Q= 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=H7PPIQfT; arc=none smtp.client-ip=209.85.160.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="H7PPIQfT" Received: by mail-oa1-f46.google.com with SMTP id 586e51a60fabf-261112c303bso2049830fac.1 for ; Mon, 22 Jul 2024 15:01:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1721685689; x=1722290489; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=vxg0ajK3ioJYPGcpD9OfHJVUObaqfpkpD5oT3VXWIto=; b=H7PPIQfTitkOkqmZKNkmjKfCOyfCJ8fHHQGJGT+Q3BhDnDF6jtipHR5TCxdfjwViJT 715ibDmjSOQ9bWMM5Wt/nYR3+8CQTqqW5MZsh3piJ8vpmKsdHo6CzbUBLSrrSpy4XO/P 3ZlYyRIPPfsvQshROymiqFFkzCPmgT+7Wv8i7po6F7t89I8pYWUkrRLwiaCYbA9UNgWb b35igBCHDFZrLhDPZjhAd5oZcGXaGwvIdPaczHHLsI7YGp/ORVZdmVmNWQzoDi8QDZIC yPNxGfP5S4Tq69Zy9Tc/iC4REfUpPoiG5qbFFMpybcXQ8sCJJCtzaMdpATblGHVOKkIB KuYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721685689; x=1722290489; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=vxg0ajK3ioJYPGcpD9OfHJVUObaqfpkpD5oT3VXWIto=; b=P9cr0duS/N0b9MPN9yI9kIHN0n0eL/hero8Va8H2yj8epYLE5dgUb/Q8/2GFqL0YoF cca7YLi1akVrpB3FFbC55vvsrXMLdwi7tvlYLJN+v2g+ShaK1zO73tStkf3Y7nymAhUZ WitsXT7qXeMwAJAKtS1vFCGAR5p4DZ0B3H7thVpcB2Y9zqgL0KeQw7Wq0MnPcyA/Qv/C GNYXVXXCa35Z8jdRBeBHS4C5lqU11Scj/ZHmn9EOGmEkBZW5QQ3nTNlbbQ0WuHZPfXE9 Ui3MNGwW+irJaHgN8z/vHh7vTb3+Irm6QY6IQ7U3QfbR+BuL8+U7K9VMUnQ8oJUmVs2o /Gkw== X-Forwarded-Encrypted: i=1; AJvYcCWRlqooXcvcfTsFYdfR7FNSMbY62E1vFAekUiEzOFFKrrs9omsRdG76geZGwGJQBgm0KpPJF1X0Rp7uMHEzq558+IS4VIXf/0PH X-Gm-Message-State: AOJu0Yy5Noi65uQ3xtVV6XCkMEkTsrKOjBZeDE1E8LL8t/RT3YsQxk7Y VRKoTnvrMDly8+hneZ+XXAqXsvRCduX7fTHt6vvvuq7UX5qQB/P0oNCj6Yvndt0= X-Google-Smtp-Source: AGHT+IHB2trKbSemE7wV84f/IpLJOdhW1QVUMqaLusjLceTiQK07D9n/6+mQwo/17/V/EwQ7masHbw== X-Received: by 2002:a05:6871:5d0:b0:25e:1cdf:c604 with SMTP id 586e51a60fabf-261215e6bd7mr9296245fac.31.1721685688591; Mon, 22 Jul 2024 15:01:28 -0700 (PDT) Received: from freyr.lechnology.com (ip98-183-112-25.ok.ok.cox.net. [98.183.112.25]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-708f60a55e1sm1719911a34.11.2024.07.22.15.01.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Jul 2024 15:01:28 -0700 (PDT) From: David Lechner To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: David Lechner , 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 Subject: [PATCH RFC v3 3/9] spi: add support for hardware triggered offload Date: Mon, 22 Jul 2024 16:57:10 -0500 Message-ID: <20240722-dlech-mainline-spi-engine-offload-2-v3-3-7420e45df69b@baylibre.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240722-dlech-mainline-spi-engine-offload-2-v3-0-7420e45df69b@baylibre.com> References: <20240722-dlech-mainline-spi-engine-offload-2-v3-0-7420e45df69b@baylibre.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Mailer: b4 0.14.0 This extends the SPI framework to support hardware triggered offloading. This allows an arbitrary hardware trigger to be used to start a SPI transfer that was previously set up with spi_offload_prepare(). Since the hardware trigger can happen at any time, this means the SPI bus must be reserved for exclusive use as long as the hardware trigger is enabled. Since a hardware trigger could be enabled indefinitely, we can't use the existing spi_bus_lock() and spi_bus_unlock() functions, otherwise this could cause deadlocks. So we introduce a new flag so that any attempt to lock or use the bus will fail with -EBUSY as long as the hardware trigger is enabled. Peripheral drivers may need to control the trigger source as well. For this, we introduce a new spi_offload_hw_trigger_get_clk() function that can be used to get a clock trigger source. This is intended for used by ADC drivers that will use the clock to control the sample rate. Additional functions to get other types of trigger sources could be added in the future. Signed-off-by: David Lechner --- TODO: Currently, spi_bus_lock() always returns 0, so none of the callers check the return value. All callers will need to be updated first before this can be merged. 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". Mark suggested that the standard SPI APIs should be aware that the hardware trigger is enabled. So I've added some locking for this. Nuno suggested that this might be overly strict though, and that we should let each individual controller driver decide what to do. For our use case though, I think we generally are going to have a single peripheral on the SPI bus, so this seems like a reasonable starting place anyway. --- drivers/spi/spi.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++-- include/linux/spi/spi.h | 40 +++++++++++++++++++++ 2 files changed, 132 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index d01b2e5c8c44..7488e71f159f 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -4495,7 +4495,7 @@ int spi_async(struct spi_device *spi, struct spi_message *message) spin_lock_irqsave(&ctlr->bus_lock_spinlock, flags); - if (ctlr->bus_lock_flag) + if (ctlr->bus_lock_flag || ctlr->offload_hw_trigger_mode_enabled) ret = -EBUSY; else ret = __spi_async(spi, message); @@ -4638,6 +4638,12 @@ int spi_sync(struct spi_device *spi, struct spi_message *message) int ret; mutex_lock(&spi->controller->bus_lock_mutex); + + if (spi->controller->offload_hw_trigger_mode_enabled) { + mutex_unlock(&spi->controller->bus_lock_mutex); + return -EBUSY; + } + ret = __spi_sync(spi, message); mutex_unlock(&spi->controller->bus_lock_mutex); @@ -4680,7 +4686,7 @@ EXPORT_SYMBOL_GPL(spi_sync_locked); * exclusive access is over. Data transfer must be done by spi_sync_locked * and spi_async_locked calls when the SPI bus lock is held. * - * Return: always zero. + * Return: 0 on success, -EBUSY if the bus is reserved by offload hardware. */ int spi_bus_lock(struct spi_controller *ctlr) { @@ -4688,6 +4694,11 @@ int spi_bus_lock(struct spi_controller *ctlr) mutex_lock(&ctlr->bus_lock_mutex); + if (ctlr->offload_hw_trigger_mode_enabled) { + mutex_unlock(&ctlr->bus_lock_mutex); + return -EBUSY; + } + spin_lock_irqsave(&ctlr->bus_lock_spinlock, flags); ctlr->bus_lock_flag = 1; spin_unlock_irqrestore(&ctlr->bus_lock_spinlock, flags); @@ -4874,6 +4885,85 @@ void spi_offload_unprepare(struct spi_device *spi, const char *id, } EXPORT_SYMBOL_GPL(spi_offload_unprepare); +/** + * spi_offload_hw_trigger_mode_enable - enables hardware trigger for offload + * @spi: The spi device to use for the transfers. + * @id: Function ID if SPI device uses more than one offload or NULL. + * + * There must be a prepared offload instance with the specified ID (i.e. + * spi_offload_prepare() was called with the same ID). This will also reserve + * the bus for exclusive use by the offload instance until the hardware 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_hw_trigger_mode_disable(). + * + * Context: can sleep + * Return: 0 on success, else a negative error code. + */ +int spi_offload_hw_trigger_mode_enable(struct spi_device *spi, const char *id) +{ + struct spi_controller *ctlr = spi->controller; + unsigned long flags; + int ret; + + if (!ctlr->offload_ops || !ctlr->offload_ops->hw_trigger_mode_enable) + return -EOPNOTSUPP; + + mutex_lock(&ctlr->bus_lock_mutex); + + if (ctlr->offload_hw_trigger_mode_enabled) { + mutex_unlock(&ctlr->bus_lock_mutex); + return -EBUSY; + } + + spin_lock_irqsave(&ctlr->bus_lock_spinlock, flags); + ctlr->offload_hw_trigger_mode_enabled = true; + spin_unlock_irqrestore(&ctlr->bus_lock_spinlock, flags); + + /* TODO: how to wait for empty message queue? */ + + mutex_lock(&ctlr->io_mutex); + ret = ctlr->offload_ops->hw_trigger_mode_enable(spi, id); + mutex_unlock(&ctlr->io_mutex); + + if (ret) { + ctlr->offload_hw_trigger_mode_enabled = false; + mutex_unlock(&ctlr->bus_lock_mutex); + return ret; + } + + mutex_unlock(&ctlr->bus_lock_mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(spi_offload_hw_trigger_mode_enable); + +/** + * spi_offload_hw_trigger_mode_disable - disables hardware trigger for offload + * @spi: The same SPI device passed to spi_offload_hw_trigger_mode_enable() + * @id: The same ID device passed to spi_offload_hw_trigger_mode_enable() + * + * 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_hw_trigger_mode_disable(struct spi_device *spi, const char *id) +{ + struct spi_controller *ctlr = spi->controller; + + if (!ctlr->offload_ops || !ctlr->offload_ops->hw_trigger_mode_disable) + return; + + mutex_lock(&ctlr->io_mutex); + ctlr->offload_ops->hw_trigger_mode_disable(spi, id); + mutex_unlock(&ctlr->io_mutex); + + ctlr->offload_hw_trigger_mode_enabled = false; +} +EXPORT_SYMBOL_GPL(spi_offload_hw_trigger_mode_disable); + /*-------------------------------------------------------------------------*/ #if IS_ENABLED(CONFIG_OF_DYNAMIC) diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 4998b48ea7fd..685548883004 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -634,6 +634,9 @@ struct spi_controller { /* Flag indicating that the SPI bus is locked for exclusive use */ bool bus_lock_flag; + /* Flag indicating the bus is reserved for use by hardware trigger */ + bool offload_hw_trigger_mode_enabled; + /* * Setup mode and clock, etc (SPI driver may call many times). * @@ -1604,12 +1607,49 @@ struct spi_controller_offload_ops { * @unprepare: Required callback to release any resources used by prepare(). */ void (*unprepare)(struct spi_device *spi, const char *id); + /** + * @hw_trigger_mode_enable: Optional callback to enable the hardware + * trigger for the given offload instance. + */ + int (*hw_trigger_mode_enable)(struct spi_device *spi, const char *id); + /** + * @hw_trigger_mode_disable: Optional callback to disable the hardware + * trigger for the given offload instance. + */ + void (*hw_trigger_mode_disable)(struct spi_device *spi, const char *id); + /** + * @hw_trigger_get_clk: Optional callback for controllers that have a + * hardware offload trigger that is connected to a clock. + */ + struct clk *(*hw_trigger_get_clk)(struct spi_device *spi, const char *id); }; extern int spi_offload_prepare(struct spi_device *spi, const char *id, struct spi_message *msg); extern void spi_offload_unprepare(struct spi_device *spi, const char *id, struct spi_message *msg); +extern int spi_offload_hw_trigger_mode_enable(struct spi_device *spi, const char *id); +extern void spi_offload_hw_trigger_mode_disable(struct spi_device *spi, const char *id); + +/** + * spi_offload_hw_trigger_get_clk - Get the clock for the offload trigger + * @spi: SPI device + * @id: Function ID if SPI device uses more than one offload or NULL. + * + * The caller is responsible for calling clk_put() on the returned clock. + * + * Return: The clock for the offload trigger, or negative error code + */ +static inline +struct clk *spi_offload_hw_trigger_get_clk(struct spi_device *spi, const char *id) +{ + struct spi_controller *ctlr = spi->controller; + + if (!ctlr->offload_ops || !ctlr->offload_ops->hw_trigger_get_clk) + return ERR_PTR(-EOPNOTSUPP); + + return ctlr->offload_ops->hw_trigger_get_clk(spi, id); +} /*---------------------------------------------------------------------------*/ From patchwork Mon Jul 22 21:57:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 13739155 Received: from mail-ot1-f47.google.com (mail-ot1-f47.google.com [209.85.210.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 7E43A51C42 for ; Mon, 22 Jul 2024 22:01:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721685695; cv=none; b=XVo6RlorylBYr8sOWToLgxqL62JmIFTjBAdD+jAcQP/IqwZAWOLEpHyH+l05eqGO3WYQ/HdGhn+Q9q83SFNv4QBqA82ZuXLz+1gN2CmszwhDHt2zvc8pcVFygI/sJ+l7eowHK2WgSjJSFaQr9vSmKMUS+Uh1gh9jy8yh+s9ooCw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721685695; c=relaxed/simple; bh=808d+A6Mqi2CTqpKZgsdKFxVcRnoQ41DCr0T6w4Q/j8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Uac9iZK+A0+PgtYVcLxMpl3axN3/Wvaw2828XwNdtuRZqrDUk2Mll/UJ8arY27rT5Drw41sJ9hweZqK70tp0V64VPzMMpyOaYLcmq9Cgatd9Zb4VyX1mE9agOBwSnCHf3P/Tg6a358rVXZfvuKZ8TUKUL7pCpk+ezfPOEG9PUMY= 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=l7TKhBO4; arc=none smtp.client-ip=209.85.210.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="l7TKhBO4" Received: by mail-ot1-f47.google.com with SMTP id 46e09a7af769-70361745053so2032719a34.0 for ; Mon, 22 Jul 2024 15:01:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1721685689; x=1722290489; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=BUS5JqRwM1ZEUN77AhcB6AZ8bgFbxFdByix5JbJ/Oks=; b=l7TKhBO42yTL066wVScBh4oalfr6KnJnjiULVhted52WA/MVqd1euKG4257ATx+lnM 3z4w2o7jg10OFVYynLJZ9IDVzMzYxwzOTEciYRxZRF4pOs8DDMlm/glDS+hUH1UKW3ov f2sjLL5qVg8DPPBzhz7GlrUO2F+75xCdNPN7TrNQQTeXfW1e/TCPhE32SHGRircCLyiy VNBEVM8YeT2RNbp7KSKpxveBQ3IxPQwjvBJuLYjzYQ8Qvhg3eti69K38GwFMQrm/Lr+n zbPld7LmdU1CLNRdofw4WiacZHXw0okvkdF64ogHWy5P2uunYdpyRhLfhrTQk7b5wY2Q sfKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721685689; x=1722290489; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=BUS5JqRwM1ZEUN77AhcB6AZ8bgFbxFdByix5JbJ/Oks=; b=NwnflMN0Ote5iZQGe1sICmC9mWWgennjfjNbp0kKC6TRb8YeDbpFq+ts7Fpd5mLKMb sHLtxUeJJhFDNh/b4LzgsHZoq1PN/H7dD4XarCC0L/EowKFIYXP+5mAIvYDFqfyIVw5e ZnOlwzV4Z/R7Eq9dagI4ndj0hVu3kmgRMocQQc5ucuFuMToJDOA9HEny7kRJ6ioXjKtm aBGwtZja55gM+k9kWn74ib59/LcR6ij6UUa8EJGlS5LaRVvBfSwEd+u5Q4nL0eqiIrdT /7uPqY4vxqWwuQEAlF/hjJr1OE6wTx92z8N7j3jz9aW14YJSnzvPzZRvGQ0U5o7uBblB Pi3A== X-Forwarded-Encrypted: i=1; AJvYcCVUaNZeF42pFsfX+MC32JsNgrZnDkEa2L5u3a8rTUyfA354Gm1d+GJnmSXUnTZn10BH9spPv93xIzySw/5N5GOjowu6Pe+AF5AT X-Gm-Message-State: AOJu0Yxn86jb0r8qjCPi40mPKOzAR1+84CUgL6/2E1vSonapQeQ98q84 eZlHk1tKzvsPL1E8ZsdHOfZaP77yTv23B+STtpcMq9c+zyX8ef9MOU7ufOkztyA= X-Google-Smtp-Source: AGHT+IHCKw3qiAfR3cucyHwYioXnYz5pH3obtA6YVtcrcIQNCW9xK6H4m0p3HPHBYSjoKe3B8zYk8Q== X-Received: by 2002:a05:6830:388f:b0:703:da11:4389 with SMTP id 46e09a7af769-7091aae7bbfmr147079a34.6.1721685689521; Mon, 22 Jul 2024 15:01:29 -0700 (PDT) Received: from freyr.lechnology.com (ip98-183-112-25.ok.ok.cox.net. [98.183.112.25]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-708f60a55e1sm1719911a34.11.2024.07.22.15.01.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Jul 2024 15:01:29 -0700 (PDT) From: David Lechner To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: David Lechner , 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 Subject: [PATCH RFC v3 4/9] spi: add offload TX/RX streaming APIs Date: Mon, 22 Jul 2024 16:57:11 -0500 Message-ID: <20240722-dlech-mainline-spi-engine-offload-2-v3-4-7420e45df69b@baylibre.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240722-dlech-mainline-spi-engine-offload-2-v3-0-7420e45df69b@baylibre.com> References: <20240722-dlech-mainline-spi-engine-offload-2-v3-0-7420e45df69b@baylibre.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Mailer: b4 0.14.0 Most configuration of SPI offloads is handled opaquely using the function ID 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 the spi_transfer structure 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 controller struct for controllers to indicate which flags are supported. This allows for generic checking of offload capabilities during __spi_validate() so that each controller doesn't have to provide 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 --- 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.c | 9 +++++++ include/linux/spi/spi.h | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 7488e71f159f..0ee741d911d3 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -4214,6 +4214,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 & ~ctlr->offload_xfer_flags) + return -EINVAL; + } } message->status = -EINPROGRESS; diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 685548883004..a4a7449c4259 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -500,6 +500,8 @@ extern struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 ch * This field is optional and should only be implemented if the * controller has native support for memory like operations. * @mem_caps: controller capabilities for the handling of memory operations. + * @offload_xfer_flags: flags supported by this controller for offloading + * transfers. See struct spi_transfer for the list of flags. * @offload_ops: operations for controllers with offload support. * @unprepare_message: undo any work done by prepare_message(). * @slave_abort: abort the ongoing transfer request on an SPI slave controller @@ -752,6 +754,7 @@ struct spi_controller { const struct spi_controller_mem_caps *mem_caps; /* Operations for controllers with offload support. */ + unsigned int offload_xfer_flags; const struct spi_controller_offload_ops *offload_ops; /* GPIO chip select */ @@ -995,6 +998,7 @@ struct spi_res { * @rx_sg_mapped: If true, the @rx_sg is mapped for DMA * @tx_sg: Scatterlist for transmit, currently not for client use * @rx_sg: Scatterlist for receive, currently not for client use + * @offload_flags: flags for xfers that use special hardware offload features * @ptp_sts_word_pre: The word (subject to bits_per_word semantics) offset * within @tx_buf for which the SPI device is requesting that the time * snapshot for this transfer begins. Upon completing the SPI transfer, @@ -1115,6 +1119,12 @@ struct spi_transfer { u32 effective_speed_hz; + unsigned int offload_flags; +/* 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) + unsigned int ptp_sts_word_pre; unsigned int ptp_sts_word_post; @@ -1622,6 +1632,20 @@ struct spi_controller_offload_ops { * hardware offload trigger that is connected to a clock. */ struct clk *(*hw_trigger_get_clk)(struct spi_device *spi, const char *id); + /** + * @tx_stream_get_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_get_dma_chan)(struct spi_device *spi, + const char *id); + /** + * @rx_stream_get_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_get_dma_chan)(struct spi_device *spi, + const char *id); }; extern int spi_offload_prepare(struct spi_device *spi, const char *id, @@ -1651,6 +1675,54 @@ struct clk *spi_offload_hw_trigger_get_clk(struct spi_device *spi, const char *i return ctlr->offload_ops->hw_trigger_get_clk(spi, id); } +/** + * spi_offload_tx_stream_get_dma_chan - Get the DMA channel for the TX stream + * @spi: SPI device + * @id: Function ID if SPI device uses more than one offload or NULL. + * + * This is the DMA channel that will provide data to transfers that use the + * %SPI_OFFLOAD_XFER_TX_STREAM offload flag. + * + * The caller is responsible for calling dma_release_channel() on the returned + * DMA channel. + * + * Return: The DMA channel for the TX stream, or negative error code + */ +static inline struct dma_chan +*spi_offload_tx_stream_get_dma_chan(struct spi_device *spi, const char *id) +{ + struct spi_controller *ctlr = spi->controller; + + if (!ctlr->offload_ops || !ctlr->offload_ops->tx_stream_get_dma_chan) + return ERR_PTR(-EOPNOTSUPP); + + return ctlr->offload_ops->tx_stream_get_dma_chan(spi, id); +} + +/** + * spi_offload_rx_stream_get_dma_chan - Get the DMA channel for the RX stream + * @spi: SPI device + * @id: Function ID if SPI device uses more than one offload or NULL. + * + * This is the DMA channel that will receive data from transfers that use the + * %SPI_OFFLOAD_XFER_RX_STREAM offload flag. + * + * The caller is responsible for calling dma_release_channel() on the returned + * DMA channel. + * + * Return: The DMA channel for the RX stream, or negative error code + */ +static inline struct dma_chan +*spi_offload_rx_stream_get_dma_chan(struct spi_device *spi, const char *id) +{ + struct spi_controller *ctlr = spi->controller; + + if (!ctlr->offload_ops || !ctlr->offload_ops->rx_stream_get_dma_chan) + return ERR_PTR(-EOPNOTSUPP); + + return ctlr->offload_ops->rx_stream_get_dma_chan(spi, id); +} + /*---------------------------------------------------------------------------*/ /* From patchwork Mon Jul 22 21:57:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 13739154 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 6B4664CB4E for ; Mon, 22 Jul 2024 22:01:31 +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=1721685693; cv=none; b=izRCfUnlPx/E2cGAqO2bACXy8Cz++1ApZFatf/Mtpu9mIsnMVXMM3EbvxJI/II1R7u1ZC6tcfjrATwyEsheq8T+9BknSOcU/VD9ijPu0HfsxlUxo4dv/PCOsuN6wuVERWGZGV+8YVZMo6GH9K1xqcYSNKl7A1SKfJISSLVWTMTU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721685693; c=relaxed/simple; bh=g+xF9JlXpviiMNJmjaApOysuZnb3kQE42/SlQHNRfAs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=RH4CwCmGgY+phmBcVLvau3++LRLTkZnl4HzBYTXMGDtuZP9fZ/Fny3TaLPR8o7hLmI7i2VOJ39K7ryp1XF8Dx4HJN38k02nnjfNpRkld3FvCwZKc0taLuXBjjWoK6T+HUwBuYQd2TQ6vV3PkOohDR6zZChDRDdp1Oq/cW13nGmc= 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=LDhFbtcb; 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="LDhFbtcb" Received: by mail-ot1-f48.google.com with SMTP id 46e09a7af769-70364e06dc6so2092004a34.0 for ; Mon, 22 Jul 2024 15:01:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1721685690; x=1722290490; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7jiC0bL0wy9+AlsO7Q0mhlDRo68Cb9JVUn8nn5AwBW8=; b=LDhFbtcbgALgFGlMfZjjOK8pY/dai09kwgByRoj9kjRG7x0h0cNCS437oImM2aA6Mq rcjLJZLiGwNNzIaMI1nul4Pd2ggC2PJbCM/YKdGg//jxYiEIJfPFEcCMOzTGiu3FDMfV cVeYH4jO7Ej4e776hHVbRJb+VCRriGfON29oPD/KwtPEgtgjzXdvGnWQ2NOToyqGH9Ip fllOo0je5d0JQ30A0hWV+ffjLUEgJSNdYymUsV83rz+3xYzGfvwQ6d3pynbxbifn9fdC GruBzpBgE4Y7Uv9Uj8KgEYTrx1OdSO1gKC3MwF+kHiJPcRawZWZubayUNtdKKCskuXM4 lM9Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721685690; x=1722290490; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7jiC0bL0wy9+AlsO7Q0mhlDRo68Cb9JVUn8nn5AwBW8=; b=fBRcEIrCg0h41vccEUZfl9VJ4C9icy7YvhQW+OteOLKatM5sW0iq915uVqyQgAqaFh aYi8w2k9Y6MIzmEb2wX0+pu30uiKp+QmT5AtL1exEUoV3idbAUWF2q7WdFh4Jgy9/AAV LWms9aLt2yfGFH2J/jmZUczDgCNBO70NzyZ9SY93fWAd7auSBjXUi8PKi8uC2VKVjSNf 6vtxCLwr7VmIHRFWK1HRb0eK11yjBnRzdCOUVkQUplGk62+HZKhd+dIO1tPux9uibC9r l/iOseusA29QWcVQVkJnj7WX6THtxS1+JRnko/186tlj+Z6je/0pZilRxqcTKkwZSNqH D1fQ== X-Forwarded-Encrypted: i=1; AJvYcCUQ8iglewKTh2HFCWJbWSi7C9A3jREZLFR1PMk146cXoz95xQmZUKMXrd/XsXXg3t9AGBUBpyKdpJAQ2BZqRRiWO+LbDKdRHXgN X-Gm-Message-State: AOJu0YyQPKLm+rANJu0kJnyGG6w3jtY96r10ON2YaBHTnLhH9YVkyza+ +UPX2M/DhpRQLyx7AcV9Magq+uR7la7FTEvbbU6LB8n5teYBdvxtLPmZRl3oUlU= X-Google-Smtp-Source: AGHT+IGs64wd91EwVV4Q/LZEgMoFqhXFy69BoOg7X1dR3lfIoah1e8xmfwOiIrdKEkWIZnK/5Kjetg== X-Received: by 2002:a05:6830:388d:b0:703:6477:460a with SMTP id 46e09a7af769-709009cd848mr6822618a34.29.1721685690446; Mon, 22 Jul 2024 15:01:30 -0700 (PDT) Received: from freyr.lechnology.com (ip98-183-112-25.ok.ok.cox.net. [98.183.112.25]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-708f60a55e1sm1719911a34.11.2024.07.22.15.01.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Jul 2024 15:01:30 -0700 (PDT) From: David Lechner To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: David Lechner , 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 Subject: [PATCH RFC v3 5/9] spi: dt-bindings: axi-spi-engine: document spi-offloads Date: Mon, 22 Jul 2024 16:57:12 -0500 Message-ID: <20240722-dlech-mainline-spi-engine-offload-2-v3-5-7420e45df69b@baylibre.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240722-dlech-mainline-spi-engine-offload-2-v3-0-7420e45df69b@baylibre.com> References: <20240722-dlech-mainline-spi-engine-offload-2-v3-0-7420e45df69b@baylibre.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Mailer: b4 0.14.0 The AXI SPI Engine has support for hardware offloading capabilities. There can be up to 32 offload instances per SPI controller, so the bindings limit the value accordingly. Signed-off-by: David Lechner --- RFC: I have a few questions about this one... 1. The trigger-source properties are borrowed from the leds bindings. Do we want to promote this to a generic binding that can be used by any type of device? 2. Some folks are working on adding DMA to TX stream support to the AXI SPI Engine hardware. I assume that the `dmas` property is like others where the order/index in the phandle array matters. So this would mean that for device that only uses 1 out of the 32 offloads and only uses 1 TX DMA channel, we would have to have 32 <0>s for each of the possible RX dmas in the array. Any way to do some kind of mapping to avoid this? 3. In v2, we discussed about having some sort of data processing unit between the AXI SPI Engine RX stream interface and the DMA channel interface on the DMA controller. I haven't included this in the bindings yet because we don't have a user yet. But it was suggested that we could use the graph bindings for this. So here is what that might look like: Additional property for the AXI SPI Engine controller bindings: out-ports: $ref: /schemas/graph.yaml#/properties/ports unevaluatedProperties: false patternProperties: "^port@1?[0-9a-f]$": $ref: /schemas/graph.yaml#/properties/port unevaluatedProperties: false And this would be connected to a device node similar to this: ip-block@3000 { // Something similar to, but not exactly like // http://analogdevicesinc.github.io/hdl/library/util_extract/index.html compatible = "adi,crc-check"; // clock that runs this IP block clocks = <&sysclk 15>; // interrupt raised on bad CRC interrupts = <&intc 99>; interrupt-names = "crc"; // output stream with CRC byte removed piped to DMA dmas = <&adc_dma 0>; dma-names = "rx"; port { adc_crc_check: endpoint { remote-endpoint: <&offload0_rx>; }; }; }; Does this sound reasonable? 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 | 41 ++++++++++++++++++++++ 1 file changed, 41 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..ec18eabb993a 100644 --- a/Documentation/devicetree/bindings/spi/adi,axi-spi-engine.yaml +++ b/Documentation/devicetree/bindings/spi/adi,axi-spi-engine.yaml @@ -41,6 +41,42 @@ properties: - const: s_axi_aclk - const: spi_clk + '#spi-offload-cells': + description: The cell value is the offload instance number. + const: 1 + + 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 + + dmas: + description: + DMA channels connected to the output stream interface of an offload instance. + minItems: 1 + maxItems: 32 + + dma-names: + minItems: 1 + maxItems: 32 + items: + pattern: "^offload(?:[12]?[0-9]|3[01])-rx$" + +patternProperties: + "^.*@[0-9a-f]+$": + type: object + $ref: spi-peripheral-props.yaml + additionalProperties: true + properties: + spi-offloads: + description: + An array of 1 or more offload instance numbers assigned to this + peripheral. + items: + minimum: 0 + maximum: 31 + required: - compatible - reg @@ -59,6 +95,11 @@ examples: clocks = <&clkc 15>, <&clkc 15>; clock-names = "s_axi_aclk", "spi_clk"; + #spi-offload-cells = <1>; + trigger-sources = <&trigger_clock>; + dmas = <&dma 0>; + dma-names = "offload0-rx"; + #address-cells = <1>; #size-cells = <0>; From patchwork Mon Jul 22 21:57:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 13739156 Received: from mail-oa1-f54.google.com (mail-oa1-f54.google.com [209.85.160.54]) (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 60DBA4F5FB for ; Mon, 22 Jul 2024 22:01:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721685695; cv=none; b=g15LEzuFPHVXODk5+naz4X0VJ5WBcMJGyhrvVSYaHFiqsA/qC7G8BHxkBWKtqfvbDx1520HWtRo1WpYrQ+Z9JUFDtuQ3Haa/AuMLF4y9qyDyzaSqXEfP5empY1q0OZ6I/1C8p5Y269Klo1bx6ienEMDU3+Q0g+suVeBkMBvQ8lQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721685695; c=relaxed/simple; bh=SvKLi9sLW623rbV1m/jcD8qu//tOAi7B0p04n7P2Gv4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Qz3JsU8MkPUt7wKzfy1yeRr5ipIIDUdgZTOy/lOYdES5ygvdDmGxj53MfbI7WG0J70Dk7/N7cFQ8XLcTAbYgcURtimJLWpm8ZfNazCUmDSh+kpSPhoTUURl/R29xEdkJA6YHvB8HN0rI8h74o1KXg9z1B7URJSPMI8/IE/XCuBY= 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=vwwCs2M/; arc=none smtp.client-ip=209.85.160.54 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="vwwCs2M/" Received: by mail-oa1-f54.google.com with SMTP id 586e51a60fabf-260f81f7fb5so2414104fac.0 for ; Mon, 22 Jul 2024 15:01:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1721685691; x=1722290491; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=KMO2ZzHCP5mlBdbeKR/leL11Eacudeaje7AAQ9UAw44=; b=vwwCs2M/A1xmgz91s8b8t3fT2Qv/FOEXmD7A4n5sIslDDkzylsePEg5S9xCpUEyZhy VbKR/4r8qTs48skA3T2TJSfqYJGOdByuDKLbCC9kAsciMeOVj8k7Op6ctNbqVNcRHPNX y042NwCoiZoVUwCG6SrYQ3+XJW+RpnqMS+aGv1A7P4gfqhKR+YOCNTg5YVwQFZTsyGOT mLOLysC5kgBfi28oT3KZlft4NXNYQNAH+TxIEqgN31OX1Kbt4C+L3irOwOAuLaKGWS80 DbvIMeO1RQJ0j7HOppobdVCA6sJ9OSlzpe4fzSWT6Nlhhn27uJtFN2AkrTJ7vI/cTuYh 6RmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721685691; x=1722290491; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=KMO2ZzHCP5mlBdbeKR/leL11Eacudeaje7AAQ9UAw44=; b=JJZFrbAXCXj2bAAkxMTGWLKGuxOVGENEweuZXD+pwOC1i6r89Bgd5llQgV3lKVJYJY in1yw5j1nmq8yzq47ZwnC+2VInTz5xwbA1KwJ3gUk0Ao1a2ULNdGQALOwj+eWq8kbLku 9k4sp3hq8UPdlYWxIDIvWK9dz/W+Tq3p/BLkfn8/RwInP5k9dsjT19d1lAcPCWpliG1y CPJRXqo76CHgw6oTh5eprefuvqEiK8u5XMcBji1mVbjAm4plh00UKucn0CsP+t3ozEqO BAuJKFvlIkjyqLZ8MjvT54GDGVHW7R0KDzfMzS3mDkTTF92eVd4GsynPXkTxaap/Eldf BOyg== X-Forwarded-Encrypted: i=1; AJvYcCUit8xRnqBfPoB0oFLL8MZLSN5NW7jGEUDVRCcmwXIF8XbiRMgHDDxju7xGK9q7lndemUjyCrPC1wLhN/VnAd1X1HYFQG6LbZGP X-Gm-Message-State: AOJu0Yz0Ingkh11rJzWxLQergN/zcMmYNj07yT7R0kK7VAaUleS1e/c/ C0V4v7k2pU54/3yXjLVdo7kjkXD41BcxAzRS+G0TENcnFAJGQEMCK6jSS8VznAc= X-Google-Smtp-Source: AGHT+IH1OF3bo9lWzo3JeDYPQ8RSTeCYa8FY/+7dJXY2MAT9oYx8cxOm3ljjhIPR4hIV1QaKOKGlmQ== X-Received: by 2002:a05:6870:5254:b0:25d:7cc4:caa8 with SMTP id 586e51a60fabf-26121321cedmr8454104fac.10.1721685691415; Mon, 22 Jul 2024 15:01:31 -0700 (PDT) Received: from freyr.lechnology.com (ip98-183-112-25.ok.ok.cox.net. [98.183.112.25]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-708f60a55e1sm1719911a34.11.2024.07.22.15.01.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Jul 2024 15:01:31 -0700 (PDT) From: David Lechner To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: David Lechner , 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 Subject: [PATCH RFC v3 6/9] spi: axi-spi-engine: implement offload support Date: Mon, 22 Jul 2024 16:57:13 -0500 Message-ID: <20240722-dlech-mainline-spi-engine-offload-2-v3-6-7420e45df69b@baylibre.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240722-dlech-mainline-spi-engine-offload-2-v3-0-7420e45df69b@baylibre.com> References: <20240722-dlech-mainline-spi-engine-offload-2-v3-0-7420e45df69b@baylibre.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Mailer: b4 0.14.0 This implements 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 --- 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/spi-axi-spi-engine.c | 341 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 337 insertions(+), 4 deletions(-) diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index cb3fdcbca2be..314f3afb9357 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -2,11 +2,13 @@ /* * SPI-Engine SPI controller driver * Copyright 2015 Analog Devices Inc. + * Copyright 2024 BayLibre, SAS * Author: Lars-Peter Clausen */ #include #include +#include #include #include #include @@ -16,6 +18,7 @@ #include #include +#define SPI_ENGINE_REG_OFFLOAD_MEM_ADDR_WIDTH 0x10 #define SPI_ENGINE_REG_RESET 0x40 #define SPI_ENGINE_REG_INT_ENABLE 0x80 @@ -23,6 +26,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 @@ -33,10 +37,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) @@ -77,6 +95,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); @@ -104,6 +126,12 @@ struct spi_engine_message_state { uint8_t *rx_buf; }; +struct spi_engine_offload { + struct spi_device *spi; + const char *id; + bool prepared; +}; + struct spi_engine { struct clk *clk; struct clk *ref_clk; @@ -116,6 +144,10 @@ 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_engine_offload offload_priv[SPI_ENGINE_MAX_NUM_OFFLOADS]; }; static void spi_engine_program_add_cmd(struct spi_engine_program *p, @@ -159,7 +191,7 @@ static void spi_engine_gen_xfer(struct spi_engine_program *p, bool dry, if (xfer->tx_buf) 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, @@ -211,16 +243,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, @@ -518,8 +558,11 @@ static irqreturn_t spi_engine_irq(int irq, void *devid) 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); @@ -531,7 +574,7 @@ 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; @@ -577,6 +620,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; @@ -612,11 +661,279 @@ static int spi_engine_transfer_one_message(struct spi_controller *host, msg->status = -ETIMEDOUT; } +out: spi_finalize_current_message(host); return msg->status; } +static bool spi_engine_offload_id_eq(const char *id1, const char *id2) +{ + if (!id1 && !id2) + return true; + + if (!id1 || !id2) + return false; + + return strcmp(id1, id2) == 0; +} + +static struct spi_engine_offload *spi_engine_get_offload(struct spi_device *spi, + const char *id, + unsigned int *offload_num) +{ + struct spi_controller *host = spi->controller; + struct spi_engine *spi_engine = spi_controller_get_devdata(host); + struct spi_engine_offload *priv; + int i; + + for (i = 0; i < SPI_ENGINE_MAX_NUM_OFFLOADS; i++) { + priv = &spi_engine->offload_priv[i]; + + if (priv->spi == spi && spi_engine_offload_id_eq(priv->id, id)) { + *offload_num = i; + return priv; + } + } + + return ERR_PTR(-ENODEV); +} + +static int spi_engine_offload_map_channel(struct spi_device *spi, + const char *id, + const unsigned int *args, + unsigned int num_args) +{ + struct spi_controller *host = spi->controller; + struct spi_engine *spi_engine = spi_controller_get_devdata(host); + struct spi_engine_offload *priv; + + if (num_args != 1) + return -EINVAL; + + if (args[0] >= SPI_ENGINE_MAX_NUM_OFFLOADS) + return -EINVAL; + + priv = &spi_engine->offload_priv[args[0]]; + + if (priv->spi) + return -EBUSY; + + priv->spi = spi; + + priv->id = kstrdup(id, GFP_KERNEL); + if (!priv->id && id) + return -ENOMEM; + + return 0; +} + +static int spi_engine_offload_prepare(struct spi_device *spi, const char *id, + struct spi_message *msg) +{ + struct spi_controller *host = 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; + struct spi_transfer *xfer; + void __iomem *cmd_addr; + void __iomem *sdo_addr; + size_t tx_word_count = 0; + unsigned int offload_num, i; + + priv = spi_engine_get_offload(spi, id, &offload_num); + if (IS_ERR(priv)) + return PTR_ERR(priv); + + if (priv->prepared) + return -EBUSY; + + 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) { + 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_sdo_mem_size) + return -EINVAL; + + cmd_addr = spi_engine->base + SPI_ENGINE_REG_OFFLOAD_CMD_FIFO(offload_num); + sdo_addr = spi_engine->base + SPI_ENGINE_REG_OFFLOAD_SDO_FIFO(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); + + msg->offload_state = (void *)(intptr_t)offload_num; + priv->prepared = true; + + return 0; +} + +static void spi_engine_offload_unprepare(struct spi_device *spi, const char *id) +{ + struct spi_controller *host = spi->controller; + struct spi_engine *spi_engine = spi_controller_get_devdata(host); + struct spi_engine_offload *priv; + unsigned int offload_num; + + priv = spi_engine_get_offload(spi, id, &offload_num); + if (IS_ERR(priv)) { + dev_warn(&spi->dev, "failed match offload in unprepare\n"); + return; + } + + writel_relaxed(1, spi_engine->base + SPI_ENGINE_REG_OFFLOAD_RESET(offload_num)); + writel_relaxed(0, spi_engine->base + SPI_ENGINE_REG_OFFLOAD_RESET(offload_num)); + + priv->prepared = false; +} + +static int spi_engine_hw_trigger_mode_enable(struct spi_device *spi, + const char *id) +{ + struct spi_controller *host = spi->controller; + struct spi_engine *spi_engine = spi_controller_get_devdata(host); + struct spi_engine_offload *priv; + unsigned int offload_num, reg; + + priv = spi_engine_get_offload(spi, id, &offload_num); + if (IS_ERR(priv)) + return PTR_ERR(priv); + + reg = readl_relaxed(spi_engine->base + + SPI_ENGINE_REG_OFFLOAD_CTRL(offload_num)); + reg |= SPI_ENGINE_OFFLOAD_CTRL_ENABLE; + writel_relaxed(reg, spi_engine->base + + SPI_ENGINE_REG_OFFLOAD_CTRL(offload_num)); + + return 0; +} + +static void spi_engine_hw_trigger_mode_disable(struct spi_device *spi, + const char *id) +{ + struct spi_controller *host = spi->controller; + struct spi_engine *spi_engine = spi_controller_get_devdata(host); + struct spi_engine_offload *priv; + unsigned int offload_num, reg; + + priv = spi_engine_get_offload(spi, id, &offload_num); + if (IS_ERR(priv)) { + dev_warn(&spi->dev, "failed match offload in disable\n"); + return; + } + + reg = readl_relaxed(spi_engine->base + + SPI_ENGINE_REG_OFFLOAD_CTRL(offload_num)); + reg &= ~SPI_ENGINE_OFFLOAD_CTRL_ENABLE; + writel_relaxed(reg, spi_engine->base + + SPI_ENGINE_REG_OFFLOAD_CTRL(offload_num)); +} + +static struct clk *spi_engine_hw_trigger_get_clk(struct spi_device *spi, + const char *id) +{ + struct spi_controller *host = spi->controller; + struct spi_engine_offload *priv; + struct of_phandle_args clkspec; + unsigned int offload_num; + struct clk *clk; + int ret; + + priv = spi_engine_get_offload(spi, id, &offload_num); + if (IS_ERR(priv)) + return ERR_CAST(priv); + + ret = of_parse_phandle_with_args(host->dev.of_node, "trigger-sources", + "#trigger-source-cells", offload_num, + &clkspec); + if (ret) + return ERR_PTR(ret); + + clk = of_clk_get_from_provider(&clkspec); + + of_node_put(clkspec.np); + + return clk; +} + +static struct dma_chan *spi_engine_rx_stream_get_dma_chan(struct spi_device *spi, + const char *id) +{ + struct spi_controller *host = spi->controller; + struct spi_engine_offload *priv; + unsigned int offload_num; + char channel_name[16]; + + priv = spi_engine_get_offload(spi, id, &offload_num); + if (IS_ERR(priv)) + return ERR_CAST(priv); + + snprintf(channel_name, sizeof(channel_name), "offload%d-rx", offload_num); + + return dma_request_chan(&host->dev, channel_name); +} + +static const struct spi_controller_offload_ops spi_engine_offload_ops = { + .map_channel = spi_engine_offload_map_channel, + .prepare = spi_engine_offload_prepare, + .unprepare = spi_engine_offload_unprepare, + .hw_trigger_mode_enable = spi_engine_hw_trigger_mode_enable, + .hw_trigger_mode_disable = spi_engine_hw_trigger_mode_disable, + .hw_trigger_get_clk = spi_engine_hw_trigger_get_clk, + .rx_stream_get_dma_chan = spi_engine_rx_stream_get_dma_chan, +}; + +static void spi_engine_cleanup(struct spi_device *spi) +{ + struct spi_controller *host = spi->controller; + struct spi_engine *spi_engine = spi_controller_get_devdata(host); + int i; + + /* remove spi device to offload mapping */ + for (i = 0; i < SPI_ENGINE_MAX_NUM_OFFLOADS; i++) { + struct spi_engine_offload *priv = &spi_engine->offload_priv[i]; + + if (priv->spi == spi) { + priv->spi = NULL; + kfree(priv->id); + priv->id = NULL; + } + } +} + static void spi_engine_release_hw(void *p) { struct spi_engine *spi_engine = p; @@ -668,6 +985,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); @@ -690,6 +1020,9 @@ static int spi_engine_probe(struct platform_device *pdev) host->optimize_message = spi_engine_optimize_message; host->unoptimize_message = spi_engine_unoptimize_message; host->num_chipselect = 8; + host->offload_xfer_flags = SPI_OFFLOAD_XFER_RX_STREAM; + host->offload_ops = &spi_engine_offload_ops; + host->cleanup = spi_engine_cleanup; /* Some features depend of the IP core version. */ if (ADI_AXI_PCORE_VER_MINOR(version) >= 2) { From patchwork Mon Jul 22 21:57:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 13739158 Received: from mail-oa1-f48.google.com (mail-oa1-f48.google.com [209.85.160.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 5969B5FEED for ; Mon, 22 Jul 2024 22:01:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721685696; cv=none; b=oPC/yua8kBM8BJ9gBWSILu3tt4PsHU3J9WDLUO46gnJVhynJiXu7Tcpsy8V6Yfv8PHqvf6wZNn5Nc0co/8VUlmZ5DCX6WJbylAonQSBku046q/Zs/Nz9+cmWmMgITc1xp3Md/jTka7mpbbUX+oTAznoC0DjjnpFfBzKs/zSiHdU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721685696; c=relaxed/simple; bh=i5fq6dLu/xqxt+O3YmVoa2/fRQ4pONuNiDxOd0O+2Ds=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=oRlB4Gh5h9u0+lBklb1fjfYl7XScsB6gDLxadKDUimG9Gfiey56avS283gwQ7D10i0mOejTT9ZMuoDP7+snl+Z0FJdNwL3wp5jjyKpAXda+wr1HxlW25oT9WA8KzM8S2EtttzfD9CnIP3/eQJ0Q8ZVQr2aknNM3EVqVuXxV9hD4= 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=sYSgEzQU; arc=none smtp.client-ip=209.85.160.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="sYSgEzQU" Received: by mail-oa1-f48.google.com with SMTP id 586e51a60fabf-260e12aac26so2866604fac.0 for ; Mon, 22 Jul 2024 15:01:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1721685692; x=1722290492; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=EUzyivP6VRGWHx7tYSGIOnQeCUO67RlyYPuJMRsarok=; b=sYSgEzQUaPhQlhgxExvZTEhKkqmTexrzn9x01IiClSRZ820BO/6Kzdb3KPXzNrbuPY G8cFs+ptsK/i0KwoM6wC+X9/KKty848/XxoFyEbwFe52tii4iX42KLoXuWxlrQBGavuz YkeOmkPS2imnqmlda6mJoZgybW6kxu+jEnMuZw4QY8bc0gQIQhoD3nqVjHVKLyiogpyc 1k/qr6Z2EU52AOkTDlvU7KLGjzc3cqVOGXvUx6lbeoJ3m8LABmOQcLRULNL0NGpih1qo Dks7RtJTKGvsmW+UakR8zHDG2l7NO5FZqz/7QkWSCGf9xTrA9ZnGJU83EAxfHlyOzNrq /rUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721685692; x=1722290492; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=EUzyivP6VRGWHx7tYSGIOnQeCUO67RlyYPuJMRsarok=; b=sDkYTFwgjp/P57ECcVbBf7nhvMYBFfWlj8kP7C0JP2pzXlNagoi2OeuQuew6xC8PW7 7CSmMPXdEikfZghU66SfoTcAiqKfmnnfLG5u690bnCnVCHQr771Mj9D6ZzVFXMDjP5Em KscSeWj9vQEkGQuVqIVc4Id2/kkO7DiooXXU1DLB8dTwLOKEuQU4mX73hB8SjUJU8mcR 1E4sf5HzpeGWmuLScvX1JlSVmhnDEbXk+KUTNKkTrCNcttnBnvM3qFvpRiPAVt+VhlvN l7lpCJA66qJR8NHLxu4LqeFHuF+bQOwfdoVSMmYAFnZlMvhbMzwTxi5x6g6RcTZmOHYg 6uwA== X-Forwarded-Encrypted: i=1; AJvYcCXma6d7XGhVG7SejNmsKVWvsQ76zVrBaGCjKYpqTbTO+cmy+mWdO32QAUigJ1QuRtnCCQ/nN2fBmj0TiJtTkfM2QzGzS/k/4I8Q X-Gm-Message-State: AOJu0YzD42jjp09eph19gY1TgjNkwt6UJziBVG05IDIAVn6qizQeSJF/ 4NgfrHiAcBvnyeeN787TNEuHy4TgquG/SLbTErf1K7bpTmKfqmxXiYgjs1BS5axGiNKIqM3ZcRe t X-Google-Smtp-Source: AGHT+IG5zMAelzP4qmAGblsSVB30TFvvH9JUw3U45Gd0sjE2FY39ATDcxmH98Vjz6qqSktUc2PQf+A== X-Received: by 2002:a05:6870:a10d:b0:260:e093:ff8d with SMTP id 586e51a60fabf-264692a6d2cmr912634fac.45.1721685692314; Mon, 22 Jul 2024 15:01:32 -0700 (PDT) Received: from freyr.lechnology.com (ip98-183-112-25.ok.ok.cox.net. [98.183.112.25]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-708f60a55e1sm1719911a34.11.2024.07.22.15.01.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Jul 2024 15:01:31 -0700 (PDT) From: David Lechner To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: David Lechner , 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 Subject: [PATCH RFC v3 7/9] iio: buffer-dmaengine: generalize requesting DMA channel Date: Mon, 22 Jul 2024 16:57:14 -0500 Message-ID: <20240722-dlech-mainline-spi-engine-offload-2-v3-7-7420e45df69b@baylibre.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240722-dlech-mainline-spi-engine-offload-2-v3-0-7420e45df69b@baylibre.com> References: <20240722-dlech-mainline-spi-engine-offload-2-v3-0-7420e45df69b@baylibre.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Mailer: b4 0.14.0 This patch generalizes the iio_dmaengine_buffer_setup_ext() functions by passing the pointer to the DMA channel as an argument rather than the channel name. This will allow future callers of the function to use other methods to get the DMA channel pointer. This aims to keep it as easy to use as possible by stealing ownership of the dma_chan pointer from the caller. This way, dma_request_chan() can be called inline in the function call without any extra error handling. Signed-off-by: David Lechner v3 changes: * This is a new patch in v3. --- drivers/iio/buffer/industrialio-buffer-dmaengine.c | 39 +++++++++++++--------- drivers/iio/dac/adi-axi-dac.c | 3 +- include/linux/iio/buffer-dmaengine.h | 11 +++--- 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c index 918f6f8d65b6..44c3b4fe0643 100644 --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c @@ -163,32 +163,34 @@ 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 - * @channel: DMA channel name, typically "rx". + * @chan: DMA channel. * * This allocates a new IIO buffer which internally uses the DMAengine framework * to perform its transfers. The parent device will be used to request the DMA * channel. * + * This "steals" the @chan pointer, so the caller must not call + * dma_release_channel() on it. @chan is also checked for error, so callers + * can pass the result of dma_request_chan() directly. + * * 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) + struct dma_chan *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); + if (IS_ERR(chan)) + return ERR_CAST(chan); - chan = dma_request_chan(dev, channel); - if (IS_ERR(chan)) { - ret = PTR_ERR(chan); - goto err_free; + dmaengine_buffer = kzalloc(sizeof(*dmaengine_buffer), GFP_KERNEL); + if (!dmaengine_buffer) { + ret = -ENOMEM; + goto err_release; } ret = dma_get_slave_caps(chan, &caps); @@ -221,6 +223,9 @@ static struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev, err_free: kfree(dmaengine_buffer); +err_release: + dma_release_channel(chan); + return ERR_PTR(ret); } @@ -244,13 +249,13 @@ EXPORT_SYMBOL_NS_GPL(iio_dmaengine_buffer_free, IIO_DMAENGINE_BUFFER); struct iio_buffer *iio_dmaengine_buffer_setup_ext(struct device *dev, struct iio_dev *indio_dev, - const char *channel, + struct dma_chan *chan, enum iio_buffer_direction dir) { struct iio_buffer *buffer; int ret; - buffer = iio_dmaengine_buffer_alloc(dev, channel); + buffer = iio_dmaengine_buffer_alloc(dev, chan); if (IS_ERR(buffer)) return ERR_CAST(buffer); @@ -277,22 +282,26 @@ 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 * @indio_dev: IIO device to which to attach this buffer. - * @channel: DMA channel name, typically "rx". + * @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 "steals" the @chan pointer, so the caller must not call + * dma_release_channel() on it. @chan is also checked for error, so callers + * can pass the result of dma_request_chan() directly. */ int devm_iio_dmaengine_buffer_setup_ext(struct device *dev, struct iio_dev *indio_dev, - const char *channel, + struct dma_chan *chan, enum iio_buffer_direction dir) { struct iio_buffer *buffer; - buffer = iio_dmaengine_buffer_setup_ext(dev, indio_dev, channel, dir); + buffer = iio_dmaengine_buffer_setup_ext(dev, indio_dev, chan, dir); if (IS_ERR(buffer)) return PTR_ERR(buffer); diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c index 880d83a014a1..7e6225920e49 100644 --- a/drivers/iio/dac/adi-axi-dac.c +++ b/drivers/iio/dac/adi-axi-dac.c @@ -124,7 +124,8 @@ static struct iio_buffer *axi_dac_request_buffer(struct iio_backend *back, if (device_property_read_string(st->dev, "dma-names", &dma_name)) dma_name = "tx"; - return iio_dmaengine_buffer_setup_ext(st->dev, indio_dev, dma_name, + return iio_dmaengine_buffer_setup_ext(st->dev, indio_dev, + dma_request_chan(st->dev, dma_name), IIO_BUFFER_DIRECTION_OUT); } diff --git a/include/linux/iio/buffer-dmaengine.h b/include/linux/iio/buffer-dmaengine.h index 81d9a19aeb91..a80397c3b198 100644 --- a/include/linux/iio/buffer-dmaengine.h +++ b/include/linux/iio/buffer-dmaengine.h @@ -7,6 +7,7 @@ #ifndef __IIO_DMAENGINE_H__ #define __IIO_DMAENGINE_H__ +#include #include struct iio_dev; @@ -15,20 +16,22 @@ struct device; void iio_dmaengine_buffer_free(struct iio_buffer *buffer); struct iio_buffer *iio_dmaengine_buffer_setup_ext(struct device *dev, struct iio_dev *indio_dev, - const char *channel, + struct dma_chan *chan, enum iio_buffer_direction dir); #define iio_dmaengine_buffer_setup(dev, indio_dev, channel) \ - iio_dmaengine_buffer_setup_ext(dev, indio_dev, channel, \ + iio_dmaengine_buffer_setup_ext(dev, indio_dev, \ + dma_request_chan(dev, channel),\ IIO_BUFFER_DIRECTION_IN) int devm_iio_dmaengine_buffer_setup_ext(struct device *dev, struct iio_dev *indio_dev, - const char *channel, + 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, \ + devm_iio_dmaengine_buffer_setup_ext(dev, indio_dev, \ + dma_request_chan(dev, channel), \ IIO_BUFFER_DIRECTION_IN) #endif From patchwork Mon Jul 22 21:57:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 13739157 Received: from mail-ot1-f54.google.com (mail-ot1-f54.google.com [209.85.210.54]) (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 419DC6DD0D for ; Mon, 22 Jul 2024 22:01:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721685696; cv=none; b=k8DaNLCAh+MapjSpH+fqc8QWiiiIQiuR7FJFn0FpYwyIdfwtKOOtsoC5tJ8Xl1hFXGtHh5mVyJcaSVicLK1pIfEOTtIBrI5jsbpXR5+afxQI3sbeoYN5K4cK9a7RG86a3dt06Fn30vr8UgJcibi8gd9qv4EqCgECfOsYnZy2YH8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721685696; c=relaxed/simple; bh=ozoXhi7TZ5bg/WgwHNio76mZ8ob0TDKqwt97BXyhuUo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Tx22pv95zPzOJcf8AvhhNrtyaKjHW9CsJFhk05yylXk2ysEk771NCDbZ+kO4t1RLNfvjXUr4WAVG9ZzEtx7JYukdV965Mzb8vaHOHi1H4EMKsFQ17CkU2NtthQUrhG7px8P+Pv+Si1ZqVrnzGF4NWgfZ5HSOfmMJxOsglsOSDhw= 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=R/lL7+jc; arc=none smtp.client-ip=209.85.210.54 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="R/lL7+jc" Received: by mail-ot1-f54.google.com with SMTP id 46e09a7af769-703ba2477bdso2237520a34.2 for ; Mon, 22 Jul 2024 15:01:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1721685693; x=1722290493; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=sbV2uifrWqiRQxhBCL8VB9LMdHewgwxJIKx2N6g6zvQ=; b=R/lL7+jcHaeV1mQQUNOhKAS5gl5OkVbk3qGw8/8HAKX6J4Q3sk8eQ3sUyp4FbTP8NC RnB3YAqK0DxJY5f4lKaI7fCnIj6aGKSlPRkqbUo3pMcpiUE3tbKAHi8FO+sRAniG29FC RzxocsvmlPUJvJzhU3qNW1baPuEoOfaXV1xACMd81fxXMcDo04Qq3NUuR0REwVRJe9qi TNzuvTevOd6bjtEeWTufiDI+PqRCXVvUxw26EvtWpURGgNzN+2dJOMitdCrxjt95uVny NvRTIO2pmue73UCWJORf30jxXDvsJ9XluqhGn39Z/yoQ09o6FpyUdz66iHhO6uQ0l60L r5hA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721685693; x=1722290493; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=sbV2uifrWqiRQxhBCL8VB9LMdHewgwxJIKx2N6g6zvQ=; b=qJgcaNYvtMl5EVKY3g8zwtPeNPTOXG4SMxtqHSfy7J0sODONqQiij7FEsj8wII9Llj zIUSqA7He7TOoqcP/R5+GAjfx15a0MXA4oZlxJBLaViJwYh924BxglLosZVoeVaAWhzt powhD7Sv7YHa0SIOwJ/7ujOraU/CNuarE4zPPoVAU5tCNMXMKfKafpO6Soushbf69Qw3 dgrQps8gRJXDr5wKP6o/KaSvSqnKe9yqeyZsJLK0Sil8ROuqt8ZZyfJScO3qjPPDs9TQ K2n8vE6f7Iddq+dvPoVNX6RKYedsaZ/Lip68FLtK7KCCtCDBMnb/b1LJyG3rUpqBlPv1 yzgg== X-Forwarded-Encrypted: i=1; AJvYcCUUPIcDZ/0/F77h0Pm7vrxOKnU5c57kFCxLabTPWfeA47FIJX8armlPwawe1wKRzfUOKMApYjgLJYW1XUTJEak6gO/f96a+R+J5 X-Gm-Message-State: AOJu0Yz3V7D6DX4kkm5KohXV534BXZd8TEyGuXqF9rQF31NW8lBk49Oy o9/xmSXav9Beserrk8p0QGwuHFQAU/++f7WHPDIUt+7Noe0vjhPnRKZRAGTRxCI= X-Google-Smtp-Source: AGHT+IGH4XrwdDU/5ZEcf8oBMum+Z6kRT3nANYPvUw3shGgmVjb0HG2TfD+RuB8Rpn5TQQUo/epIsw== X-Received: by 2002:a05:6830:2a0e:b0:703:61ea:f289 with SMTP id 46e09a7af769-708fdbb4afdmr12042986a34.28.1721685693197; Mon, 22 Jul 2024 15:01:33 -0700 (PDT) Received: from freyr.lechnology.com (ip98-183-112-25.ok.ok.cox.net. [98.183.112.25]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-708f60a55e1sm1719911a34.11.2024.07.22.15.01.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Jul 2024 15:01:32 -0700 (PDT) From: David Lechner To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: David Lechner , 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 Subject: [PATCH RFC v3 8/9] dt-bindings: iio: adc: adi,ad7944: add SPI offload properties Date: Mon, 22 Jul 2024 16:57:15 -0500 Message-ID: <20240722-dlech-mainline-spi-engine-offload-2-v3-8-7420e45df69b@baylibre.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240722-dlech-mainline-spi-engine-offload-2-v3-0-7420e45df69b@baylibre.com> References: <20240722-dlech-mainline-spi-engine-offload-2-v3-0-7420e45df69b@baylibre.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Mailer: b4 0.14.0 To enable capturing data at high rates, the AD7944 is frequently used with the AXI SPI Engine IP core. This patch adds the properties needed to describe the SPI offload configuration in the device tree. Signed-off-by: David Lechner --- v3 changes: * Dropped properties that should be SPI controller properties. v2 changes: This is a new patch that partially replaces "dt-bindings: iio: offload: add binding for PWM/DMA triggered buffer". In the previous review, it was suggested that having a separate binding and object node for the offload was overcomplicated. So instead this opts to use the proposed standard spi-offloads property as a flag to allow the SPI periperhal node require additional properties that are resources that are physically connected to the SPI offload. --- Documentation/devicetree/bindings/iio/adc/adi,ad7944.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7944.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7944.yaml index d17d184842d3..6533459add87 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7944.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7944.yaml @@ -129,6 +129,9 @@ properties: line goes high while the SDI and CNV lines are high (chain mode), maxItems: 1 + spi-offloads: + maxItems: 1 + required: - compatible - reg From patchwork Mon Jul 22 21:57:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Lechner X-Patchwork-Id: 13739159 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 6ABDE4CB2B for ; Mon, 22 Jul 2024 22:01:35 +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=1721685698; cv=none; b=G+MwZaUEeeGoO/vzXLHYwqTrSu5YsgoXs2fixvIl2fjh1ZU4CIlIpa7XBc4XeLy6NVgSofHxizs4TdiXBcnDX70cn9cV0spl2qpXM1diybFYAyPpuiscjX8ARS9X+ZFM3hkHTgpzJ8u5I6LBmkDe9eeWfEWTPjYxjZAFnNrJsEg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721685698; c=relaxed/simple; bh=wLwtAkIBM4hq/kR6Mmx+dPtGfZzSSBSwcvcMoP+c4hU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ZxHw01wxF2N3bbQ1wkQfjpP/DxdaGK3r3LsN50X4PVQ8Z1R+ESpdkgWaUbMo5YGQoLlJe8rrT8tqk7Zc2ngn52VLyWX7ncZo0fRukBIdHpLJI0glh6D+dM+DiLiZzsas2SO6oLtef+5OkQ3S8LR0wrB2PJZP0quh496AxGECDEY= 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=KwXQMUiT; 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="KwXQMUiT" Received: by mail-ot1-f52.google.com with SMTP id 46e09a7af769-704466b19c4so2251935a34.0 for ; Mon, 22 Jul 2024 15:01:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1721685694; x=1722290494; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=UhPgWBgcgXIA+u+ClJPVILjR7vSD2cCOFhbPqeE2xbQ=; b=KwXQMUiTtm5zOKk7tW2xHx1Gl/lne+8fBJsfiSG3ccUbsqMrz8QsIhrQGK5sYbHFz4 hWEeIPLMr/veXavhXXw2N4re2PmZjpMxDqKq+iRa+Jcu/LeGoNM0ecH6Eiw9sk1l01en CRa3/kUdncvsC8PXaWXDiriYo8+geX0pQpQnLcGiBYh04ruoUezi2qeTJpJWMBl/grzQ Kf78qZIRkyhNaZH766N3ClXt9AF3UJqtWgg9NeJirK4UAmNsT6QgCMbSjGAHwzvX6Kqb UDq7NiI6jHgqWMZaLhcL8YSvAvShVFCggeL9jq3TVpVw7CojK+JcEzQ8uRFVgiHrhMOf X+0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1721685694; x=1722290494; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=UhPgWBgcgXIA+u+ClJPVILjR7vSD2cCOFhbPqeE2xbQ=; b=QR8lYoQSqm+9ojVj8juEJ1Bt3/PfZTW2RFo4ByPJYDk7luilvfkIt8+cfL8vwF34US M1c27G0yTdWjMQ8Vlv9xWpJYYrpTv9zylijgjfkMqFfe+1N3HM/3qmNl9fHdHFaoowJu FPY/GCPdHEzbOeEjZ4Mxh0hRbiOG8G3//7VHDwz59pRgX4RDyk+//gh02Q/AQAZkdX5e WeG22xFLXjeciSv1zafu3agUd4ek60BisDJgCs4HC+DwNdpDGT6zrLBjr6gc6zFSCMlL hJadcZu8LX5BOBcmqYxX1wcopitpPhW+djUaolk2ll/UkliPFuVx84e9zWSPgZyGZVG4 EK6Q== X-Forwarded-Encrypted: i=1; AJvYcCXOpqgmUSFREFVE1xix38Ju/YxfVstTna9NG61LEI3GAQb7ktusJuF4b9D61hXwCqJgny4oeQsMkKBjLNe851AhDtQluryS1k5H X-Gm-Message-State: AOJu0YzCW5ixZPeKsrj/C4qtG0hkFejy3pkWBOf5pbzSMf7NV/fNlGqe F4yQy+T0tGLdXYrG2sWz58Apu6l6Sv4/j+OQ8uZRqD5GGGZGmOB736kJAqVTjOg= X-Google-Smtp-Source: AGHT+IHXDgeNbeZYlN1uzwQdl3tCZ2beK6K+VycJjOQkxwH827CZ/P//PGWZ3iQGkscdaaE2b16UQA== X-Received: by 2002:a05:6830:6a16:b0:703:6ca6:27 with SMTP id 46e09a7af769-708fdb34f44mr13425465a34.16.1721685694085; Mon, 22 Jul 2024 15:01:34 -0700 (PDT) Received: from freyr.lechnology.com (ip98-183-112-25.ok.ok.cox.net. [98.183.112.25]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-708f60a55e1sm1719911a34.11.2024.07.22.15.01.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 22 Jul 2024 15:01:33 -0700 (PDT) From: David Lechner To: Mark Brown , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , =?utf-8?q?Nuno_S=C3=A1?= Cc: David Lechner , 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 Subject: [PATCH RFC v3 9/9] iio: adc: ad7944: add support for SPI offload Date: Mon, 22 Jul 2024 16:57:16 -0500 Message-ID: <20240722-dlech-mainline-spi-engine-offload-2-v3-9-7420e45df69b@baylibre.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240722-dlech-mainline-spi-engine-offload-2-v3-0-7420e45df69b@baylibre.com> References: <20240722-dlech-mainline-spi-engine-offload-2-v3-0-7420e45df69b@baylibre.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Mailer: b4 0.14.0 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 --- Note: in v2 we discussed if we should make the SPI offload use buffer1 instead of buffer0 as to not break userspace. I'm still on the fence about if we should do that or not. Mainly because many userspace tools aren't aware of multiple buffers yet, so would make it harder to use the driver. And technically, the way it is implemented right now is not going to change anything for existing users since they won't be using the offload feature. So the argument could be made that this isn't really breaking userspace after all. 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/ad7944.c | 173 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 166 insertions(+), 7 deletions(-) diff --git a/drivers/iio/adc/ad7944.c b/drivers/iio/adc/ad7944.c index 0f36138a7144..43674ff439d2 100644 --- a/drivers/iio/adc/ad7944.c +++ b/drivers/iio/adc/ad7944.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ #include #include +#include #include #include @@ -54,6 +56,8 @@ struct ad7944_adc { enum ad7944_spi_mode spi_mode; struct spi_transfer xfers[3]; struct spi_message msg; + struct spi_transfer offload_xfers[3]; + struct spi_message offload_msg; void *chain_mode_buf; /* Chip-specific timing specifications. */ const struct ad7944_timing_spec *timing_spec; @@ -65,6 +69,8 @@ struct ad7944_adc { bool always_turbo; /* Reference voltage (millivolts). */ unsigned int ref_mv; + /* Clock that triggers SPI offload. */ + struct clk *trigger_clk; /* * DMA (thus cache coherency maintenance) requires the @@ -81,6 +87,8 @@ struct ad7944_adc { /* quite time before CNV rising edge */ #define T_QUIET_NS 20 +/* minimum CNV high time to trigger conversion */ +#define T_CNVH_NS 20 static const struct ad7944_timing_spec ad7944_timing_spec = { .conv_ns = 420, @@ -123,6 +131,7 @@ static const struct ad7944_chip_info _name##_chip_info = { \ .scan_type.endianness = IIO_CPU, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) \ | BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ }, \ IIO_CHAN_SOFT_TIMESTAMP(1), \ }, \ @@ -236,6 +245,54 @@ static int ad7944_chain_mode_init_msg(struct device *dev, struct ad7944_adc *adc return devm_spi_optimize_message(dev, adc->spi, &adc->msg); } +static void ad7944_offload_unprepare(void *p) +{ + struct ad7944_adc *adc = p; + + spi_offload_unprepare(adc->spi, NULL, &adc->offload_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 = T_QUIET_NS; + xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS; + + /* CNV has to be high for a minimum time to trigger conversion. */ + xfers[1].cs_off = 1; + xfers[1].delay.value = T_CNVH_NS; + xfers[1].delay.unit = SPI_DELAY_UNIT_NSECS; + + /* Then we can read the previous sample during the conversion phase */ + xfers[2].offload_flags = SPI_OFFLOAD_XFER_RX_STREAM; + xfers[2].len = BITS_TO_BYTES(chan->scan_type.storagebits); + xfers[2].bits_per_word = chan->scan_type.realbits; + + spi_message_init_with_transfers(&adc->offload_msg, xfers, + ARRAY_SIZE(adc->offload_xfers)); + + ret = spi_offload_prepare(adc->spi, NULL, &adc->offload_msg); + if (ret) + return dev_err_probe(dev, ret, "failed to prepare offload\n"); + + return devm_add_action_or_reset(dev, ad7944_offload_unprepare, adc); +} + /** * ad7944_convert_and_acquire - Perform a single conversion and acquisition * @adc: The ADC device structure @@ -323,6 +380,30 @@ static int ad7944_read_raw(struct iio_dev *indio_dev, return -EINVAL; } + case IIO_CHAN_INFO_SAMP_FREQ: + if (!adc->trigger_clk) + return -EOPNOTSUPP; + + *val = clk_get_rate(adc->trigger_clk); + return IIO_VAL_INT; + + default: + return -EINVAL; + } +} + +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 (!adc->trigger_clk) + return -EOPNOTSUPP; + + return clk_set_rate(adc->trigger_clk, val); default: return -EINVAL; } @@ -330,6 +411,48 @@ static int ad7944_read_raw(struct iio_dev *indio_dev, static const struct iio_info ad7944_iio_info = { .read_raw = &ad7944_read_raw, + .write_raw = &ad7944_write_raw, +}; + +static int ad7944_offload_buffer_postenable(struct iio_dev *indio_dev) +{ + struct ad7944_adc *adc = iio_priv(indio_dev); + int ret; + + gpiod_set_value_cansleep(adc->turbo, 1); + + ret = clk_prepare_enable(adc->trigger_clk); + if (ret) + goto err_turbo_off; + + ret = spi_offload_hw_trigger_mode_enable(adc->spi, NULL); + if (ret) + goto err_clk_off; + + return 0; + +err_clk_off: + clk_disable_unprepare(adc->trigger_clk); +err_turbo_off: + 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_hw_trigger_mode_disable(adc->spi, NULL); + clk_disable_unprepare(adc->trigger_clk); + 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) @@ -444,6 +567,11 @@ static const char * const ad7944_power_supplies[] = { "avdd", "dvdd", "bvdd", "vio" }; +static void ad7944_put_clk_trigger(void *p) +{ + clk_put(p); +} + static int ad7944_probe(struct spi_device *spi) { const struct ad7944_chip_info *chip_info; @@ -554,13 +682,11 @@ static int ad7944_probe(struct spi_device *spi) ret = ad7944_4wire_mode_init_msg(dev, adc, &chip_info->channels[0]); if (ret) return ret; - break; case AD7944_SPI_MODE_SINGLE: ret = ad7944_3wire_cs_mode_init_msg(dev, adc, &chip_info->channels[0]); if (ret) return ret; - break; case AD7944_SPI_MODE_CHAIN: ret = device_property_read_u32(dev, "#daisy-chained-devices", @@ -597,11 +723,43 @@ static int ad7944_probe(struct spi_device *spi) 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; + if (device_property_present(dev, "spi-offloads")) { + if (adc->spi_mode != AD7944_SPI_MODE_SINGLE) + return dev_err_probe(dev, -EINVAL, + "offload only supported in single mode\n"); + + ret = ad7944_3wire_cs_mode_init_offload_msg(dev, adc, + &chip_info->channels[0]); + if (ret) + return ret; + + adc->trigger_clk = spi_offload_hw_trigger_get_clk(spi, NULL); + if (IS_ERR(adc->trigger_clk)) + return dev_err_probe(dev, PTR_ERR(adc->trigger_clk), + "failed to get trigger clk\n"); + + ret = devm_add_action_or_reset(dev, ad7944_put_clk_trigger, + adc->trigger_clk); + if (ret) + return ret; + + ret = devm_iio_dmaengine_buffer_setup_ext(dev, indio_dev, + spi_offload_rx_stream_get_dma_chan(spi, NULL), + IIO_BUFFER_DIRECTION_IN); + if (ret) + return ret; + + indio_dev->setup_ops = &ad7944_offload_buffer_setup_ops; + /* offload can't have soft timestamp */ + indio_dev->num_channels--; + } else { + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, + iio_pollfunc_store_time, + ad7944_trigger_handler, + NULL); + if (ret) + return ret; + } return devm_iio_device_register(dev, indio_dev); } @@ -636,3 +794,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);