From patchwork Mon Nov 25 13:35:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Budai, Robert" X-Patchwork-Id: 13884904 Received: from mx0a-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 61D84191F94; Mon, 25 Nov 2024 13:36:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.135.77 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732541764; cv=none; b=BtvlcwbNNoxIZCNcvjHVlZBFj4aDm6j+eQ0cSZwJSAl99Ww95QPCzNtNbrWI57PPhMoAASiYWf0hG4gw6605gqeRgeja1+7oDabHv11CtrHXynMyVG3mQLf19KppQYcpaJHtXYFI3e11trlzMNmR+gGa7WvDHWjOjFyu39ay2xg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732541764; c=relaxed/simple; bh=DeS6JEneGDIVfZY5mOAWjMHgtWno+UVU6a1zm+o0aeA=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=nXinc4Tc3pBAN+BmuvDa8BbP3XOwgfy9PN4bzhkq07annk2aWdxKscQAEb4O4JxrZlRkyJwbQmjhTMZm2rr7CEH7IQGurhg4IgrTsVQeSwKIDu7ekfph/1tktKEwIxfWCzASkz1u4ZQiIWgsG/R5Ypo+bxfHUWetaamo7j7omqg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com; spf=pass smtp.mailfrom=analog.com; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b=l9SCM4Sd; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=analog.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b="l9SCM4Sd" Received: from pps.filterd (m0167088.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AP985Hl014714; Mon, 25 Nov 2024 08:35:49 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h= content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=WmrpA hDEj5raQU91pCwTrKA6mb0Tl1Y5Jqg1NOatAMs=; b=l9SCM4Sd5D+oLc4+Ua4gP UoJbPtK4z34Eycu/E4bOHzpL2IHLNgSw114jPyXlYAPSVffT02IfzOu2Cb2rgzo9 nYLUb8CTWUxEZ3127z9V/9PCAFrMlFmOOg2lqLRqEQjH8uBc5JyQXsr28Uql/aSJ zL1CebhzcOEmDfE2dg6PBt0gCbLMCQvz++z583riNTMkzbHFjqLbkN0+c5geYKDb PMA3p0U/OV5pDvqoWpZ3tORC9CwGvrONjv9XkUC1xyzvK1ybguh0whw3jNjsbSsv h5SeGO60xyakdwRjUbNZVFG3p4rAEkUH3SsBv15aRogI7MKYLAG8UlcswEhhUHpk w== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 434pbd10yn-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 25 Nov 2024 08:35:49 -0500 (EST) Received: from ASHBMBX8.ad.analog.com (ASHBMBX8.ad.analog.com [10.64.17.5]) by nwd2mta4.analog.com (8.14.7/8.14.7) with ESMTP id 4APDZlJN030664 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 25 Nov 2024 08:35:48 -0500 Received: from ASHBCASHYB5.ad.analog.com (10.64.17.133) by ASHBMBX8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Mon, 25 Nov 2024 08:35:47 -0500 Received: from ASHBMBX8.ad.analog.com (10.64.17.5) by ASHBCASHYB5.ad.analog.com (10.64.17.133) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Mon, 25 Nov 2024 08:35:47 -0500 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Mon, 25 Nov 2024 08:35:47 -0500 Received: from dell-precision-robert.ad.analog.com ([10.48.65.197]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 4APDZR2B031415; Mon, 25 Nov 2024 08:35:43 -0500 From: Robert Budai To: Lars-Peter Clausen , Michael Hennerich , Nuno Sa , "Ramona Gradinariu" , Antoniu Miclaus , Jonathan Cameron , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" , Jonathan Corbet , Robert Budai , , , , Subject: [PATCH 1/7] iio: imu: adis: Remove documented not used elements Date: Mon, 25 Nov 2024 15:35:08 +0200 Message-ID: <20241125133520.24328-2-robert.budai@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241125133520.24328-1-robert.budai@analog.com> References: <20241125133520.24328-1-robert.budai@analog.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-GUID: PDy7TmRnD2eCK8uS_RltStkI_aHIEepz X-Proofpoint-ORIG-GUID: PDy7TmRnD2eCK8uS_RltStkI_aHIEepz X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 adultscore=0 phishscore=0 priorityscore=1501 suspectscore=0 lowpriorityscore=0 spamscore=0 impostorscore=0 malwarescore=0 mlxlogscore=999 clxscore=1015 mlxscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411250116 This patch removes elements from adis.h that are documented but not used anymore. Signed-off-by: Robert Budai --- v2: - added patch as requested in previous review - signed of by submitter include/linux/iio/imu/adis.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index e6a75356567a..4bb98d9731de 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -99,7 +99,6 @@ struct adis_data { * @spi: Reference to SPI device which owns this ADIS IIO device * @trig: IIO trigger object data * @data: ADIS chip variant specific data - * @burst: ADIS burst transfer information * @burst_extra_len: Burst extra length. Should only be used by devices that can * dynamically change their burst mode length. * @state_lock: Lock used by the device to protect state From patchwork Mon Nov 25 13:35:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Budai, Robert" X-Patchwork-Id: 13884905 Received: from mx0a-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E60661ADFF7; Mon, 25 Nov 2024 13:36:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.135.77 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732541779; cv=none; b=Vkkl59Y2eu47/GNC1O2Dy62bhy25MOf5GJ0WA65BvYom0Hl8TBFXkEVWYLtokxpXCpGtN6S0rxXebPuYwvVi+0JvLIAxL27Bn99YU3S9xbZFZ3wcW9OJ670gebATU9wHqgVwo9gsF5XA8O/hx4kug0N/C1wQqbLdUyETRxowEJ0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732541779; c=relaxed/simple; bh=lJb10xBV2P7hfYi0ndADTxtjgaNL2Dk2SPvDfA+j3Ec=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=oCeEDVmla1t7sOo5RBicmQGaxl99kOQde6vj2C2NvZFqb8vxJYwBshTYc6boOnb5qV5zhsYGpvZ2gNZow2aLcKkjFOMLDEfzrNjuxOvqDcex6Z2dVt8G9mWTq+0XHRC3KtzUFkhklL0q+rFQa2mpPHgjIcl0Y+5rVEt7Ln05W6E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com; spf=pass smtp.mailfrom=analog.com; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b=Ib+wu3+0; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=analog.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b="Ib+wu3+0" Received: from pps.filterd (m0167089.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AP975xW006623; Mon, 25 Nov 2024 08:36:04 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h= content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=lCQIX 6jWUNmyYsi7I+w2Bfkjl2MEHu0dqpeLiDV6JDE=; b=Ib+wu3+0NaZSy0tAAUuLp OZ5GHNTPsRJ5cAXdGu+QSknpWhXCOgfRw7I0tT0A19VkQJPAPbLbmriWNGSnCbfr Cf4MSXqRE9v7Tq4yQrZNDVO+JXaK4VLSISnBbzNsIMeqdh3wTomBCKz24v7c8yil NIQ77u/SqIt4FHggBstZ9bH1hru/0A4cmYndtDgIcoqWMzmhoMsLPfKAU9HlFPkY s9NrCVnwPvvAXorObW7LelwQyJLS/3/52MLgAT/5WqoNfH0cmdPKz0lrPvavap0A CzlmJfSaJP6NYzlWgUTSaOkYlqwyrw0s37oKDvpaUJQvMY984TTVN8cQJqwwoqgE A== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 433cu6rr7h-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 25 Nov 2024 08:36:04 -0500 (EST) Received: from ASHBMBX8.ad.analog.com (ASHBMBX8.ad.analog.com [10.64.17.5]) by nwd2mta4.analog.com (8.14.7/8.14.7) with ESMTP id 4APDa3xX030670 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 25 Nov 2024 08:36:03 -0500 Received: from ASHBCASHYB4.ad.analog.com (10.64.17.132) by ASHBMBX8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Mon, 25 Nov 2024 08:36:03 -0500 Received: from ASHBMBX8.ad.analog.com (10.64.17.5) by ASHBCASHYB4.ad.analog.com (10.64.17.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Mon, 25 Nov 2024 08:36:03 -0500 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Mon, 25 Nov 2024 08:36:03 -0500 Received: from dell-precision-robert.ad.analog.com ([10.48.65.197]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 4APDZR2C031415; Mon, 25 Nov 2024 08:35:58 -0500 From: Robert Budai To: Nuno Sa , Ramona Gradinariu , Antoniu Miclaus , Lars-Peter Clausen , Michael Hennerich , Jonathan Cameron , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" , Jonathan Corbet , Robert Budai , , , , Subject: [PATCH 2/7] iio: imu: adis: Add custom ops struct Date: Mon, 25 Nov 2024 15:35:09 +0200 Message-ID: <20241125133520.24328-3-robert.budai@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241125133520.24328-1-robert.budai@analog.com> References: <20241125133520.24328-1-robert.budai@analog.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-GUID: F7BeCj3nTgz7oB0LVM9kF67rDqNekbGm X-Proofpoint-ORIG-GUID: F7BeCj3nTgz7oB0LVM9kF67rDqNekbGm X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxlogscore=999 malwarescore=0 phishscore=0 clxscore=1015 spamscore=0 suspectscore=0 mlxscore=0 adultscore=0 lowpriorityscore=0 priorityscore=1501 impostorscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411250116 This patch introduces a custom ops struct letting users define custom read and write functions. Some adis devices might define a completely different spi protocol from the one used in the default implementation. Co-developed-by: Ramona Gradinariu Signed-off-by: Ramona Gradinariu Co-developed-by: Antoniu Miclaus Signed-off-by: Antoniu Miclaus Signed-off-by: Nuno Sá Signed-off-by: Robert Budai --- v2: - separated read and write ops as requested - signed of by submitter drivers/iio/imu/adis.c | 13 ++++++++++--- include/linux/iio/imu/adis.h | 28 +++++++++++++++++++++------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 99410733c1ca..fa7a817b7d99 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -223,13 +223,13 @@ int __adis_update_bits_base(struct adis *adis, unsigned int reg, const u32 mask, int ret; u32 __val; - ret = __adis_read_reg(adis, reg, &__val, size); + ret = adis->ops->read(adis, reg, &__val, size); if (ret) return ret; __val = (__val & ~mask) | (val & mask); - return __adis_write_reg(adis, reg, __val, size); + return adis->ops->write(adis, reg, __val, size); } EXPORT_SYMBOL_NS_GPL(__adis_update_bits_base, IIO_ADISLIB); @@ -468,7 +468,7 @@ int adis_single_conversion(struct iio_dev *indio_dev, guard(mutex)(&adis->state_lock); - ret = __adis_read_reg(adis, chan->address, &uval, + ret = adis->ops->read(adis, chan->address, &uval, chan->scan_type.storagebits / 8); if (ret) return ret; @@ -488,6 +488,11 @@ int adis_single_conversion(struct iio_dev *indio_dev, } EXPORT_SYMBOL_NS_GPL(adis_single_conversion, IIO_ADISLIB); +static const struct adis_ops adis_default_ops = { + .read = __adis_read_reg, + .write = __adis_write_reg, +}; + /** * adis_init() - Initialize adis device structure * @adis: The adis device @@ -517,6 +522,8 @@ int adis_init(struct adis *adis, struct iio_dev *indio_dev, adis->spi = spi; adis->data = data; + if (!adis->ops->write || !adis->ops->read) + return -EINVAL; iio_device_set_drvdata(indio_dev, adis); if (data->has_paging) { diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index 4bb98d9731de..89cfa75ae9ea 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -94,6 +94,18 @@ struct adis_data { unsigned int burst_max_speed_hz; }; +/** + * struct adis_ops: Custom ops for adis devices. + * @write: Custom spi write implementation. + * @read: Custom spi read implementation. + */ +struct adis_ops { + int (*write)(struct adis *adis, unsigned int reg, unsigned int value, + unsigned int size); + int (*read)(struct adis *adis, unsigned int reg, unsigned int *value, + unsigned int size); +}; + /** * struct adis - ADIS device instance data * @spi: Reference to SPI device which owns this ADIS IIO device @@ -101,6 +113,7 @@ struct adis_data { * @data: ADIS chip variant specific data * @burst_extra_len: Burst extra length. Should only be used by devices that can * dynamically change their burst mode length. + * @ops: ops struct for custom read and write functions * @state_lock: Lock used by the device to protect state * @msg: SPI message object * @xfer: SPI transfer objects to be used for a @msg @@ -116,6 +129,7 @@ struct adis { const struct adis_data *data; unsigned int burst_extra_len; + const struct adis_ops *ops; /** * The state_lock is meant to be used during operations that require * a sequence of SPI R/W in order to protect the SPI transfer @@ -168,7 +182,7 @@ int __adis_read_reg(struct adis *adis, unsigned int reg, static inline int __adis_write_reg_8(struct adis *adis, unsigned int reg, u8 val) { - return __adis_write_reg(adis, reg, val, 1); + return adis->ops->write(adis, reg, val, 1); } /** @@ -180,7 +194,7 @@ static inline int __adis_write_reg_8(struct adis *adis, unsigned int reg, static inline int __adis_write_reg_16(struct adis *adis, unsigned int reg, u16 val) { - return __adis_write_reg(adis, reg, val, 2); + return adis->ops->write(adis, reg, val, 2); } /** @@ -192,7 +206,7 @@ static inline int __adis_write_reg_16(struct adis *adis, unsigned int reg, static inline int __adis_write_reg_32(struct adis *adis, unsigned int reg, u32 val) { - return __adis_write_reg(adis, reg, val, 4); + return adis->ops->write(adis, reg, val, 4); } /** @@ -207,7 +221,7 @@ static inline int __adis_read_reg_16(struct adis *adis, unsigned int reg, unsigned int tmp; int ret; - ret = __adis_read_reg(adis, reg, &tmp, 2); + ret = adis->ops->read(adis, reg, &tmp, 2); if (ret == 0) *val = tmp; @@ -226,7 +240,7 @@ static inline int __adis_read_reg_32(struct adis *adis, unsigned int reg, unsigned int tmp; int ret; - ret = __adis_read_reg(adis, reg, &tmp, 4); + ret = adis->ops->read(adis, reg, &tmp, 4); if (ret == 0) *val = tmp; @@ -244,7 +258,7 @@ static inline int adis_write_reg(struct adis *adis, unsigned int reg, unsigned int val, unsigned int size) { guard(mutex)(&adis->state_lock); - return __adis_write_reg(adis, reg, val, size); + return adis->ops->write(adis, reg, val, size); } /** @@ -258,7 +272,7 @@ static int adis_read_reg(struct adis *adis, unsigned int reg, unsigned int *val, unsigned int size) { guard(mutex)(&adis->state_lock); - return __adis_read_reg(adis, reg, val, size); + return adis->ops->read(adis, reg, val, size); } /** From patchwork Mon Nov 25 13:35:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Budai, Robert" X-Patchwork-Id: 13884906 Received: from mx0a-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A01F21ABEBF; Mon, 25 Nov 2024 13:36:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.135.77 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732541788; cv=none; b=gM6r8rgWCrj1cEqzkdPiWF72+Jn/voY3ZH2XxasZuEwESMNbqOoh6TKJBVHIKCOppNFvF58Y+ojjn5zk7jYbkR9aUx82dtNuYscdghVkpaH+XUvdhL5reAZUXXl1oTE275LNLBAUqE7hScBjYBGeqwAEDyNZXZsINCMvvQbK1og= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732541788; c=relaxed/simple; bh=hJSfGrQUBoTfXtYbD4uVAztsA1pywly7g8hk4h/n9s4=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=lx/MZfc2ZWGkK2Cxcsyvmk41llpXfRTbNYtNs/nI1LZ93rYKdIJ+y8zBpz23l21ROeymi3yqrwWufVF5qehOc6XPrHACpq4lsH7XOVHodccYGCQEVvTQXuQ34D1R6CueAGXYA3A4tLBbgOltKikhMoGAMWCMIsAtHDZdUKZC3Ho= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com; spf=pass smtp.mailfrom=analog.com; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b=PQKQzEkP; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=analog.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b="PQKQzEkP" Received: from pps.filterd (m0167089.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AP97oIi005194; Mon, 25 Nov 2024 08:36:13 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h= content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=Gh6tw spJKNrJ1uM4677uAOJ0uB3tlYFo49uusnYZBOw=; b=PQKQzEkPKVSbfv6tlU0VW gnYJZo8uYI23ad3LSEGrEFMkWxqzmkibwfzOISNuCRoimw45gtkMEhoKPkhP1jQH m4nEqKFJaNBeVhB39/5Dxjxqb3B6abPb62uXbXUzJySt5B6lZHMrYzNJfAuzDRQ3 1UiyY31Ew3G4Q7sBPn1cMnPqu9jKqT3z2/Sfm4IEwYy7ReP+LL3cFwVCpWIUbxs7 k+RPT6+j9gEZgaULq2GkyO4n0W3ky7MIQRbxomUYynk+BLpIlWUfjaSXY2GctvSr TTRDtq796QVVCYgF75FYFqXq2iVsGk0OdlrlkMx/PueY1mmkZNnMEfGYk+LovLS5 A== Received: from nwd2mta3.analog.com ([137.71.173.56]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 433cu6rr8b-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 25 Nov 2024 08:36:13 -0500 (EST) Received: from ASHBMBX9.ad.analog.com (ASHBMBX9.ad.analog.com [10.64.17.10]) by nwd2mta3.analog.com (8.14.7/8.14.7) with ESMTP id 4APDaCkL046350 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 25 Nov 2024 08:36:12 -0500 Received: from ASHBCASHYB4.ad.analog.com (10.64.17.132) by ASHBMBX9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Mon, 25 Nov 2024 08:36:12 -0500 Received: from ASHBMBX8.ad.analog.com (10.64.17.5) by ASHBCASHYB4.ad.analog.com (10.64.17.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Mon, 25 Nov 2024 08:36:12 -0500 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Mon, 25 Nov 2024 08:36:12 -0500 Received: from dell-precision-robert.ad.analog.com ([10.48.65.197]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 4APDZR2D031415; Mon, 25 Nov 2024 08:36:05 -0500 From: Robert Budai To: Nuno Sa , Ramona Gradinariu , Antoniu Miclaus , Lars-Peter Clausen , Michael Hennerich , Jonathan Cameron , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" , Jonathan Corbet , Robert Budai , , , , Subject: [PATCH 3/7] iio: imu: adis: Add reset to custom ops Date: Mon, 25 Nov 2024 15:35:10 +0200 Message-ID: <20241125133520.24328-4-robert.budai@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241125133520.24328-1-robert.budai@analog.com> References: <20241125133520.24328-1-robert.budai@analog.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-GUID: MvdAhsVYE1LaeJV-q7oq-6A2zX2MNVS- X-Proofpoint-ORIG-GUID: MvdAhsVYE1LaeJV-q7oq-6A2zX2MNVS- X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxlogscore=999 malwarescore=0 phishscore=0 clxscore=1015 spamscore=0 suspectscore=0 mlxscore=0 adultscore=0 lowpriorityscore=0 priorityscore=1501 impostorscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411250116 This patch allows the custom definition of reset funcitonality for adis object. It is useful in cases where the reset does not need to sleep after the reset since it is handled by the library. Co-developed-by: Ramona Gradinariu Signed-off-by: Ramona Gradinariu Co-developed-by: Antoniu Miclaus Signed-off-by: Antoniu Miclaus Signed-off-by: Nuno Sá Signed-off-by: Robert Budai --- v2: -added reset ops as a different patch - signed of by submitter drivers/iio/imu/adis.c | 7 +++++-- include/linux/iio/imu/adis.h | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index fa7a817b7d99..865f7c56717a 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -339,8 +339,11 @@ int __adis_reset(struct adis *adis) int ret; const struct adis_timeout *timeouts = adis->data->timeouts; - ret = __adis_write_reg_8(adis, adis->data->glob_cmd_reg, - ADIS_GLOB_CMD_SW_RESET); + if (adis->ops->reset) + ret = adis->ops->reset(adis); + else + ret = __adis_write_reg_8(adis, adis->data->glob_cmd_reg, + ADIS_GLOB_CMD_SW_RESET); if (ret) { dev_err(&adis->spi->dev, "Failed to reset device: %d\n", ret); return ret; diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index 89cfa75ae9ea..52652f51db2e 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -98,12 +98,15 @@ struct adis_data { * struct adis_ops: Custom ops for adis devices. * @write: Custom spi write implementation. * @read: Custom spi read implementation. + * @reset: Custom sw reset implementation. The custom implementation does not + * need to sleep after the reset. It's done by the library already. */ struct adis_ops { int (*write)(struct adis *adis, unsigned int reg, unsigned int value, unsigned int size); int (*read)(struct adis *adis, unsigned int reg, unsigned int *value, unsigned int size); + int (*reset)(struct adis *adis); }; /** From patchwork Mon Nov 25 13:35:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Budai, Robert" X-Patchwork-Id: 13884907 Received: from mx0a-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 36ACF1ABEBF; Mon, 25 Nov 2024 13:36:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.135.77 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732541795; cv=none; b=PWgS2hEO6XA+kgLiruytFUmgY27+tAqAj0tQdnb7meNv/S9ny88EPMrSVNXLE6rJc1Gjt712cRRdmTgFfh8I3Pk61Et+qzNeYpxdnfHZqJv6CVFg9CIl8CmkSWLepvlu1Mjv9mTMrpbCOfPqPHoaVaJuGmjVa46duAAQscivKpI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732541795; c=relaxed/simple; bh=CG3WFYYgvkz5nXR64JpYf80kCkGIiiHMLy2y/ywY/v4=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=uM2WAPHNFTwlen7b1xAD05mUsUQDgHvapzFRY/rmZQbPQt9fMUArydYhNvoXpvy5yT8qI6y7egvt9XnksOO4qh+tp42aDiTpdbjQuR0GiedfuYxOsRIkKNHsRJJkukNqfUhfLMTT8KTU2lbZxSkW5MO/aBOS0okXTYYB9YMhRDs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com; spf=pass smtp.mailfrom=analog.com; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b=OH/3BJMu; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=analog.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b="OH/3BJMu" Received: from pps.filterd (m0167088.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AP98AXg014880; Mon, 25 Nov 2024 08:36:21 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h= content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=r1kqV 70odboThrdpH3fUrHEu2Qxw5HY490RveAsqhis=; b=OH/3BJMu9LZjZL+YCNcp1 k6ydp00x9Gfu/dK+eScPGTVDN37OsAFc1LrXcOP58NNhzEQyQq5QqvxvAURagMhs 4arNJVywNEdSV3Wh7aIbs4Dh6FOqCoYc/A3h3PI3LG4YM6Zp3QVcn4Ag173iI7aD H95RIEfmuwHoHWvqFP5RG2368WJNcmoChMQQLaTRFaHTzd9QJeOYViydzNOm8DaK DytkhRY6eElGCCvI/t3Li5k+g0PMW4SY+JFCNbV1rLXguGEnel2BkNLjJVFgbgWx pUf+55BkkvQnmOWuLlctBvzbmQsJmrTioUDjAlULbxXgAXn4eCngAAWO/0fDVZVp Q== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 434pbd112t-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 25 Nov 2024 08:36:21 -0500 (EST) Received: from ASHBMBX8.ad.analog.com (ASHBMBX8.ad.analog.com [10.64.17.5]) by nwd2mta4.analog.com (8.14.7/8.14.7) with ESMTP id 4APDaKAU030691 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 25 Nov 2024 08:36:20 -0500 Received: from ASHBMBX8.ad.analog.com (10.64.17.5) by ASHBMBX8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Mon, 25 Nov 2024 08:36:20 -0500 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Mon, 25 Nov 2024 08:36:20 -0500 Received: from dell-precision-robert.ad.analog.com ([10.48.65.197]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 4APDZR2E031415; Mon, 25 Nov 2024 08:36:13 -0500 From: Robert Budai To: Lars-Peter Clausen , Michael Hennerich , Nuno Sa , Ramona Gradinariu , Antoniu Miclaus , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , Robert Budai , , , , Subject: [PATCH 4/7] iio: imu: adis: Add DIAG_STAT register size Date: Mon, 25 Nov 2024 15:35:11 +0200 Message-ID: <20241125133520.24328-5-robert.budai@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241125133520.24328-1-robert.budai@analog.com> References: <20241125133520.24328-1-robert.budai@analog.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-GUID: 82RiEQEngXAy1hdeKugk3QQLroUabDeE X-Proofpoint-ORIG-GUID: 82RiEQEngXAy1hdeKugk3QQLroUabDeE X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 adultscore=0 phishscore=0 priorityscore=1501 suspectscore=0 lowpriorityscore=0 spamscore=0 impostorscore=0 malwarescore=0 mlxlogscore=999 clxscore=1015 mlxscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411250116 Some devices may have more than 16 bits of status. This patch allows the user to specify the size of the DIAG_STAT register. It defaults to 2 if not specified. This is mainly for backward compatibility. Co-developed-by: Ramona Gradinariu Signed-off-by: Ramona Gradinariu Co-developed-by: Antoniu Miclaus Signed-off-by: Antoniu Miclaus Signed-off-by: Nuno Sá Signed-off-by: Robert Budai --- v2: - removed default 2 byte STAT_REG length - used already defined MACROS - signed of by submitter drivers/iio/imu/adis.c | 11 ++++++++--- include/linux/iio/imu/adis.h | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 865f7c56717a..29998f3b29f4 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -304,11 +304,15 @@ EXPORT_SYMBOL_NS(__adis_enable_irq, IIO_ADISLIB); */ int __adis_check_status(struct adis *adis) { - u16 status; + unsigned int status; int ret; int i; - ret = __adis_read_reg_16(adis, adis->data->diag_stat_reg, &status); + if (adis->data->diag_stat_size) + ret = adis->ops->read(adis, adis->data->diag_stat_reg, &status, + adis->data->diag_stat_size); + else + ret = __adis_read_reg_16(adis, adis->data->diag_stat_reg, (u16 *)&status); if (ret) return ret; @@ -317,7 +321,8 @@ int __adis_check_status(struct adis *adis) if (status == 0) return 0; - for (i = 0; i < 16; ++i) { + for (i = 0; i < BITS_PER_BYTE * ((adis->data->diag_stat_size) ? + adis->data->diag_stat_size : 2); ++i) { if (status & BIT(i)) { dev_err(&adis->spi->dev, "%s.\n", adis->data->status_error_msgs[i]); diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index 52652f51db2e..b888b22f5c8c 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -44,6 +44,7 @@ struct adis_timeout { * @glob_cmd_reg: Register address of the GLOB_CMD register * @msc_ctrl_reg: Register address of the MSC_CTRL register * @diag_stat_reg: Register address of the DIAG_STAT register + * @diag_stat_size: Length (in bytes) of the DIAG_STAT register. * @prod_id_reg: Register address of the PROD_ID register * @prod_id: Product ID code that should be expected when reading @prod_id_reg * @self_test_mask: Bitmask of supported self-test operations @@ -70,6 +71,7 @@ struct adis_data { unsigned int glob_cmd_reg; unsigned int msc_ctrl_reg; unsigned int diag_stat_reg; + unsigned int diag_stat_size; unsigned int prod_id_reg; unsigned int prod_id; From patchwork Mon Nov 25 13:35:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Budai, Robert" X-Patchwork-Id: 13884908 Received: from mx0b-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8EF991ABEBF; Mon, 25 Nov 2024 13:36:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.135.77 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732541804; cv=none; b=SCZDvMePqiZEH1Fh2RMaouHXI+PQTnTcdhPcxFnzT0Ef3RXGyICmbyrwL5k/pOFf4Ctn0VfeHttQMZBT66TxTSNIbL2XsH2fVjsp7gBzS3TDVnTJaZ9pgNfz9v3Eyh/o60ddV33AVER6HGmujfhihglQT/rzqNzvoFq68C6VSXU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732541804; c=relaxed/simple; bh=B6bSts6FalS/WVMupvec72o/d2wy1GWRk5tlur6sjMM=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=OiLPbgb5sr2jVT5aVcS36zXrvlBdwL1r+Wj5s2wqIcavDnA4f4B2wIiYGlxdSKe3PDan+r1kETq3CkX7J+OT69ZwNyK6wbkFr+kxdVAx/2Yvf6Q5U51arh/Dny9+OQdYn3S+OU9am72TZBqmLUeoIy7ns/Fat+FT/D7yjMU/iNI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com; spf=pass smtp.mailfrom=analog.com; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b=I0zcPdye; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=analog.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b="I0zcPdye" Received: from pps.filterd (m0375855.ppops.net [127.0.0.1]) by mx0b-00128a01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AP9VtC5017858; Mon, 25 Nov 2024 08:36:29 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h= content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=hrbsY o0tJ2wB9cGH61UOvdROZ5uIqy/CHxsR1REJekA=; b=I0zcPdyeUhGWCPaMLUHmg mho4nQOPQr5BXfZ4eL7lObHkCeejDq9m96gIOIvRZSvg+/ss5KSolzImcFdQ9m4t MUE8ogMhE489hPducJWXFZm7OGAQpidjAy8r6G3Tkb9UFAoPoYE9UK3E10pWQ4nv mRjt22oQFGvXAckdOnPYrwtLaLLEUgIsNMeW+tzX5TLaVFQN6ErLZwPde4UEHVxY DwtZZAcTB0xdcvntRwAVXGRZIJkXePskbXXhTz0eSyR1kokQHtixuE355hAUWsJd jgL31brTwenKKie/Yz3ve5ZQR4acHfBx+17NL8otbvD08xlU6ELXbqdPbjngC8XP w== Received: from nwd2mta3.analog.com ([137.71.173.56]) by mx0b-00128a01.pphosted.com (PPS) with ESMTPS id 434pph0wgx-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 25 Nov 2024 08:36:29 -0500 (EST) Received: from ASHBMBX9.ad.analog.com (ASHBMBX9.ad.analog.com [10.64.17.10]) by nwd2mta3.analog.com (8.14.7/8.14.7) with ESMTP id 4APDaRUD046424 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 25 Nov 2024 08:36:27 -0500 Received: from ASHBCASHYB4.ad.analog.com (10.64.17.132) by ASHBMBX9.ad.analog.com (10.64.17.10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Mon, 25 Nov 2024 08:36:27 -0500 Received: from ASHBMBX8.ad.analog.com (10.64.17.5) by ASHBCASHYB4.ad.analog.com (10.64.17.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Mon, 25 Nov 2024 08:36:27 -0500 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Mon, 25 Nov 2024 08:36:27 -0500 Received: from dell-precision-robert.ad.analog.com ([10.48.65.197]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 4APDZR2F031415; Mon, 25 Nov 2024 08:36:21 -0500 From: Robert Budai To: Lars-Peter Clausen , Michael Hennerich , Nuno Sa , "Ramona Gradinariu" , Antoniu Miclaus , Jonathan Cameron , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" , Jonathan Corbet , Robert Budai , , , , Subject: [PATCH 5/7] dt-bindings: iio: Add adis16550 bindings Date: Mon, 25 Nov 2024 15:35:12 +0200 Message-ID: <20241125133520.24328-6-robert.budai@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241125133520.24328-1-robert.budai@analog.com> References: <20241125133520.24328-1-robert.budai@analog.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-GUID: uwWIAAFvIZXMf-8omTLLjrh2kEbF9yfE X-Proofpoint-ORIG-GUID: uwWIAAFvIZXMf-8omTLLjrh2kEbF9yfE X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 suspectscore=0 clxscore=1015 phishscore=0 priorityscore=1501 malwarescore=0 adultscore=0 mlxscore=0 bulkscore=0 mlxlogscore=999 impostorscore=0 spamscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411250116 Document the ADIS16550 device devicetree bindings. Co-developed-by: Antoniu Miclaus Signed-off-by: Antoniu Miclaus Signed-off-by: Ramona Gradinariu Signed-off-by: Robert Budai --- v2: - signed of by submitter .../bindings/iio/imu/adi,adis16550.yaml | 97 +++++++++++++++++++ MAINTAINERS | 9 ++ 2 files changed, 106 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/imu/adi,adis16550.yaml diff --git a/Documentation/devicetree/bindings/iio/imu/adi,adis16550.yaml b/Documentation/devicetree/bindings/iio/imu/adi,adis16550.yaml new file mode 100644 index 000000000000..767b500afbaa --- /dev/null +++ b/Documentation/devicetree/bindings/iio/imu/adi,adis16550.yaml @@ -0,0 +1,97 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/imu/adi,adis16550.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices ADIS16550 and similar IMUs + +maintainers: + - Nuno Sa + - Ramona Gradinariu + - Antoniu Miclaus + +properties: + compatible: + enum: + - adi,adis16550 + - adi,adis16550w + + reg: + maxItems: 1 + + spi-cpha: true + + spi-cpol: true + + spi-max-frequency: + maximum: 15000000 + + vdd-supply: true + + interrupts: + maxItems: 1 + + reset-gpios: + description: + Must be the device tree identifier of the RESET pin. If specified, + it will be asserted during driver probe. As the line is active low, + it should be marked GPIO_ACTIVE_LOW. + maxItems: 1 + + clocks: + maxItems: 1 + description: If not provided, then the internal clock is used. + + adi,sync-mode: + $ref: /schemas/types.yaml#/definitions/string + description: | + Configures the device SYNC pin. + scaled_sync: Device handles internally custom scaled + sync mode. It is stored in a designated register. + enum: + - direct_sync + - scaled_sync + +required: + - compatible + - reg + - interrupts + - spi-cpha + - spi-cpol + - spi-max-frequency + - vdd-supply + +allOf: + - if: + properties: + adi,sync-mode: + enum: [direct_sync, scaled_sync] + + then: + dependencies: + adi,sync-mode: [ clocks ] + + - $ref: /schemas/spi/spi-peripheral-props.yaml# + +additionalProperties: false + +examples: + - | + #include + spi { + #address-cells = <1>; + #size-cells = <0>; + + imu@0 { + compatible = "adi,adis16550"; + reg = <0>; + spi-max-frequency = <15000000>; + spi-cpol; + spi-cpha; + vdd-supply = <&vdd>; + interrupts = <4 IRQ_TYPE_EDGE_FALLING>; + interrupt-parent = <&gpio>; + }; + }; +... diff --git a/MAINTAINERS b/MAINTAINERS index a4628d566e98..b8ea8c9af74a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1412,6 +1412,15 @@ W: https://ez.analog.com/linux-software-drivers F: Documentation/devicetree/bindings/iio/imu/adi,adis16475.yaml F: drivers/iio/imu/adis16475.c +ANALOG DEVICES INC ADIS16550 DRIVER +M: Nuno Sa +M: Ramona Gradinariu +M: Antoniu Miclaus +L: linux-iio@vger.kernel.org +S: Supported +W: https://ez.analog.com/linux-software-drivers +F: Documentation/devicetree/bindings/iio/imu/adi,adis16550.yaml + ANALOG DEVICES INC ADM1177 DRIVER M: Michael Hennerich L: linux-hwmon@vger.kernel.org From patchwork Mon Nov 25 13:35:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Budai, Robert" X-Patchwork-Id: 13884909 Received: from mx0a-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8451D1ABEBF; Mon, 25 Nov 2024 13:36:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.135.77 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732541817; cv=none; b=NpOK2HwsDbZ05Pmxe5zgvQelILYA7K/5UEkhqNzYc8EnqAe0lWhndKe85oFKAF1vyUKqC4NbOcT9aw+tD2zLp/NwQAQLAFlcqsgBQqF8OBW3jgicFiltJfA/74GPjT+WRrUatbiahpCjfzDWk7d6wDA4cEcFbWvZ/6Dm7nRXhnc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732541817; c=relaxed/simple; bh=gEmfD+oSn4Y5PK6JQKXC8312PkU86C/KWRD3k3BQOqI=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=GliAcdPPNcyxCAgJdoq4XwCVYeIm6zGtIz52zkLa7KN/vrA7vdkxjtTF37KUv8S21S0Xx9GqiHfeY5iWAV0UzBRr4DP8mkEyXnk5NXRs573rDmHwfoHbCPPNjd6uHuD2Cl96QoJh+qI9j4rczLch2x0nY4GiKy+RAsQGi3ubx4A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com; spf=pass smtp.mailfrom=analog.com; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b=yIXH0H0e; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=analog.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b="yIXH0H0e" Received: from pps.filterd (m0167088.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AP988Js014757; Mon, 25 Nov 2024 08:36:39 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h= content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=leFhq wJdfCA2e63fCAgaaSjIBSgELW244u1kfHAaY/A=; b=yIXH0H0eH8IH07lHl4jUv /9S5dUzTCDV1V35Zc1xcoFvTTO3+vYoYVdhutvrp9SUdYwYGE4d1y/Nhk1QoTE8k UnUoq/S7eNmyDb6SU2rDKlY1+IR5yhGjYnl0cdjorWvMF010aV+ZkZ3Ew6utagsm KP2R5xFLTMkhUCOQNU8lMu3cwhDYaQ5s91shAt+xHRsWZh/YM/aYpIohWw5s9z/K qIdW7VImf++Pv37bDtaWFHyqZv7cuhZZFQxj5VYRtd5h+GpcOT+/b3bBBv4A5mEE 4ywIOanmIHOdnUtpHIz8jD9GHhvPkfm/lWE0Kk/HNUnxUJ0yMvJwzsD6P/N5CCH9 w== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 434pbd114u-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 25 Nov 2024 08:36:39 -0500 (EST) Received: from ASHBMBX8.ad.analog.com (ASHBMBX8.ad.analog.com [10.64.17.5]) by nwd2mta4.analog.com (8.14.7/8.14.7) with ESMTP id 4APDacwb030748 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 25 Nov 2024 08:36:38 -0500 Received: from ASHBMBX8.ad.analog.com (10.64.17.5) by ASHBMBX8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Mon, 25 Nov 2024 08:36:37 -0500 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Mon, 25 Nov 2024 08:36:37 -0500 Received: from dell-precision-robert.ad.analog.com ([10.48.65.197]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 4APDZR2G031415; Mon, 25 Nov 2024 08:36:29 -0500 From: Robert Budai To: Lars-Peter Clausen , Michael Hennerich , Nuno Sa , Ramona Gradinariu , Antoniu Miclaus , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , Robert Budai , , , , Subject: [PATCH 6/7] iio: imu: adis16550: add adis16550 support Date: Mon, 25 Nov 2024 15:35:13 +0200 Message-ID: <20241125133520.24328-7-robert.budai@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241125133520.24328-1-robert.budai@analog.com> References: <20241125133520.24328-1-robert.budai@analog.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-GUID: ewcVWgxJhQhSJ1MU1N6K0bvVYKn85tZH X-Proofpoint-ORIG-GUID: ewcVWgxJhQhSJ1MU1N6K0bvVYKn85tZH X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 adultscore=0 phishscore=0 priorityscore=1501 suspectscore=0 lowpriorityscore=0 spamscore=0 impostorscore=0 malwarescore=0 mlxlogscore=999 clxscore=1015 mlxscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411250116 The ADIS16550 is a complete inertial system that includes a triaxis gyroscope and a triaxis accelerometer. Each inertial sensor in the ADIS16550 combines industry leading MEMS only technology with signal conditioning that optimizes dynamic performance. The factory calibration characterizes each sensor for sensitivity, bias, and alignment. As a result, each sensor has its own dynamic com- pensation formulas that provide accurate sensor measurements Co-developed-by: Ramona Gradinariu Signed-off-by: Ramona Gradinariu Co-developed-by: Antoniu Miclaus Signed-off-by: Antoniu Miclaus Signed-off-by: Nuno Sá Signed-off-by: Robert Budai --- v2: - replaced mutex locks with adis_dev_auto_lock - "unaligned.h" library correctd - replaced burst read memory copy with memcpy - initialized adis.buffer and adis.xfer in probe, and used memset to set them to zero - used DT fallback for adis16550 and adis16550w - removed extra memory allocation for IIO_CHAN_SOFT_TIMESTAMP - removed arrays of chip info structures - added units for variables - signed of by submitter drivers/iio/imu/Kconfig | 13 + drivers/iio/imu/Makefile | 1 + drivers/iio/imu/adis16550.c | 1203 +++++++++++++++++++++++++++++++++++ 3 files changed, 1217 insertions(+) create mode 100644 drivers/iio/imu/adis16550.c diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index 782fb80e44c2..1b80f7e488c4 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig @@ -52,6 +52,19 @@ config ADIS16480 Say yes here to build support for Analog Devices ADIS16375, ADIS16480, ADIS16485, ADIS16488 inertial sensors. +config ADIS16550 + tristate "Analog Devices ADIS16550 and similar IMU driver" + depends on SPI + select IIO_ADIS_LIB + select IIO_ADIS_LIB_BUFFER if IIO_BUFFER + select CRC32 + help + Say yes here to build support for Analog Devices ADIS16550 inertial + sensor. + + To compile this driver as a module, choose M here: the module will be + called adis16550. + source "drivers/iio/imu/bmi160/Kconfig" source "drivers/iio/imu/bmi323/Kconfig" source "drivers/iio/imu/bno055/Kconfig" diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile index 7e2d7d5c3b7b..006fa5b71d12 100644 --- a/drivers/iio/imu/Makefile +++ b/drivers/iio/imu/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_ADIS16400) += adis16400.o obj-$(CONFIG_ADIS16460) += adis16460.o obj-$(CONFIG_ADIS16475) += adis16475.o obj-$(CONFIG_ADIS16480) += adis16480.o +obj-$(CONFIG_ADIS16550) += adis16550.o adis_lib-y += adis.o adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_trigger.o diff --git a/drivers/iio/imu/adis16550.c b/drivers/iio/imu/adis16550.c new file mode 100644 index 000000000000..db0e9dcadca2 --- /dev/null +++ b/drivers/iio/imu/adis16550.c @@ -0,0 +1,1203 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ADIS16550 IMU driver + * + * Copyright 2024 Analog Devices Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define ADIS16550_REG_BURST_GYRO_ACCEL 0x0a +#define ADIS16550_REG_BURST_DELTA_ANG_VEL 0x0b +#define ADIS16550_BURST_DATA_GYRO_ACCEL_MASK GENMASK(5, 0) +#define ADIS16550_BURST_DATA_DELTA_ANG_VEL_MASK GENMASK(12, 7) + +#define ADIS16550_REG_STATUS 0x0e +#define ADIS16550_REG_TEMP 0x10 +#define ADIS16550_REG_X_GYRO 0x12 +#define ADIS16550_REG_Y_GYRO 0x14 +#define ADIS16550_REG_Z_GYRO 0x16 +#define ADIS16550_REG_X_ACCEL 0x18 +#define ADIS16550_REG_Y_ACCEL 0x1a +#define ADIS16550_REG_Z_ACCEL 0x1c +#define ADIS16550_REG_X_DELTANG_L 0x1E +#define ADIS16550_REG_Y_DELTANG_L 0x20 +#define ADIS16550_REG_Z_DELTANG_L 0x22 +#define ADIS16550_REG_X_DELTVEL_L 0x24 +#define ADIS16550_REG_Y_DELTVEL_L 0x26 +#define ADIS16550_REG_Z_DELTVEL_L 0x28 +#define ADIS16550_REG_X_GYRO_SCALE 0x30 +#define ADIS16550_REG_Y_GYRO_SCALE 0x32 +#define ADIS16550_REG_Z_GYRO_SCALE 0x34 +#define ADIS16550_REG_X_ACCEL_SCALE 0x36 +#define ADIS16550_REG_Y_ACCEL_SCALE 0x38 +#define ADIS16550_REG_Z_ACCEL_SCALE 0x3a +#define ADIS16550_REG_X_GYRO_BIAS 0x40 +#define ADIS16550_REG_Y_GYRO_BIAS 0x42 +#define ADIS16550_REG_Z_GYRO_BIAS 0x44 +#define ADIS16550_REG_X_ACCEL_BIAS 0x46 +#define ADIS16550_REG_Y_ACCEL_BIAS 0x48 +#define ADIS16550_REG_Z_ACCEL_BIAS 0x4a +#define ADIS16550_REG_COMMAND 0x50 +#define ADIS16550_REG_CONFIG 0x52 +#define ADIS16550_GYRO_FIR_EN_MASK BIT(3) +#define ADIS16550_ACCL_FIR_EN_MASK BIT(2) +#define ADIS16550_SYNC_MASK \ + (ADIS16550_SYNC_EN_MASK | ADIS16550_SYNC_MODE_MASK) +#define ADIS16550_SYNC_MODE_MASK BIT(1) +#define ADIS16550_SYNC_EN_MASK BIT(0) +/* max of 4000 SPS in scale sync */ +#define ADIS16550_SYNC_SCALE_MAX_RATE (4000 * 1000) +#define ADIS16550_REG_DEC_RATE 0x54 +#define ADIS16550_REG_SYNC_SCALE 0x56 +#define ADIS16550_REG_SERIAL_NUM 0x76 +#define ADIS16550_REG_FW_REV 0x7A +#define ADIS16550_REG_FW_DATE 0x7C +#define ADIS16550_REG_PROD_ID 0x7E +#define ADIS16550_REG_FLASH_CNT 0x72 +/* spi protocol*/ +#define ADIS16550_SPI_DATA_MASK GENMASK(31, 16) +#define ADIS16550_SPI_REG_MASK GENMASK(14, 8) +#define ADIS16550_SPI_R_W_MASK BIT(7) +#define ADIS16550_SPI_CRC_MASK GENMASK(3, 0) +#define ADIS16550_SPI_SV_MASK GENMASK(7, 6) +/* burst read */ +#define ADIS16550_BURST_N_ELEM 12 +#define ADIS16550_BURST_DATA_LEN (ADIS16550_BURST_N_ELEM * 4) +#define ADIS16550_MAX_SCAN_DATA 12 + +struct adis16550_sync { + u16 sync_mode; + u16 min_rate; + u16 max_rate; +}; + +struct adis16550_chip_info { + const struct iio_chan_spec *channels; + const struct adis16550_sync *sync_mode; + char *name; + u32 num_channels; + u32 gyro_max_val; + u32 gyro_max_scale; + u32 accel_max_val; + u32 accel_max_scale; + u32 temp_scale; + u32 deltang_max_val; + u32 deltvel_max_val; + u32 int_clk; + u16 max_dec; + u16 num_sync; +}; + +struct adis16550 { + const struct adis16550_chip_info *info; + struct adis adis; + unsigned long clk_freq_hz; + u32 sync_mode; +}; + +enum { + ADIS16550_SV_INIT, + ADIS16550_SV_OK, + ADIS16550_SV_NOK, + ADIS16550_SV_SPI_ERROR, +}; + +/* + * This is a simplified implementation of lib/crc4.c. It could not be used + * directly since the polynomial used is different from the one used by the + * 16550 which is 0b10001 + */ +static u8 spi_crc4(const u32 val) +{ + int i; + const int bits = 28; + u8 crc = 0xa; + /* ignore 4lsb */ + const u32 __val = val >> 4; + + /* Calculate crc4 over four-bit nibbles, starting at the MSbit */ + for (i = bits - 4; i >= 0; i -= 4) + crc = crc ^ ((__val >> i) & 0xf); + + return crc; +} + +static int adis16550_spi_validate(const struct adis *adis, __be32 dout, + u16 *data) +{ + u32 __dout; + u8 crc, crc_rcv, sv; + + __dout = be32_to_cpu(dout); + + /* validate received message */ + crc_rcv = FIELD_GET(ADIS16550_SPI_CRC_MASK, __dout); + crc = spi_crc4(__dout); + if (crc_rcv != crc) { + dev_err(&adis->spi->dev, + "Invalid crc, rcv: 0x%02x, calc: 0x%02x!\n", + crc_rcv, crc); + return -EIO; + } + sv = FIELD_GET(ADIS16550_SPI_SV_MASK, __dout); + if (sv >= ADIS16550_SV_NOK) { + dev_err(&adis->spi->dev, + "State vector error detected: %02X", sv); + return -EIO; + } + *data = FIELD_GET(ADIS16550_SPI_DATA_MASK, __dout); + + return 0; +} + +static void adis16550_spi_msg_prepare(const u32 reg, const bool write, + const u16 data, __be32 *din) +{ + u8 crc; + u32 __din; + + __din = FIELD_PREP(ADIS16550_SPI_REG_MASK, reg); + + if (write) { + __din |= FIELD_PREP(ADIS16550_SPI_R_W_MASK, true); + __din |= FIELD_PREP(ADIS16550_SPI_DATA_MASK, data); + } + + crc = spi_crc4(__din); + __din |= FIELD_PREP(ADIS16550_SPI_CRC_MASK, crc); + + *din = cpu_to_be32(__din); +} + +static int adis16550_spi_xfer(const struct adis *adis, u32 reg, u32 len, + u32 *readval, u32 writeval) +{ + int ret; + u16 data = 0; + struct spi_message msg; + __be32 __din[2], __dout[2]; + bool wr = readval ? false : true; + struct spi_device *spi = adis->spi; + struct spi_transfer xfers[] = { + { + .tx_buf = &__din[0], + .len = 4, + .cs_change = 1, + }, { + .tx_buf = &__din[1], + .len = 4, + .cs_change = 1, + .rx_buf = __dout, + }, { + .tx_buf = &__din[1], + .rx_buf = &__dout[1], + .len = 4, + }, + }; + + spi_message_init(&msg); + + switch (len) { + case 4: + adis16550_spi_msg_prepare(reg + 1, wr, writeval >> 16, + &__din[0]); + spi_message_add_tail(&xfers[0], &msg); + fallthrough; + case 2: + adis16550_spi_msg_prepare(reg, wr, writeval, &__din[1]); + spi_message_add_tail(&xfers[1], &msg); + spi_message_add_tail(&xfers[2], &msg); + break; + default: + return -EINVAL; + } + + ret = spi_sync(spi, &msg); + if (ret) { + dev_err(&spi->dev, "Spi failure %d\n", ret); + return ret; + } + /* + * When writing a register, the device will reply with a readback on the + * transfer so that we can validate if our data was actually written.. + */ + switch (len) { + case 4: + ret = adis16550_spi_validate(adis, __dout[0], &data); + if (ret) + return ret; + + if (readval) { + *readval = data << 16; + } else if ((writeval >> 16) != data && reg != ADIS16550_REG_COMMAND) { + dev_err(&spi->dev, + "Data not written: wr: 0x%04X, rcv: 0x%04X\n", + writeval >> 16, data); + return -EIO; + } + + fallthrough; + case 2: + ret = adis16550_spi_validate(adis, __dout[1], &data); + if (ret) + return ret; + + if (readval) { + *readval = (*readval & GENMASK(31, 16)) | data; + } else if ((writeval & GENMASK(15, 0)) != data && reg != ADIS16550_REG_COMMAND) { + dev_err(&spi->dev, + "Data not written: wr: 0x%04X, rcv: 0x%04X\n", + (u16)writeval, data); + return -EIO; + } + } + + return 0; +} + +static int adis16550_spi_read(struct adis *adis, const u32 reg, + u32 *value, const u32 len) +{ + return adis16550_spi_xfer(adis, reg, len, value, 0); +} + +static int adis16550_spi_write(struct adis *adis, const u32 reg, + const u32 value, const u32 len) +{ + return adis16550_spi_xfer(adis, reg, len, NULL, value); +} + +static ssize_t adis16550_show_firmware_revision(struct file *file, + char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct adis16550 *st = file->private_data; + char buf[7]; + size_t len; + u16 rev; + int ret; + + ret = adis_read_reg_16(&st->adis, ADIS16550_REG_FW_REV, &rev); + if (ret) + return ret; + + len = scnprintf(buf, sizeof(buf), "%x.%x\n", rev >> 8, rev & 0xff); + + return simple_read_from_buffer(userbuf, count, ppos, buf, len); +} + +static const struct file_operations adis16550_firmware_revision_fops = { + .open = simple_open, + .read = adis16550_show_firmware_revision, + .llseek = default_llseek, + .owner = THIS_MODULE, +}; + +static ssize_t adis16550_show_firmware_date(struct file *file, + char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct adis16550 *st = file->private_data; + u32 date; + char buf[12]; + size_t len; + int ret; + + ret = adis_read_reg_32(&st->adis, ADIS16550_REG_FW_DATE, &date); + if (ret) + return ret; + + len = scnprintf(buf, sizeof(buf), "%.2x-%.2x-%.4x\n", date & 0xff, + (date >> 8) & 0xff, date >> 16); + + return simple_read_from_buffer(userbuf, count, ppos, buf, len); +} + +static const struct file_operations adis16550_firmware_date_fops = { + .open = simple_open, + .read = adis16550_show_firmware_date, + .llseek = default_llseek, + .owner = THIS_MODULE, +}; + +static int adis16550_show_serial_number(void *arg, u64 *val) +{ + struct adis16550 *st = arg; + u32 serial; + int ret; + + ret = adis_read_reg_32(&st->adis, ADIS16550_REG_SERIAL_NUM, &serial); + if (ret) + return ret; + + *val = serial; + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(adis16550_serial_number_fops, + adis16550_show_serial_number, NULL, "0x%.8llx\n"); + +static int adis16550_show_product_id(void *arg, u64 *val) +{ + struct adis16550 *st = arg; + u16 prod_id; + int ret; + + ret = adis_read_reg_16(&st->adis, ADIS16550_REG_PROD_ID, &prod_id); + if (ret) + return ret; + + *val = prod_id; + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(adis16550_product_id_fops, + adis16550_show_product_id, NULL, "%llu\n"); + +static int adis16550_show_flash_count(void *arg, u64 *val) +{ + struct adis16550 *st = arg; + u16 flash_count; + int ret; + + ret = adis_read_reg_16(&st->adis, ADIS16550_REG_FLASH_CNT, &flash_count); + if (ret) + return ret; + + *val = flash_count; + + return 0; +} +DEFINE_DEBUGFS_ATTRIBUTE(adis16550_flash_count_fops, + adis16550_show_flash_count, NULL, "%lld\n"); + +static void adis16550_debugfs_init(struct iio_dev *indio_dev) +{ + struct adis16550 *st = iio_priv(indio_dev); + struct dentry *d = iio_get_debugfs_dentry(indio_dev); + + debugfs_create_file_unsafe("serial_number", 0400, + d, st, &adis16550_serial_number_fops); + debugfs_create_file_unsafe("product_id", 0400, + d, st, &adis16550_product_id_fops); + debugfs_create_file("firmware_revision", 0400, + d, st, &adis16550_firmware_revision_fops); + debugfs_create_file("firmware_date", 0400, d, + st, &adis16550_firmware_date_fops); + debugfs_create_file_unsafe("flash_count", 0400, + d, st, &adis16550_flash_count_fops); +} + +enum { + ADIS16550_SYNC_MODE_DIRECT, + ADIS16550_SYNC_MODE_SCALED, +}; + +static int adis16550_get_freq(struct adis16550 *st, u32 *freq) +{ + int ret; + u16 dec = 0; + u32 sample_rate = st->clk_freq_hz; + + adis_dev_auto_lock(&st->adis); + + if (st->sync_mode == ADIS16550_SYNC_MODE_SCALED) { + u16 sync_scale; + + ret = __adis_read_reg_16(&st->adis, ADIS16550_REG_SYNC_SCALE, &sync_scale); + if (ret) + return ret; + + sample_rate = st->clk_freq_hz * sync_scale; + } + + ret = __adis_read_reg_16(&st->adis, ADIS16550_REG_DEC_RATE, &dec); + if (ret) + return -EINVAL; + + *freq = DIV_ROUND_CLOSEST(sample_rate, dec + 1); + + return 0; +} + +static int adis16550_set_freq_hz(struct adis16550 *st, u32 freq_hz) +{ + u16 dec; + int ret; + u32 sample_rate = st->clk_freq_hz; + /* + * The optimal sample rate for the supported IMUs is between + * int_clk - 1000 and int_clk + 500. + */ + u32 max_sample_rate = st->info->int_clk * 1000 + 500000; + u32 min_sample_rate = st->info->int_clk * 1000 - 1000000; + + if (!freq_hz) + return -EINVAL; + + adis_dev_auto_lock(&st->adis); + + if (st->sync_mode == ADIS16550_SYNC_MODE_SCALED) { + unsigned long scaled_rate = lcm(st->clk_freq_hz, freq_hz); + int sync_scale; + + if (scaled_rate > max_sample_rate) + scaled_rate = max_sample_rate / st->clk_freq_hz * st->clk_freq_hz; + else + scaled_rate = max_sample_rate / scaled_rate * scaled_rate; + + if (scaled_rate < min_sample_rate) + scaled_rate = roundup(min_sample_rate, st->clk_freq_hz); + + sync_scale = scaled_rate / st->clk_freq_hz; + ret = __adis_write_reg_16(&st->adis, ADIS16550_REG_SYNC_SCALE, + sync_scale); + if (ret) + return ret; + + sample_rate = scaled_rate; + } + + dec = DIV_ROUND_CLOSEST(sample_rate, freq_hz); + + if (dec) + dec--; + + dec = min(dec, st->info->max_dec); + + ret = __adis_write_reg_16(&st->adis, ADIS16550_REG_DEC_RATE, dec); + + return ret; +} + +static int adis16550_get_accl_filter_freq(struct adis16550 *st, int *freq_hz) +{ + int ret; + u16 config = 0; + + ret = adis_read_reg_16(&st->adis, ADIS16550_REG_CONFIG, &config); + if (ret) + return -EINVAL; + + if (FIELD_GET(ADIS16550_ACCL_FIR_EN_MASK, config)) + *freq_hz = 100; + else + *freq_hz = 0; + + return 0; +} + +static int adis16550_set_accl_filter_freq(struct adis16550 *st, int freq_hz) +{ + bool en = false; + + if (freq_hz) + en = true; + + return __adis_update_bits(&st->adis, ADIS16550_REG_CONFIG, + ADIS16550_ACCL_FIR_EN_MASK, + (u32)FIELD_PREP(ADIS16550_ACCL_FIR_EN_MASK, en)); +} + +static int adis16550_get_gyro_filter_freq(struct adis16550 *st, int *freq_hz) +{ + int ret; + u16 config = 0; + + ret = adis_read_reg_16(&st->adis, ADIS16550_REG_CONFIG, &config); + if (ret) + return -EINVAL; + + if (FIELD_GET(ADIS16550_GYRO_FIR_EN_MASK, config)) + *freq_hz = 100; + else + *freq_hz = 0; + + return 0; +} + +static int adis16550_set_gyro_filter_freq(struct adis16550 *st, int freq_hz) +{ + bool en = false; + + if (freq_hz) + en = true; + + return __adis_update_bits(&st->adis, ADIS16550_REG_CONFIG, + ADIS16550_GYRO_FIR_EN_MASK, + (u32)FIELD_PREP(ADIS16550_GYRO_FIR_EN_MASK, en)); +} + +enum adis16550_variants { + ADIS16550, + ADIS16550W +}; + +enum { + ADIS16550_SCAN_GYRO_X, + ADIS16550_SCAN_GYRO_Y, + ADIS16550_SCAN_GYRO_Z, + ADIS16550_SCAN_ACCEL_X, + ADIS16550_SCAN_ACCEL_Y, + ADIS16550_SCAN_ACCEL_Z, + ADIS16550_SCAN_TEMP, + ADIS16550_SCAN_DELTANG_X, + ADIS16550_SCAN_DELTANG_Y, + ADIS16550_SCAN_DELTANG_Z, + ADIS16550_SCAN_DELTVEL_X, + ADIS16550_SCAN_DELTVEL_Y, + ADIS16550_SCAN_DELTVEL_Z, +}; + +static const u32 adis16550_calib_bias[] = { + [ADIS16550_SCAN_GYRO_X] = ADIS16550_REG_X_GYRO_BIAS, + [ADIS16550_SCAN_GYRO_Y] = ADIS16550_REG_Y_GYRO_BIAS, + [ADIS16550_SCAN_GYRO_Z] = ADIS16550_REG_Z_GYRO_BIAS, + [ADIS16550_SCAN_ACCEL_X] = ADIS16550_REG_X_ACCEL_BIAS, + [ADIS16550_SCAN_ACCEL_Y] = ADIS16550_REG_Y_ACCEL_BIAS, + [ADIS16550_SCAN_ACCEL_Z] = ADIS16550_REG_Z_ACCEL_BIAS, + +}; + +static const u32 adis16550_calib_scale[] = { + [ADIS16550_SCAN_GYRO_X] = ADIS16550_REG_X_GYRO_SCALE, + [ADIS16550_SCAN_GYRO_Y] = ADIS16550_REG_Y_GYRO_SCALE, + [ADIS16550_SCAN_GYRO_Z] = ADIS16550_REG_Z_GYRO_SCALE, + [ADIS16550_SCAN_ACCEL_X] = ADIS16550_REG_X_ACCEL_SCALE, + [ADIS16550_SCAN_ACCEL_Y] = ADIS16550_REG_Y_ACCEL_SCALE, + [ADIS16550_SCAN_ACCEL_Z] = ADIS16550_REG_Z_ACCEL_SCALE, +}; + +static int adis16550_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + int *val, int *val2, long info) +{ + struct adis16550 *st = iio_priv(indio_dev); + const int idx = chan->scan_index; + u16 scale; + int ret; + u32 tmp; + + switch (info) { + case IIO_CHAN_INFO_RAW: + return adis_single_conversion(indio_dev, chan, 0, val); + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ANGL_VEL: + *val = st->info->gyro_max_val; + *val2 = st->info->gyro_max_scale; + return IIO_VAL_FRACTIONAL; + case IIO_ACCEL: + *val = st->info->accel_max_val; + *val2 = st->info->accel_max_scale; + return IIO_VAL_FRACTIONAL; + case IIO_TEMP: + *val = st->info->temp_scale; + return IIO_VAL_INT; + case IIO_DELTA_ANGL: + *val = st->info->deltang_max_val; + *val2 = 31; + return IIO_VAL_FRACTIONAL_LOG2; + case IIO_DELTA_VELOCITY: + *val = st->info->deltvel_max_val; + *val2 = 31; + return IIO_VAL_FRACTIONAL_LOG2; + default: + return -EINVAL; + } + case IIO_CHAN_INFO_OFFSET: + /* temperature centered at 25°C */ + *val = DIV_ROUND_CLOSEST(25000, st->info->temp_scale); + return IIO_VAL_INT; + case IIO_CHAN_INFO_CALIBBIAS: + ret = adis_read_reg_32(&st->adis, + adis16550_calib_bias[idx], val); + if (ret) + return ret; + + return IIO_VAL_INT; + case IIO_CHAN_INFO_CALIBSCALE: + ret = adis_read_reg_16(&st->adis, + adis16550_calib_scale[idx], &scale); + if (ret) + return ret; + + *val = scale; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SAMP_FREQ: + ret = adis16550_get_freq(st, &tmp); + if (ret) + return ret; + + *val = tmp / 1000; + *val2 = (tmp % 1000) * 1000; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + switch (chan->type) { + case IIO_ANGL_VEL: + ret = adis16550_get_accl_filter_freq(st, val); + if (ret) + return ret; + return IIO_VAL_INT; + case IIO_ACCEL: + ret = adis16550_get_gyro_filter_freq(st, val); + if (ret) + return ret; + return IIO_VAL_INT; + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +static int adis16550_write_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + int val, int val2, long info) +{ + struct adis16550 *st = iio_priv(indio_dev); + const int idx = chan->scan_index; + u32 tmp; + + switch (info) { + case IIO_CHAN_INFO_SAMP_FREQ: + tmp = val * 1000 + val2 / 1000; + return adis16550_set_freq_hz(st, tmp); + case IIO_CHAN_INFO_CALIBBIAS: + return adis_write_reg_32(&st->adis, adis16550_calib_bias[idx], + val); + case IIO_CHAN_INFO_CALIBSCALE: + return adis_write_reg_16(&st->adis, adis16550_calib_scale[idx], + val); + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + switch (chan->type) { + case IIO_ANGL_VEL: + return adis16550_set_accl_filter_freq(st, val); + case IIO_ACCEL: + return adis16550_set_gyro_filter_freq(st, val); + default: + return -EINVAL; + } + default: + return -EINVAL; + } +} + +#define ADIS16550_MOD_CHAN(_type, _mod, _address, _si) \ + { \ + .type = (_type), \ + .modified = 1, \ + .channel2 = (_mod), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_CALIBBIAS) | \ + BIT(IIO_CHAN_INFO_CALIBSCALE), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .address = (_address), \ + .scan_index = (_si), \ + .scan_type = { \ + .sign = 's', \ + .realbits = 32, \ + .storagebits = 32, \ + .endianness = IIO_BE, \ + }, \ + } + +#define ADIS16550_GYRO_CHANNEL(_mod) \ + ADIS16550_MOD_CHAN(IIO_ANGL_VEL, IIO_MOD_ ## _mod, \ + ADIS16550_REG_ ## _mod ## _GYRO, ADIS16550_SCAN_GYRO_ ## _mod) + +#define ADIS16550_ACCEL_CHANNEL(_mod) \ + ADIS16550_MOD_CHAN(IIO_ACCEL, IIO_MOD_ ## _mod, \ + ADIS16550_REG_ ## _mod ## _ACCEL, ADIS16550_SCAN_ACCEL_ ## _mod) + +#define ADIS16550_TEMP_CHANNEL() { \ + .type = IIO_TEMP, \ + .indexed = 1, \ + .channel = 0, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .address = ADIS16550_REG_TEMP, \ + .scan_index = ADIS16550_SCAN_TEMP, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 32, \ + .endianness = IIO_BE, \ + }, \ + } + +#define ADIS16550_MOD_CHAN_DELTA(_type, _mod, _address, _si) { \ + .type = (_type), \ + .modified = 1, \ + .channel2 = (_mod), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .address = (_address), \ + .scan_index = _si, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 32, \ + .storagebits = 32, \ + .endianness = IIO_BE, \ + }, \ + } + +#define ADIS16550_DELTANG_CHAN(_mod) \ + ADIS16550_MOD_CHAN_DELTA(IIO_DELTA_ANGL, IIO_MOD_ ## _mod, \ + ADIS16550_REG_ ## _mod ## _DELTANG_L, ADIS16550_SCAN_DELTANG_ ## _mod) + +#define ADIS16550_DELTVEL_CHAN(_mod) \ + ADIS16550_MOD_CHAN_DELTA(IIO_DELTA_VELOCITY, IIO_MOD_ ## _mod, \ + ADIS16550_REG_ ## _mod ## _DELTVEL_L, ADIS16550_SCAN_DELTVEL_ ## _mod) + +#define ADIS16550_DELTANG_CHAN_NO_SCAN(_mod) \ + ADIS16550_MOD_CHAN_DELTA(IIO_DELTA_ANGL, IIO_MOD_ ## _mod, \ + ADIS16550_REG_ ## _mod ## _DELTANG_L, -1) + +#define ADIS16550_DELTVEL_CHAN_NO_SCAN(_mod) \ + ADIS16550_MOD_CHAN_DELTA(IIO_DELTA_VELOCITY, IIO_MOD_ ## _mod, \ + ADIS16550_REG_ ## _mod ## _DELTVEL_L, -1) + +static const struct iio_chan_spec adis16550_channels[] = { + ADIS16550_GYRO_CHANNEL(X), + ADIS16550_GYRO_CHANNEL(Y), + ADIS16550_GYRO_CHANNEL(Z), + ADIS16550_ACCEL_CHANNEL(X), + ADIS16550_ACCEL_CHANNEL(Y), + ADIS16550_ACCEL_CHANNEL(Z), + ADIS16550_TEMP_CHANNEL(), + ADIS16550_DELTANG_CHAN(X), + ADIS16550_DELTANG_CHAN(Y), + ADIS16550_DELTANG_CHAN(Z), + ADIS16550_DELTVEL_CHAN(X), + ADIS16550_DELTVEL_CHAN(Y), + ADIS16550_DELTVEL_CHAN(Z), + IIO_CHAN_SOFT_TIMESTAMP(13), +}; + +static const struct adis16550_sync adis16550_sync_modes[] = { + { ADIS16550_SYNC_MODE_DIRECT, 3000, 4500 }, + { ADIS16550_SYNC_MODE_SCALED, 1, 128 }, +}; + +static const struct adis16550_chip_info adis16550_chip_info_ip = { + .num_channels = ARRAY_SIZE(adis16550_channels), + .channels = adis16550_channels, + .name = "adis16550", + .gyro_max_val = 1, + .gyro_max_scale = IIO_RAD_TO_DEGREE(80 << 16), + .accel_max_val = 1, + .accel_max_scale = IIO_M_S_2_TO_G(102400000), + .temp_scale = 4, + .deltang_max_val = IIO_DEGREE_TO_RAD(720), + .deltvel_max_val = 125, + .int_clk = 4000, + .max_dec = 4095, + .sync_mode = adis16550_sync_modes, + .num_sync = ARRAY_SIZE(adis16550_sync_modes), +}; + +static u32 adis16550_validate_crc(const u32 *buf, const u8 n_elem, + const u32 crc) +{ + int i; + u32 crc_calc; + u32 crc_buf[ADIS16550_BURST_N_ELEM - 2]; + /* + * The crc calculation of the data is done in little endian. Hence, we + * always swap the 32bit elements making sure that the data LSB is + * always on address 0... + */ + for (i = 0; i < n_elem; i++) + crc_buf[i] = swab32(buf[i]); + + crc_calc = crc32(~0, crc_buf, n_elem * 4); + crc_calc ^= ~0; + + return (crc_calc == crc); +} + +static irqreturn_t adis16550_trigger_handler(int irq, void *p) +{ + u32 crc; + u16 dummy; + bool valid; + int ret, i = 0; + u8 data_offset = 4; + struct iio_poll_func *pf = p; + __be32 data[ADIS16550_MAX_SCAN_DATA]; + struct iio_dev *indio_dev = pf->indio_dev; + struct adis16550 *st = iio_priv(indio_dev); + struct adis *adis = iio_device_get_drvdata(indio_dev); + __be32 *buffer = adis->buffer; + + ret = spi_sync(adis->spi, &adis->msg); + if (ret) + goto done; + /* + * Validate the header. The header is a normal spi reply with state + * vector and crc4. + */ + ret = adis16550_spi_validate(&st->adis, buffer[0], &dummy); + if (ret) + goto done; + + crc = be32_to_cpu(buffer[ADIS16550_BURST_N_ELEM - 1]); + /* the header is not included in the crc */ + valid = adis16550_validate_crc((u32 *)&buffer[1], + ADIS16550_BURST_N_ELEM - 2, crc); + if (!valid) { + dev_err(&adis->spi->dev, "Burst Invalid crc!\n"); + goto done; + } + + if (*indio_dev->active_scan_mask & BIT(ADIS16550_SCAN_GYRO_X)) { + memcpy(&data[i], &buffer[data_offset], (ADIS16550_SCAN_ACCEL_Z - + ADIS16550_SCAN_GYRO_X + 1) * + sizeof(__be32)); + i += ADIS16550_SCAN_ACCEL_Z - ADIS16550_SCAN_GYRO_X + 1; + } + if (*indio_dev->active_scan_mask & BIT(ADIS16550_SCAN_TEMP)) + data[i++] = buffer[data_offset - 1]; + if (*indio_dev->active_scan_mask & BIT(ADIS16550_SCAN_DELTANG_X)) + memcpy(&data[i], &buffer[data_offset], (ADIS16550_SCAN_DELTVEL_Z - + ADIS16550_SCAN_DELTANG_X + 1) * + sizeof(__be32)); + + iio_push_to_buffers_with_timestamp(indio_dev, data, pf->timestamp); +done: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + +static const unsigned long adis16550_channel_masks[] = { + ADIS16550_BURST_DATA_GYRO_ACCEL_MASK | BIT(ADIS16550_SCAN_TEMP), + ADIS16550_BURST_DATA_DELTA_ANG_VEL_MASK | BIT(ADIS16550_SCAN_TEMP), + 0, +}; + +static int adis16550_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct adis *adis = iio_device_get_drvdata(indio_dev); + u16 burst_length = ADIS16550_BURST_DATA_LEN; + u8 burst_cmd; + u8 *tx; + + if (*scan_mask & ADIS16550_BURST_DATA_GYRO_ACCEL_MASK) + burst_cmd = ADIS16550_REG_BURST_GYRO_ACCEL; + else + burst_cmd = ADIS16550_REG_BURST_DELTA_ANG_VEL; + + if (adis->xfer) + memset(adis->xfer, 0, 2 * sizeof(*adis->xfer)); + if (adis->buffer) + memset(adis->buffer, 0, burst_length + sizeof(u32)); + + tx = adis->buffer + burst_length; + tx[0] = 0x00; + tx[1] = 0x00; + tx[2] = burst_cmd; + /* crc4 is 0 on burst command */ + tx[3] = spi_crc4(get_unaligned_le32(tx)); + + adis->xfer[0].tx_buf = tx; + adis->xfer[0].len = 4; + adis->xfer[0].cs_change = 1; + adis->xfer[0].delay.value = 8; + adis->xfer[0].delay.unit = SPI_DELAY_UNIT_USECS; + adis->xfer[1].rx_buf = adis->buffer; + adis->xfer[1].len = burst_length; + + spi_message_init_with_transfers(&adis->msg, adis->xfer, 2); + + return 0; +} + +static int adis16550_reset(struct adis *adis) +{ + return __adis_write_reg_16(adis, ADIS16550_REG_COMMAND, BIT(15)); +} + +static int adis16550_config_sync(struct adis16550 *st) +{ + struct device *dev = &st->adis.spi->dev; + const struct adis16550_sync *sync; + struct clk *clk; + u32 sync_mode; + u16 mode; + int ret; + + if (!device_property_present(dev, "adi,sync-mode")) { + st->clk_freq_hz = st->info->int_clk * 1000; + return 0; + } + + if (!device_property_match_string(dev, "adi,sync-mode", "direct_sync")) + sync_mode = 0; + else if (!device_property_match_string(dev, "adi,sync-mode", "scaled_sync")) + sync_mode = 1; + else + return -EINVAL; + + sync = &st->info->sync_mode[sync_mode]; + st->sync_mode = sync->sync_mode; + + clk = devm_clk_get_enabled(dev, NULL); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + st->clk_freq_hz = clk_get_rate(clk); + if (st->clk_freq_hz > sync->max_rate || st->clk_freq_hz < sync->min_rate) + return dev_err_probe(dev, -EINVAL, + "Clk rate: %lu not in a valid range:[%u %u]\n", + st->clk_freq_hz, sync->min_rate, sync->max_rate); + + if (sync->sync_mode == ADIS16550_SYNC_MODE_SCALED) { + u16 sync_scale; + u32 scaled_freq = 0; + /* + * In pps scaled sync we must scale the input clock to a range + * of [3000 45000]. + */ + ret = device_property_read_u32(dev, "adi,scaled-output-hz", + &scaled_freq); + if (ret) + return dev_err_probe(dev, ret, + "adi,scaled-output-hz property not found"); + + if (scaled_freq < 3000 || scaled_freq > 4500) + return dev_err_probe(dev, -EINVAL, + "Invalid value:%u for adi,scaled-output-hz", + scaled_freq); + + sync_scale = DIV_ROUND_CLOSEST(scaled_freq, st->clk_freq_hz); + + ret = adis_write_reg_16(&st->adis, ADIS16550_REG_SYNC_SCALE, + sync_scale); + if (ret) + return ret; + + st->clk_freq_hz = scaled_freq; + } + + st->clk_freq_hz *= 1000; + + mode = FIELD_PREP(ADIS16550_SYNC_MODE_MASK, sync->sync_mode) | + FIELD_PREP(ADIS16550_SYNC_EN_MASK, true); + + return __adis_update_bits(&st->adis, ADIS16550_REG_CONFIG, + ADIS16550_SYNC_MASK, mode); +} + +static const struct iio_info adis16550_info = { + .read_raw = &adis16550_read_raw, + .write_raw = &adis16550_write_raw, + .update_scan_mode = adis16550_update_scan_mode, + .debugfs_reg_access = adis_debugfs_reg_access, +}; + +enum { + ADIS16550_STATUS_CRC_CODE, + ADIS16550_STATUS_CRC_CONFIG, + ADIS16550_STATUS_FLASH_UPDATE, + ADIS16550_STATUS_INERIAL, + ADIS16550_STATUS_SENSOR, + ADIS16550_STATUS_TEMPERATURE, + ADIS16550_STATUS_SPI, + ADIS16550_STATUS_PROCESSING, + ADIS16550_STATUS_POWER, + ADIS16550_STATUS_BOOT, + ADIS16550_STATUS_WATCHDOG = 15, + ADIS16550_STATUS_REGULATOR = 28, + ADIS16550_STATUS_SENSOR_SUPPLY, + ADIS16550_STATUS_CPU_SUPPLY, + ADIS16550_STATUS_5V_SUPPLY +}; + +static const char * const adis16550_status_error_msgs[] = { + [ADIS16550_STATUS_CRC_CODE] = "Code CRC Error", + [ADIS16550_STATUS_CRC_CONFIG] = "Configuration/Calibration CRC Error", + [ADIS16550_STATUS_FLASH_UPDATE] = "Flash Update Error", + [ADIS16550_STATUS_INERIAL] = "Overrange for Inertial Signals", + [ADIS16550_STATUS_SENSOR] = "Sensor failure", + [ADIS16550_STATUS_TEMPERATURE] = "Temperature Error", + [ADIS16550_STATUS_SPI] = "SPI Communication Error", + [ADIS16550_STATUS_PROCESSING] = "Processing Overrun Error", + [ADIS16550_STATUS_POWER] = "Power Supply Failure", + [ADIS16550_STATUS_BOOT] = "Boot Memory Failure", + [ADIS16550_STATUS_WATCHDOG] = "Watchdog timer flag", + [ADIS16550_STATUS_REGULATOR] = "Internal Regulator Error", + [ADIS16550_STATUS_SENSOR_SUPPLY] = "Internal Sensor Supply Error.", + [ADIS16550_STATUS_CPU_SUPPLY] = "Internal Processor Supply Error.", + [ADIS16550_STATUS_5V_SUPPLY] = "External 5V Supply Error", +}; + +static const struct adis_timeout adis16550_timeouts = { + .reset_ms = 1000, + .sw_reset_ms = 1000, + .self_test_ms = 1000, +}; + +static const struct adis_data adis16550_data = { + .diag_stat_reg = ADIS16550_REG_STATUS, + .diag_stat_size = 4, + .prod_id_reg = ADIS16550_REG_PROD_ID, + .prod_id = 16550, + .self_test_mask = BIT(1), + .self_test_reg = ADIS16550_REG_COMMAND, + .cs_change_delay = 5, + .unmasked_drdy = true, + .status_error_msgs = adis16550_status_error_msgs, + .status_error_mask = BIT(ADIS16550_STATUS_CRC_CODE) | + BIT(ADIS16550_STATUS_CRC_CONFIG) | + BIT(ADIS16550_STATUS_FLASH_UPDATE) | + BIT(ADIS16550_STATUS_INERIAL) | + BIT(ADIS16550_STATUS_SENSOR) | + BIT(ADIS16550_STATUS_TEMPERATURE) | + BIT(ADIS16550_STATUS_SPI) | + BIT(ADIS16550_STATUS_PROCESSING) | + BIT(ADIS16550_STATUS_POWER) | + BIT(ADIS16550_STATUS_BOOT) | + BIT(ADIS16550_STATUS_WATCHDOG) | + BIT(ADIS16550_STATUS_REGULATOR) | + BIT(ADIS16550_STATUS_SENSOR_SUPPLY) | + BIT(ADIS16550_STATUS_CPU_SUPPLY) | + BIT(ADIS16550_STATUS_5V_SUPPLY) | + BIT(ADIS16550_STATUS_CRC_CODE), + .timeouts = &adis16550_timeouts, +}; + +static const struct adis_ops adis16550_ops = { + .write = adis16550_spi_write, + .read = adis16550_spi_read, + .reset = adis16550_reset, +}; + +static inline void void_cleaner(void *v) {kfree(v); } + +DEFINE_FREE(void, void *, if (_T) void_cleaner(_T)) + +static int adis16550_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct iio_dev *indio_dev; + struct adis16550 *st; + int ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + st->info = &adis16550_chip_info_ip; + if (!st->info) + return -EINVAL; + + indio_dev->name = spi_get_device_id(spi)->name; + indio_dev->channels = st->info->channels; + indio_dev->num_channels = st->info->num_channels; + indio_dev->available_scan_masks = adis16550_channel_masks; + indio_dev->info = &adis16550_info; + indio_dev->modes = INDIO_DIRECT_MODE; + + st->adis.ops = &adis16550_ops; + + st->adis.xfer = kcalloc(2, sizeof(*st->adis.xfer), GFP_KERNEL); + if (!st->adis.xfer) + return -ENOMEM; + + void *buffer_tmp __free(void) = kzalloc(ADIS16550_BURST_DATA_LEN + sizeof(u32), + GFP_KERNEL); + if (!buffer_tmp) { + kfree(st->adis.xfer); + return -ENOMEM; + } + st->adis.buffer = no_free_ptr(buffer_tmp); + + ret = devm_regulator_get_enable(dev, "vdd"); + if (ret) + return dev_err_probe(dev, ret, + "Failed to get vdd regulator\n"); + + ret = adis_init(&st->adis, indio_dev, spi, &adis16550_data); + if (ret) + return ret; + + ret = __adis_initial_startup(&st->adis); + if (ret) + return ret; + + ret = adis16550_config_sync(st); + if (ret) + return ret; + + ret = devm_adis_setup_buffer_and_trigger(&st->adis, indio_dev, + adis16550_trigger_handler); + if (ret) + return ret; + + ret = devm_iio_device_register(dev, indio_dev); + if (ret) + return ret; + + adis16550_debugfs_init(indio_dev); + + return 0; +} + +static const struct spi_device_id adis16550_id[] = { + { "adis16550", ADIS16550 }, + { "adis16550w", ADIS16550W }, + { } +}; +MODULE_DEVICE_TABLE(spi, adis16550_id); + +static const struct of_device_id adis16550_of_match[] = { + { .compatible = "adi,adis16550" }, + { .compatible = "adi,adis16550w" }, + { } +}; +MODULE_DEVICE_TABLE(of, adis16550_of_match); + +static struct spi_driver adis16550_driver = { + .driver = { + .name = "adis16550", + .of_match_table = adis16550_of_match, + }, + .probe = adis16550_probe, + .id_table = adis16550_id, +}; +module_spi_driver(adis16550_driver); + +MODULE_AUTHOR("Nuno Sa "); +MODULE_AUTHOR("Ramona Gradinariu "); +MODULE_AUTHOR("Antoniu Miclaus "); +MODULE_DESCRIPTION("Analog Devices ADIS16550 IMU driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(IIO_ADISLIB); From patchwork Mon Nov 25 13:35:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Budai, Robert" X-Patchwork-Id: 13884910 Received: from mx0a-00128a01.pphosted.com (mx0a-00128a01.pphosted.com [148.163.135.77]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 629C81AE01C; Mon, 25 Nov 2024 13:36:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.135.77 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732541821; cv=none; b=ijcAJ8JAUHvzkFzwxgokefSauo1Rwc6qVTYCwlDTcD7geCjYKxt5i2EVEFOsWDQdGxzZaqY/FC3jrxgcSaI6zr3vi8bNwAU20fcuejx1rNz5rX7dynBfEe8y6par8vCLAA1DpbYqfYYBEcOJTl4pF5NeVDyVmJLhUjpsB/EzFMA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732541821; c=relaxed/simple; bh=OP1cvK1E1LTNMdwWJVXhDrx0QnVBd/fEBtLO7VTZnm4=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=GtAR5MpPZWPSXJKBp4mnyrIwDV0GK0AFcp+ngatFZkgqXfNEVWrBqA+TxeXPOPPqljXqYG59cjsLwdDt2x2ZLJaWBbC1vKmPMjhVynROoiUhBpmx+SmhAnV3S4ck2/BCPtsZfDNt6+SPRP4XzmvaaT02kiaeZyLLhEI0lb+guhU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com; spf=pass smtp.mailfrom=analog.com; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b=bk/rIo9n; arc=none smtp.client-ip=148.163.135.77 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=analog.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=analog.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=analog.com header.i=@analog.com header.b="bk/rIo9n" Received: from pps.filterd (m0167089.ppops.net [127.0.0.1]) by mx0a-00128a01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 4AP92hZJ005108; Mon, 25 Nov 2024 08:36:46 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=analog.com; h= content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=DKIM; bh=UfRKS WB3F4hpp4YIyoSvhDpb+QjZ07zm41OhATao2Ac=; b=bk/rIo9nv9ugjHEoN7Ra9 KXvyTLu3OKmjejvlqR70zuB4oskwEFUQ+B+7G17AWwpdMXLwIuCf+lDGYVlHWTWN Kd6w+1LYIVrasZKEib9fnhszxRVlhfdvGvgzUQ8wnQtavYMXVHPxOq3zZ/trxES/ kMInG1gMWll9jnyVAvTtbqxvhODI87iLARKnaNellPb0FEwKM2PFQhucAL3oM7PK cOG8fdEARa09s9G3W4+0Eag/Jn5C4MH+V8Kfjtds3K/yEt/stYdc5wUDPaRXtLyH JyyAzUkKrvToOHWhx/fMjEOL8kC50hcgbKLE+sXgVy8DFdv27Sr6cY6Edq1SuMyb g== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 433cu6rrcb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 25 Nov 2024 08:36:45 -0500 (EST) Received: from ASHBMBX8.ad.analog.com (ASHBMBX8.ad.analog.com [10.64.17.5]) by nwd2mta4.analog.com (8.14.7/8.14.7) with ESMTP id 4APDaiqf030786 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Mon, 25 Nov 2024 08:36:44 -0500 Received: from ASHBCASHYB4.ad.analog.com (10.64.17.132) by ASHBMBX8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Mon, 25 Nov 2024 08:36:44 -0500 Received: from ASHBMBX8.ad.analog.com (10.64.17.5) by ASHBCASHYB4.ad.analog.com (10.64.17.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.14; Mon, 25 Nov 2024 08:36:43 -0500 Received: from zeus.spd.analog.com (10.66.68.11) by ashbmbx8.ad.analog.com (10.64.17.5) with Microsoft SMTP Server id 15.2.986.14 via Frontend Transport; Mon, 25 Nov 2024 08:36:43 -0500 Received: from dell-precision-robert.ad.analog.com ([10.48.65.197]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 4APDZR2H031415; Mon, 25 Nov 2024 08:36:37 -0500 From: Robert Budai To: Lars-Peter Clausen , Michael Hennerich , Nuno Sa , "Ramona Gradinariu" , Antoniu Miclaus , Jonathan Cameron , "Rob Herring" , Krzysztof Kozlowski , "Conor Dooley" , Jonathan Corbet , Robert Budai , , , , Subject: [PATCH 7/7] docs: iio: add documentation for adis16550 driver Date: Mon, 25 Nov 2024 15:35:14 +0200 Message-ID: <20241125133520.24328-8-robert.budai@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241125133520.24328-1-robert.budai@analog.com> References: <20241125133520.24328-1-robert.budai@analog.com> Precedence: bulk X-Mailing-List: linux-iio@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ADIRuleOP-NewSCL: Rule Triggered X-Proofpoint-GUID: daeZlgMR_UN2SVNKzqSiGFhgQiERcGCK X-Proofpoint-ORIG-GUID: daeZlgMR_UN2SVNKzqSiGFhgQiERcGCK X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxlogscore=999 malwarescore=0 phishscore=0 clxscore=1015 spamscore=0 suspectscore=0 mlxscore=0 adultscore=0 lowpriorityscore=0 priorityscore=1501 impostorscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2409260000 definitions=main-2411250116 Add documentation for adis16550 driver which describes the driver device files and shows how the user may use the ABI for various scenarios (configuration, measurement, etc.). Co-developed-by: Antoniu Miclaus Signed-off-by: Antoniu Miclaus Signed-off-by: Ramona Gradinariu Signed-off-by: Robert Budai --- v2: - signed of by submitter Documentation/iio/adis16550.rst | 389 ++++++++++++++++++++++++++++++++ Documentation/iio/index.rst | 1 + 2 files changed, 390 insertions(+) create mode 100644 Documentation/iio/adis16550.rst diff --git a/Documentation/iio/adis16550.rst b/Documentation/iio/adis16550.rst new file mode 100644 index 000000000000..fde38060f8fe --- /dev/null +++ b/Documentation/iio/adis16550.rst @@ -0,0 +1,389 @@ +.. SPDX-License-Identifier: GPL-2.0 + +================ +ADIS16550 driver +================ + +This driver supports Analog Device's IMUs on SPI bus. + +1. Supported devices +==================== + +* `ADIS16550 `_ + +The ADIS16550 is a complete inertial system that includes a triaxis gyroscope +and a triaxis accelerometer. Each inertial sensor in the ADIS16550 combines +industry leading MEMS only technology with signal conditioning that optimizes +dynamic performance. The factory calibration characterizes each sensor for +sensitivity, bias, and alignment. As a result, each sensor has its own dynamic +compensation formulas that provide accurate sensor measurements. + +The ADIS16550 provides a simple, cost-effective method for integrating accurate, +multiaxis inertial sensing into industrial systems, especially when compared +with the complexity and investment associated with discrete designs. All +necessary motion testing and calibration are part of the production process at +the factory, greatly reducing system integration time. Tight orthogonal +alignment simplifies inertial frame alignment in navigation systems. The serial +peripheral interface (SPI) and register structure provide a simple interface for +data collection and configuration control. + +2. Device attributes +==================== + +Accelerometer, gyroscope measurements are always provided. Furthermore, the +driver offers the capability to retrieve the delta angle and the delta velocity +measurements computed by the device. + +The delta angle measurements represent a calculation of angular displacement +between each sample update, while the delta velocity measurements represent a +calculation of linear velocity change between each sample update. + +Finally, temperature data are provided which show a coarse measurement of +the temperature inside of the IMU device. This data is most useful for +monitoring relative changes in the thermal environment. + +Each IIO device, has a device folder under ``/sys/bus/iio/devices/iio:deviceX``, +where X is the IIO index of the device. Under these folders reside a set of +device files, depending on the characteristics and features of the hardware +device in questions. These files are consistently generalized and documented in +the IIO ABI documentation. + +The following tables show the adis16550 related device files, found in the +specific device folder path ``/sys/bus/iio/devices/iio:deviceX``. + ++-------------------------------------------+----------------------------------------------------------+ +| 3-Axis Accelerometer related device files | Description | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_scale | Scale for the accelerometer channels. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_filter_low_pass_3db_frequency | Bandwidth for the accelerometer channels. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_x_calibbias | Calibration offset for the X-axis accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_x_calibscale | Calibration scale for the X-axis accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_x_raw | Raw X-axis accelerometer channel value. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_y_calibbias | Calibration offset for the Y-axis accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_y_calibscale | Calibration scale for the Y-axis accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_y_raw | Raw Y-axis accelerometer channel value. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_z_calibbias | Calibration offset for the Z-axis accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_z_calibscale | Calibration scale for the Z-axis accelerometer channel. | ++-------------------------------------------+----------------------------------------------------------+ +| in_accel_z_raw | Raw Z-axis accelerometer channel value. | ++-------------------------------------------+----------------------------------------------------------+ +| in_deltavelocity_scale | Scale for delta velocity channels. | ++-------------------------------------------+----------------------------------------------------------+ +| in_deltavelocity_x_raw | Raw X-axis delta velocity channel value. | ++-------------------------------------------+----------------------------------------------------------+ +| in_deltavelocity_y_raw | Raw Y-axis delta velocity channel value. | ++-------------------------------------------+----------------------------------------------------------+ +| in_deltavelocity_z_raw | Raw Z-axis delta velocity channel value. | ++-------------------------------------------+----------------------------------------------------------+ + ++--------------------------------------------+------------------------------------------------------+ +| 3-Axis Gyroscope related device files | Description | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_scale | Scale for the gyroscope channels. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_filter_low_pass_3db_frequency | Scale for the gyroscope channels. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_x_calibbias | Calibration offset for the X-axis gyroscope channel. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_x_calibscale | Calibration scale for the X-axis gyroscope channel. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_x_raw | Raw X-axis gyroscope channel value. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_y_calibbias | Calibration offset for the Y-axis gyroscope channel. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_y_calibscale | Calibration scale for the Y-axis gyroscope channel. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_y_raw | Raw Y-axis gyroscope channel value. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_z_calibbias | Calibration offset for the Z-axis gyroscope channel. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_z_calibscale | Calibration scale for the Z-axis gyroscope channel. | ++--------------------------------------------+------------------------------------------------------+ +| in_anglvel_z_raw | Raw Z-axis gyroscope channel value. | ++--------------------------------------------+------------------------------------------------------+ +| in_deltaangl_scale | Scale for delta angle channels. | ++--------------------------------------------+------------------------------------------------------+ +| in_deltaangl_x_raw | Raw X-axis delta angle channel value. | ++--------------------------------------------+------------------------------------------------------+ +| in_deltaangl_y_raw | Raw Y-axis delta angle channel value. | ++--------------------------------------------+------------------------------------------------------+ +| in_deltaangl_z_raw | Raw Z-axis delta angle channel value. | ++--------------------------------------------+------------------------------------------------------+ + ++----------------------------------+-------------------------------------------+ +| Temperature sensor related files | Description | ++----------------------------------+-------------------------------------------+ +| in_temp0_raw | Raw temperature channel value. | ++----------------------------------+-------------------------------------------+ +| in_temp0_offset | Offset for the temperature sensor channel.| ++----------------------------------+-------------------------------------------+ +| in_temp0_scale | Scale for the temperature sensor channel. | ++----------------------------------+-------------------------------------------+ + ++----------------------------+--------------------------------------------------------------------------------+ +| Miscellaneous device files | Description | ++----------------------------+--------------------------------------------------------------------------------+ +| name | Name of the IIO device. | ++----------------------------+--------------------------------------------------------------------------------+ +| sampling_frequency | Currently selected sample rate. | ++----------------------------+--------------------------------------------------------------------------------+ +| write_lock_enable | Lock the device from further configuration. Only a reset will remove the lock. | ++----------------------------+--------------------------------------------------------------------------------+ + +The following table shows the adis16550 related device debug files, found in the +specific device debug folder path ``/sys/kernel/debug/iio/iio:deviceX``. + ++----------------------+-------------------------------------------------------------------------+ +| Debugfs device files | Description | ++----------------------+-------------------------------------------------------------------------+ +| serial_number | The serial number of the chip in hexadecimal format. | ++----------------------+-------------------------------------------------------------------------+ +| product_id | Chip specific product id (16550). | ++----------------------+-------------------------------------------------------------------------+ +| flash_count | The number of flash writes performed on the device. | ++----------------------+-------------------------------------------------------------------------+ +| firmware_revision | String containing the firmware revision in the following format ##.##. | ++----------------------+-------------------------------------------------------------------------+ +| firmware_date | String containing the firmware date in the following format mm-dd-yyyy. | ++----------------------+-------------------------------------------------------------------------+ + +Channels processed values +------------------------- + +A channel value can be read from its _raw attribute. The value returned is the +raw value as reported by the devices. To get the processed value of the channel, +apply the following formula: + +.. code-block:: bash + + processed value = (_raw + _offset) * _scale + +Where _offset and _scale are device attributes. If no _offset attribute is +present, simply assume its value is 0. + +The adis16550 driver offers data for 5 types of channels, the table below shows +the measurement units for the processed value, which are defined by the IIO +framework: + ++--------------------------------------+---------------------------+ +| Channel type | Measurement unit | ++--------------------------------------+---------------------------+ +| Acceleration on X, Y, and Z axis | Meters per Second squared | ++--------------------------------------+---------------------------+ +| Angular velocity on X, Y and Z axis | Radians per second | ++--------------------------------------+---------------------------+ +| Delta velocity on X. Y, and Z axis | Meters per Second | ++--------------------------------------+---------------------------+ +| Delta angle on X, Y, and Z axis | Radians | ++--------------------------------------+---------------------------+ +| Temperature | Millidegrees Celsius | ++--------------------------------------+---------------------------+ + +Usage examples +-------------- + +Show device name: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat name + adis16550 + +Show accelerometer channels value: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_raw + 6903851 + root:/sys/bus/iio/devices/iio:device0> cat in_accel_y_raw + 5650550 + root:/sys/bus/iio/devices/iio:device0> cat in_accel_z_raw + 104873530 + root:/sys/bus/iio/devices/iio:device0> cat in_accel_scale + 0.000000095 + +- X-axis acceleration = in_accel_x_raw * in_accel_scale = 0.655865845 m/s^2 +- Y-axis acceleration = in_accel_y_raw * in_accel_scale = 0.53680225 m/s^2 +- Z-axis acceleration = in_accel_z_raw * in_accel_scale = 9.96298535 m/s^2 + +Show gyroscope channels value: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat in_anglvel_x_raw + 193309 + root:/sys/bus/iio/devices/iio:device0> cat in_anglvel_y_raw + -763676 + root:/sys/bus/iio/devices/iio:device0> cat in_anglvel_z_raw + -358108 + root:/sys/bus/iio/devices/iio:device0> cat in_anglvel_scale + 0.000000003 + +- X-axis angular velocity = in_anglvel_x_raw * in_anglvel_scale = 0.000579927 rad/s +- Y-axis angular velocity = in_anglvel_y_raw * in_anglvel_scale = −0.002291028 rad/s +- Z-axis angular velocity = in_anglvel_z_raw * in_anglvel_scale = −0.001074324 rad/s + +Set calibration offset for accelerometer channels: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_calibbias + 0 + + root:/sys/bus/iio/devices/iio:device0> echo 5000 > in_accel_x_calibbias + root:/sys/bus/iio/devices/iio:device0> cat in_accel_x_calibbias + 5000 + +Set calibration offset for gyroscope channels: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat in_anglvel_y_calibbias + 0 + + root:/sys/bus/iio/devices/iio:device0> echo -5000 > in_anglvel_y_calibbias + root:/sys/bus/iio/devices/iio:device0> cat in_anglvel_y_calibbias + -5000 + +Set sampling frequency: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat sampling_frequency + 4000.000000 + + root:/sys/bus/iio/devices/iio:device0> echo 1000 > sampling_frequency + 1000.000000 + +Set bandwidth for accelerometer channels: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat in_accel_filter_low_pass_3db_frequency + 0 + + root:/sys/bus/iio/devices/iio:device0> echo 100 > in_accel_filter_low_pass_3db_frequency + root:/sys/bus/iio/devices/iio:device0> cat in_accel_filter_low_pass_3db_frequency + 100 + +Show serial number: + +.. code-block:: bash + + root:/sys/kernel/debug/iio/iio:device0> cat serial_number + 0x000000b6 + +Show product id: + +.. code-block:: bash + + root:/sys/kernel/debug/iio/iio:device0> cat product_id + 16550 + +Show flash count: + +.. code-block:: bash + + root:/sys/kernel/debug/iio/iio:device0> cat flash_count + 13 + +Show firmware revision: + +.. code-block:: bash + + root:/sys/kernel/debug/iio/iio:device0> cat firmware_revision + 1.5 + +Show firmware date: + +.. code-block:: bash + + root:/sys/kernel/debug/iio/iio:device0> cat firmware_date + 28-04-2021 + +3. Device buffers +================= + +This driver supports IIO buffers. + +The device supports retrieving the raw acceleration, gyroscope, delta velocity, +delta angle and temperature measurements using buffers. + +However, when retrieving acceleration or gyroscope data using buffers, delta +readings will not be available and vice versa. This is because the device only +allows to read either acceleration and gyroscope data or delta velocity and +delta angle data at a time and switching between these two burst data selection +modes is time consuming. + +Usage examples +-------------- + +Set device trigger in current_trigger, if not already set: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> cat trigger/current_trigger + + root:/sys/bus/iio/devices/iio:device0> echo adis16550-dev0 > trigger/current_trigger + root:/sys/bus/iio/devices/iio:device0> cat trigger/current_trigger + adis16550-dev0 + +Select channels for buffer read: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_deltavelocity_x_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_deltavelocity_y_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_deltavelocity_z_en + root:/sys/bus/iio/devices/iio:device0> echo 1 > scan_elements/in_temp0_en + +Set the number of samples to be stored in the buffer: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> echo 10 > buffer/length + +Enable buffer readings: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> echo 1 > buffer/enable + +Obtain buffered data: + +.. code-block:: bash + + root:/sys/bus/iio/devices/iio:device0> hexdump -C /dev/iio\:device0 + ... + 0000cdf0 00 00 0d 2f 00 00 08 43 00 00 09 09 00 00 a4 5f |.../...C......._| + 0000ce00 00 00 0d 2f 00 00 07 de 00 00 08 db 00 00 a4 4b |.../...........K| + 0000ce10 00 00 0d 2f 00 00 07 58 00 00 08 a3 00 00 a4 55 |.../...X.......U| + 0000ce20 00 00 0d 2f 00 00 06 d6 00 00 08 5c 00 00 a4 62 |.../.......\...b| + 0000ce30 00 00 0d 2f 00 00 06 45 00 00 08 37 00 00 a4 47 |.../...E...7...G| + 0000ce40 00 00 0d 2f 00 00 05 d4 00 00 08 30 00 00 a3 fa |.../.......0....| + 0000ce50 00 00 0d 2f 00 00 05 d0 00 00 08 12 00 00 a3 d3 |.../............| + 0000ce60 00 00 0d 2f 00 00 05 dd 00 00 08 2e 00 00 a3 e9 |.../............| + 0000ce70 00 00 0d 2f 00 00 05 cc 00 00 08 51 00 00 a3 d5 |.../.......Q....| + 0000ce80 00 00 0d 2f 00 00 05 ba 00 00 08 22 00 00 a3 9a |.../......."....| + 0000ce90 00 00 0d 2f 00 00 05 9c 00 00 07 d9 00 00 a3 40 |.../...........@| + 0000cea0 00 00 0d 2f 00 00 05 68 00 00 07 94 00 00 a2 e4 |.../...h........| + 0000ceb0 00 00 0d 2f 00 00 05 25 00 00 07 8d 00 00 a2 ce |.../...%........| + ... + +See ``Documentation/iio/iio_devbuf.rst`` for more information about how buffered +data is structured. + +4. IIO Interfacing Tools +======================== + +See ``Documentation/iio/iio_tools.rst`` for the description of the available IIO +interfacing tools. diff --git a/Documentation/iio/index.rst b/Documentation/iio/index.rst index dfcf9618568a..03829b2de2c0 100644 --- a/Documentation/iio/index.rst +++ b/Documentation/iio/index.rst @@ -24,6 +24,7 @@ Industrial I/O Kernel Drivers ad7944 adis16475 adis16480 + adis16550 adxl380 bno055 ep93xx_adc