From nobody Tue Dec 16 05:36:42 2025 Received: from mail-ot1-f44.google.com (mail-ot1-f44.google.com [209.85.210.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2DE1C17D8B3 for ; Thu, 30 May 2024 15:14:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717082072; cv=none; b=th/EeQxaFSJFn+SVlyqdBZw22xvehqGl2coMRUHe6mkwpbBjNPcD2MqNGvblEn5vgxc6CcJoxBvDyfIFWTyCeuzZEvyNu1npzWJ9LSwr6vNgJDemaPP2MWiZC6faP2Fo5KN0UTPu7wng6W3myYyVD5YKOSm9dnVp3vk3Hj7c8YI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717082072; c=relaxed/simple; bh=ZRrBEnty0a3OvlAcxFKH/wVNDRG+6DSpTucqWWr66pQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=YbWu2icWKjft3rudG0qq8jBmMsiDSfY7IVZBoh7I0ia/3y//qNvylB6rX6cDfUDsHMLEdbf3EBgqRHYuM+27HoDl4tnL6bc9SMdb2Ev0CHE9c1GFahdCvHVCLwSW5utzxILYqGcWk4U2e3qpBcUekb1d+z19oqZnDAECsqgqYO0= 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=IA0CP7al; arc=none smtp.client-ip=209.85.210.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="IA0CP7al" Received: by mail-ot1-f44.google.com with SMTP id 46e09a7af769-6f8d0a00a35so38690a34.2 for ; Thu, 30 May 2024 08:14:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1717082069; x=1717686869; 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=FbWYNDGeB4acdSvzLHvqWONXfu2Ni8kWHZVRyossuwM=; b=IA0CP7alcnAhoaw0ReGN3EZynNr/XEzvSWs+w6TKe4f+X5SVe04w8nFkvj+jymikic 5QYcY3eBou1//g9hryIINrBQirenZ85DvWk5ppdc+u3r6WskxZIiF7HSNvEwAE/jzyAz q2yC6I3p1fafA+YBZC60mQ+3n9sVqBVpTsUEGNBUcI78wkYFJ1m7gTTtluVKJlH40KM8 5WiXVRJNN2hWgQLNwU4M6wwQoNpuLO141M3B6wmMFttkd6CtZ6oblh94jTu6M4arzqs9 MAY2fxA7hG1pcCpnaiWSP3c6Ew/+6u32i4veEDCl9n3J3OK/iGJIl0rnYHa0ECqU7ne+ NNWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1717082069; x=1717686869; 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=FbWYNDGeB4acdSvzLHvqWONXfu2Ni8kWHZVRyossuwM=; b=hN5FvNcsJh0f2rr89oHiuZKBclOGq9T6rVo4xS+wNJjaETB9yYFPNaJ8n3z3JxjYTh 2QlwvtjCak94szlx6ayHfCHfgKEM2ZWa2yJXizsHtplH0x7l8yJ6k2z4dMt9Mr7t5NVM Ruz7ffnm0f7aBFhUFQtIvzG3McO7vIfx6sJZ1aTz7526PZOrjHMVQJFn20lsaWJvv5Rw /ogivFV+HFJojE1U6mL6DAqXrzpUsxpvlXeVkHnJcwHXF8jfAqAJnZJXgMToOPHxM0Kb eQ+BuuXqHZHSYUtsb73eCV6UU5PGYHVSfW00AAnP/Facbro1aDJprT70qhezFf07ddEd 5XTg== X-Forwarded-Encrypted: i=1; AJvYcCVje/4E3xZz7dyuIJvi7uyjAALPiHiqq0r+bcbg9cCBQQ/4nk92JE0mHZ4+oP7+haGKaJBmxpbRydWfUFT2GxOh63bw91tbqGyMbUaC X-Gm-Message-State: AOJu0Yw15Ohi3V4V+d9FOdlJC9eo6yH0BzWOLcKbEQMUw47DT1cKKRWR Kmp3gOTrc8+5XccP4c9oEYzmIb/1B1dHBOk68Xub7wJ7f54SSyjt1C69pRbQj3o= X-Google-Smtp-Source: AGHT+IE2lyAsahNdb+M+r2VsDVKfYnrWiFE+5vnGDiP3IBTld3L7Pf2jxyrJMpOL2y8G8xxJqtOR7w== X-Received: by 2002:a9d:4802:0:b0:6f0:e7c3:945c with SMTP id 46e09a7af769-6f90af1c9b2mr2439771a34.36.1717082069189; Thu, 30 May 2024 08:14: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-6f8d0de6314sm2803425a34.41.2024.05.30.08.14.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 May 2024 08:14:28 -0700 (PDT) From: David Lechner To: Jonathan Cameron Cc: David Lechner , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , Julien Stephan , Esteban Blanc , linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 1/5] iio: introduce struct iio_scan_type Date: Thu, 30 May 2024 10:14:08 -0500 Message-ID: <20240530-iio-add-support-for-multiple-scan-types-v3-1-cbc4acea2cfa@baylibre.com> X-Mailer: git-send-email 2.45.1 In-Reply-To: <20240530-iio-add-support-for-multiple-scan-types-v3-0-cbc4acea2cfa@baylibre.com> References: <20240530-iio-add-support-for-multiple-scan-types-v3-0-cbc4acea2cfa@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: quoted-printable This gives the channel scan_type a named type so that it can be used to simplify code in later commits. Signed-off-by: David Lechner Reviewed-by: Nuno Sa --- v3 changes: none v2 changes: none --- include/linux/iio/iio.h | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 55e2b22086a1..19de573a944a 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -173,6 +173,27 @@ struct iio_event_spec { unsigned long mask_shared_by_all; }; =20 +/** + * struct iio_scan_type - specification for channel data format in buffer + * @sign: 's' or 'u' to specify signed or unsigned + * @realbits: Number of valid bits of data + * @storagebits: Realbits + padding + * @shift: Shift right by this before masking out realbits. + * @repeat: Number of times real/storage bits repeats. When the + * repeat element is more than 1, then the type element in + * sysfs will show a repeat value. Otherwise, the number + * of repetitions is omitted. + * @endianness: little or big endian + */ +struct iio_scan_type { + char sign; + u8 realbits; + u8 storagebits; + u8 shift; + u8 repeat; + enum iio_endian endianness; +}; + /** * struct iio_chan_spec - specification of a single channel * @type: What type of measurement is the channel making. @@ -184,17 +205,6 @@ struct iio_event_spec { * @scan_index: Monotonic index to give ordering in scans when read * from a buffer. * @scan_type: struct describing the scan type - * @scan_type.sign: 's' or 'u' to specify signed or unsigned - * @scan_type.realbits: Number of valid bits of data - * @scan_type.storagebits: Realbits + padding - * @scan_type.shift: Shift right by this before masking out - * realbits. - * @scan_type.repeat: Number of times real/storage bits repeats. - * When the repeat element is more than 1, then - * the type element in sysfs will show a repeat - * value. Otherwise, the number of repetitions - * is omitted. - * @scan_type.endianness: little or big endian * @info_mask_separate: What information is to be exported that is specifi= c to * this channel. * @info_mask_separate_available: What availability information is to be @@ -245,14 +255,7 @@ struct iio_chan_spec { int channel2; unsigned long address; int scan_index; - struct { - char sign; - u8 realbits; - u8 storagebits; - u8 shift; - u8 repeat; - enum iio_endian endianness; - } scan_type; + struct iio_scan_type scan_type; long info_mask_separate; long info_mask_separate_available; long info_mask_shared_by_type; --=20 2.45.1 From nobody Tue Dec 16 05:36:42 2025 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 EA5C318755D for ; Thu, 30 May 2024 15:14:30 +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=1717082073; cv=none; b=ilhsSHVr6BmVkpmbrZ2ewhv8EN4tuYBVNzSbtoC7YEa18ujgwPT8RmKrVMBUomXpKs719szVtfXaKSmCNWcyjk8LLbstAHNnQ8TSbUsCtfyVKKxWu03bcYtUwHqexJFuYENwYSgvQbUVH2Gv7Bctvwz+b67CNTpoztddUs2uCLE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717082073; c=relaxed/simple; bh=DY1EeagIOvwFMlI+7rFTIpnLVX0E678JEXnN9mdCJIU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=P22lEF1Fdn/qzYotwArB7jNMOV9WXjnr9+x/m0iHfQoIhQHuoQxOaDRfk4cP3P1dW+oBTZGasjfHsBO9n3lEMZYXr1ammLVgJBso16PPFxEP5MdSj4U3OeVb8ZzUiRfR2VnOwkIRfk89aw6xs+g1LQhr6IGkAu3vJFgMqz4Fl0M= 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=gGRQ/DEb; 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="gGRQ/DEb" Received: by mail-ot1-f48.google.com with SMTP id 46e09a7af769-6f8ef894ecdso611333a34.1 for ; Thu, 30 May 2024 08:14:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1717082070; x=1717686870; 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=etE6dgY3ZZdPAacneXLnj+Gq8AOjqNZk3KGQXXeWybg=; b=gGRQ/DEbi0NqlwgpRoPz9DSzkWT3wseQbS0BKn+LnURYP0WYJ6GZ98uOPVpWjPLmi0 rojs1O0hCNNk0H2TrEJD9n7q3ncvmkWRVWnWHrLcXfBLhl9KpJs/NDD9qNhr4XRVM52P JI6z23QvLPnPa/946ltbv3FGNyvYE88dMXI/caFJCjzSp5y5U8f8lAUedEHGlFG7CW1t KCgLEEl646xPRVwtspYkFVcrRD6IfNJaGlF2cbDYiWLweQ3pMVeoN1YtpgpPAJlzQu2j HfzMTgkcwYemv6xgz1+x2ct+6UqvaDAXu6jZPjW450SFUqRSoLfrD7vq74KN1kaU1LCp yA4w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1717082070; x=1717686870; 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=etE6dgY3ZZdPAacneXLnj+Gq8AOjqNZk3KGQXXeWybg=; b=EIv7wzlrUHkDAoGSHdricRE15HU836cbNseFRfc0xLCyZHOmoHlErMojaa50ksvTGQ Hd/rM1at7vHXghKdzrhukwHuCUguOozWJ+f6aQdwkmn7yglSfoAAjxk+lDIrkxUmh/jK TY79H1zkyzWX6r3OXBFCrrdTbKITW3oiz4ZN8Tg2Kpa7pYMYua/kLeZ5DIsF7e5R9EK9 9H9EPDXpYQZU4y9YXVvj7IojaGjUw7yVLUbjSOcGt3jNeXyqsWTZHJNraanUvgSy1Zl+ ILlvZjpuuLRcZ4S2Gl3jd3AtPmQG26x790E2DQpecjtUwzWMX+B2pVqHd7ngIng0MztG LgAA== X-Forwarded-Encrypted: i=1; AJvYcCWsNfmYuqu3IYKipdovdJMbz81KCRm5b3U9wqYhVcHobojReScs4mJOrhQZC8i7YHPQFo22WN0mmR+oAZFEi3LpvguS8ONoYNbu6UPp X-Gm-Message-State: AOJu0Yw+HAb/U15UTTnDMMox5Klc7HlZcl7a+51PhlP0qBdaQeHVpCod ngGGRnD7ZAErRGIIJ+4o4ihjxsTK4uwK8YeuY6RMGhAOgzRvhEzYnaly5+xTpZI= X-Google-Smtp-Source: AGHT+IE/h5aelZG+YZNL4s6+2Bhy1f8X4krqjpF70XwmB1I5d0qIYdIKpDRbeTfsgSEchn0kRq6ecQ== X-Received: by 2002:a05:6830:3b0d:b0:6f0:e71c:6065 with SMTP id 46e09a7af769-6f90aec54b8mr2744897a34.19.1717082070067; Thu, 30 May 2024 08:14: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-6f8d0de6314sm2803425a34.41.2024.05.30.08.14.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 May 2024 08:14:29 -0700 (PDT) From: David Lechner To: Jonathan Cameron Cc: David Lechner , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , Julien Stephan , Esteban Blanc , linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 2/5] iio: buffer: use struct iio_scan_type to simplify code Date: Thu, 30 May 2024 10:14:09 -0500 Message-ID: <20240530-iio-add-support-for-multiple-scan-types-v3-2-cbc4acea2cfa@baylibre.com> X-Mailer: git-send-email 2.45.1 In-Reply-To: <20240530-iio-add-support-for-multiple-scan-types-v3-0-cbc4acea2cfa@baylibre.com> References: <20240530-iio-add-support-for-multiple-scan-types-v3-0-cbc4acea2cfa@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: quoted-printable By using struct iio_scan_type, we can simplify the code by removing lots of duplicate pointer dereferences. This make the code a bit easier to read. This also prepares for a future where channels may have more than one scan_type. Signed-off-by: David Lechner Reviewed-by: Nuno Sa --- v3 changes: none v2 changes: * fixed spelling of dereferences in commit message --- drivers/iio/industrialio-buffer.c | 48 +++++++++++++++++++++++------------= ---- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-b= uffer.c index cec58a604d73..08103a9e77f7 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -366,7 +366,8 @@ static ssize_t iio_show_fixed_type(struct device *dev, char *buf) { struct iio_dev_attr *this_attr =3D to_iio_dev_attr(attr); - u8 type =3D this_attr->c->scan_type.endianness; + const struct iio_scan_type *scan_type =3D &this_attr->c->scan_type; + u8 type =3D scan_type->endianness; =20 if (type =3D=3D IIO_CPU) { #ifdef __LITTLE_ENDIAN @@ -375,21 +376,21 @@ static ssize_t iio_show_fixed_type(struct device *dev, type =3D IIO_BE; #endif } - if (this_attr->c->scan_type.repeat > 1) + if (scan_type->repeat > 1) return sysfs_emit(buf, "%s:%c%d/%dX%d>>%u\n", iio_endian_prefix[type], - this_attr->c->scan_type.sign, - this_attr->c->scan_type.realbits, - this_attr->c->scan_type.storagebits, - this_attr->c->scan_type.repeat, - this_attr->c->scan_type.shift); + scan_type->sign, + scan_type->realbits, + scan_type->storagebits, + scan_type->repeat, + scan_type->shift); else return sysfs_emit(buf, "%s:%c%d/%d>>%u\n", iio_endian_prefix[type], - this_attr->c->scan_type.sign, - this_attr->c->scan_type.realbits, - this_attr->c->scan_type.storagebits, - this_attr->c->scan_type.shift); + scan_type->sign, + scan_type->realbits, + scan_type->storagebits, + scan_type->shift); } =20 static ssize_t iio_scan_el_show(struct device *dev, @@ -694,12 +695,16 @@ static unsigned int iio_storage_bytes_for_si(struct i= io_dev *indio_dev, unsigned int scan_index) { const struct iio_chan_spec *ch; + const struct iio_scan_type *scan_type; unsigned int bytes; =20 ch =3D iio_find_channel_from_si(indio_dev, scan_index); - bytes =3D ch->scan_type.storagebits / 8; - if (ch->scan_type.repeat > 1) - bytes *=3D ch->scan_type.repeat; + scan_type =3D &ch->scan_type; + bytes =3D scan_type->storagebits / 8; + + if (scan_type->repeat > 1) + bytes *=3D scan_type->repeat; + return bytes; } =20 @@ -1616,18 +1621,21 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct= iio_buffer *buffer, if (channels) { /* new magic */ for (i =3D 0; i < indio_dev->num_channels; i++) { + const struct iio_scan_type *scan_type; + if (channels[i].scan_index < 0) continue; =20 + scan_type =3D &channels[i].scan_type; + /* Verify that sample bits fit into storage */ - if (channels[i].scan_type.storagebits < - channels[i].scan_type.realbits + - channels[i].scan_type.shift) { + if (scan_type->storagebits < + scan_type->realbits + scan_type->shift) { dev_err(&indio_dev->dev, "Channel %d storagebits (%d) < shifted realbits (%d + %d)\n", - i, channels[i].scan_type.storagebits, - channels[i].scan_type.realbits, - channels[i].scan_type.shift); + i, scan_type->storagebits, + scan_type->realbits, + scan_type->shift); ret =3D -EINVAL; goto error_cleanup_dynamic; } --=20 2.45.1 From nobody Tue Dec 16 05:36:42 2025 Received: from mail-ot1-f50.google.com (mail-ot1-f50.google.com [209.85.210.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CCB3C17F509 for ; Thu, 30 May 2024 15:14:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717082075; cv=none; b=J/2kfNJ/qGRJNSvperLKUxP0fkEd+1e+dVgZb+dJU/52rmTG9Zj7ZbHF5NH4tlqhcaO7WlCR8eTE52VNIpvyxvoOazTw1UNhj4BhspGz+NmS5bwWDV1yaEDD8WixcHk/ZNyMKPUqaPBB7p0f8RgolpuCL8QQeYaLXbgckOtIltE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717082075; c=relaxed/simple; bh=D6UyROuZwAs3IFuLEy0yyT2LzcvHAh4TBhmxLHlH9HA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=LlWjgu3yxU6CpGyklW5TlpiwH7a0FfxCSz2hl0cNwCOUKMEEcFsGhzLw8i9itC+qhLTAtTvdMwxKKp5WgGDYsb+TCwcT6iIOtL+qzYAAOQthOR6WrvGz6RLduwOmV3mVwE05fySuZ4PLFONkSpW0Wx/NT2D1iSzIGsoHmAEwu30= 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=bY+E8qT+; arc=none smtp.client-ip=209.85.210.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="bY+E8qT+" Received: by mail-ot1-f50.google.com with SMTP id 46e09a7af769-6f8e5115cfbso632546a34.0 for ; Thu, 30 May 2024 08:14:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1717082071; x=1717686871; 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=ARkP3gEjLJuFmKmn7+LYv5VdtcnLNuF1mAXkD5YuF4Y=; b=bY+E8qT+ryhrTgcpIrK2qTufRWdUL2t/fv/k9QD5jq5c4qsOUe2PcoIryi0tSyqaWL 3NKJzro3MRtrEujaLacfP6OP9+LK9q6y8EqC3dzJ1DLUoSafpWjYELDn5enilNVJ+2ff vjd1f2QnOY+f2pLx7SL9nQ8Kc99r9wgCqVMhz2q4Sc9Hupb3+QxhL2lsTGyGa1FADUol 7sc3lP/+zP9uv2fBa3ms2HZa0BJ8p8FnOz8FYiziE6I0z72MN2y+bK6d/Hoew/6qptuF +hFKv8opPZAaWXvWkVNmNLxjXYazW5o7xR7NUSf8DUcNTu7Fi6pBdcsyL2wjgePmyuTL 7a7g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1717082071; x=1717686871; 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=ARkP3gEjLJuFmKmn7+LYv5VdtcnLNuF1mAXkD5YuF4Y=; b=kgEiS+iSP283OE7Vfn2NbWzLkJoCmpsG5gzV8tRYxYnRNc3ifKzILMm+J9JKNiFuJu fS4eP3vu3LwtHXWPnrqa36EF4YHaOTc9I3iX0CbX5UycJvcdeYeYsHYn4UmvtD6pUxgn dSYcaw/SR6HEmVxctbMOWjd30Nof8dic9CAHFkHJuA6rft41QZNM2vzAvTfplibHKDXY n4OwKFNas5B0X2hQgLPYuN0CAIzld5QYNEq5KJfQkvAHgl207Z9UKB9H5d2KGiEUnr4s XfTAaJf8m8DiciG2VEqoFT0tyVha2HXK/Kt61KHu3nJSoeTx1x/K3E9prkjTsb2dOcS1 wesg== X-Forwarded-Encrypted: i=1; AJvYcCUOgVFQqYNwByxl57jZ6FQ+xHXTxqx2GN/Eo2FpcMT9fxj22+5Z9SYKnN5QnV4WoZvJtbYgtCFG0nIickl4xAeQYkgzI7VD3TZCQtBC X-Gm-Message-State: AOJu0Yx1pt1TliXHynVkvOByRetVPSWKPi7siu8lWXh4gZD3ZOgtedUq AEq16i8xs/GmI9sdyO9bH4i5Er2T8doADn4kZDzk/0pXmd7+D8Cs+UrVe6v8MDIMoCTRVd/NSod HVaI= X-Google-Smtp-Source: AGHT+IH9DRwESXdM4dQ809LwnSFT5ogp09S5MU08X8hkaC+tPLhprQerdIbzSMHC3HwkZOfEGoWpJA== X-Received: by 2002:a9d:7f11:0:b0:6f5:a8a5:be6a with SMTP id 46e09a7af769-6f90aeccf55mr2717045a34.22.1717082070956; Thu, 30 May 2024 08:14: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-6f8d0de6314sm2803425a34.41.2024.05.30.08.14.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 May 2024 08:14:30 -0700 (PDT) From: David Lechner To: Jonathan Cameron Cc: David Lechner , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , Julien Stephan , Esteban Blanc , linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 3/5] iio: add support for multiple scan types per channel Date: Thu, 30 May 2024 10:14:10 -0500 Message-ID: <20240530-iio-add-support-for-multiple-scan-types-v3-3-cbc4acea2cfa@baylibre.com> X-Mailer: git-send-email 2.45.1 In-Reply-To: <20240530-iio-add-support-for-multiple-scan-types-v3-0-cbc4acea2cfa@baylibre.com> References: <20240530-iio-add-support-for-multiple-scan-types-v3-0-cbc4acea2cfa@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: quoted-printable This adds new fields to the iio_channel structure to support multiple scan types per channel. This is useful for devices that support multiple resolution modes or other modes that require different data formats of the raw data. To make use of this, drivers need to implement the new callback get_current_scan_type() to resolve the scan type for a given channel based on the current state of the driver. There is a new scan_type_ext field in the iio_channel structure that should be used to store the scan types for any channel that has more than one. There is also a new flag has_ext_scan_type that acts as a type discriminator for the scan_type/ext_scan_type union. A union is used so that we don't grow the size of the iio_channel structure and also makes it clear that scan_type and ext_scan_type are mutually exclusive. The buffer code is the only code in the IIO core code that is using the scan_type field. This patch updates the buffer code to use the new iio_channel_validate_scan_type() function to ensure it is returning the correct scan type for the current state of the device when reading the sysfs attributes. The buffer validation code is also update to validate any additional scan types that are set in the scan_type_ext field. Part of that code is refactored to a new function to avoid duplication. Some userspace tools may need to be updated to re-read the scan type after writing any other attribute. During testing, we noticed that we had to restart iiod to get it to re-read the scan type after enabling oversampling on the ad7380 driver. Signed-off-by: David Lechner Reviewed-by: Nuno Sa --- v3 changes: * change return type of get_current_scan_type callback to int * add error checks since iio_get_current_scan_type() can can now return an error v2 changes: * use union for scan_type and ext_scan_type/num_ext_scan_types * add has_ext_scan_type flag for type discrimination * add extra validation check for get_current_scan_type when has_ext_scan_type is set --- drivers/iio/industrialio-buffer.c | 101 ++++++++++++++++++++++++++++++----= ---- include/linux/iio/iio.h | 55 ++++++++++++++++++++- 2 files changed, 133 insertions(+), 23 deletions(-) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-b= uffer.c index 08103a9e77f7..0138b21b244f 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -365,9 +365,16 @@ static ssize_t iio_show_fixed_type(struct device *dev, struct device_attribute *attr, char *buf) { + struct iio_dev *indio_dev =3D dev_to_iio_dev(dev); struct iio_dev_attr *this_attr =3D to_iio_dev_attr(attr); - const struct iio_scan_type *scan_type =3D &this_attr->c->scan_type; - u8 type =3D scan_type->endianness; + const struct iio_scan_type *scan_type; + u8 type; + + scan_type =3D iio_get_current_scan_type(indio_dev, this_attr->c); + if (IS_ERR(scan_type)) + return PTR_ERR(scan_type); + + type =3D scan_type->endianness; =20 if (type =3D=3D IIO_CPU) { #ifdef __LITTLE_ENDIAN @@ -691,15 +698,18 @@ static ssize_t enable_show(struct device *dev, struct= device_attribute *attr, return sysfs_emit(buf, "%d\n", iio_buffer_is_active(buffer)); } =20 -static unsigned int iio_storage_bytes_for_si(struct iio_dev *indio_dev, - unsigned int scan_index) +static int iio_storage_bytes_for_si(struct iio_dev *indio_dev, + unsigned int scan_index) { const struct iio_chan_spec *ch; const struct iio_scan_type *scan_type; unsigned int bytes; =20 ch =3D iio_find_channel_from_si(indio_dev, scan_index); - scan_type =3D &ch->scan_type; + scan_type =3D iio_get_current_scan_type(indio_dev, ch); + if (IS_ERR(scan_type)) + return PTR_ERR(scan_type); + bytes =3D scan_type->storagebits / 8; =20 if (scan_type->repeat > 1) @@ -708,7 +718,7 @@ static unsigned int iio_storage_bytes_for_si(struct iio= _dev *indio_dev, return bytes; } =20 -static unsigned int iio_storage_bytes_for_timestamp(struct iio_dev *indio_= dev) +static int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev) { struct iio_dev_opaque *iio_dev_opaque =3D to_iio_dev_opaque(indio_dev); =20 @@ -726,6 +736,9 @@ static int iio_compute_scan_bytes(struct iio_dev *indio= _dev, for_each_set_bit(i, mask, indio_dev->masklength) { length =3D iio_storage_bytes_for_si(indio_dev, i); + if (length < 0) + return length; + bytes =3D ALIGN(bytes, length); bytes +=3D length; largest =3D max(largest, length); @@ -733,6 +746,9 @@ static int iio_compute_scan_bytes(struct iio_dev *indio= _dev, =20 if (timestamp) { length =3D iio_storage_bytes_for_timestamp(indio_dev); + if (length < 0) + return length; + bytes =3D ALIGN(bytes, length); bytes +=3D length; largest =3D max(largest, length); @@ -1012,14 +1028,22 @@ static int iio_buffer_update_demux(struct iio_dev *= indio_dev, indio_dev->masklength, in_ind + 1); while (in_ind !=3D out_ind) { - length =3D iio_storage_bytes_for_si(indio_dev, in_ind); + ret =3D iio_storage_bytes_for_si(indio_dev, in_ind); + if (ret < 0) + goto error_clear_mux_table; + + length =3D ret; /* Make sure we are aligned */ in_loc =3D roundup(in_loc, length) + length; in_ind =3D find_next_bit(indio_dev->active_scan_mask, indio_dev->masklength, in_ind + 1); } - length =3D iio_storage_bytes_for_si(indio_dev, in_ind); + ret =3D iio_storage_bytes_for_si(indio_dev, in_ind); + if (ret < 0) + goto error_clear_mux_table; + + length =3D ret; out_loc =3D roundup(out_loc, length); in_loc =3D roundup(in_loc, length); ret =3D iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length); @@ -1030,7 +1054,11 @@ static int iio_buffer_update_demux(struct iio_dev *i= ndio_dev, } /* Relies on scan_timestamp being last */ if (buffer->scan_timestamp) { - length =3D iio_storage_bytes_for_timestamp(indio_dev); + ret =3D iio_storage_bytes_for_timestamp(indio_dev); + if (ret < 0) + goto error_clear_mux_table; + + length =3D ret; out_loc =3D roundup(out_loc, length); in_loc =3D roundup(in_loc, length); ret =3D iio_buffer_add_demux(buffer, &p, in_loc, out_loc, length); @@ -1597,6 +1625,22 @@ static long iio_device_buffer_ioctl(struct iio_dev *= indio_dev, struct file *filp } } =20 +static int iio_channel_validate_scan_type(struct device *dev, int ch, + const struct iio_scan_type *scan_type) +{ + /* Verify that sample bits fit into storage */ + if (scan_type->storagebits < scan_type->realbits + scan_type->shift) { + dev_err(dev, + "Channel %d storagebits (%d) < shifted realbits (%d + %d)\n", + ch, scan_type->storagebits, + scan_type->realbits, + scan_type->shift); + return -EINVAL; + } + + return 0; +} + static int __iio_buffer_alloc_sysfs_and_mask(struct iio_buffer *buffer, struct iio_dev *indio_dev, int index) @@ -1626,18 +1670,33 @@ static int __iio_buffer_alloc_sysfs_and_mask(struct= iio_buffer *buffer, if (channels[i].scan_index < 0) continue; =20 - scan_type =3D &channels[i].scan_type; - - /* Verify that sample bits fit into storage */ - if (scan_type->storagebits < - scan_type->realbits + scan_type->shift) { - dev_err(&indio_dev->dev, - "Channel %d storagebits (%d) < shifted realbits (%d + %d)\n", - i, scan_type->storagebits, - scan_type->realbits, - scan_type->shift); - ret =3D -EINVAL; - goto error_cleanup_dynamic; + if (channels[i].has_ext_scan_type) { + int j; + + /* + * get_current_scan_type is required when using + * extended scan types. + */ + if (!indio_dev->info->get_current_scan_type) { + ret =3D -EINVAL; + goto error_cleanup_dynamic; + } + + for (j =3D 0; j < channels[i].num_ext_scan_type; j++) { + scan_type =3D &channels[i].ext_scan_type[j]; + + ret =3D iio_channel_validate_scan_type( + &indio_dev->dev, i, scan_type); + if (ret) + goto error_cleanup_dynamic; + } + } else { + scan_type =3D &channels[i].scan_type; + + ret =3D iio_channel_validate_scan_type( + &indio_dev->dev, i, scan_type); + if (ret) + goto error_cleanup_dynamic; } =20 ret =3D iio_buffer_add_channel_sysfs(indio_dev, buffer, diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index 19de573a944a..894309294182 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -204,7 +204,13 @@ struct iio_scan_type { * @address: Driver specific identifier. * @scan_index: Monotonic index to give ordering in scans when read * from a buffer. - * @scan_type: struct describing the scan type + * @scan_type: struct describing the scan type - mutually exclusive + * with ext_scan_type. + * @ext_scan_type: Used in rare cases where there is more than one scan + * format for a channel. When this is used, the flag + * has_ext_scan_type must be set and the driver must + * implement get_current_scan_type in struct iio_info. + * @num_ext_scan_type: Number of elements in ext_scan_type. * @info_mask_separate: What information is to be exported that is specifi= c to * this channel. * @info_mask_separate_available: What availability information is to be @@ -248,6 +254,7 @@ struct iio_scan_type { * attributes but not for event codes. * @output: Channel is output. * @differential: Channel is differential. + * @has_ext_scan_type: True if ext_scan_type is used instead of scan_type. */ struct iio_chan_spec { enum iio_chan_type type; @@ -255,7 +262,13 @@ struct iio_chan_spec { int channel2; unsigned long address; int scan_index; - struct iio_scan_type scan_type; + union { + struct iio_scan_type scan_type; + struct { + const struct iio_scan_type *ext_scan_type; + unsigned int num_ext_scan_type; + }; + }; long info_mask_separate; long info_mask_separate_available; long info_mask_shared_by_type; @@ -273,6 +286,7 @@ struct iio_chan_spec { unsigned indexed:1; unsigned output:1; unsigned differential:1; + unsigned has_ext_scan_type:1; }; =20 =20 @@ -435,6 +449,9 @@ struct iio_trigger; /* forward declaration */ * for better event identification. * @validate_trigger: function to validate the trigger when the * current trigger gets changed. + * @get_current_scan_type: must be implemented by drivers that use ext_sca= n_type + * in the channel spec to return the index of the currently + * active ext_scan type for a channel. * @update_scan_mode: function to configure device and scan buffer when * channels have changed * @debugfs_reg_access: function to read or write register value of device @@ -519,6 +536,8 @@ struct iio_info { =20 int (*validate_trigger)(struct iio_dev *indio_dev, struct iio_trigger *trig); + int (*get_current_scan_type)(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan); int (*update_scan_mode)(struct iio_dev *indio_dev, const unsigned long *scan_mask); int (*debugfs_reg_access)(struct iio_dev *indio_dev, @@ -804,6 +823,38 @@ static inline bool iio_read_acpi_mount_matrix(struct d= evice *dev, } #endif =20 +/** + * iio_get_current_scan_type - Get the current scan type for a channel + * @indio_dev: the IIO device to get the scan type for + * @chan: the channel to get the scan type for + * + * Most devices only have one scan type per channel and can just access it + * directly without calling this function. Core IIO code and drivers that + * implement ext_scan_type in the channel spec should use this function to + * get the current scan type for a channel. + * + * Returns: the current scan type for the channel or error. + */ +static inline const struct iio_scan_type +*iio_get_current_scan_type(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + int ret; + + if (chan->has_ext_scan_type) { + ret =3D indio_dev->info->get_current_scan_type(indio_dev, chan); + if (ret < 0) + return ERR_PTR(ret); + + if (ret >=3D chan->num_ext_scan_type) + return ERR_PTR(-EINVAL); + + return &chan->ext_scan_type[ret]; + } + + return &chan->scan_type; +} + ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals= ); =20 int iio_str_to_fixpoint(const char *str, int fract_mult, int *integer, --=20 2.45.1 From nobody Tue Dec 16 05:36:42 2025 Received: from mail-oi1-f170.google.com (mail-oi1-f170.google.com [209.85.167.170]) (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 BEDFB17F502 for ; Thu, 30 May 2024 15:14:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717082074; cv=none; b=AuXm9Mb5Cmuw6Wk1JC1Rh7m8xXBuiOlMTpZXvioGgJdodt7CHcEnUMwTOljFS3wtWhA6dOho/R0qVHrIa6TTTZwsXgcqFW4Q2llgJ8YUo8QYrOZ78w+LTsODQ5nS8xYxJAPpxdjEy5paNh0gUj8VekJu9WsCJ0xMjK238ODned8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717082074; c=relaxed/simple; bh=Xoa77mLrBZvVx2uEYxjsfkSdZpI7/EICencdXSVB99M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=AITT79+JtX+8c9es1scPc5qsi7ZbKZoCkSOXK+J/GABSoNfVzUSPHzAWVLPo3nyYbSxz5ISdfM44HQt8Jsfoq6/Ll8XMZxsdNGMLVQJYS6nVobYd9aQ6aXxHJvD1rIU89d+r/K7/7dIKF+Ip93ZFHtZHLw0ZiN6GTpLT6MLR+sw= 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=MG+qVzYY; arc=none smtp.client-ip=209.85.167.170 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="MG+qVzYY" Received: by mail-oi1-f170.google.com with SMTP id 5614622812f47-3d1bcad2ceeso543213b6e.0 for ; Thu, 30 May 2024 08:14:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1717082072; x=1717686872; 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=6/68b/SzzuRQNI8g1rtkBQU2w+J/r1CLstX409XeBLE=; b=MG+qVzYYuGx6G7CBzoctIegCW9hgw2hIxGIQjuqpKWsAPGOwQW9NH5XvYkCu4qG+Wf pc4yduUIq5RgKQ2eo3Z+QeDDt6yVBNiAEn/8o1eL6ORMIseOXDxiXP43/y2DUkoF4bM2 EXfMCgnkhFRyhivOLTpfwVvXhagbkJqCTUbJ4FHvBmKJAou7eRPek32SZBC9MCqtSayV ki5uvyS0HqZrX1yGiQTD5kWr/JJZGNhnl/HWC8vRtwLmHi4jStnwkFyOR2+uBOoiiOlF qFoGEzwLKo32wSO/OnFaf6COZC757Z/8U66lJfVKLL2DPMdS20hsg3uG8xJmkvK0rKb7 TRCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1717082072; x=1717686872; 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=6/68b/SzzuRQNI8g1rtkBQU2w+J/r1CLstX409XeBLE=; b=pfvd3qM5+a/yrY7Tj3YyrCufjtTSLWNwgOXIqSyRf5OvkE8J3K578PF3s/pu7O+9nL KaKAg3kLI9CtDmgLFUUgOJ5kyS3aTWuEehZT3Ngasogr8GkS5HZlrvrivfH06VKB6kAu LGTwNm4yZMKLXaFG7POc0onPTBm9wjXJKnU7C4vAznv9Ke/5GeXLemylTvFqMXFfDTkd nGwM8bB7DYOCoCNmVnKQp/tfTuE65TJskei0w8t8J80KOpcjqg3gjipzF/I+M92VRaxP LnrnH1FZKz+aSawjqlyKJo+7WsFJ0BNEN9I+s6DrMvHoumw59NZvC9RVd8QfDeMDaxva ybXQ== X-Forwarded-Encrypted: i=1; AJvYcCV0V9XAJPdKNxiWfcYdkNc93EqAmXUlPWqzEjV3E3PpfGj9dNqtcKALB8ZsflBEVo1Q3AJQpjoc20Lqo5O0epHoI/SRTn4+MXyK7R02 X-Gm-Message-State: AOJu0YzQFZt8uK3yCr6ryxZKnXceDh104/7B66N2KvKvErypcfyznMCR Koo5q5S3ZPz3eUM2Zi3CDGQsalgx5n8xxOsBUPqm19ruBI3MOc1ZiBkhQUNDgqQ= X-Google-Smtp-Source: AGHT+IHL6d3EZT2jTd7bfKSK4pIy4e6GYOcsZNBh9G51hqhfnpXKdBnKgN9f0yHfcfUpHGZbi+jj2g== X-Received: by 2002:a05:6808:2013:b0:3d1:e059:feb2 with SMTP id 5614622812f47-3d1e05a02d2mr388238b6e.20.1717082071844; Thu, 30 May 2024 08:14: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-6f8d0de6314sm2803425a34.41.2024.05.30.08.14.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 May 2024 08:14:31 -0700 (PDT) From: David Lechner To: Jonathan Cameron Cc: David Lechner , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , Julien Stephan , Esteban Blanc , linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 4/5] iio: adc: ad7380: use spi_optimize_message() Date: Thu, 30 May 2024 10:14:11 -0500 Message-ID: <20240530-iio-add-support-for-multiple-scan-types-v3-4-cbc4acea2cfa@baylibre.com> X-Mailer: git-send-email 2.45.1 In-Reply-To: <20240530-iio-add-support-for-multiple-scan-types-v3-0-cbc4acea2cfa@baylibre.com> References: <20240530-iio-add-support-for-multiple-scan-types-v3-0-cbc4acea2cfa@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: quoted-printable This changes the AD7380 to use spi_optimize_message() to optimize buffered reads. This changes both direct reads and buffered reads to use the same spi_message. This has some (welcome) side effects. The first is that in buffered reads, the timestamp will now correspond to the same sample rather than the previous sample. The second is that direct reads now use the same SPI bus speed as buffered reads. This reduces CPU usage of the IRQ thread from around 25% to around 20% when sampling at 10 kHz on a ZedBoard. Signed-off-by: David Lechner Reviewed-by: Nuno Sa --- v3 changes: * New patch for this series * A similar patch was sent at [1]. [1]: https://lore.kernel.org/linux-iio/20240219-mainline-spi-precook-messag= e-v2-5-4a762c6701b9@baylibre.com/ --- drivers/iio/adc/ad7380.c | 70 ++++++++++++++++++++++++++------------------= ---- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c index 6b0b1b0be363..006496807de9 100644 --- a/drivers/iio/adc/ad7380.c +++ b/drivers/iio/adc/ad7380.c @@ -232,6 +232,9 @@ struct ad7380_state { struct regmap *regmap; unsigned int vref_mv; unsigned int vcm_mv[MAX_NUM_CHANNELS]; + /* xfers, message an buffer for reading sample data */ + struct spi_transfer xfer[2]; + struct spi_message msg; /* * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. @@ -331,15 +334,9 @@ static irqreturn_t ad7380_trigger_handler(int irq, voi= d *p) struct iio_poll_func *pf =3D p; struct iio_dev *indio_dev =3D pf->indio_dev; struct ad7380_state *st =3D iio_priv(indio_dev); - struct spi_transfer xfer =3D { - .bits_per_word =3D st->chip_info->channels[0].scan_type.realbits, - .len =3D (st->chip_info->num_channels - 1) * - BITS_TO_BYTES(st->chip_info->channels->scan_type.storagebits), - .rx_buf =3D st->scan_data.raw, - }; int ret; =20 - ret =3D spi_sync_transfer(st->spi, &xfer, 1); + ret =3D spi_sync(st->spi, &st->msg); if (ret) goto out; =20 @@ -355,33 +352,9 @@ static irqreturn_t ad7380_trigger_handler(int irq, voi= d *p) static int ad7380_read_direct(struct ad7380_state *st, struct iio_chan_spec const *chan, int *val) { - struct spi_transfer xfers[] =3D { - /* toggle CS (no data xfer) to trigger a conversion */ - { - .speed_hz =3D AD7380_REG_WR_SPEED_HZ, - .bits_per_word =3D chan->scan_type.realbits, - .delay =3D { - .value =3D T_CONVERT_NS, - .unit =3D SPI_DELAY_UNIT_NSECS, - }, - .cs_change =3D 1, - .cs_change_delay =3D { - .value =3D st->chip_info->timing_specs->t_csh_ns, - .unit =3D SPI_DELAY_UNIT_NSECS, - }, - }, - /* then read all channels */ - { - .speed_hz =3D AD7380_REG_WR_SPEED_HZ, - .bits_per_word =3D chan->scan_type.realbits, - .rx_buf =3D st->scan_data.raw, - .len =3D (st->chip_info->num_channels - 1) * - ((chan->scan_type.storagebits > 16) ? 4 : 2), - }, - }; int ret; =20 - ret =3D spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers)); + ret =3D spi_sync(st->spi, &st->msg); if (ret < 0) return ret; =20 @@ -464,6 +437,11 @@ static void ad7380_regulator_disable(void *p) regulator_disable(p); } =20 +static void ad7380_unoptimize_msg(void *msg) +{ + spi_unoptimize_message(msg); +} + static int ad7380_probe(struct spi_device *spi) { struct iio_dev *indio_dev; @@ -552,6 +530,34 @@ static int ad7380_probe(struct spi_device *spi) return dev_err_probe(&spi->dev, PTR_ERR(st->regmap), "failed to allocate register map\n"); =20 + /* + * Setting up a low latency read for getting sample data. Used for both + * direct read an triggered buffer. + */ + + /* toggle CS (no data xfer) to trigger a conversion */ + st->xfer[0].delay.value =3D T_CONVERT_NS; + st->xfer[0].delay.unit =3D SPI_DELAY_UNIT_NSECS; + st->xfer[0].cs_change =3D 1; + st->xfer[0].cs_change_delay.value =3D st->chip_info->timing_specs->t_csh_= ns; + st->xfer[0].cs_change_delay.unit =3D SPI_DELAY_UNIT_NSECS; + + /* then do a second xfer to read the data */ + st->xfer[1].bits_per_word =3D st->chip_info->channels[0].scan_type.realbi= ts; + st->xfer[1].rx_buf =3D st->scan_data.raw; + st->xfer[1].len =3D BITS_TO_BYTES(st->chip_info->channels[0].scan_type.st= oragebits) + * (st->chip_info->num_channels - 1); + + spi_message_init_with_transfers(&st->msg, st->xfer, ARRAY_SIZE(st->xfer)); + + ret =3D spi_optimize_message(st->spi, &st->msg); + if (ret) + return ret; + + ret =3D devm_add_action_or_reset(&spi->dev, ad7380_unoptimize_msg, &st->m= sg); + if (ret) + return ret; + indio_dev->channels =3D st->chip_info->channels; indio_dev->num_channels =3D st->chip_info->num_channels; indio_dev->name =3D st->chip_info->name; --=20 2.45.1 From nobody Tue Dec 16 05:36:42 2025 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 D1365182D04 for ; Thu, 30 May 2024 15:14:33 +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=1717082076; cv=none; b=jn+7JgND/szsmYIB+U4o4yKUYt3DoMqccnDtTsD8Ne4v7VNj5B8FDUlghaOXIFHgPftOTYx4RHc2jBmY/mAgGekIkVYIIASUsKwE0Rabuee1iAASWb7ihccntgJIq0WX+8RMGBqr4tPeZDpN53BvYSguMOpr4aLdLif5BH9gF90= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717082076; c=relaxed/simple; bh=y1tnKl81vB9sKRsENdbw7mPcxKNdOM0WJoCUmHL48lc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=EYubvd6geC2aQ5D1E39YuerllIiJb+9gvMLPTHAEVHT+Wr5irhA2NZxa1SUFDc/Stlbjf+/AozzJRyFcvOb4HHPtvt73Lrpw+vZF37kB2iJOTVuI9+6I8X5D81y7Ibmdp0jI1xfEvgsq8AqTozrtL1RcEwpl613gK7Q1rqnwwvA= 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=EqTAk0HD; 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="EqTAk0HD" Received: by mail-ot1-f46.google.com with SMTP id 46e09a7af769-6f8d0a00a35so38728a34.2 for ; Thu, 30 May 2024 08:14:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1717082073; x=1717686873; 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=1uS+7HdM7gPQMh4nz20sm9gmVe3Fbi635e2p6q2SK0c=; b=EqTAk0HDMiog2fdsuYym9oGCwrpLxKI3LnbCXyVjMdINLMz5CAb0lStsSrs1cMCPDQ Vx63zYMiksotUfdvd9YG5q5c1isJUH/x6cpB2OgIdg+UBHSq7nmdea/PqtFHrgNNeZ0A LcZp/vCcS7sOkIkJyt/rF8Cy8ilOCHaBvCxLMjQKUscOaKHzslOo8/lm7bht8O3mV2Ea cI1MjCVF2qkyje/VNXEC+jRapu2twigya0amiEgFZHIiyrREpNRvllN6htoBBoGx99fY Y6mQQl3VIfpW9cFlg5C1tg+bGnike9PpIUFItt6VzCsGdBQUgiByB8YHGfz8A5MEzOKG MxEw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1717082073; x=1717686873; 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=1uS+7HdM7gPQMh4nz20sm9gmVe3Fbi635e2p6q2SK0c=; b=NYDB5Nxe3i5J0bFkihaEF1slinejr6dpyX/tMBUms31KkCBeAlO919whSMUGcVS0C1 iWDD3pHYJ0NNCtH3I9dW0DMS40eiSZdGsW2BTcmjTmzxVO6Ow7Y8cJka1nJp3FRYuPkr 6tUp1p572kHvyz1c+eFCtkaUeI5Ya3Hy/YVUq+hysiZ5qQ90Upu/ODFhoghJmAAIT2zj iXXauMQNXsikySDDcQzesh7hR5kjPL71Idx3246/vSatZhY28Sye1aRP2FFJTJs1wK6k Jynj9Gfq2NROblWhQVfMKOvGaMIx6cpPo7rrlroUd4gbn+xJXutHoXGiVilPluG73rrY SiNg== X-Forwarded-Encrypted: i=1; AJvYcCUfhuVCSfq99r3cUdnIvbfmQZ7SmYAMm0A9PWa2QVC2QitCRrtXyN4dKUwGzX6gPmnC7wxltxfAFik3xFYFhqJHszjeZTpMSgKz/Jmj X-Gm-Message-State: AOJu0Yx9z5879J/Y7yZUbWnP7s8Q7Qmi8Vkv3qomJqWWr5dBMi8KndXT 8Sf+oq6Kp+nfCj8Lg0hrL+glvhWWeRVWbREZvR1IoJlWeUyDN8gLv12D42pxJbg= X-Google-Smtp-Source: AGHT+IG/EEmzr4DFqTUvQIOD9G+C1icZCdRmwofW65huY55CffB9nwBvBXn27P+t/Nh+L9qOth1PgA== X-Received: by 2002:a9d:6d04:0:b0:6f8:f6d4:ba31 with SMTP id 46e09a7af769-6f90aeb073dmr2771912a34.12.1717082072779; Thu, 30 May 2024 08:14: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-6f8d0de6314sm2803425a34.41.2024.05.30.08.14.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 May 2024 08:14:32 -0700 (PDT) From: David Lechner To: Jonathan Cameron Cc: David Lechner , Michael Hennerich , =?utf-8?q?Nuno_S=C3=A1?= , Julien Stephan , Esteban Blanc , linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 5/5] iio: adc: ad7380: add oversampling support Date: Thu, 30 May 2024 10:14:12 -0500 Message-ID: <20240530-iio-add-support-for-multiple-scan-types-v3-5-cbc4acea2cfa@baylibre.com> X-Mailer: git-send-email 2.45.1 In-Reply-To: <20240530-iio-add-support-for-multiple-scan-types-v3-0-cbc4acea2cfa@baylibre.com> References: <20240530-iio-add-support-for-multiple-scan-types-v3-0-cbc4acea2cfa@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: quoted-printable From: Julien Stephan ad7380x(-4) parts are able to do oversampling to increase accuracy. This chips supports a normal oversampling mode and a rolling mode and also allows enabling and disabling extra resolution bits when oversampling is enabled. We have intentionally left out the rolling mode for now as there is not a compelling use case for it. User can process a captured data buffer to get the same effect. We are also currently not supporting changing the oversampling mode independently of the resolution bits. The resolution boost feature can only be enabled when oversampling is enabled and oversampling is not as useful without the resolution boost. So for now we consider the features tightly coupled. When oversampling is enabled, the resolution boost is enabled and when oversampling is disabled, the resolution boost is disabled. Since the resolution boost feature causes 16-bit chips to now have 18-bit data which means the storagebits has to change from 16 to 32 bits, we use the new ext_scan_type feature to allow changing the scan_type at runtime based on if the resolution boost is enabled or not. SPI message optimization has to be moved since now some of the xfer parameters change based on the resolution boost mode. A few neighboring comments are also fixed up while we are touching this code. Signed-off-by: Julien Stephan Co-developed-by: David Lechner Signed-off-by: David Lechner Reviewed-by: Nuno Sa --- v3 changes: * This is a combination/rework of [1] from v1 of this series plus [2] and [3] from v6 of the ad7380 introductory series. * Fixed comment lengths to ~80 characters. * Renamed osr_check function. * Resolution boost is no longer a separate feature from oversampling. * Convert scan_data to u8[] and use ALIGN to ensure correct size. * Reworked ext_scan_type to accommodate other revisions from this series. [1]: https://lore.kernel.org/linux-iio/20240507-iio-add-support-for-multipl= e-scan-types-v1-4-95ac33ee51e9@baylibre.com/ [2]: https://lore.kernel.org/linux-iio/20240501-adding-new-ad738x-driver-v6= -8-3c0741154728@baylibre.com/ [3]: https://lore.kernel.org/linux-iio/20240501-adding-new-ad738x-driver-v6= -10-3c0741154728@baylibre.com/ --- drivers/iio/adc/ad7380.c | 305 ++++++++++++++++++++++++++++++++++++++++---= ---- 1 file changed, 260 insertions(+), 45 deletions(-) diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c index 006496807de9..2f9f871a0ae0 100644 --- a/drivers/iio/adc/ad7380.c +++ b/drivers/iio/adc/ad7380.c @@ -13,6 +13,7 @@ * ad7383/4-4 : https://www.analog.com/media/en/technical-documentation/da= ta-sheets/ad7383-4-ad7384-4.pdf */ =20 +#include #include #include #include @@ -68,6 +69,9 @@ #define AD7380_ALERT_HIGH_TH GENMASK(11, 0) =20 #define T_CONVERT_NS 190 /* conversion time */ +#define T_CONVERT_0_NS 10 /* 1st conversion start time (oversampling) */ +#define T_CONVERT_X_NS 500 /* xth conversion start time (oversampling) */ + struct ad7380_timing_specs { const unsigned int t_csh_ns; /* CS minimum high time */ }; @@ -82,22 +86,59 @@ struct ad7380_chip_info { const struct ad7380_timing_specs *timing_specs; }; =20 +enum { + AD7380_SCAN_TYPE_NORMAL, + AD7380_SCAN_TYPE_RESOLUTION_BOOST, +}; + +/* Extended scan types for 14-bit chips. */ +static const struct iio_scan_type ad7380_scan_type_14[] =3D { + [AD7380_SCAN_TYPE_NORMAL] =3D { + .sign =3D 's', + .realbits =3D 14, + .storagebits =3D 16, + .endianness =3D IIO_CPU + }, + [AD7380_SCAN_TYPE_RESOLUTION_BOOST] =3D { + .sign =3D 's', + .realbits =3D 16, + .storagebits =3D 16, + .endianness =3D IIO_CPU + }, +}; + +/* Extended scan types for 16-bit chips. */ +static const struct iio_scan_type ad7380_scan_type_16[] =3D { + [AD7380_SCAN_TYPE_NORMAL] =3D { + .sign =3D 's', + .realbits =3D 16, + .storagebits =3D 16, + .endianness =3D IIO_CPU + }, + [AD7380_SCAN_TYPE_RESOLUTION_BOOST] =3D { + .sign =3D 's', + .realbits =3D 18, + .storagebits =3D 32, + .endianness =3D IIO_CPU + }, +}; + #define AD7380_CHANNEL(index, bits, diff) { \ .type =3D IIO_VOLTAGE, \ .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | \ ((diff) ? 0 : BIT(IIO_CHAN_INFO_OFFSET)), \ - .info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_type =3D BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ + .info_mask_shared_by_type_available =3D \ + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \ .indexed =3D 1, \ .differential =3D (diff), \ .channel =3D (diff) ? (2 * (index)) : (index), \ .channel2 =3D (diff) ? (2 * (index) + 1) : 0, \ .scan_index =3D (index), \ - .scan_type =3D { \ - .sign =3D 's', \ - .realbits =3D (bits), \ - .storagebits =3D 16, \ - .endianness =3D IIO_CPU, \ - }, \ + .has_ext_scan_type =3D 1, \ + .ext_scan_type =3D ad7380_scan_type_##bits, \ + .num_ext_scan_type =3D ARRAY_SIZE(ad7380_scan_type_##bits),\ } =20 #define DEFINE_AD7380_2_CHANNEL(name, bits, diff) \ @@ -154,6 +195,15 @@ static const struct ad7380_timing_specs ad7380_4_timin= g =3D { .t_csh_ns =3D 20, }; =20 +/* + * Available oversampling ratios. The indices correspond with the bit value + * expected by the chip. The available ratios depend on the averaging mod= e, + * only normal averaging is supported for now. + */ +static const int ad7380_oversampling_ratios[] =3D { + 1, 2, 4, 8, 16, 32, +}; + static const struct ad7380_chip_info ad7380_chip_info =3D { .name =3D "ad7380", .channels =3D ad7380_channels, @@ -230,23 +280,23 @@ struct ad7380_state { const struct ad7380_chip_info *chip_info; struct spi_device *spi; struct regmap *regmap; + unsigned int oversampling_ratio; + bool resolution_boost_enabled; unsigned int vref_mv; unsigned int vcm_mv[MAX_NUM_CHANNELS]; /* xfers, message an buffer for reading sample data */ struct spi_transfer xfer[2]; struct spi_message msg; /* - * DMA (thus cache coherency maintenance) requires the - * transfer buffers to live in their own cache lines. - * Make the buffer large enough for MAX_NUM_CHANNELS 16-bit samples and o= ne 64-bit - * aligned 64 bit timestamp. - * As MAX_NUM_CHANNELS is 4 the layout of the structure is the same for a= ll parts + * DMA (thus cache coherency maintenance) requires the transfer buffers + * to live in their own cache lines. + * + * Make the buffer large enough for MAX_NUM_CHANNELS 32-bit samples and + * one 64-bit aligned 64-bit timestamp. */ - struct { - u16 raw[MAX_NUM_CHANNELS]; - - s64 ts __aligned(8); - } scan_data __aligned(IIO_DMA_MINALIGN); + u8 scan_data[ALIGN(MAX_NUM_CHANNELS * sizeof(u32), sizeof(s64)) + + sizeof(s64)] __aligned(IIO_DMA_MINALIGN); + /* buffers for reading/writing registers */ u16 tx; u16 rx; }; @@ -329,6 +379,69 @@ static int ad7380_debugfs_reg_access(struct iio_dev *i= ndio_dev, u32 reg, unreachable(); } =20 +/** + * ad7380_update_xfers - update the SPI transfers base on the current scan= type + * @indio_dev: IIO device structure + * @chan: IIO channel + */ +static void ad7380_update_xfers(struct ad7380_state *st, + const struct iio_scan_type *scan_type) +{ + /* + * First xfer only triggers conversion and has to be long enough for + * all conversions to complete, which can be multiple conversion in the + * case of oversampling. Technically T_CONVERT_X_NS is lower for some + * chips, but we use the maximum value for simplicity for now. + */ + if (st->oversampling_ratio > 1) + st->xfer[0].delay.value =3D T_CONVERT_0_NS + T_CONVERT_X_NS * + (st->oversampling_ratio - 1); + else + st->xfer[0].delay.value =3D T_CONVERT_NS; + + st->xfer[0].delay.unit =3D SPI_DELAY_UNIT_NSECS; + + /* + * Second xfer reads all channels. Data size depends on if resolution + * boost is enabled or not. + */ + st->xfer[1].bits_per_word =3D scan_type->realbits; + st->xfer[1].len =3D BITS_TO_BYTES(scan_type->storagebits) * + (st->chip_info->num_channels - 1); +} + +static int ad7380_triggered_buffer_preenable(struct iio_dev *indio_dev) +{ + struct ad7380_state *st =3D iio_priv(indio_dev); + const struct iio_scan_type *scan_type; + + /* + * Currently, we always read all channels at the same time. The scan_type + * is the same for all channels, so we just pass the first channel. + */ + scan_type =3D iio_get_current_scan_type(indio_dev, &indio_dev->channels[0= ]); + if (IS_ERR(scan_type)) + return PTR_ERR(scan_type); + + ad7380_update_xfers(st, scan_type); + + return spi_optimize_message(st->spi, &st->msg); +} + +static int ad7380_triggered_buffer_postdisable(struct iio_dev *indio_dev) +{ + struct ad7380_state *st =3D iio_priv(indio_dev); + + spi_unoptimize_message(&st->msg); + + return 0; +} + +static const struct iio_buffer_setup_ops ad7380_buffer_setup_ops =3D { + .preenable =3D ad7380_triggered_buffer_preenable, + .postdisable =3D ad7380_triggered_buffer_postdisable, +}; + static irqreturn_t ad7380_trigger_handler(int irq, void *p) { struct iio_poll_func *pf =3D p; @@ -349,17 +462,23 @@ static irqreturn_t ad7380_trigger_handler(int irq, vo= id *p) return IRQ_HANDLED; } =20 -static int ad7380_read_direct(struct ad7380_state *st, - struct iio_chan_spec const *chan, int *val) +static int ad7380_read_direct(struct ad7380_state *st, unsigned int scan_i= ndex, + const struct iio_scan_type *scan_type, int *val) { int ret; =20 + ad7380_update_xfers(st, scan_type); + ret =3D spi_sync(st->spi, &st->msg); if (ret < 0) return ret; =20 - *val =3D sign_extend32(st->scan_data.raw[chan->scan_index], - chan->scan_type.realbits - 1); + if (scan_type->storagebits > 16) + *val =3D sign_extend32(*(u32 *)(st->scan_data + 4 * scan_index), + scan_type->realbits - 1); + else + *val =3D sign_extend32(*(u16 *)(st->scan_data + 2 * scan_index), + scan_type->realbits - 1); =20 return IIO_VAL_INT; } @@ -369,11 +488,18 @@ static int ad7380_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long info) { struct ad7380_state *st =3D iio_priv(indio_dev); + const struct iio_scan_type *scan_type; + + scan_type =3D iio_get_current_scan_type(indio_dev, chan); + + if (IS_ERR(scan_type)) + return PTR_ERR(scan_type); =20 switch (info) { case IIO_CHAN_INFO_RAW: iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { - return ad7380_read_direct(st, chan, val); + return ad7380_read_direct(st, chan->scan_index, + scan_type, val); } unreachable(); case IIO_CHAN_INFO_SCALE: @@ -384,7 +510,7 @@ static int ad7380_read_raw(struct iio_dev *indio_dev, * where N is the ADC resolution (i.e realbits) */ *val =3D st->vref_mv; - *val2 =3D chan->scan_type.realbits - chan->differential; + *val2 =3D scan_type->realbits - chan->differential; =20 return IIO_VAL_FRACTIONAL_LOG2; case IIO_CHAN_INFO_OFFSET: @@ -392,17 +518,118 @@ static int ad7380_read_raw(struct iio_dev *indio_dev, * According to IIO ABI, offset is applied before scale, * so offset is: vcm_mv / scale */ - *val =3D st->vcm_mv[chan->channel] * (1 << chan->scan_type.realbits) + *val =3D st->vcm_mv[chan->channel] * (1 << scan_type->realbits) / st->vref_mv; =20 return IIO_VAL_INT; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + *val =3D st->oversampling_ratio; + + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int ad7380_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + *vals =3D ad7380_oversampling_ratios; + *length =3D ARRAY_SIZE(ad7380_oversampling_ratios); + *type =3D IIO_VAL_INT; + + return IIO_AVAIL_LIST; default: return -EINVAL; } } =20 +/** + * ad7380_osr_to_regval - convert ratio to OSR register value + * @ratio: ratio to check + * + * Check if ratio is present in the list of available ratios and return the + * corresponding value that needs to be written to the register to select = that + * ratio. + * + * Returns: register value (0 to 7) or -EINVAL if there is not an exact ma= tch + */ +static int ad7380_osr_to_regval(int ratio) +{ + int i; + + for (i =3D 0; i < ARRAY_SIZE(ad7380_oversampling_ratios); i++) { + if (ratio =3D=3D ad7380_oversampling_ratios[i]) + return i; + } + + return -EINVAL; +} + +static int ad7380_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, + int val2, long mask) +{ + struct ad7380_state *st =3D iio_priv(indio_dev); + int ret, osr, boost; + + switch (mask) { + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + osr =3D ad7380_osr_to_regval(val); + if (osr < 0) + return osr; + + /* always enable resolution boost when oversampling is enabled */ + boost =3D osr > 0 ? 1 : 0; + + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { + ret =3D regmap_update_bits(st->regmap, + AD7380_REG_ADDR_CONFIG1, + AD7380_CONFIG1_OSR | AD7380_CONFIG1_RES, + FIELD_PREP(AD7380_CONFIG1_OSR, osr) | + FIELD_PREP(AD7380_CONFIG1_RES, boost)); + + if (ret) + return ret; + + st->oversampling_ratio =3D val; + st->resolution_boost_enabled =3D boost; + + /* + * Perform a soft reset. This will flush the oversampling + * block and FIFO but will maintain the content of the + * configurable registers. + */ + return regmap_update_bits(st->regmap, + AD7380_REG_ADDR_CONFIG2, + AD7380_CONFIG2_RESET, + FIELD_PREP(AD7380_CONFIG2_RESET, + AD7380_CONFIG2_RESET_SOFT)); + } + unreachable(); + default: + return -EINVAL; + } +} + +static int ad7380_get_current_scan_type(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct ad7380_state *st =3D iio_priv(indio_dev); + + return st->resolution_boost_enabled ? AD7380_SCAN_TYPE_RESOLUTION_BOOST + : AD7380_SCAN_TYPE_NORMAL; +} + static const struct iio_info ad7380_info =3D { .read_raw =3D &ad7380_read_raw, + .read_avail =3D &ad7380_read_avail, + .write_raw =3D &ad7380_write_raw, + .get_current_scan_type =3D &ad7380_get_current_scan_type, .debugfs_reg_access =3D &ad7380_debugfs_reg_access, }; =20 @@ -426,6 +653,9 @@ static int ad7380_init(struct ad7380_state *st, struct = regulator *vref) if (ret < 0) return ret; =20 + /* This is the default value after reset. */ + st->oversampling_ratio =3D 1; + /* SPI 1-wire mode */ return regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2, AD7380_CONFIG2_SDO, @@ -437,11 +667,6 @@ static void ad7380_regulator_disable(void *p) regulator_disable(p); } =20 -static void ad7380_unoptimize_msg(void *msg) -{ - spi_unoptimize_message(msg); -} - static int ad7380_probe(struct spi_device *spi) { struct iio_dev *indio_dev; @@ -532,32 +757,21 @@ static int ad7380_probe(struct spi_device *spi) =20 /* * Setting up a low latency read for getting sample data. Used for both - * direct read an triggered buffer. + * direct read an triggered buffer. Additional fields will be set up in + * ad7380_update_xfers() based on the current state of the driver at the + * time of the read. */ =20 /* toggle CS (no data xfer) to trigger a conversion */ - st->xfer[0].delay.value =3D T_CONVERT_NS; - st->xfer[0].delay.unit =3D SPI_DELAY_UNIT_NSECS; st->xfer[0].cs_change =3D 1; st->xfer[0].cs_change_delay.value =3D st->chip_info->timing_specs->t_csh_= ns; st->xfer[0].cs_change_delay.unit =3D SPI_DELAY_UNIT_NSECS; =20 /* then do a second xfer to read the data */ - st->xfer[1].bits_per_word =3D st->chip_info->channels[0].scan_type.realbi= ts; - st->xfer[1].rx_buf =3D st->scan_data.raw; - st->xfer[1].len =3D BITS_TO_BYTES(st->chip_info->channels[0].scan_type.st= oragebits) - * (st->chip_info->num_channels - 1); + st->xfer[1].rx_buf =3D st->scan_data; =20 spi_message_init_with_transfers(&st->msg, st->xfer, ARRAY_SIZE(st->xfer)); =20 - ret =3D spi_optimize_message(st->spi, &st->msg); - if (ret) - return ret; - - ret =3D devm_add_action_or_reset(&spi->dev, ad7380_unoptimize_msg, &st->m= sg); - if (ret) - return ret; - indio_dev->channels =3D st->chip_info->channels; indio_dev->num_channels =3D st->chip_info->num_channels; indio_dev->name =3D st->chip_info->name; @@ -567,7 +781,8 @@ static int ad7380_probe(struct spi_device *spi) =20 ret =3D devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, iio_pollfunc_store_time, - ad7380_trigger_handler, NULL); + ad7380_trigger_handler, + &ad7380_buffer_setup_ops); if (ret) return ret; =20 --=20 2.45.1