From patchwork Tue Feb 11 17:56:58 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Budai, Robert" X-Patchwork-Id: 13970656 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 AC530265605; Tue, 11 Feb 2025 19:58: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=1739303936; cv=none; b=tVQIPnpKAzpsruBFikBm1pFtvdY3pSdZK4h2UizNSx6TobQQNrKtN/up18ZHnUYvvu/I1+gTgFpl/Wuy7A4w1dme7sSIAaetZ9EKu9mEW+ECd+2Hvpm1yzNxKGWo6C/E9mu58f8ezC5kdHPDLQHsszPHmIHvbT22/0ezJDZWHas= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739303936; c=relaxed/simple; bh=4ZM2WgL+T8cIquKBekV02dQPmIPb2AFnGvzlDKlyp/4=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=eohbmTTSQ4GwHnM+maIU8ndpvY88mECqgFD5SQesZoyy4rm/stLBFfIQLClyJEvqPoF9MbOcE10cuEUfw+/gTStMMyhv+22edw3Vb7Nh5oW9X/yKeD5zt61TayFK7Xg7c7Ukfm0VSVsElqFW1sAqyxf0YGxVTcKkXdpkUeZdj0Y= 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=A8hA4nYk; 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="A8hA4nYk" 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 51BJE1ZZ001753; Tue, 11 Feb 2025 14:58:36 -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=BG99a eeIRx/zKRZn8pNuTHI9zBFH3GTb1z0TklKTcaY=; b=A8hA4nYkRDVeVNVQgB6FK y8HHoBwOIDg8aKhpFPNcjGL6DJ2CtcfPAVnINnvJObm4Wao/SpOP3fqku1Ajoeg0 IyU3vrJ59GnHt7kA/rMjC0ZBo4Xc1vRJJ1oPqzUU1Xq+MT1aBbbFFkwDXtXjfgPM EFNFl9U7EzNMPYQMn7cm5sShVX2lKuhsKrmi4XjYt0ewOixlzYfKnLKhjkL+mX+0 jetO6hOEyOaK1VQTngK9n7NSc6B65gwy5kFZ0f1VHo3uDj3rmpfZdkN+LMqi3Jk+ Sc9gFooWmZMLXOEFd5bZKihZZWk3Uv25XAA7xy5KCYKqUktmete/qGksK/v0WsY0 Q== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0b-00128a01.pphosted.com (PPS) with ESMTPS id 44r857hd0n-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 11 Feb 2025 14:58:35 -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 51BJwYk2048365 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 11 Feb 2025 14:58:34 -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; Tue, 11 Feb 2025 14:58:34 -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; Tue, 11 Feb 2025 14:58:34 -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; Tue, 11 Feb 2025 14:58:34 -0500 Received: from desktop-robi.ad.analog.com ([10.48.65.85]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 51BJwFRA031076; Tue, 11 Feb 2025 14:58:27 -0500 From: Robert Budai To: Nuno Sa , Ramona Gradinariu , Antoniu Miclaus , Robert Budai , Lars-Peter Clausen , Michael Hennerich , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , , , , Subject: [PATCH v7 1/6] iio: imu: adis: Add custom ops struct Date: Tue, 11 Feb 2025 19:56:58 +0200 Message-ID: <20250211175706.276987-2-robert.budai@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250211175706.276987-1-robert.budai@analog.com> References: <20250211175706.276987-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: zGNMQqytIqfNiYkPudnroQCoLqg4ZFrs X-Proofpoint-ORIG-GUID: zGNMQqytIqfNiYkPudnroQCoLqg4ZFrs X-Authority-Analysis: v=2.4 cv=U5VoDfru c=1 sm=1 tr=0 ts=67ababeb cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=IkcTkHD0fZMA:10 a=T2h4t0Lz3GQA:10 a=gAnH3GRIAAAA:8 a=TSjxcLmW1dtBEzIpq6IA:9 a=3ZKOabzyN94A:10 a=QEXdDO2ut3YA:10 a=oVHKYsEdi7-vN-J5QA_j:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-02-11_08,2025-02-11_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 impostorscore=0 clxscore=1015 mlxlogscore=999 lowpriorityscore=0 priorityscore=1501 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 spamscore=0 mlxscore=0 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2501170000 definitions=main-2502110129 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 --- drivers/iio/imu/adis.c | 16 +++++++++++++--- include/linux/iio/imu/adis.h | 28 +++++++++++++++++++++------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 494171844..54915c7a3 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,11 @@ int adis_init(struct adis *adis, struct iio_dev *indio_dev, adis->spi = spi; adis->data = data; + if (!adis->ops->write && !adis->ops->read) + adis->ops = &adis_default_ops; + else 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 4bb98d973..89cfa75ae 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 Tue Feb 11 17:56:59 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Budai, Robert" X-Patchwork-Id: 13970655 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 B4EEB265602; Tue, 11 Feb 2025 19:58:53 +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=1739303935; cv=none; b=m7qTGLAV+PcxN9IyxfhTt/ncbnX5SC0XB+Q6J2jZ3r6VXx6kEgi3rZSNrvXGLa9ZPwVfgz6EoDyB0JOsc6sqNBUSXXQOu6M+uTNn32Txu+uL35/B/pFVD4Lb1UlHafL9e0H8TpX/RYgE/R4MiARzmBEi2DSuR+ZmFXnx8Utko8E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739303935; c=relaxed/simple; bh=UMLSFGJg84k+XaBqJ+DpN+iXL7e0612risMbdVeEipQ=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=nEPfNDXcIu12K2RsPVk1JNFHN4YR2bMewT0pVq4fhqVyiu2v7vM+2q4RH9I4pwycMBg7VQ0t/akrSE3LeoVQfYxFEBHIJrnx+pVUxKDEqPQis/zfS5gO4p/fezYHN6atcVqBDhgcVIGPLxVW+EYZwsgtoLOBLNe/KJHhDZupW4k= 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=POKryIPy; 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="POKryIPy" 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 51BEqa7P012586; Tue, 11 Feb 2025 14:58:40 -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=8UzHC 9GhYsvZVjOmKAtN3TuSjqx4mcOHBC6XDtlkujM=; b=POKryIPyXqYDK1hmEKoD2 hSKPPg8YO8GJMZhOekH/i5XMJWHTWI/MRVhAY0OLNEgp63yZC+HwPk+RJhVUoeqT DhlxHgF2WmeUXLd2aQzRDxfNd7OrsOr0nHhfcZsOSjSZZSXxoHWWpVTtmnVo4Eyp 8nUXBogXIlalBTCC39+S4c7BBZ167ckvOZiiJ4zGLpu5bN7zYaW2fwq5od3V4His jLwW4VtmWS3i1UPtBL18fZ5s1aJrVhWyQhoxj5b+WuhZjd/DXkajzFCI3TI6nWxQ Y4N0f0JPP6As+p6nK/53pzCWNGLRfH6qLTLWNK+NtEJS2kJz1RkcTpEYdD2ZE6es g== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 44p529xf7m-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 11 Feb 2025 14:58:40 -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 51BJwdqY048368 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 11 Feb 2025 14:58:39 -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; Tue, 11 Feb 2025 14:58:39 -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; Tue, 11 Feb 2025 14:58:39 -0500 Received: from desktop-robi.ad.analog.com ([10.48.65.85]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 51BJwFRB031076; Tue, 11 Feb 2025 14:58:32 -0500 From: Robert Budai To: Lars-Peter Clausen , Michael Hennerich , Nuno Sa , Ramona Gradinariu , Antoniu Miclaus , Robert Budai , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , , , , Subject: [PATCH v7 2/6] iio: imu: adis: Add reset to custom ops Date: Tue, 11 Feb 2025 19:56:59 +0200 Message-ID: <20250211175706.276987-3-robert.budai@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250211175706.276987-1-robert.budai@analog.com> References: <20250211175706.276987-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-ORIG-GUID: 2RD4UVedKxYgSbzF9lZbpZo-fjL0KxrW X-Authority-Analysis: v=2.4 cv=FabNxI+6 c=1 sm=1 tr=0 ts=67ababf0 cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=IkcTkHD0fZMA:10 a=T2h4t0Lz3GQA:10 a=gAnH3GRIAAAA:8 a=RUNVjLDSgTOuRutKXbcA:9 a=3ZKOabzyN94A:10 a=QEXdDO2ut3YA:10 a=Lq0aAXxcDe89wZWtTDul:22 a=oVHKYsEdi7-vN-J5QA_j:22 X-Proofpoint-GUID: 2RD4UVedKxYgSbzF9lZbpZo-fjL0KxrW X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-02-11_08,2025-02-11_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 malwarescore=0 mlxscore=0 lowpriorityscore=0 bulkscore=0 suspectscore=0 adultscore=0 spamscore=0 impostorscore=0 priorityscore=1501 phishscore=0 mlxlogscore=999 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2501170000 definitions=main-2502110129 This patch allows the custom definition of reset functionality for adis object. It is useful in cases where the driver 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 --- drivers/iio/imu/adis.c | 5 +++-- include/linux/iio/imu/adis.h | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 54915c7a3..84344f052 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -491,6 +491,7 @@ 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, + .reset = __adis_reset, }; /** @@ -522,9 +523,9 @@ int adis_init(struct adis *adis, struct iio_dev *indio_dev, adis->spi = spi; adis->data = data; - if (!adis->ops->write && !adis->ops->read) + if (!adis->ops->write && !adis->ops->read && !adis->ops->reset) adis->ops = &adis_default_ops; - else if (!adis->ops->write || !adis->ops->read) + else if (!adis->ops->write || !adis->ops->read || !adis->ops->reset) return -EINVAL; iio_device_set_drvdata(indio_dev, adis); diff --git a/include/linux/iio/imu/adis.h b/include/linux/iio/imu/adis.h index 89cfa75ae..52652f51d 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 Tue Feb 11 17:57:00 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Budai, Robert" X-Patchwork-Id: 13970657 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 C408B2641C7; Tue, 11 Feb 2025 19:58: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=1739303941; cv=none; b=CSReRcnWNFrC7dXBt5PIS5iJ5cdlMvraL/syOuMIndVFCi8CrYJ0oNk3ujfTW2SMdZm3OhNTk/bIXqISlEsNDQr/SraDvmRnZ6szQkambQbLMCX+ZhtKlkz4S7NT3HoUHrfBOtuApCmXtAVQAHmuHFS6GWeniN28w2lFcL5DMMM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739303941; c=relaxed/simple; bh=Xvibdq8i7rMxPCEiHkEkv92fdm42FyQDvfsS7zHs1GA=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=RIcMVKl1ZsehzG0mKVGMcqsmT9oVQamSpM+/qIOUP4VyJG8LxaFcJ0SPEKZa+FBP7urPaRe50bxdsBs9sF0pO0wldAPUZv1S3bC+vehlzxEOMYNprJmB/3a0HOra65KB+64o/2jWIAQ60+WoryOk5rM6SXmCTseJ1wTX0kSgjCg= 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=iXGaSPVU; 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="iXGaSPVU" 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 51BJXJ8B001679; Tue, 11 Feb 2025 14:58: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=KcGZY 3LEheYGQYNGB8qP+UqqUsY+w00H19H481Insaw=; b=iXGaSPVUWGSAvzowT+8Ve G+anr/mM7Kr68Q7v+yZnkfxDUaGHaurZ/KzJkdfyM56q+RIBC5bgCQVppVn0cYpy 46+EHrPuCXIe1emfFivDL3GZ6wn8WdgU0Ml+MWjAcS12aF7VlxbF3ijyRTEaig02 +LxE3bAYHIj0YP6A8zkPXytYzn4BHp27ZtvYPtZ1yBOTf+lSX2BlT4TfdjJ8ZLNo 8sxbNE8c6TxfCCd/NEVzQy73RbVT+Mq1GxfH0ub88p6hp0Ik2htCQSjVlUE3ku3v Yvis8IgUKfu76LXwobBTqI27AWEZyvTeVXdR8Xt7w5LBubZZhp4I9ESOLutsU07A w== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0b-00128a01.pphosted.com (PPS) with ESMTPS id 44r857hd19-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 11 Feb 2025 14:58:46 -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 51BJwi3T048374 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 11 Feb 2025 14:58:44 -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; Tue, 11 Feb 2025 14:58:44 -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; Tue, 11 Feb 2025 14:58:44 -0500 Received: from desktop-robi.ad.analog.com ([10.48.65.85]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 51BJwFRC031076; Tue, 11 Feb 2025 14:58:37 -0500 From: Robert Budai To: Lars-Peter Clausen , Michael Hennerich , Nuno Sa , Ramona Gradinariu , Antoniu Miclaus , Robert Budai , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , , , , Subject: [PATCH v7 3/6] iio: imu: adis: Add DIAG_STAT register Date: Tue, 11 Feb 2025 19:57:00 +0200 Message-ID: <20250211175706.276987-4-robert.budai@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250211175706.276987-1-robert.budai@analog.com> References: <20250211175706.276987-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: MXtFUBo5WfocjxX3JiTwSN5h6FsX33Ki X-Proofpoint-ORIG-GUID: MXtFUBo5WfocjxX3JiTwSN5h6FsX33Ki X-Authority-Analysis: v=2.4 cv=U5VoDfru c=1 sm=1 tr=0 ts=67ababf6 cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=IkcTkHD0fZMA:10 a=T2h4t0Lz3GQA:10 a=gAnH3GRIAAAA:8 a=RUNVjLDSgTOuRutKXbcA:9 a=3ZKOabzyN94A:10 a=QEXdDO2ut3YA:10 a=oVHKYsEdi7-vN-J5QA_j:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-02-11_08,2025-02-11_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 impostorscore=0 clxscore=1015 mlxlogscore=999 lowpriorityscore=0 priorityscore=1501 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 spamscore=0 mlxscore=0 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2501170000 definitions=main-2502110129 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 --- drivers/iio/imu/adis.c | 19 ++++++++++++++++--- include/linux/iio/imu/adis.h | 3 +++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index 84344f052..b3f074116 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -304,11 +304,21 @@ EXPORT_SYMBOL_NS(__adis_enable_irq, "IIO_ADISLIB"); */ int __adis_check_status(struct adis *adis) { - u16 status; + unsigned int status; + int diag_stat_bits; + u16 status_16; 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, + status_16); + status = status_16; + } if (ret) return ret; @@ -317,7 +327,10 @@ int __adis_check_status(struct adis *adis) if (status == 0) return 0; - for (i = 0; i < 16; ++i) { + diag_stat_bits = BITS_PER_BYTE * (adis->data->diag_stat_size ? + adis->data->diag_stat_size : 2); + + for (i = 0; i < diag_stat_bits; ++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 52652f51d..35797fe93 100644 --- a/include/linux/iio/imu/adis.h +++ b/include/linux/iio/imu/adis.h @@ -44,6 +44,8 @@ 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. If 0 the + * default length is 2 bytes long. * @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 +72,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 Tue Feb 11 17:57:01 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Budai, Robert" X-Patchwork-Id: 13970658 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 D102C2641DE; Tue, 11 Feb 2025 19:59:02 +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=1739303944; cv=none; b=OIM49u1qfwWBoHTtb4cSNz8xnKzP7v8snvFhwvxg9IBuK7to/Vq1AtLSPzcFtVtSHCG0DvptZSac2NcVfNfEDRDnTK/pIWuyacA03S5aqJ4/UnGG8QIL0NdEVXl5mwDdzv/PItmLQytdv3zXQNd8dGLv9AREM6CBlMammfsXV3A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739303944; c=relaxed/simple; bh=pk0dE3jWIp2mV+M8rCD1+ry+6ym2ZfPpI5W3SlEELCI=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Jr8he4ojcWlV6+vW3NvQzYyycGA99i26NbP814bbhqdmABjptG52Flv8+Mt8ffk/6rVrZrQ688MHl652WQFvkSMfh+FGvp0xfwM+hA76TFf3Xn6N247L+IMBxtCftJO3HNWwA9XSVwogfWUEw2ppWiQ+K6Qb0yAOLzOT5Fe59jQ= 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=oDezxTCC; 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="oDezxTCC" 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 51BJAUhV002747; Tue, 11 Feb 2025 14:58: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=a3dok mUJp+evdf/DyLLSiGp0MpLEmvPYdgx6ztZG520=; b=oDezxTCCuz9rmQnFVt6FT W7vcKG4QIKY1WhbZrMxb06f8NFygu8GbdW/jm0LUlyPU1aLACQZPza2fv/3IqnIH /MxkmH4s5p4V0IJhQJktpzawIBgqiuPhpYZeRJEEfsEaw95lrxnzs/fRnt2ra40t +5RnOY3wNDKij/kgjVYAdLp5BZck13okjoBVPOlQAKBKWqoRjD63Qx0JK2lK52CT 4zjqbU48qqu0fW7PFRlAJX1An2sGzDb6Thn9PeWwFlBZYaUTehJKbj8wsTkjPxNU F3IFI/t7zDCyCYqkL7zVs7DifgtmI4L5H+fHgAtWln7Xq6qU5mkmVB9vaU04xTBy A== Received: from nwd2mta3.analog.com ([137.71.173.56]) by mx0b-00128a01.pphosted.com (PPS) with ESMTPS id 44r857hd1e-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 11 Feb 2025 14:58:49 -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 51BJwlik065157 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 11 Feb 2025 14:58:47 -0500 Received: from ASHBCASHYB5.ad.analog.com (10.64.17.133) 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; Tue, 11 Feb 2025 14:58: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; Tue, 11 Feb 2025 14:58: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; Tue, 11 Feb 2025 14:58:47 -0500 Received: from desktop-robi.ad.analog.com ([10.48.65.85]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 51BJwFRD031076; Tue, 11 Feb 2025 14:58:43 -0500 From: Robert Budai To: Nuno Sa , Ramona Gradinariu , Antoniu Miclaus , Robert Budai , Lars-Peter Clausen , Michael Hennerich , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , , , , Subject: [PATCH v7 4/6] dt-bindings: iio: Add adis16550 bindings Date: Tue, 11 Feb 2025 19:57:01 +0200 Message-ID: <20250211175706.276987-5-robert.budai@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250211175706.276987-1-robert.budai@analog.com> References: <20250211175706.276987-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: bNXsBfHUy38j3oqlDydPe5C6SNCX6l8g X-Proofpoint-ORIG-GUID: bNXsBfHUy38j3oqlDydPe5C6SNCX6l8g X-Authority-Analysis: v=2.4 cv=U5VoDfru c=1 sm=1 tr=0 ts=67ababf9 cx=c_pps a=PpDZqlmH/M8setHirZLBMw==:117 a=PpDZqlmH/M8setHirZLBMw==:17 a=T2h4t0Lz3GQA:10 a=gEfo2CItAAAA:8 a=gAnH3GRIAAAA:8 a=VwQbUJbxAAAA:8 a=neJRz3qJz1uz_Or4AKoA:9 a=sptkURWiP4Gy88Gu7hUp:22 a=oVHKYsEdi7-vN-J5QA_j:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-02-11_08,2025-02-11_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 impostorscore=0 clxscore=1015 mlxlogscore=999 lowpriorityscore=0 priorityscore=1501 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 spamscore=0 mlxscore=0 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2501170000 definitions=main-2502110129 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 --- v7: - dropped clock-frequency binding as suggested .../bindings/iio/imu/adi,adis16550.yaml | 73 +++++++++++++++++++ MAINTAINERS | 10 +++ 2 files changed, 83 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 000000000..b55cd0f7e --- /dev/null +++ b/Documentation/devicetree/bindings/iio/imu/adi,adis16550.yaml @@ -0,0 +1,73 @@ +# 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 + - Robert Budai + +properties: + compatible: + enum: + - adi,adis16550 + + 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: + description: If not provided, then the internal clock is used. + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - spi-cpha + - spi-cpol + - spi-max-frequency + - vdd-supply + +allOf: + - $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 25c86f473..d3e6258fa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1485,6 +1485,16 @@ 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 +M: Robert Budai +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 Tue Feb 11 17:57:02 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Budai, Robert" X-Patchwork-Id: 13970659 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 5A2D826563E; Tue, 11 Feb 2025 19:59:12 +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=1739303955; cv=none; b=g4ocDkku3M4UYs5zRTflpniZlXc6EL3e0RHdZobjuzW/0JefsAGDnvWiH7QO+o/y+f0gy1TbGKOPg2nmSPKySBJqDyQHmYcxAGFpSkAhHoHhwZ6/LiSXCiehMuTLUYWY0L6eJVkXdeyMi7YXaD9YdGvgzxQm0GBntUboYsIM64Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739303955; c=relaxed/simple; bh=hYVzBQv5ALW1hXi99Cm9LSEWCTQ9wNaFIWUkqldHoy0=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=VVbrE2PWygFmlGWaeuENoCc08EqfbQh/7LivAYQVi8og2VD2+277h7O/LP/A7S4PXI+jTfkEOUmM+w7q8NV2AA/wBJEKYDw5S8YKREoLLVoPPuLkbBSIPbnyK8Ne8KnnFqhx4KFuWLzJM47l/Ygeg3zsdlkgraJTmuzGTP1VBeQ= 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=ZJiiF5Jj; 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="ZJiiF5Jj" 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 51BFZPqA012589; Tue, 11 Feb 2025 14:58:57 -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=pYe+b iI8O0jh83U497MfUQDNmKHCsXpb1xmsU/cBW48=; b=ZJiiF5JjXHDLcwaoPUDsN xA87Vmw1UDkeBi0b3LSYZvgDqv/BVYmr+aJi8/Oc+kDcM+dqpfHbokpVEACT1K8C hTnTDayiK0y1mLtjzQyF1kYib2s0K+QG+ndj8TlMKfZ6bYzRiMF7XqsZiqd4mGg2 3Fj01pqIBUb3bW5lE2VD2nTI7kdrAk876+a+tSORaNP6ctr2ZptheJRFCX2HGet1 hv3FkwPqSN69XwHLFsBXo0JyqGzjz9yHV1Fhxnw6KrNPhRJOXfxuhBCOtJQ1U1Yp LHpOeHE/RDHMKb1z1cylZTLNhIEZ8h+bbfZMQ9oVbPeUFimIDUPmQKlothN43x7c A== Received: from nwd2mta3.analog.com ([137.71.173.56]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 44p529xf87-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 11 Feb 2025 14:58:56 -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 51BJwtwb065169 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 11 Feb 2025 14:58:55 -0500 Received: from ASHBMBX8.ad.analog.com (10.64.17.5) 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; Tue, 11 Feb 2025 14:58:55 -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; Tue, 11 Feb 2025 14:58:55 -0500 Received: from desktop-robi.ad.analog.com ([10.48.65.85]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 51BJwFRE031076; Tue, 11 Feb 2025 14:58:49 -0500 From: Robert Budai To: Lars-Peter Clausen , Michael Hennerich , Nuno Sa , Ramona Gradinariu , Antoniu Miclaus , Robert Budai , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , , , , Subject: [PATCH v7 5/6] iio: imu: adis16550: add adis16550 support Date: Tue, 11 Feb 2025 19:57:02 +0200 Message-ID: <20250211175706.276987-6-robert.budai@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250211175706.276987-1-robert.budai@analog.com> References: <20250211175706.276987-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-ORIG-GUID: 96-TrnM65MVHORQjJVUsJ8-PHohwRTDO X-Authority-Analysis: v=2.4 cv=FabNxI+6 c=1 sm=1 tr=0 ts=67abac01 cx=c_pps a=PpDZqlmH/M8setHirZLBMw==:117 a=PpDZqlmH/M8setHirZLBMw==:17 a=IkcTkHD0fZMA:10 a=T2h4t0Lz3GQA:10 a=gAnH3GRIAAAA:8 a=_-Ay4P9v7Kik70hs8QcA:9 a=3ZKOabzyN94A:10 a=QEXdDO2ut3YA:10 a=oVHKYsEdi7-vN-J5QA_j:22 X-Proofpoint-GUID: 96-TrnM65MVHORQjJVUsJ8-PHohwRTDO X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-02-11_08,2025-02-11_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 malwarescore=0 mlxscore=0 lowpriorityscore=0 bulkscore=0 suspectscore=0 adultscore=0 spamscore=0 impostorscore=0 priorityscore=1501 phishscore=0 mlxlogscore=999 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2501170000 definitions=main-2502110129 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. 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 --- v7: - minor changes according to PR suggestions drivers/iio/imu/Kconfig | 13 + drivers/iio/imu/Makefile | 1 + drivers/iio/imu/adis16550.c | 1151 +++++++++++++++++++++++++++++++++++ 3 files changed, 1165 insertions(+) create mode 100644 drivers/iio/imu/adis16550.c diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index ca0efecb5..15612f0f1 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 containing triaxis gyroscope and triaxis accelerometer. + + 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/bmi270/Kconfig" source "drivers/iio/imu/bmi323/Kconfig" diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile index 04c77c2c4..e901aea49 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 000000000..b4a88e31c --- /dev/null +++ b/drivers/iio/imu/adis16550.c @@ -0,0 +1,1151 @@ +// 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 + +#define ADIS16550_REG_BURST_GYRO_ACCEL 0x0a +#define ADIS16550_REG_BURST_DELTA_ANG_VEL 0x0b +#define ADIS16550_BURST_DATA_GYRO_ACCEL_MASK GENMASK(6, 1) +#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; + struct spi_transfer xfer[2]; + u8 buffer[ADIS16550_BURST_DATA_LEN + sizeof(u32)] __aligned(IIO_DMA_MINALIGN); + __be32 din[2] __aligned(IIO_DMA_MINALIGN); + __be32 dout[2]; +}; + +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, 1); + __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; + bool wr = readval ? false : true; + struct spi_device *spi = adis->spi; + struct adis16550 *st = container_of(adis, struct adis16550, adis); + struct spi_transfer xfers[] = { + { + .tx_buf = &st->din[0], + .len = 4, + .cs_change = 1, + }, { + .tx_buf = &st->din[1], + .len = 4, + .cs_change = 1, + .rx_buf = st->dout, + }, { + .tx_buf = &st->din[1], + .rx_buf = &st->dout[1], + .len = 4, + }, + }; + + spi_message_init(&msg); + + switch (len) { + case 4: + adis16550_spi_msg_prepare(reg + 1, wr, writeval >> 16, + &st->din[0]); + spi_message_add_tail(&xfers[0], &msg); + fallthrough; + case 2: + adis16550_spi_msg_prepare(reg, wr, writeval, &st->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, st->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, st->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; + char buf[12]; + size_t len; + u32 date; + 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); + + return __adis_write_reg_16(&st->adis, ADIS16550_REG_DEC_RATE, dec); +} + +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) +{ + u8 en = freq_hz ? 1 : 0; + + return __adis_update_bits(&st->adis, ADIS16550_REG_CONFIG, + ADIS16550_ACCL_FIR_EN_MASK, + 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) +{ + u8 en = freq_hz ? 1 : 0; + + return __adis_update_bits(&st->adis, ADIS16550_REG_CONFIG, + ADIS16550_GYRO_FIR_EN_MASK, + FIELD_PREP(ADIS16550_GYRO_FIR_EN_MASK, en)); +} + +enum { + ADIS16550_SCAN_TEMP, + 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_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_TEMP_CHANNEL(), + 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_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 = { + .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; + int ret; + u16 dummy; + bool valid; + 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 = (__be32 *)st->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; + } + + /* copy the temperature together with sensor data */ + memcpy(data, &buffer[3], + (ADIS16550_SCAN_ACCEL_Z - ADIS16550_SCAN_GYRO_X + 2) * + 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) +{ + u16 burst_length = ADIS16550_BURST_DATA_LEN; + struct adis16550 *st = iio_priv(indio_dev); + u8 burst_cmd; + u8 *tx; + + memset(st->buffer, 0, burst_length + sizeof(u32)); + + 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; + + tx = st->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)); + + 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_mode_data; + struct clk *clk; + int ret, i; + u16 mode; + + clk = devm_clk_get_optional_enabled(dev, NULL); + if (IS_ERR(clk)) + return PTR_ERR(clk); + if (!clk) { + st->clk_freq_hz = st->info->int_clk * 1000; + return 0; + } + + st->clk_freq_hz = clk_get_rate(clk); + + for (i = 0; i < st->info->num_sync; i++) { + if (st->clk_freq_hz >= st->info->sync_mode[i].min_rate && + st->clk_freq_hz <= st->info->sync_mode[i].max_rate) { + sync_mode_data = &st->info->sync_mode[i]; + break; + } + } + + if (i == st->info->num_sync) + return dev_err_probe(dev, -EINVAL, "Clk rate: %lu not in a valid range", + st->clk_freq_hz); + + if (sync_mode_data->sync_mode == ADIS16550_SYNC_MODE_SCALED) { + u16 sync_scale; + /* + * In sps scaled sync we must scale the input clock to a range + * of [3000 4500]. + */ + + sync_scale = DIV_ROUND_CLOSEST(st->info->int_clk, st->clk_freq_hz); + + if (3000 > sync_scale || 4500 < sync_scale) + return dev_err_probe(dev, -EINVAL, + "Invalid value:%u for sync_scale", + sync_scale); + + ret = adis_write_reg_16(&st->adis, ADIS16550_REG_SYNC_SCALE, + sync_scale); + if (ret) + return ret; + + st->clk_freq_hz = st->info->int_clk; + } + + st->clk_freq_hz *= 1000; + + mode = FIELD_PREP(ADIS16550_SYNC_MODE_MASK, sync_mode_data->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 int adis16550_probe(struct spi_device *spi) +{ + u16 burst_length = ADIS16550_BURST_DATA_LEN; + struct device *dev = &spi->dev; + struct iio_dev *indio_dev; + struct adis16550 *st; + struct adis *adis; + int ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + st->info = spi_get_device_match_data(spi); + if (!st->info) + return -EINVAL; + adis = &st->adis; + indio_dev->name = st->info->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->xfer[0].tx_buf = st->buffer + burst_length; + st->xfer[0].len = 4; + st->xfer[0].cs_change = 1; + st->xfer[0].delay.value = 8; + st->xfer[0].delay.unit = SPI_DELAY_UNIT_USECS; + st->xfer[1].rx_buf = st->buffer; + st->xfer[1].len = burst_length; + + spi_message_init_with_transfers(&adis->msg, st->xfer, 2); + + 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", (kernel_ulong_t)&adis16550_chip_info}, + { } +}; +MODULE_DEVICE_TABLE(spi, adis16550_id); + +static const struct of_device_id adis16550_of_match[] = { + { .compatible = "adi,adis16550", .data = &adis16550_chip_info }, + { } +}; +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_AUTHOR("Robert Budai ") +MODULE_DESCRIPTION("Analog Devices ADIS16550 IMU driver"); +MODULE_IMPORT_NS("IIO_ADISLIB"); +MODULE_LICENSE("GPL"); From patchwork Tue Feb 11 17:57:03 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Budai, Robert" X-Patchwork-Id: 13970660 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 D9B2C262179; Tue, 11 Feb 2025 19:59:16 +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=1739303960; cv=none; b=iiQBrRhCzgNhYZ4cTdlZzIJi9zGRLGqNAl3zDXOC9cnmVqsusX8ByTTTse/t5S+z1gJqA5hBSmXvL6+J3Mkb0WRMQuQvgBr5BCah21KeBa9S2RpzjwrI+4EjsdMD/l1eu1lHiBy6ZwTQohaFj1/bkDXz+IFw4ktT6xDUegaty5I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739303960; c=relaxed/simple; bh=qz1cZqi/yuFyhg5b7Q9dmNpwqxB1x98e1HYbqrq0Eic=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=gRgf0Cj3WpVO/uyA/p8qk1KN2J7drxg6DfpSGjix015JiHDfBLvp8oliKuCvRjeXMB5SEpcrsVTkcTxpOuL2KR1tmR1Yq/oU/9uSxirr/sNmfe54Co9KksYyFuAEx0Tk8hNoMYosdTBo7PqeLPfj6NBBKFINJunq0LWimEQ9eec= 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=t/FVPQsE; 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="t/FVPQsE" 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 51BJCs5p014211; Tue, 11 Feb 2025 14:59:03 -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=H29cq cV7kkyq6wACcf36pcZDV0NhsViDxbNXS3ZQUGM=; b=t/FVPQsEZE8b7LJJRkDqi bJPvz4Q35Oy2/cphxreG+I1IS6NmcysfnG8NZCFFf/UIxxJKDfUhD9H5kTpJYIG2 H/nncVHly9kFFo59WeqDsfOqm0t4Dzobp0V+6aQ5rhPmHvKBY29aYTB7fsiKenW6 duCFkCRr7QjctMXpAJ499Ao1zlMNQycgvjCwUl5bDLttqNz0LgIyQjROjFrkVRW9 kpLIDot6HCDul0MKhtVyVM2FF/6Lqz6O9QSmtL0NkgNX4i9gUDkH6YHdLAPyv5Eb GwBf6OSaIH6dv0JPSU8O8+NEqQ7M1yVJb3/EJOY0NiuOzMh3rUOLfGZpKNQbzyYZ g== Received: from nwd2mta4.analog.com ([137.71.173.58]) by mx0a-00128a01.pphosted.com (PPS) with ESMTPS id 44p529xf8e-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 11 Feb 2025 14:59:02 -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 51BJx1JK048389 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 11 Feb 2025 14:59:01 -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; Tue, 11 Feb 2025 14:59:01 -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; Tue, 11 Feb 2025 14:59:01 -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; Tue, 11 Feb 2025 14:59:01 -0500 Received: from desktop-robi.ad.analog.com ([10.48.65.85]) by zeus.spd.analog.com (8.15.1/8.15.1) with ESMTP id 51BJwFRF031076; Tue, 11 Feb 2025 14:58:54 -0500 From: Robert Budai To: Nuno Sa , Ramona Gradinariu , Antoniu Miclaus , Robert Budai , Lars-Peter Clausen , Michael Hennerich , Jonathan Cameron , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jonathan Corbet , , , , Subject: [PATCH v7 6/6] docs: iio: add documentation for adis16550 driver Date: Tue, 11 Feb 2025 19:57:03 +0200 Message-ID: <20250211175706.276987-7-robert.budai@analog.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250211175706.276987-1-robert.budai@analog.com> References: <20250211175706.276987-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-ORIG-GUID: bl9VZ__9XarVj-JMqKm0Lw_2gqokX085 X-Authority-Analysis: v=2.4 cv=FabNxI+6 c=1 sm=1 tr=0 ts=67abac06 cx=c_pps a=3WNzaoukacrqR9RwcOSAdA==:117 a=3WNzaoukacrqR9RwcOSAdA==:17 a=IkcTkHD0fZMA:10 a=T2h4t0Lz3GQA:10 a=gAnH3GRIAAAA:8 a=fAjUVFDDO8eWv5JNfJ0A:9 a=3ZKOabzyN94A:10 a=QEXdDO2ut3YA:10 a=oVHKYsEdi7-vN-J5QA_j:22 X-Proofpoint-GUID: bl9VZ__9XarVj-JMqKm0Lw_2gqokX085 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1057,Hydra:6.0.680,FMLib:17.12.68.34 definitions=2025-02-11_08,2025-02-11_01,2024-11-22_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 malwarescore=0 mlxscore=0 lowpriorityscore=0 bulkscore=0 suspectscore=0 adultscore=0 spamscore=0 impostorscore=0 priorityscore=1501 phishscore=0 mlxlogscore=999 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2501170000 definitions=main-2502110129 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 --- Documentation/iio/adis16550.rst | 376 ++++++++++++++++++++++++++++++++ Documentation/iio/index.rst | 1 + 2 files changed, 377 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 000000000..f929c460a --- /dev/null +++ b/Documentation/iio/adis16550.rst @@ -0,0 +1,376 @@ +.. 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. 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. + +1. 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. | ++----------------------------+--------------------------------------------------------------------------------+ + +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 5710f5b9e..039ed2d75 100644 --- a/Documentation/iio/index.rst +++ b/Documentation/iio/index.rst @@ -26,6 +26,7 @@ Industrial I/O Kernel Drivers ad7944 adis16475 adis16480 + adis16550 adxl380 bno055 ep93xx_adc