From nobody Mon Feb 9 20:53:32 2026 Received: from mail-qv1-f46.google.com (mail-qv1-f46.google.com [209.85.219.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 C4A3017DFE4 for ; Wed, 13 Nov 2024 20:53:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731531188; cv=none; b=rp67nPUicfbtEBzC8qLlbhEy0kEfbhFrM9wdh0n7AJ1CEkuDdKmUnDB6eaAFacGcq0TdF/vSk7V4vj2xlwhUOgWcuVUCdrgVTXYp1E6ALlkifYesMP2fwhN/8fOMV9TG8cEdULP2ZeXr/MGLOKomPa52xdavGaCqDg3fmJKBOec= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731531188; c=relaxed/simple; bh=inYPjYm6sWO4oCa64YYvhao2qecb1g1DwZ4g5dtN9AI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=AcRvGtQG/erveEXEILR5J5imYikcPAidcAELy6Y242uhOPGXBzVMmf4LXe0u2Tu+vMduPFx5kKo99rgTzYjfDckIPaoiYaeAmX4yO6TXvmesUWqGCeAfbcunEfQIHte+FFWprvNhRqZ88rPZRZYfZ9zBKU7qy4ngtz+qU6v/JVo= 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=Iu2415SD; arc=none smtp.client-ip=209.85.219.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="Iu2415SD" Received: by mail-qv1-f46.google.com with SMTP id 6a1803df08f44-6d382677c92so49349776d6.3 for ; Wed, 13 Nov 2024 12:53:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1731531185; x=1732135985; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=H1IRlM14Re6YTgXmGb4nIZwdTV5d6qwkRvdoFKXb/hE=; b=Iu2415SDL+VxfrSFLsO6yfi8X0BDcsHlkHqkqZ08ImD2j4FLsVL0o2j7DHFtHcURAC yhrLz4cnf6mxLqacyFz11SNJB4AiwXPcbup/iIH7lRAvPAIvsaZflUuK6VOZ+AGP1F0c oV6kVdPgvj7ZVhUCXJ43I9vAtMf/NlDY6dF+cbH+5v7cmGkTusRjUtxbbVFCO5QeVyWb hh3DqK11mmclmZt3K0WlTs3WbRRl8q6W978J35msBllASFY6Uh7oGttYC1iXnrdNZHHm TJ9cGN/2GV0Fhkp+4ikdWNKF2w1J7kiav7l3UPFJJtFF2mq0FI7MssAaVvl4TAwVyS8J MZIQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731531185; x=1732135985; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=H1IRlM14Re6YTgXmGb4nIZwdTV5d6qwkRvdoFKXb/hE=; b=OENzyFVHkreyu8ooxVdFsnZCsFoH/0ThublTBD9hyBwKdmYijzZXysX+iOoScyn9LY rGj/m3g55cKkUayvfPdQxyDcnC3qW9fXZgCg0gEPSoxSPvwngwYvg7CdpRD9ZDMNPAjh 3KGsKn+PhIlKwlitVm7Huw/hFOLguLKV0lI6+R8KqtftF/kNe4JxgZ/ZemSTS/Fvtn3W WqwKri3egThs4k2xpuznpJMvaOOWZyQ5TWD+LM1TjQFPPxUDugELAy7aWYlsiqmeAy60 C5eTSzDS148XEzRWm7B6uWwDHvrj9io2sz9ucYcHO2RahIVtJlT6avwgFUNXhquzLxFr 3F5Q== X-Forwarded-Encrypted: i=1; AJvYcCWiEsUqhRyZ5d0x4Md6WWZd2uy3wCPlv0XUILUp2ZXh5VngiuXFhVij+bP1CX3GbTM6xR78pgQCr1RGSPo=@vger.kernel.org X-Gm-Message-State: AOJu0YwWwhPJt8lt9LePuuxmYUz6CJ/oRdbsCfx6Vlkf8ZQxAva8X0WZ ZgMPlU2hYsCmBRxCzoe+bVsVC/zevhFfD2Ts/IaZj/xrz/infFIcCKgvYdbX510= X-Google-Smtp-Source: AGHT+IF67ezHsmerGAYtKOJ6aXjMLI5v44DpR71gf0fhQIS/DNRdN3lY67eE0w9zQq/Qb/LryneyOg== X-Received: by 2002:a05:6214:3290:b0:6d1:86b2:5569 with SMTP id 6a1803df08f44-6d39e112ac1mr294129606d6.16.1731531185555; Wed, 13 Nov 2024 12:53:05 -0800 (PST) Received: from [127.0.1.1] (d24-150-219-207.home.cgocable.net. [24.150.219.207]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-6d3961df2f5sm88829336d6.2.2024.11.13.12.53.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Nov 2024 12:53:04 -0800 (PST) From: Trevor Gamblin Date: Wed, 13 Nov 2024 15:52:58 -0500 Subject: [PATCH v2 1/3] iio: adc: ad4695: fix buffered read, single sample timings Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20241113-tgamblin-ad4695_improvements-v2-1-b6bb7c758fc4@baylibre.com> References: <20241113-tgamblin-ad4695_improvements-v2-0-b6bb7c758fc4@baylibre.com> In-Reply-To: <20241113-tgamblin-ad4695_improvements-v2-0-b6bb7c758fc4@baylibre.com> To: Lars-Peter Clausen , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , David Lechner , Jonathan Cameron Cc: Jonathan Cameron , linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, Trevor Gamblin X-Mailer: b4 0.14.1 Modify ad4695_buffer_preenable() by adding an extra SPI transfer after each data read to help ensure that the timing requirement between the last SCLK rising edge and the next CNV rising edge is met. This requires a restructure of the buf_read_xfer array in ad4695_state. Also define AD4695_T_SCK_CNV_DELAY_NS to use for each added transfer. Without this change it is possible for the data to become corrupted on sequential buffered reads due to the device not properly exiting conversion mode. Similarly, make adjustments to ad4695_read_one_sample() so that timings are respected, and clean up the function slightly in the process. Fixes: 6cc7e4bf2e08 ("iio: adc: ad4695: implement triggered buffer") Co-developed-by: David Lechner Signed-off-by: David Lechner Signed-off-by: Trevor Gamblin Reviewed-by: David Lechner Suggested-by: David Lechner Tested-by: David Lechner --- drivers/iio/adc/ad4695.c | 100 ++++++++++++++++++++++++++++++++-----------= ---- 1 file changed, 69 insertions(+), 31 deletions(-) diff --git a/drivers/iio/adc/ad4695.c b/drivers/iio/adc/ad4695.c index 595ec4158e73..0146aed9069f 100644 --- a/drivers/iio/adc/ad4695.c +++ b/drivers/iio/adc/ad4695.c @@ -91,6 +91,7 @@ #define AD4695_T_WAKEUP_SW_MS 3 #define AD4695_T_REFBUF_MS 100 #define AD4695_T_REGCONFIG_NS 20 +#define AD4695_T_SCK_CNV_DELAY_NS 80 #define AD4695_REG_ACCESS_SCLK_HZ (10 * MEGA) =20 /* Max number of voltage input channels. */ @@ -132,8 +133,13 @@ struct ad4695_state { unsigned int vref_mv; /* Common mode input pin voltage. */ unsigned int com_mv; - /* 1 per voltage and temperature chan plus 1 xfer to trigger 1st CNV */ - struct spi_transfer buf_read_xfer[AD4695_MAX_CHANNELS + 2]; + /* + * 2 per voltage and temperature chan plus 1 xfer to trigger 1st + * CNV. Excluding the trigger xfer, every 2nd xfer only serves + * to control CS and add a delay between the last SCLK and next + * CNV rising edges. + */ + struct spi_transfer buf_read_xfer[AD4695_MAX_CHANNELS * 2 + 3]; struct spi_message buf_read_msg; /* Raw conversion data received. */ u8 buf[ALIGN((AD4695_MAX_CHANNELS + 2) * AD4695_MAX_CHANNEL_SIZE, @@ -423,7 +429,7 @@ static int ad4695_buffer_preenable(struct iio_dev *indi= o_dev) u8 temp_chan_bit =3D st->chip_info->num_voltage_inputs; u32 bit, num_xfer, num_slots; u32 temp_en =3D 0; - int ret; + int ret, rx_buf_offset =3D 0; =20 /* * We are using the advanced sequencer since it is the only way to read @@ -449,11 +455,9 @@ static int ad4695_buffer_preenable(struct iio_dev *ind= io_dev) iio_for_each_active_channel(indio_dev, bit) { xfer =3D &st->buf_read_xfer[num_xfer]; xfer->bits_per_word =3D 16; - xfer->rx_buf =3D &st->buf[(num_xfer - 1) * 2]; + xfer->rx_buf =3D &st->buf[rx_buf_offset]; xfer->len =3D 2; - xfer->cs_change =3D 1; - xfer->cs_change_delay.value =3D AD4695_T_CONVERT_NS; - xfer->cs_change_delay.unit =3D SPI_DELAY_UNIT_NSECS; + rx_buf_offset +=3D xfer->len; =20 if (bit =3D=3D temp_chan_bit) { temp_en =3D 1; @@ -468,21 +472,44 @@ static int ad4695_buffer_preenable(struct iio_dev *in= dio_dev) } =20 num_xfer++; + + /* + * We need to add a blank xfer in data reads, to meet the timing + * requirement of a minimum delay between the last SCLK rising + * edge and the CS deassert. + */ + xfer =3D &st->buf_read_xfer[num_xfer]; + xfer->delay.value =3D AD4695_T_SCK_CNV_DELAY_NS; + xfer->delay.unit =3D SPI_DELAY_UNIT_NSECS; + xfer->cs_change =3D 1; + xfer->cs_change_delay.value =3D AD4695_T_CONVERT_NS; + xfer->cs_change_delay.unit =3D SPI_DELAY_UNIT_NSECS; + + num_xfer++; } =20 /* * The advanced sequencer requires that at least 2 slots are enabled. * Since slot 0 is always used for other purposes, we need only 1 - * enabled voltage channel to meet this requirement. If the temperature - * channel is the only enabled channel, we need to add one more slot - * in the sequence but not read from it. + * enabled voltage channel to meet this requirement. If the temperature + * channel is the only enabled channel, we need to add one more slot in + * the sequence but not read from it. This is because the temperature + * sensor is sampled at the end of the channel sequence in advanced + * sequencer mode (see datasheet page 38). + * + * From the iio_for_each_active_channel() block above, we now have an + * xfer with data followed by a blank xfer to allow us to meet the + * timing spec, so move both of those up before adding an extra to + * handle the temperature-only case. */ if (num_slots < 2) { - /* move last xfer so we can insert one more xfer before it */ - st->buf_read_xfer[num_xfer] =3D *xfer; + /* Move last two xfers */ + st->buf_read_xfer[num_xfer] =3D st->buf_read_xfer[num_xfer - 1]; + st->buf_read_xfer[num_xfer - 1] =3D st->buf_read_xfer[num_xfer - 2]; num_xfer++; =20 - /* modify 2nd to last xfer for extra slot */ + /* Modify inserted xfer for extra slot. */ + xfer =3D &st->buf_read_xfer[num_xfer - 3]; memset(xfer, 0, sizeof(*xfer)); xfer->cs_change =3D 1; xfer->delay.value =3D st->chip_info->t_acq_ns; @@ -499,6 +526,12 @@ static int ad4695_buffer_preenable(struct iio_dev *ind= io_dev) return ret; =20 num_slots++; + + /* + * We still want to point at the last xfer when finished, so + * update the pointer. + */ + xfer =3D &st->buf_read_xfer[num_xfer - 1]; } =20 /* @@ -583,8 +616,20 @@ static irqreturn_t ad4695_trigger_handler(int irq, voi= d *p) */ static int ad4695_read_one_sample(struct ad4695_state *st, unsigned int ad= dress) { - struct spi_transfer xfer[2] =3D { }; - int ret, i =3D 0; + struct spi_transfer xfers[2] =3D { + { + .speed_hz =3D AD4695_REG_ACCESS_SCLK_HZ, + .bits_per_word =3D 16, + .tx_buf =3D &st->cnv_cmd, + .len =3D 2, + }, + { + /* Required delay between last SCLK and CNV/CS */ + .delay.value =3D AD4695_T_SCK_CNV_DELAY_NS, + .delay.unit =3D SPI_DELAY_UNIT_NSECS, + } + }; + int ret; =20 ret =3D ad4695_set_single_cycle_mode(st, address); if (ret) @@ -592,29 +637,22 @@ static int ad4695_read_one_sample(struct ad4695_state= *st, unsigned int address) =20 /* * Setting the first channel to the temperature channel isn't supported - * in single-cycle mode, so we have to do an extra xfer to read the - * temperature. + * in single-cycle mode, so we have to do an extra conversion to read + * the temperature. */ if (address =3D=3D AD4695_CMD_TEMP_CHAN) { - /* We aren't reading, so we can make this a short xfer. */ - st->cnv_cmd2 =3D AD4695_CMD_TEMP_CHAN << 3; - xfer[0].tx_buf =3D &st->cnv_cmd2; - xfer[0].len =3D 1; - xfer[0].cs_change =3D 1; - xfer[0].cs_change_delay.value =3D AD4695_T_CONVERT_NS; - xfer[0].cs_change_delay.unit =3D SPI_DELAY_UNIT_NSECS; - - i =3D 1; + st->cnv_cmd =3D AD4695_CMD_TEMP_CHAN << 11; + + ret =3D spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); + if (ret) + return ret; } =20 /* Then read the result and exit conversion mode. */ st->cnv_cmd =3D AD4695_CMD_EXIT_CNV_MODE << 11; - xfer[i].bits_per_word =3D 16; - xfer[i].tx_buf =3D &st->cnv_cmd; - xfer[i].rx_buf =3D &st->raw_data; - xfer[i].len =3D 2; + xfers[0].rx_buf =3D &st->raw_data; =20 - return spi_sync_transfer(st->spi, xfer, i + 1); + return spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); } =20 static int ad4695_read_raw(struct iio_dev *indio_dev, --=20 2.39.5 From nobody Mon Feb 9 20:53:32 2026 Received: from mail-qv1-f45.google.com (mail-qv1-f45.google.com [209.85.219.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A726A205ABD for ; Wed, 13 Nov 2024 20:53:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731531189; cv=none; b=NfNOARYg8wu2qjtLXIUhOE4u0znqFRO8u0jJgR3I+suyj9LEC24byAzCdRQqYM3N6Hlcoi1nFp97m77ErKrDyWQLdD+D2t4cemNY+h+vRF6gdNbKT8ZlKn3zV21qoQXy+s+oFpOm8YHEO3aT3bgezVLsEzyXkvFz0K2dRuAqomQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731531189; c=relaxed/simple; bh=usxnLSOifC75UUbscRAQm9vBt1XSyQeNy/RrQ8fENrA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=cEc6Gh6JGcfIwC9b3yXd+GSIRuIxiqh1KFIfeeA75oPsEqKyrmU9Bypg+r9frgx6M0MibdAiEHaIPtzqJgg3D4PVmi6awJmxjwxnFEfOQM1laP6ghZPw7vtmO6Uu3xiQcGZX2flefTiHATcOQuhG3K0f6vQohrFCDfSKINf86e8= 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=fTXpgNMg; arc=none smtp.client-ip=209.85.219.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="fTXpgNMg" Received: by mail-qv1-f45.google.com with SMTP id 6a1803df08f44-6cbcd49b833so48169576d6.3 for ; Wed, 13 Nov 2024 12:53:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1731531186; x=1732135986; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=ITogGBSwNSbrmJAZixpXgO1FJBpp7STOlbU6R2lyybE=; b=fTXpgNMgiVAthfGxCj7joIwTxK9auxbn9ZbaU2qXjnRJeuaxY79PSIIffCCdfJQ/t0 nyH4tccmAUpGhkQhxe7RxhVBDT1jaSHRvHwW1nfPCsLAoMN4HkZLbmooIClCAaJHryd1 3lVn3VBXgsFe9UsmrE4g5lRKJdLeIWOH3a49nYZ740nQJHgaKFi+ykdI+EvmMpPqRsfD ADtMmMqShxSPnd0scGqzeH//BfV001mFQEUiA9VyzRWPEfEYzx2F1PK9lbq4C/HYzVGw qp+BX00jHr4JXlewPaArbp5TYSLTJ5KuKIalHfMH2O808/pMxlX9Oc8VcNfQ+6CARzPV vMUw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731531186; x=1732135986; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ITogGBSwNSbrmJAZixpXgO1FJBpp7STOlbU6R2lyybE=; b=IxCsERxhcdes73CneAOfIZ7I/utUf70U4uFp1cYVk3kupgvD3UyZ/lDuuIgq+vajpm 7d3fcBO0ILxiIH5vcYaWz7ZGGcoAjjtUnCzbgyaacqTGIM7mAdES6Gu9biLyrkVl9Xa8 XaJXJp6y9MALoyKJKb8AY3Z4g9snuSaJooTiMpEPjSnPb7knNZnoxM8B4fVJF3zvwDDx c3HNm+pQnnKRZBqWV1DHJyyMB73YcjKXnIApHtjAHnPNEAc14+PldjNMMlgkzp/fMz5a Byblxom9n3pmDqMgp6uNt0HiwDA1/5SHLdegc/agVvENThR0Gt0sWRFkKV41N6U93l2x ddBA== X-Forwarded-Encrypted: i=1; AJvYcCWRo7PrXZFPvRkqTrY7YlObuu4uPDd36vsOaaDfEb4od4gXd3ytXzNpu88bdKhJd+IDZvwFs8D/tv2cKTQ=@vger.kernel.org X-Gm-Message-State: AOJu0YyBlAFBWKUGIp5//yoDkJtY+mAIKpZUAiYIoSODWMj7aCTBY6LY 9U1Y5ImFOEnPSYPGO+1fORnXdnhlaRo/hKNZPYW4dM3Sd2Kx2WnuMNsGevv/vtg= X-Google-Smtp-Source: AGHT+IFDgRdfRwbHfCGhimMOMUXkC66ocOQWIyw72aM4GlMmOQLibfUV596pHenrKWvqiaZX5Xuoyg== X-Received: by 2002:a05:6214:3290:b0:6cb:f87f:f073 with SMTP id 6a1803df08f44-6d39e1078dbmr293135896d6.6.1731531186505; Wed, 13 Nov 2024 12:53:06 -0800 (PST) Received: from [127.0.1.1] (d24-150-219-207.home.cgocable.net. [24.150.219.207]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-6d3961df2f5sm88829336d6.2.2024.11.13.12.53.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Nov 2024 12:53:06 -0800 (PST) From: Trevor Gamblin Date: Wed, 13 Nov 2024 15:52:59 -0500 Subject: [PATCH v2 2/3] iio: adc: ad4695: make ad4695_exit_conversion_mode() more robust Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20241113-tgamblin-ad4695_improvements-v2-2-b6bb7c758fc4@baylibre.com> References: <20241113-tgamblin-ad4695_improvements-v2-0-b6bb7c758fc4@baylibre.com> In-Reply-To: <20241113-tgamblin-ad4695_improvements-v2-0-b6bb7c758fc4@baylibre.com> To: Lars-Peter Clausen , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , David Lechner , Jonathan Cameron Cc: Jonathan Cameron , linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, Trevor Gamblin X-Mailer: b4 0.14.1 Ensure that conversion mode is successfully exited when the command is issued by adding an extra transfer beforehand, matching the minimum CNV high and low times from the AD4695 datasheet. The AD4695 has a quirk where the exit command only works during a conversion, so guarantee this happens by triggering a conversion in ad4695_exit_conversion_mode(). Then make this even more robust by ensuring that the exit command is run at AD4695_REG_ACCESS_SCLK_HZ rather than the bus maximum. Signed-off-by: Trevor Gamblin Reviewed-by: David Lechner Suggested-by: David Lechner Tested-by: David Lechner --- drivers/iio/adc/ad4695.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/drivers/iio/adc/ad4695.c b/drivers/iio/adc/ad4695.c index 0146aed9069f..4bc800293e60 100644 --- a/drivers/iio/adc/ad4695.c +++ b/drivers/iio/adc/ad4695.c @@ -92,6 +92,8 @@ #define AD4695_T_REFBUF_MS 100 #define AD4695_T_REGCONFIG_NS 20 #define AD4695_T_SCK_CNV_DELAY_NS 80 +#define AD4695_T_CNVL_NS 80 +#define AD4695_T_CNVH_NS 10 #define AD4695_REG_ACCESS_SCLK_HZ (10 * MEGA) =20 /* Max number of voltage input channels. */ @@ -364,11 +366,31 @@ static int ad4695_enter_advanced_sequencer_mode(struc= t ad4695_state *st, u32 n) */ static int ad4695_exit_conversion_mode(struct ad4695_state *st) { - struct spi_transfer xfer =3D { - .tx_buf =3D &st->cnv_cmd2, - .len =3D 1, - .delay.value =3D AD4695_T_REGCONFIG_NS, - .delay.unit =3D SPI_DELAY_UNIT_NSECS, + /* + * An extra transfer is needed to trigger a conversion here so + * that we can be 100% sure the command will be processed by the + * ADC, rather than relying on it to be in the correct state + * when this function is called (this chip has a quirk where the + * command only works when reading a conversion, and if the + * previous conversion was already read then it won't work). The + * actual conversion command is then run at the slower + * AD4695_REG_ACCESS_SCLK_HZ speed to guarantee this works. + */ + struct spi_transfer xfers[] =3D { + { + .delay.value =3D AD4695_T_CNVL_NS, + .delay.unit =3D SPI_DELAY_UNIT_NSECS, + .cs_change =3D 1, + .cs_change_delay.value =3D AD4695_T_CNVH_NS, + .cs_change_delay.unit =3D SPI_DELAY_UNIT_NSECS, + }, + { + .speed_hz =3D AD4695_REG_ACCESS_SCLK_HZ, + .tx_buf =3D &st->cnv_cmd2, + .len =3D 1, + .delay.value =3D AD4695_T_REGCONFIG_NS, + .delay.unit =3D SPI_DELAY_UNIT_NSECS, + }, }; =20 /* @@ -377,7 +399,7 @@ static int ad4695_exit_conversion_mode(struct ad4695_st= ate *st) */ st->cnv_cmd2 =3D AD4695_CMD_EXIT_CNV_MODE << 3; =20 - return spi_sync_transfer(st->spi, &xfer, 1); + return spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); } =20 static int ad4695_set_ref_voltage(struct ad4695_state *st, int vref_mv) --=20 2.39.5 From nobody Mon Feb 9 20:53:32 2026 Received: from mail-oi1-f178.google.com (mail-oi1-f178.google.com [209.85.167.178]) (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 B9C07206E9A for ; Wed, 13 Nov 2024 20:53:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731531191; cv=none; b=RLZ6WOElmrfXSpofvXte4pRnB8C1L3Qd+BlNp5oNoj9lUl7bPBJgZT6TTcfv33WkGO+TH7sxs4nIziw05XtdoCAZyawXjpVWZD9qlijC51HFLTeWK0faDJPeYnrAHRZqAeTfWcsQfgBmbmGj9NZpPuPLm9360XhptEp+xjimrEY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731531191; c=relaxed/simple; bh=Pz2KKu4E0S8gxWyDYqUJ4IikQCVVFbB/FjvWce4wrK4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=muYdaI9HwhZYBTEe1B3mDwNAebBraExEKPCMlTXIaoD1DqEJAmBFPZhoATTiJCpPKlEg3hoF0ATz8XtYqVhXt8YVLbp+XmlfoGHS8TTFeeTdH9hnsJRzCIQeUa/Y2R59T0S3940wMAGeg5tfVVP8dxlyB1TeD+OMm12rDq4R0I8= 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=gC/VtcRk; arc=none smtp.client-ip=209.85.167.178 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="gC/VtcRk" Received: by mail-oi1-f178.google.com with SMTP id 5614622812f47-3e6089a1d39so3347006b6e.0 for ; Wed, 13 Nov 2024 12:53:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1731531188; x=1732135988; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=j973tQMecbg2dQpmCZmqY7EOAwkOr6g0JYqv1pBH+KE=; b=gC/VtcRkfFZhaQbcmQr7ADLYv5Zse1Ld928A2/LYMA4jAOTRtG9q/FERlKoEuIOpeO zpdMKJn47vszq3BDlDso773+OKxxNoTm7Ewu2oYpg3oIrAl0gj9zYQ3dGH2KL5UhluF8 32z2GyoG9UYPGaEpWttex5HYNl85mp04sk9/xj3P/QUwPFtcvlMaLUaBgWOpZd66iqos ApQIH1vzmU0iErIXrZihQpEXaEPu/FyQ6epE4xR3cPUhvt5Xs++Gve+uTINm/d5Bi+Od 8bydBFIsOXP7Pvaz7FoJ+m6Ko6NV8Axjv2R4Iz1McFWfGBo8xUSUPFfXJgOkzw3sXlgy OlBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1731531188; x=1732135988; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=j973tQMecbg2dQpmCZmqY7EOAwkOr6g0JYqv1pBH+KE=; b=H+aYkS4adc1EA/xCRNgR9xwoCTG4qedEqebjF7aYNGxB9nM7apSLp61MOPmIDDxvua BYZaHrPsW58IJrfA3OMKyYvlpNPI1fJUuSsdBpsYdFzreBtW0R6F8pzibEwhQ9HLP4m6 cYyygPt0+tiJ6Vu7I6fTKjjJSbmyyHyBx0WIDnjupSfXLq1NopFebXPCDqucUUrjJCQ2 cCXQ8bBrtvRy9oxm2Xypm8cJHihB4CVt2yS/1CNRyeiqoWMpn4yQljib78EnFA8oBivu LFdPUN/VmdoKlbh6Jef0tOz9xyV9MigUhp5iixjEm2AVkkwIZz4ilvdl3XPw3kZQOmJl +zsw== X-Forwarded-Encrypted: i=1; AJvYcCXl/Q152guOxRrI+v4V84ylmgdnDbdp+6mm3bFMrqVCf6tnGKJZa623ZUMP9a/iBgnSo2zH4n3nG4hMYDM=@vger.kernel.org X-Gm-Message-State: AOJu0YxYfXQ/3e9qcIuW1HCbpoBHXL2yECdpyhylHqRPxp8wGHmBtrgU CCekUBqa//m1LSNjzc4v5N25M6yAh3xILxu//rtJD+L/tCXLZVQRU5f3h8Ec0dc= X-Google-Smtp-Source: AGHT+IG5f7b1sekg4Dycf1CVNaaQ7HdwRKLYHyGVFUKWYUSjmL0f7fHis9LeoVV7mKWpeJQ82PRNnQ== X-Received: by 2002:a05:6808:21a7:b0:3e6:3777:76a7 with SMTP id 5614622812f47-3e7946af87cmr19038718b6e.23.1731531187576; Wed, 13 Nov 2024 12:53:07 -0800 (PST) Received: from [127.0.1.1] (d24-150-219-207.home.cgocable.net. [24.150.219.207]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-6d3961df2f5sm88829336d6.2.2024.11.13.12.53.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 13 Nov 2024 12:53:07 -0800 (PST) From: Trevor Gamblin Date: Wed, 13 Nov 2024 15:53:00 -0500 Subject: [PATCH v2 3/3] iio: adc: ad4695: add custom regmap bus callbacks Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20241113-tgamblin-ad4695_improvements-v2-3-b6bb7c758fc4@baylibre.com> References: <20241113-tgamblin-ad4695_improvements-v2-0-b6bb7c758fc4@baylibre.com> In-Reply-To: <20241113-tgamblin-ad4695_improvements-v2-0-b6bb7c758fc4@baylibre.com> To: Lars-Peter Clausen , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , David Lechner , Jonathan Cameron Cc: Jonathan Cameron , linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, Trevor Gamblin X-Mailer: b4 0.14.1 Add a custom implementation of regmap read/write callbacks using the SPI bus. This allows them to be performed at a lower SCLK rate than data reads. Previously, all SPI transfers were being performed at a lower speed, but with this change sample data is read at the max bus speed while the register reads/writes remain at the lower rate. Also remove .can_multi_write from the AD4695 driver's regmap_configs, as this isn't implemented or needed. For some background context, see: https://lore.kernel.org/linux-iio/20241028163907.00007e12@Huawei.com/ Suggested-by: David Lechner Signed-off-by: Trevor Gamblin Reviewed-by: David Lechner Tested-by: David Lechner --- drivers/iio/adc/Kconfig | 2 +- drivers/iio/adc/ad4695.c | 74 +++++++++++++++++++++++++++++++++++++++++++-= ---- 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 6c4e74420fd2..e0f9d01ce37d 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -51,9 +51,9 @@ config AD4130 config AD4695 tristate "Analog Device AD4695 ADC Driver" depends on SPI - select REGMAP_SPI select IIO_BUFFER select IIO_TRIGGERED_BUFFER + select REGMAP help Say yes here to build support for Analog Devices AD4695 and similar analog to digital converters (ADC). diff --git a/drivers/iio/adc/ad4695.c b/drivers/iio/adc/ad4695.c index 4bc800293e60..921d996fff79 100644 --- a/drivers/iio/adc/ad4695.c +++ b/drivers/iio/adc/ad4695.c @@ -150,6 +150,8 @@ struct ad4695_state { /* Commands to send for single conversion. */ u16 cnv_cmd; u8 cnv_cmd2; + /* Buffer for storing data from regmap bus reads/writes */ + u8 regmap_bus_data[4]; }; =20 static const struct regmap_range ad4695_regmap_rd_ranges[] =3D { @@ -194,7 +196,6 @@ static const struct regmap_config ad4695_regmap_config = =3D { .max_register =3D AD4695_REG_AS_SLOT(127), .rd_table =3D &ad4695_regmap_rd_table, .wr_table =3D &ad4695_regmap_wr_table, - .can_multi_write =3D true, }; =20 static const struct regmap_range ad4695_regmap16_rd_ranges[] =3D { @@ -226,7 +227,67 @@ static const struct regmap_config ad4695_regmap16_conf= ig =3D { .max_register =3D AD4695_REG_GAIN_IN(15), .rd_table =3D &ad4695_regmap16_rd_table, .wr_table =3D &ad4695_regmap16_wr_table, - .can_multi_write =3D true, +}; + +static int ad4695_regmap_bus_reg_write(void *context, const void *data, + size_t count) +{ + struct ad4695_state *st =3D context; + struct spi_transfer xfer =3D { + .speed_hz =3D AD4695_REG_ACCESS_SCLK_HZ, + .len =3D count, + .tx_buf =3D st->regmap_bus_data, + }; + + if (count > ARRAY_SIZE(st->regmap_bus_data)) + return -EINVAL; + + memcpy(st->regmap_bus_data, data, count); + + return spi_sync_transfer(st->spi, &xfer, 1); +} + +static int ad4695_regmap_bus_reg_read(void *context, const void *reg, + size_t reg_size, void *val, + size_t val_size) +{ + struct ad4695_state *st =3D context; + struct spi_transfer xfers[] =3D { + { + .speed_hz =3D AD4695_REG_ACCESS_SCLK_HZ, + .len =3D reg_size, + .tx_buf =3D &st->regmap_bus_data[0], + }, { + .speed_hz =3D AD4695_REG_ACCESS_SCLK_HZ, + .len =3D val_size, + .rx_buf =3D &st->regmap_bus_data[2], + }, + }; + int ret; + + if (reg_size > 2) + return -EINVAL; + + if (val_size > 2) + return -EINVAL; + + memcpy(&st->regmap_bus_data[0], reg, reg_size); + + ret =3D spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); + if (ret) + return ret; + + memcpy(val, &st->regmap_bus_data[2], val_size); + + return 0; +} + +static const struct regmap_bus ad4695_regmap_bus =3D { + .write =3D ad4695_regmap_bus_reg_write, + .read =3D ad4695_regmap_bus_reg_read, + .read_flag_mask =3D 0x80, + .reg_format_endian_default =3D REGMAP_ENDIAN_BIG, + .val_format_endian_default =3D REGMAP_ENDIAN_BIG, }; =20 static const struct iio_chan_spec ad4695_channel_template =3D { @@ -1061,15 +1122,14 @@ static int ad4695_probe(struct spi_device *spi) if (!st->chip_info) return -EINVAL; =20 - /* Registers cannot be read at the max allowable speed */ - spi->max_speed_hz =3D AD4695_REG_ACCESS_SCLK_HZ; - - st->regmap =3D devm_regmap_init_spi(spi, &ad4695_regmap_config); + st->regmap =3D devm_regmap_init(dev, &ad4695_regmap_bus, st, + &ad4695_regmap_config); if (IS_ERR(st->regmap)) return dev_err_probe(dev, PTR_ERR(st->regmap), "Failed to initialize regmap\n"); =20 - st->regmap16 =3D devm_regmap_init_spi(spi, &ad4695_regmap16_config); + st->regmap16 =3D devm_regmap_init(dev, &ad4695_regmap_bus, st, + &ad4695_regmap16_config); if (IS_ERR(st->regmap16)) return dev_err_probe(dev, PTR_ERR(st->regmap16), "Failed to initialize regmap16\n"); --=20 2.39.5