Received: by 2002:ab2:6a05:0:b0:1f8:1780:a4ed with SMTP id w5csp837711lqo; Fri, 10 May 2024 17:52:20 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCV6aTnB0TeEGUyORS1ZuGh7h8Ia85XA7TmMZyn+/nG0ENIfeC4BYFO6CjswWDqrct7nl++pjs6Ben+0b3CaLYVLP7w+mIwCtG5WzIM43Q== X-Google-Smtp-Source: AGHT+IFLYfj6j4xr8EdJxakNPUghYUDKFaeCIDrwdgk5lATZYKkvSHDoTywKj2VJ/tFv8RDJoPAH X-Received: by 2002:a50:baeb:0:b0:570:3b4:53ff with SMTP id 4fb4d7f45d1cf-5734d5903c1mr3004958a12.6.1715388740605; Fri, 10 May 2024 17:52:20 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1715388740; cv=pass; d=google.com; s=arc-20160816; b=O55+V/tIDOUGeL3TEKaaXJC18kHIU62VHLiiX//lf44uo3xntkPKXY672N6YLsVVRR 5Lcy1yi8tNjs4QV1h7uHJjQ5ic/22daMGAxocJ4qfK8VKyF5sUKPxSnxikJv5q6qbl83 7bIQcFkkt35f36mxT7ZNIG1tcL4TXolxMgYAawdIY+m3TPpjzb/wKR8SFRC1Oyar5Sg1 OllP/lTJ0Uyx6Q/82Gk7XRDPBvbqhTXZuq3fuayBUKaFNGllRmwxagU6QMuXbwpJ/SUr TvDRNZ+oLv3jb2kWo8nBqDgwOUJTP2IiL/+zm9dBbGDLJLqKgX43647tJ34SYp2XeRDn 51FA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=Sef0yxj3M0McfXOWyYuZh5QNVIS4E8ybwIxSMPcOtQk=; fh=5u1XucZRDhHRoRk6ufBtSxV0ztGAFTjzSMfD5YXRlc4=; b=P3htYSysPTKkX1IlyaMh7Nymm4Fai31iEfyAa6GQOjTPjNWGcaI16vOATvnwfcSh46 1NOrGFsIqThqhAX38Ep04Jwo0Esi66ubYNJFtPVU8E5VwLsuI560rTQsvLB9GD5nkvYa Pq6kftoy6A8oCDrxRaKw1njO5fiSVgSsg93M3njIXrFhjtylxKLc6XdyRG1fT5CnE24v aRab8anEgMPcVOdsffj5S8KGk/SCye/EdnMJQBTPeZF6+tI6R6uNmvDMcL/4vqpoDUeD kYK1DDvKj/MG6Z8JYU3Xsy/M24pIULQGENRWp1igrzUHmjrmOaJ4QuIyXMDsquSDIBeb +2SQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@baylibre-com.20230601.gappssmtp.com header.s=20230601 header.b=JXcOWyD8; arc=pass (i=1 spf=pass spfdomain=baylibre.com dkim=pass dkdomain=baylibre-com.20230601.gappssmtp.com); spf=pass (google.com: domain of linux-kernel+bounces-176331-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-176331-linux.lists.archive=gmail.com@vger.kernel.org" Return-Path: Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [2604:1380:4601:e00::3]) by mx.google.com with ESMTPS id 4fb4d7f45d1cf-5733c362b97si2504179a12.516.2024.05.10.17.52.20 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 May 2024 17:52:20 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-176331-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) client-ip=2604:1380:4601:e00::3; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20230601.gappssmtp.com header.s=20230601 header.b=JXcOWyD8; arc=pass (i=1 spf=pass spfdomain=baylibre.com dkim=pass dkdomain=baylibre-com.20230601.gappssmtp.com); spf=pass (google.com: domain of linux-kernel+bounces-176331-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:4601:e00::3 as permitted sender) smtp.mailfrom="linux-kernel+bounces-176331-linux.lists.archive=gmail.com@vger.kernel.org" Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id 40A9E1F22ECC for ; Sat, 11 May 2024 00:52:05 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 98B2420B04; Sat, 11 May 2024 00:50:08 +0000 (UTC) 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="JXcOWyD8" Received: from mail-oo1-f54.google.com (mail-oo1-f54.google.com [209.85.161.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 012E31BC3F for ; Sat, 11 May 2024 00:50:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.54 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715388607; cv=none; b=thIvKNXL1o7yIDx0iJ2xWM3KoR0mH7OD6xRuvwPAQVIJmLW12YiNc/MXobT5cJU/wRQhiCcNtnXth1dl4avXFCNFRWTFTKZ7i8c+poL8v6JQMYpdWBtK5uW3006LtQFkX7lNIR+2QxPPtmm1zHkN6TnbOHWKBNtiFhxTfWtS0x4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1715388607; c=relaxed/simple; bh=qfovg8GPkCrYv+M58MvC1AwOylMJYvN79Ny2UrHzdtM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=lbuCdC/oO3+8EWsBT4k22YVsquuuaUMKKIQxMhVsHE17c/oesyiDmreJOHcIgEKdQEICh12DIx1+L4TjNxg80WeE8ETmiBbbeXUSsL7RUd0Wlvfdc3VGkGomHZbcsgHCe/xpp5IuDDnvLaTwTOzqEzVDIeit/k//Fi4CvMoW1c8= 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=JXcOWyD8; arc=none smtp.client-ip=209.85.161.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 Received: by mail-oo1-f54.google.com with SMTP id 006d021491bc7-5b277e17e15so1232228eaf.2 for ; Fri, 10 May 2024 17:50:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1715388604; x=1715993404; 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=Sef0yxj3M0McfXOWyYuZh5QNVIS4E8ybwIxSMPcOtQk=; b=JXcOWyD8VBvKnYW77q19opIK1vz4yClDsHyCvB/utsUPEdO5Mr3R39PJR0/oEAbYcl kRviy2Kc2QENOgs/R/0n8vfpVSKhaazqNdkght3zIY+CDWkj99Mj1NNanFdfDdHAPqVC FX4K8EJPdTWfYltaAHNSPWg4LysuT7tfgPNhhlv+6MhHXSn199YjNx0wkqmTD1nUOqdv o7xXLsZJXsMqrWd4Fia5EPtoMEtxhptNowK7IofVxdaAIuMzZLEOzAw6aLkzs2pz8Sq5 KApBEZVm6pufbasNL/la4BRiH6YW9OQsKeYQYvpLtt8GGMqaGm8VXFZUd6pg22pMJViR fQ6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1715388604; x=1715993404; 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=Sef0yxj3M0McfXOWyYuZh5QNVIS4E8ybwIxSMPcOtQk=; b=DqH6XRhdDn/Vs838nUNviVWTvrK4Rer7rpReXXSXXQBfRJm6tKDlLVNPErU5nIvruO 0bqgX0e7XVXnJzO9v3GBFnhQjKRU/YI3dAiMm1QFYcIiWi4+fDPilfPLJlHyElqNm5iW iSZeDjnm0i3wb1wEBV7YY6gOEqSfJjf8JRt4zoyocs4RWWFuB5Fp6X9fzrrduHWUi40K sTFJHHPCH9XCAnMhZqLEXTow2W2fLs0KdLnbU8C5WD1zKrgTsHIxErlBVw5hNBb2q3OL jwd9wgH4ro/8/1Y8129zppWVev8u3KuWHQlsp+os9w2GHXsb/15cwsWXvDhhc6wXsn7C sV5g== X-Forwarded-Encrypted: i=1; AJvYcCWxugaOOI4+VUH4a9xeFLUgKMhJsnkUIV4PY849uPhm95cPOFDAZS8VonSDtkcHfN63gWZYBM6Z+z+EPE09CSlD1tWDxesFEG0wuVjk X-Gm-Message-State: AOJu0YxD1OGEoQNu2hRfxpolmGaiK1LsIWzoF/0TtCMwbkUBO0rZ3V1W kOnsiVjtvZ+o/C+D2GBqkMIfJ1GLaCC3tFCmQgULqNcU/i0Mvh0vcZ8oyao7zP0= X-Received: by 2002:a4a:8c21:0:b0:5b1:b8a4:bce4 with SMTP id 006d021491bc7-5b281a1b6a7mr4188517eaf.8.1715388604085; Fri, 10 May 2024 17:50:04 -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 006d021491bc7-5b29015a3dbsm321132eaf.46.2024.05.10.17.50.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 10 May 2024 17:50:03 -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 v2 8/8] iio: adc: ad7944: add support for SPI offload Date: Fri, 10 May 2024 19:44:31 -0500 Message-ID: <20240510-dlech-mainline-spi-engine-offload-2-v2-8-8707a870c435@baylibre.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240510-dlech-mainline-spi-engine-offload-2-v2-0-8707a870c435@baylibre.com> References: <20240510-dlech-mainline-spi-engine-offload-2-v2-0-8707a870c435@baylibre.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" X-Mailer: b4 0.12.4 Content-Transfer-Encoding: 8bit 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 --- 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. RFC: This isn't very polished yet, just FYI. A few things to sort out: Rather than making the buffer either triggered buffer or hardware buffer, I'm considering allowing both, e.g. buffer0 will always be the triggered buffer and buffer1 will will be the hardware buffer if connected to a SPI controller with offload support, otherwise buffer1 is absent. But since multiple buffers haven't been used much so far, more investigation is needed to see how that would work in practice. If we do that though, then we would always have the sampling_frequency attribute though even though it only applies to one buffer. --- drivers/iio/adc/ad7944.c | 147 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 111 insertions(+), 36 deletions(-) diff --git a/drivers/iio/adc/ad7944.c b/drivers/iio/adc/ad7944.c index 4602ab5ed2a6..6724d6c92778 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 @@ -65,6 +67,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 @@ -123,6 +127,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), \ }, \ @@ -134,18 +139,12 @@ AD7944_DEFINE_CHIP_INFO(ad7985, ad7944, 16, 0); /* fully differential */ AD7944_DEFINE_CHIP_INFO(ad7986, ad7986, 18, 1); -static void ad7944_unoptimize_msg(void *msg) -{ - spi_unoptimize_message(msg); -} - -static int ad7944_3wire_cs_mode_init_msg(struct device *dev, struct ad7944_adc *adc, - const struct iio_chan_spec *chan) +static void ad7944_3wire_cs_mode_init_msg(struct device *dev, struct ad7944_adc *adc, + const struct iio_chan_spec *chan) { unsigned int t_conv_ns = adc->always_turbo ? adc->timing_spec->turbo_conv_ns : adc->timing_spec->conv_ns; struct spi_transfer *xfers = adc->xfers; - int ret; /* * NB: can get better performance from some SPI controllers if we use @@ -174,21 +173,14 @@ static int ad7944_3wire_cs_mode_init_msg(struct device *dev, struct ad7944_adc * xfers[2].bits_per_word = chan->scan_type.realbits; spi_message_init_with_transfers(&adc->msg, xfers, 3); - - ret = spi_optimize_message(adc->spi, &adc->msg); - if (ret) - return ret; - - return devm_add_action_or_reset(dev, ad7944_unoptimize_msg, &adc->msg); } -static int ad7944_4wire_mode_init_msg(struct device *dev, struct ad7944_adc *adc, - const struct iio_chan_spec *chan) +static void ad7944_4wire_mode_init_msg(struct device *dev, struct ad7944_adc *adc, + const struct iio_chan_spec *chan) { unsigned int t_conv_ns = adc->always_turbo ? adc->timing_spec->turbo_conv_ns : adc->timing_spec->conv_ns; struct spi_transfer *xfers = adc->xfers; - int ret; /* * NB: can get better performance from some SPI controllers if we use @@ -208,12 +200,6 @@ static int ad7944_4wire_mode_init_msg(struct device *dev, struct ad7944_adc *adc xfers[1].bits_per_word = chan->scan_type.realbits; spi_message_init_with_transfers(&adc->msg, xfers, 2); - - ret = spi_optimize_message(adc->spi, &adc->msg); - if (ret) - return ret; - - return devm_add_action_or_reset(dev, ad7944_unoptimize_msg, &adc->msg); } static int ad7944_chain_mode_init_msg(struct device *dev, struct ad7944_adc *adc, @@ -345,6 +331,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; } @@ -352,6 +362,28 @@ 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_ex_buffer_postenable(struct iio_dev *indio_dev) +{ + struct ad7944_adc *adc = iio_priv(indio_dev); + + return spi_offload_hw_trigger_enable(adc->spi, 0); +} + +static int ad7944_offload_ex_buffer_predisable(struct iio_dev *indio_dev) +{ + struct ad7944_adc *adc = iio_priv(indio_dev); + + spi_offload_hw_trigger_disable(adc->spi, 0); + + return 0; +} + +static const struct iio_buffer_setup_ops ad7944_offload_ex_buffer_setup_ops = { + .postenable = &ad7944_offload_ex_buffer_postenable, + .predisable = &ad7944_offload_ex_buffer_predisable, }; static irqreturn_t ad7944_trigger_handler(int irq, void *p) @@ -471,6 +503,18 @@ static void ad7944_ref_disable(void *ref) regulator_disable(ref); } +static void ad7944_offload_unprepare(void *p) +{ + struct ad7944_adc *adc = p; + + spi_offload_unprepare(adc->spi, 0, &adc->msg); +} + +static void ad7944_unoptimize_msg(void *msg) +{ + spi_unoptimize_message(msg); +} + static int ad7944_probe(struct spi_device *spi) { const struct ad7944_chip_info *chip_info; @@ -603,16 +647,10 @@ static int ad7944_probe(struct spi_device *spi) switch (adc->spi_mode) { case AD7944_SPI_MODE_DEFAULT: - ret = ad7944_4wire_mode_init_msg(dev, adc, &chip_info->channels[0]); - if (ret) - return ret; - + ad7944_4wire_mode_init_msg(dev, adc, &chip_info->channels[0]); break; case AD7944_SPI_MODE_SINGLE: - ret = ad7944_3wire_cs_mode_init_msg(dev, adc, &chip_info->channels[0]); - if (ret) - return ret; - + ad7944_3wire_cs_mode_init_msg(dev, adc, &chip_info->channels[0]); break; case AD7944_SPI_MODE_CHAIN: ret = device_property_read_u32(dev, "#daisy-chained-devices", @@ -649,11 +687,48 @@ 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")) { + /* TODO: make this a parameter to ad7944_3wire_cs_mode_init_msg() */ + /* FIXME: wrong index for 4-wire mode */ + adc->xfers[2].rx_buf = NULL; + adc->xfers[2].offload_flags = SPI_OFFLOAD_XFER_RX_STREAM; + + ret = spi_offload_prepare(adc->spi, 0, &adc->msg); + if (ret) + return dev_err_probe(dev, ret, "failed to prepare offload\n"); + + ret = devm_add_action_or_reset(dev, ad7944_offload_unprepare, adc); + if (ret) + return ret; + + adc->trigger_clk = devm_clk_get_enabled(dev, "trigger"); + if (IS_ERR(adc->trigger_clk)) + return dev_err_probe(dev, PTR_ERR(adc->trigger_clk), + "failed to get trigger clk\n"); + + ret = devm_iio_dmaengine_buffer_setup(dev, indio_dev, "rx"); + if (ret) + return ret; + + indio_dev->setup_ops = &ad7944_offload_ex_buffer_setup_ops; + /* offload can't have soft timestamp */ + indio_dev->num_channels--; + } else { + ret = spi_optimize_message(adc->spi, &adc->msg); + if (ret) + return ret; + + ret = devm_add_action_or_reset(dev, ad7944_unoptimize_msg, &adc->msg); + if (ret) + return ret; + + 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); } -- 2.43.2