From patchwork Thu May 7 14:42:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jean-Baptiste Maneyrol X-Patchwork-Id: 200941 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, MSGID_FROM_MTA_HEADER, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 91852C38A24 for ; Thu, 7 May 2020 14:44:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 62D9020575 for ; Thu, 7 May 2020 14:44:04 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="WZSpN8vS"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="EZjefep+" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726907AbgEGOnW (ORCPT ); Thu, 7 May 2020 10:43:22 -0400 Received: from mx0b-00328301.pphosted.com ([148.163.141.47]:22320 "EHLO mx0b-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726470AbgEGOnV (ORCPT ); Thu, 7 May 2020 10:43:21 -0400 Received: from pps.filterd (m0156136.ppops.net [127.0.0.1]) by mx0b-00328301.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 047EbhbW006057; Thu, 7 May 2020 07:43:09 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=invensense.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : content-type : content-transfer-encoding : mime-version; s=pfpt1; bh=UgS9409OZ7jcsrOpUf1U/Wt1Y50MnDXXPDLeOEz14qE=; b=WZSpN8vSamnu76c6jvcyil5daJQibX+MeQkv3z8kV3am0tZ3Lf91P9VA8ObwaBiMEQv8 t/A0YcTK/oSHWI+rDdFZamZe/KIC92NErqs//8QylC4wgb2gsvwXDLzaLZKZp2jzeS+N gWFLi1+7JYW+5qcjUTrngKwx5b8s0vl85j27YqtLiDPjMbAR2/F94i/GtbZhIkHMZ8ao +ZJZYwLwL/CHHr0PxqWzqLFhF6C0/nS1KfaBJB7ksiLPOL/RJrraWxs4Id9Rr/st8Sz6 1UzaJ2dScSRBh3tmhfVZtW9d/zML3XKkz1yGKdVarWzljY0rRaVTzLeYTeom+t9GNuOW Pw== Received: from nam11-dm6-obe.outbound.protection.outlook.com (mail-dm6nam11lp2174.outbound.protection.outlook.com [104.47.57.174]) by mx0b-00328301.pphosted.com with ESMTP id 30s4tnatwj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 07 May 2020 07:43:09 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=A5GOEEv8EHPBF/oGbRFPkgs7MjVBtwSiR+azfOfRTvp6nbLfBswym3MVgKohvBxwmOLhbwM8etBMmFVBU0vRL6tuQkgUvi4BpxTIgsUEks4aMKlcP2e7h3JjMQCq1gGTutCw+QURTk6NgG9o0ZAg+upSkCsnnU8OY9vUM7lFognKe379BnyFSCSpQYLiR6d7nNcbgmdWjnezwtp/3MGpm7HwZeh6DRUnoKZW0a7DpER+SXfmXSeM6mXq6E+ARg2fDMDMvxp6WQSF4cQklxRdwHznkj+QspQYKAap4y0CfoLYBuPWRf8vtlkiw9NUzXDgrHHOCD271zfhrWlUQS9o3g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=UgS9409OZ7jcsrOpUf1U/Wt1Y50MnDXXPDLeOEz14qE=; b=bYh+1EGIEH61SJPoma/OK+Uy21hU3FZSjVSePPavGay/4mCz5ziq0Azq5eo+Cjvp1qmKU+KkKKDhDXUsg0EQufyodeQZcKtjSkWoMCxMuPpaW77DpgM4JTbj7CMnY+zc6GX8Y3SLFaMhWa/px4JQK5ouM8J1qlSvjBwx+LxbkkICNIQ0i24Oej9f7yrgyYgpJn7jFjrA1vihK4WsCOOxFthnSkt8xEfuZm8M2zRIoRfAp+ooeoMGpX8xe0RaIUS6MCyl5VycnWfSfV/G5sNW0CZ/Zc/YxI8dSf9crtPlscIZags1t1L/20P32bGFYSNYIgK9Zi6rhtkta7oQFT8nvw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=invensense.com; dmarc=pass action=none header.from=invensense.com; dkim=pass header.d=invensense.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=invensense.onmicrosoft.com; s=selector2-invensense-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=UgS9409OZ7jcsrOpUf1U/Wt1Y50MnDXXPDLeOEz14qE=; b=EZjefep+9ltCeQr4LMON9ItqkhCUxZvTu9qd5UwvViRqFDPROsjUroTORCR7kNSjcBjmw6CKd5Nq8+c/be592PvzG6pUKeT1UFqelj6ZJGXvKJQQD7vOLjYDsvpg0N3kTbUG7D9DMljbxVXZbigkKB/JWoTZCi/WbkzCKpNkW6w= Authentication-Results: kernel.org; dkim=none (message not signed) header.d=none; kernel.org; dmarc=none action=none header.from=invensense.com; Received: from MN2PR12MB4422.namprd12.prod.outlook.com (2603:10b6:208:265::9) by MN2PR12MB4269.namprd12.prod.outlook.com (2603:10b6:208:1d4::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2979.28; Thu, 7 May 2020 14:43:07 +0000 Received: from MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::7471:da8b:8ca1:6af0]) by MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::7471:da8b:8ca1:6af0%4]) with mapi id 15.20.2979.028; Thu, 7 May 2020 14:43:07 +0000 From: Jean-Baptiste Maneyrol To: jic23@kernel.org, robh+dt@kernel.org, robh@kernel.org, mchehab+huawei@kernel.org, davem@davemloft.net, gregkh@linuxfoundation.org Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Jean-Baptiste Maneyrol Subject: [PATCH 01/12] iio: imu: inv_icm42600: add core of new inv_icm42600 driver Date: Thu, 7 May 2020 16:42:11 +0200 Message-Id: <20200507144222.20989-2-jmaneyrol@invensense.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200507144222.20989-1-jmaneyrol@invensense.com> References: <20200507144222.20989-1-jmaneyrol@invensense.com> X-ClientProxiedBy: LNXP265CA0048.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:5c::36) To MN2PR12MB4422.namprd12.prod.outlook.com (2603:10b6:208:265::9) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from frgnb-buildozer.invcorp.invensense.com (77.157.193.39) by LNXP265CA0048.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:5c::36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2979.26 via Frontend Transport; Thu, 7 May 2020 14:43:05 +0000 X-Mailer: git-send-email 2.17.1 X-Originating-IP: [77.157.193.39] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 6c9c07fa-7c95-46b3-e710-08d7f294f4b1 X-MS-TrafficTypeDiagnostic: MN2PR12MB4269: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:48; X-Forefront-PRVS: 03965EFC76 X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: mjOwBsOnNhwIv1/j44yYpcqKCgHFs7Cbsox1VNJVPUuqpaw6XwdWTvX63nV4E0i10kSLHtbTQkJm4P+QxRpP1dEqzGbezDZELU4mGQfFLXz7XSJ+Yhf1yPtDv9HHqqWPPO1+14N0Wb/jAgUQfw6B46BN6BZARxl4FLnREwX50Pgfd1YS2sRdz36Dsn5QVPR0OUrldTy0u48t4dueXV2OtHGwNzlqZUb6wKK/bSY05zB45VBBC6DvlAh6oXaw0yTiz/o9ozDszBJgjc7Btqs/HwItxSINc9D8Nh8XgAWyXAk0TnTyj8/dPbBn4o+zVkwBUkWdsXZJt8YTnOCj0lktP1Ql7Ef9eUVu8GI1qlKwxciwmeQv3r9/W0EbqL4F0tpAO6nTfkZvUZgjqIV+3P2HPEP89JBGZvUWlv8UnLAskb/VaLGYj4BQGgTPRf/Zf2JwQrnBZcjmToVLoFttL74+HwKU48MEP1xuE8MPBERMMJz7z9VWya5fnFbgDGYsMLlFpNnrylgQm3K+SmUt1q34dA== X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:MN2PR12MB4422.namprd12.prod.outlook.com; PTR:; CAT:NONE; SFTY:; SFS:(346002)(396003)(136003)(366004)(39850400004)(376002)(33430700001)(186003)(6486002)(478600001)(16526019)(5660300002)(4326008)(33440700001)(30864003)(66556008)(8676002)(1076003)(36756003)(316002)(66946007)(66476007)(6666004)(52116002)(8936002)(86362001)(2616005)(83280400001)(956004)(83320400001)(83290400001)(83310400001)(26005)(2906002)(7696005)(83300400001)(107886003); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData: ujYys01TYH18auPkkP6wsgT0ptgw99vTBsnHwnYEKYMKFAv70X7A8A/U0zc/xxy7dbi/9keiMxpuLmyUn8kNg/y+iLp0N6N7qI9PPk0AD1Dagf23QSxJ8YN/yLzAPi6ejRievtB9z3CmIvWwGI9OoVm18ooXO/YXZHc/MyaEhNJyTw3bTybpMOjk6N2cYq6ed5dhQyN7K9I3MZTUbEtKOSmxgBQjfWEnkhF9EL8kdgcmbn4dXt6FQBxiG6gISYWSexO21PjPbnoqTfAf5ys1tTIiO7d6yW5svkjwSUtAQRPKR2n9pGRwQ0MiVWb4GmC9IERMmg+Or4egjCLZN7VwwrCKCawkuu3AivThNK7oG8VEw6zcmY9PMGLIxNFh/PR/JfuAuYoUgOSWRLvKfE7VbhMVHy3vZ1GBClmf39pnDY991fIEKW49RPNn9U45JqsdU/dpSsMeLJNJHZr6+3SZelroxRxp1Qe0t9YrpuiGJ0uoflhAZXt6teYdyMaOkEzz0ey4Mn22WksI8ay2rlz1YPauk1r0Vmdq6B67LFZ+w4XWdoInv6blfEW69IxE+l9Ia2prCLF2qUEuIblS0aEHh39vIlx8H9+IU4JI8OuiDFbeuQZ7+KnZJyYkYdodLGw+ngFXnb1RrsXKjrw4EAV/rJSYXHNs+Z9vAZIeMbRaFsMVe4jidc6HP9f8nxbIqs7xHn8pZ3DAEY0pWic1Y3FxT1iSjSSHO/G0r1RgieQjb7k2H1BQ5TvxXB5i5+rnUOk2s1zPoUcXGlkv+lGHdgIF9vIbf1ylWRS7xahLmVMD8+I= X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: 6c9c07fa-7c95-46b3-e710-08d7f294f4b1 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 May 2020 14:43:07.5583 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 462b3b3b-e42b-47ea-801a-f1581aac892d X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 00xaBwL4GtppzIAcCT64jsxp2Y48gvpgEOSoYF7MDtmQOnmD3M0JRI92EEr1nccI2b8aQbvsp7eEz/6+3FdTqa9PIeGkhAQ2UvSiUYkT1+g= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4269 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216, 18.0.676 definitions=2020-05-07_09:2020-05-07,2020-05-07 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 adultscore=0 priorityscore=1501 spamscore=0 mlxlogscore=999 impostorscore=0 suspectscore=0 phishscore=0 malwarescore=0 lowpriorityscore=0 bulkscore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2005070118 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Core component of a new driver for InvenSense ICM-426xx devices. It includes registers definition, main probe/setup, and device utility functions. ICM-426xx devices are latest generation of 6-axis IMU, gyroscope+accelerometer and temperature sensor. This device includes a 2K FIFO, supports I2C/I3C/SPI, and provides intelligent motion features like pedometer, tilt detection, and tap detection. Signed-off-by: Jean-Baptiste Maneyrol --- drivers/iio/imu/inv_icm42600/inv_icm42600.h | 372 +++++++++++ .../iio/imu/inv_icm42600/inv_icm42600_core.c | 618 ++++++++++++++++++ 2 files changed, 990 insertions(+) create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600.h create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_core.c diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h b/drivers/iio/imu/inv_icm42600/inv_icm42600.h new file mode 100644 index 000000000000..8da4c8249aed --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h @@ -0,0 +1,372 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#ifndef INV_ICM42600_H_ +#define INV_ICM42600_H_ + +#include +#include +#include +#include +#include +#include +#include + +enum inv_icm42600_chip { + INV_CHIP_ICM42600, + INV_CHIP_ICM42602, + INV_CHIP_ICM42605, + INV_CHIP_ICM42622, + INV_CHIP_NB, +}; + +/* serial bus slew rates */ +enum inv_icm42600_slew_rate { + INV_ICM42600_SLEW_RATE_20_60NS, + INV_ICM42600_SLEW_RATE_12_36NS, + INV_ICM42600_SLEW_RATE_6_18NS, + INV_ICM42600_SLEW_RATE_4_12NS, + INV_ICM42600_SLEW_RATE_2_6NS, + INV_ICM42600_SLEW_RATE_INF_2NS, +}; + +enum inv_icm42600_sensor_mode { + INV_ICM42600_SENSOR_MODE_OFF, + INV_ICM42600_SENSOR_MODE_STANDBY, + INV_ICM42600_SENSOR_MODE_LOW_POWER, + INV_ICM42600_SENSOR_MODE_LOW_NOISE, + INV_ICM42600_SENSOR_MODE_NB, +}; + +/* gyroscope fullscale values */ +enum inv_icm42600_gyro_fs { + INV_ICM42600_GYRO_FS_2000DPS, + INV_ICM42600_GYRO_FS_1000DPS, + INV_ICM42600_GYRO_FS_500DPS, + INV_ICM42600_GYRO_FS_250DPS, + INV_ICM42600_GYRO_FS_125DPS, + INV_ICM42600_GYRO_FS_62_5DPS, + INV_ICM42600_GYRO_FS_31_25DPS, + INV_ICM42600_GYRO_FS_15_625DPS, + INV_ICM42600_GYRO_FS_NB, +}; + +/* accelerometer fullscale values */ +enum inv_icm42600_accel_fs { + INV_ICM42600_ACCEL_FS_16G, + INV_ICM42600_ACCEL_FS_8G, + INV_ICM42600_ACCEL_FS_4G, + INV_ICM42600_ACCEL_FS_2G, + INV_ICM42600_ACCEL_FS_NB, +}; + +/* ODR suffixed by LN or LP are Low-Noise or Low-Power mode only */ +enum inv_icm42600_odr { + INV_ICM42600_ODR_8KHZ_LN = 3, + INV_ICM42600_ODR_4KHZ_LN, + INV_ICM42600_ODR_2KHZ_LN, + INV_ICM42600_ODR_1KHZ_LN, + INV_ICM42600_ODR_200HZ, + INV_ICM42600_ODR_100HZ, + INV_ICM42600_ODR_50HZ, + INV_ICM42600_ODR_25HZ, + INV_ICM42600_ODR_12_5HZ, + INV_ICM42600_ODR_6_25HZ_LP, + INV_ICM42600_ODR_3_125HZ_LP, + INV_ICM42600_ODR_1_5625HZ_LP, + INV_ICM42600_ODR_500HZ, + INV_ICM42600_ODR_NB, +}; + +enum inv_icm42600_filter { + /* Low-Noise mode sensor data filter (3rd order filter by default) */ + INV_ICM42600_FILTER_BW_ODR_DIV_2, + + /* Low-Power mode sensor data filter (averaging) */ + INV_ICM42600_FILTER_AVG_1X = 1, + INV_ICM42600_FILTER_AVG_16X = 6, +}; + +struct inv_icm42600_sensor_conf { + int mode; + int fs; + int odr; + int filter; +}; +#define INV_ICM42600_SENSOR_CONF_INIT {-1, -1, -1, -1} + +struct inv_icm42600_conf { + struct inv_icm42600_sensor_conf gyro; + struct inv_icm42600_sensor_conf accel; + bool temp_en; +}; + +struct inv_icm42600_suspended { + enum inv_icm42600_sensor_mode gyro; + enum inv_icm42600_sensor_mode accel; + bool temp; +}; + +/* + * struct inv_icm42600_state - driver state variables + * @lock: chip access lock. + * @chip: chip identifier. + * @name: chip name. + * @map: regmap pointer. + * @vdd_supply: VDD voltage regulator for the chip. + * @vddio_supply: I/O voltage regulator for the chip. + * @orientation: sensor chip orientation relative to main hardware. + * @conf: chip sensors configurations. + * @suspended: suspended sensors configuration. + */ +struct inv_icm42600_state { + struct mutex lock; + enum inv_icm42600_chip chip; + const char *name; + struct regmap *map; + struct regulator *vdd_supply; + struct regulator *vddio_supply; + struct iio_mount_matrix orientation; + struct inv_icm42600_conf conf; + struct inv_icm42600_suspended suspended; +}; + +/* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */ + +/* Bank selection register, available in all banks */ +#define INV_ICM42600_REG_BANK_SEL 0x76 +#define INV_ICM42600_BANK_SEL_MASK GENMASK(2, 0) + +/* User bank 0 (MSB 0x00) */ +#define INV_ICM42600_REG_DEVICE_CONFIG 0x0011 +#define INV_ICM42600_DEVICE_CONFIG_SOFT_RESET BIT(0) + +#define INV_ICM42600_REG_DRIVE_CONFIG 0x0013 +#define INV_ICM42600_DRIVE_CONFIG_I2C_MASK GENMASK(5, 3) +#define INV_ICM42600_DRIVE_CONFIG_I2C(_rate) \ + FIELD_PREP(INV_ICM42600_DRIVE_CONFIG_I2C_MASK, (_rate)) +#define INV_ICM42600_DRIVE_CONFIG_SPI_MASK GENMASK(2, 0) +#define INV_ICM42600_DRIVE_CONFIG_SPI(_rate) \ + FIELD_PREP(INV_ICM42600_DRIVE_CONFIG_SPI_MASK, (_rate)) + +#define INV_ICM42600_REG_INT_CONFIG 0x0014 +#define INV_ICM42600_INT_CONFIG_INT2_LATCHED BIT(5) +#define INV_ICM42600_INT_CONFIG_INT2_PUSH_PULL BIT(4) +#define INV_ICM42600_INT_CONFIG_INT2_ACTIVE_HIGH BIT(3) +#define INV_ICM42600_INT_CONFIG_INT2_ACTIVE_LOW 0x00 +#define INV_ICM42600_INT_CONFIG_INT1_LATCHED BIT(2) +#define INV_ICM42600_INT_CONFIG_INT1_PUSH_PULL BIT(1) +#define INV_ICM42600_INT_CONFIG_INT1_ACTIVE_HIGH BIT(0) +#define INV_ICM42600_INT_CONFIG_INT1_ACTIVE_LOW 0x00 + +#define INV_ICM42600_REG_FIFO_CONFIG 0x0016 +#define INV_ICM42600_FIFO_CONFIG_MASK GENMASK(7, 6) +#define INV_ICM42600_FIFO_CONFIG_BYPASS \ + FIELD_PREP(INV_ICM42600_FIFO_CONFIG_MASK, 0) +#define INV_ICM42600_FIFO_CONFIG_STREAM \ + FIELD_PREP(INV_ICM42600_FIFO_CONFIG_MASK, 1) +#define INV_ICM42600_FIFO_CONFIG_STOP_ON_FULL \ + FIELD_PREP(INV_ICM42600_FIFO_CONFIG_MASK, 2) + +/* all sensor data are 16 bits (2 registers wide) in big-endian */ +#define INV_ICM42600_REG_TEMP_DATA 0x001D +#define INV_ICM42600_REG_ACCEL_DATA_X 0x001F +#define INV_ICM42600_REG_ACCEL_DATA_Y 0x0021 +#define INV_ICM42600_REG_ACCEL_DATA_Z 0x0023 +#define INV_ICM42600_REG_GYRO_DATA_X 0x0025 +#define INV_ICM42600_REG_GYRO_DATA_Y 0x0027 +#define INV_ICM42600_REG_GYRO_DATA_Z 0x0029 +#define INV_ICM42600_DATA_INVALID -32768 + +#define INV_ICM42600_REG_INT_STATUS 0x002D +#define INV_ICM42600_INT_STATUS_UI_FSYNC BIT(6) +#define INV_ICM42600_INT_STATUS_PLL_RDY BIT(5) +#define INV_ICM42600_INT_STATUS_RESET_DONE BIT(4) +#define INV_ICM42600_INT_STATUS_DATA_RDY BIT(3) +#define INV_ICM42600_INT_STATUS_FIFO_THS BIT(2) +#define INV_ICM42600_INT_STATUS_FIFO_FULL BIT(1) +#define INV_ICM42600_INT_STATUS_AGC_RDY BIT(0) + +/* + * FIFO access registers + * FIFO count is 16 bits (2 registers) big-endian + * FIFO data is a continuous read register to read FIFO content + */ +#define INV_ICM42600_REG_FIFO_COUNT 0x002E +#define INV_ICM42600_REG_FIFO_DATA 0x0030 + +#define INV_ICM42600_REG_SIGNAL_PATH_RESET 0x004B +#define INV_ICM42600_SIGNAL_PATH_RESET_DMP_INIT_EN BIT(6) +#define INV_ICM42600_SIGNAL_PATH_RESET_DMP_MEM_RESET BIT(5) +#define INV_ICM42600_SIGNAL_PATH_RESET_RESET BIT(3) +#define INV_ICM42600_SIGNAL_PATH_RESET_TMST_STROBE BIT(2) +#define INV_ICM42600_SIGNAL_PATH_RESET_FIFO_FLUSH BIT(1) + +/* default configuration: all data big-endian and fifo count in bytes */ +#define INV_ICM42600_REG_INTF_CONFIG0 0x004C +#define INV_ICM42600_INTF_CONFIG0_FIFO_HOLD_LAST_DATA BIT(7) +#define INV_ICM42600_INTF_CONFIG0_FIFO_COUNT_REC BIT(6) +#define INV_ICM42600_INTF_CONFIG0_FIFO_COUNT_ENDIAN BIT(5) +#define INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN BIT(4) +#define INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK GENMASK(1, 0) +#define INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_SPI_DIS \ + FIELD_PREP(INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK, 2) +#define INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS \ + FIELD_PREP(INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK, 3) + +#define INV_ICM42600_REG_INTF_CONFIG1 0x004D +#define INV_ICM42600_INTF_CONFIG1_ACCEL_LP_CLK_RC BIT(3) + +#define INV_ICM42600_REG_PWR_MGMT0 0x004E +#define INV_ICM42600_PWR_MGMT0_TEMP_DIS BIT(5) +#define INV_ICM42600_PWR_MGMT0_IDLE BIT(4) +#define INV_ICM42600_PWR_MGMT0_GYRO(_mode) \ + FIELD_PREP(GENMASK(3, 2), (_mode)) +#define INV_ICM42600_PWR_MGMT0_ACCEL(_mode) \ + FIELD_PREP(GENMASK(1, 0), (_mode)) + +#define INV_ICM42600_REG_GYRO_CONFIG0 0x004F +#define INV_ICM42600_GYRO_CONFIG0_FS(_fs) \ + FIELD_PREP(GENMASK(7, 5), (_fs)) +#define INV_ICM42600_GYRO_CONFIG0_ODR(_odr) \ + FIELD_PREP(GENMASK(3, 0), (_odr)) + +#define INV_ICM42600_REG_ACCEL_CONFIG0 0x0050 +#define INV_ICM42600_ACCEL_CONFIG0_FS(_fs) \ + FIELD_PREP(GENMASK(7, 5), (_fs)) +#define INV_ICM42600_ACCEL_CONFIG0_ODR(_odr) \ + FIELD_PREP(GENMASK(3, 0), (_odr)) + +#define INV_ICM42600_REG_GYRO_ACCEL_CONFIG0 0x0052 +#define INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(_f) \ + FIELD_PREP(GENMASK(7, 4), (_f)) +#define INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(_f) \ + FIELD_PREP(GENMASK(3, 0), (_f)) + +#define INV_ICM42600_REG_TMST_CONFIG 0x0054 +#define INV_ICM42600_TMST_CONFIG_MASK GENMASK(4, 0) +#define INV_ICM42600_TMST_CONFIG_TMST_TO_REGS_EN BIT(4) +#define INV_ICM42600_TMST_CONFIG_TMST_RES_16US BIT(3) +#define INV_ICM42600_TMST_CONFIG_TMST_DELTA_EN BIT(2) +#define INV_ICM42600_TMST_CONFIG_TMST_FSYNC_EN BIT(1) +#define INV_ICM42600_TMST_CONFIG_TMST_EN BIT(0) + +#define INV_ICM42600_REG_FIFO_CONFIG1 0x005F +#define INV_ICM42600_FIFO_CONFIG1_RESUME_PARTIAL_RD BIT(6) +#define INV_ICM42600_FIFO_CONFIG1_WM_GT_TH BIT(5) +#define INV_ICM42600_FIFO_CONFIG1_TMST_FSYNC_EN BIT(3) +#define INV_ICM42600_FIFO_CONFIG1_TEMP_EN BIT(2) +#define INV_ICM42600_FIFO_CONFIG1_GYRO_EN BIT(1) +#define INV_ICM42600_FIFO_CONFIG1_ACCEL_EN BIT(0) + +/* FIFO watermark is 16 bits (2 registers wide) in little-endian */ +#define INV_ICM42600_REG_FIFO_WATERMARK 0x0060 +#define INV_ICM42600_FIFO_WATERMARK_VAL(_wm) \ + cpu_to_le16((_wm) & GENMASK(11, 0)) +/* FIFO is 2048 bytes, let 12 samples for reading latency */ +#define INV_ICM42600_FIFO_WATERMARK_MAX (2048 - 12 * 16) + +#define INV_ICM42600_REG_INT_CONFIG1 0x0064 +#define INV_ICM42600_INT_CONFIG1_TPULSE_DURATION BIT(6) +#define INV_ICM42600_INT_CONFIG1_TDEASSERT_DISABLE BIT(5) +#define INV_ICM42600_INT_CONFIG1_ASYNC_RESET BIT(4) + +#define INV_ICM42600_REG_INT_SOURCE0 0x0065 +#define INV_ICM42600_INT_SOURCE0_UI_FSYNC_INT1_EN BIT(6) +#define INV_ICM42600_INT_SOURCE0_PLL_RDY_INT1_EN BIT(5) +#define INV_ICM42600_INT_SOURCE0_RESET_DONE_INT1_EN BIT(4) +#define INV_ICM42600_INT_SOURCE0_UI_DRDY_INT1_EN BIT(3) +#define INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN BIT(2) +#define INV_ICM42600_INT_SOURCE0_FIFO_FULL_INT1_EN BIT(1) +#define INV_ICM42600_INT_SOURCE0_UI_AGC_RDY_INT1_EN BIT(0) + +#define INV_ICM42600_REG_WHOAMI 0x0075 +#define INV_ICM42600_WHOAMI_ICM42600 0x40 +#define INV_ICM42600_WHOAMI_ICM42602 0x41 +#define INV_ICM42600_WHOAMI_ICM42605 0x42 +#define INV_ICM42600_WHOAMI_ICM42622 0x46 + +/* User bank 1 (MSB 0x10) */ +#define INV_ICM42600_REG_SENSOR_CONFIG0 0x1003 +#define INV_ICM42600_SENSOR_CONFIG0_ZG_DISABLE BIT(5) +#define INV_ICM42600_SENSOR_CONFIG0_YG_DISABLE BIT(4) +#define INV_ICM42600_SENSOR_CONFIG0_XG_DISABLE BIT(3) +#define INV_ICM42600_SENSOR_CONFIG0_ZA_DISABLE BIT(2) +#define INV_ICM42600_SENSOR_CONFIG0_YA_DISABLE BIT(1) +#define INV_ICM42600_SENSOR_CONFIG0_XA_DISABLE BIT(0) + +/* Timestamp value is 20 bits (3 registers) in little-endian */ +#define INV_ICM42600_REG_TMSTVAL 0x1062 +#define INV_ICM42600_TMSTVAL_MASK GENMASK(19, 0) + +#define INV_ICM42600_REG_INTF_CONFIG4 0x107A +#define INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY BIT(6) +#define INV_ICM42600_INTF_CONFIG4_SPI_AP_4WIRE BIT(1) + +#define INV_ICM42600_REG_INTF_CONFIG6 0x107C +#define INV_ICM42600_INTF_CONFIG6_MASK GENMASK(4, 0) +#define INV_ICM42600_INTF_CONFIG6_I3C_EN BIT(4) +#define INV_ICM42600_INTF_CONFIG6_I3C_IBI_BYTE_EN BIT(3) +#define INV_ICM42600_INTF_CONFIG6_I3C_IBI_EN BIT(2) +#define INV_ICM42600_INTF_CONFIG6_I3C_DDR_EN BIT(1) +#define INV_ICM42600_INTF_CONFIG6_I3C_SDR_EN BIT(0) + +/* User bank 4 (MSB 0x40) */ +#define INV_ICM42600_REG_INT_SOURCE8 0x404F +#define INV_ICM42600_INT_SOURCE8_FSYNC_IBI_EN BIT(5) +#define INV_ICM42600_INT_SOURCE8_PLL_RDY_IBI_EN BIT(4) +#define INV_ICM42600_INT_SOURCE8_UI_DRDY_IBI_EN BIT(3) +#define INV_ICM42600_INT_SOURCE8_FIFO_THS_IBI_EN BIT(2) +#define INV_ICM42600_INT_SOURCE8_FIFO_FULL_IBI_EN BIT(1) +#define INV_ICM42600_INT_SOURCE8_AGC_RDY_IBI_EN BIT(0) + +#define INV_ICM42600_REG_OFFSET_USER0 0x4077 +#define INV_ICM42600_REG_OFFSET_USER1 0x4078 +#define INV_ICM42600_REG_OFFSET_USER2 0x4079 +#define INV_ICM42600_REG_OFFSET_USER3 0x407A +#define INV_ICM42600_REG_OFFSET_USER4 0x407B +#define INV_ICM42600_REG_OFFSET_USER5 0x407C +#define INV_ICM42600_REG_OFFSET_USER6 0x407D +#define INV_ICM42600_REG_OFFSET_USER7 0x407E +#define INV_ICM42600_REG_OFFSET_USER8 0x407F + +/* Sleep times required by the driver */ +#define INV_ICM42600_POWER_UP_TIME_MS 100 +#define INV_ICM42600_RESET_TIME_MS 1 +#define INV_ICM42600_ACCEL_STARTUP_TIME_MS 20 +#define INV_ICM42600_GYRO_STARTUP_TIME_MS 60 +#define INV_ICM42600_GYRO_STOP_TIME_MS 150 +#define INV_ICM42600_TEMP_STARTUP_TIME_MS 14 +#define INV_ICM42600_SUSPEND_DELAY_MS 2000 + +typedef int (*inv_icm42600_bus_setup)(struct inv_icm42600_state *); + +extern const struct regmap_config inv_icm42600_regmap_config; +extern const struct dev_pm_ops inv_icm42600_pm_ops; + +const struct iio_mount_matrix * +inv_icm42600_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan); + +uint32_t inv_icm42600_odr_to_period(enum inv_icm42600_odr odr); + +int inv_icm42600_set_accel_conf(struct inv_icm42600_state *st, + struct inv_icm42600_sensor_conf *conf, + unsigned int *sleep); + +int inv_icm42600_set_gyro_conf(struct inv_icm42600_state *st, + struct inv_icm42600_sensor_conf *conf, + unsigned int *sleep); + +int inv_icm42600_set_temp_conf(struct inv_icm42600_state *st, bool enable, + unsigned int *sleep); + +int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg, + unsigned int writeval, unsigned int *readval); + +int inv_icm42600_core_probe(struct regmap *regmap, int chip, + inv_icm42600_bus_setup bus_setup); + +#endif diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c new file mode 100644 index 000000000000..35bdf4f9d31e --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c @@ -0,0 +1,618 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "inv_icm42600.h" + +static const struct regmap_range_cfg inv_icm42600_regmap_ranges[] = { + { + .name = "user banks", + .range_min = 0x0000, + .range_max = 0x4FFF, + .selector_reg = INV_ICM42600_REG_BANK_SEL, + .selector_mask = INV_ICM42600_BANK_SEL_MASK, + .selector_shift = 0, + .window_start = 0, + .window_len = 0x1000, + }, +}; + +const struct regmap_config inv_icm42600_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x4FFF, + .ranges = inv_icm42600_regmap_ranges, + .num_ranges = ARRAY_SIZE(inv_icm42600_regmap_ranges), +}; +EXPORT_SYMBOL_GPL(inv_icm42600_regmap_config); + +struct inv_icm42600_hw { + uint8_t whoami; + const char *name; + const struct inv_icm42600_conf *conf; +}; + +/* chip initial default configuration */ +static const struct inv_icm42600_conf inv_icm42600_default_conf = { + .gyro = { + .mode = INV_ICM42600_SENSOR_MODE_OFF, + .fs = INV_ICM42600_GYRO_FS_2000DPS, + .odr = INV_ICM42600_ODR_50HZ, + .filter = INV_ICM42600_FILTER_BW_ODR_DIV_2, + }, + .accel = { + .mode = INV_ICM42600_SENSOR_MODE_OFF, + .fs = INV_ICM42600_ACCEL_FS_16G, + .odr = INV_ICM42600_ODR_50HZ, + .filter = INV_ICM42600_FILTER_BW_ODR_DIV_2, + }, + .temp_en = false, +}; + +static const struct inv_icm42600_hw inv_icm42600_hw[] = { + [INV_CHIP_ICM42600] = { + .whoami = INV_ICM42600_WHOAMI_ICM42600, + .name = "icm42600", + .conf = &inv_icm42600_default_conf, + }, + [INV_CHIP_ICM42602] = { + .whoami = INV_ICM42600_WHOAMI_ICM42602, + .name = "icm42602", + .conf = &inv_icm42600_default_conf, + }, + [INV_CHIP_ICM42605] = { + .whoami = INV_ICM42600_WHOAMI_ICM42605, + .name = "icm42605", + .conf = &inv_icm42600_default_conf, + }, + [INV_CHIP_ICM42622] = { + .whoami = INV_ICM42600_WHOAMI_ICM42622, + .name = "icm42622", + .conf = &inv_icm42600_default_conf, + }, +}; + +const struct iio_mount_matrix * +inv_icm42600_get_mount_matrix(const struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + const struct inv_icm42600_state *st = + iio_device_get_drvdata((struct iio_dev *)indio_dev); + + return &st->orientation; +} + +uint32_t inv_icm42600_odr_to_period(enum inv_icm42600_odr odr) +{ + static uint32_t odr_periods[INV_ICM42600_ODR_NB] = { + /* reserved values */ + 0, 0, 0, + /* 8kHz */ + 125000, + /* 4kHz */ + 250000, + /* 2kHz */ + 500000, + /* 1kHz */ + 1000000, + /* 200Hz */ + 5000000, + /* 100Hz */ + 10000000, + /* 50Hz */ + 20000000, + /* 25Hz */ + 40000000, + /* 12.5Hz */ + 80000000, + /* 6.25Hz */ + 160000000, + /* 3.125Hz */ + 320000000, + /* 1.5625Hz */ + 640000000, + /* 500Hz */ + 2000000, + }; + + return odr_periods[odr]; +} + +static int inv_icm42600_set_pwr_mgmt0(struct inv_icm42600_state *st, + enum inv_icm42600_sensor_mode gyro, + enum inv_icm42600_sensor_mode accel, + bool temp, unsigned int *sleep) +{ + enum inv_icm42600_sensor_mode oldgyro = st->conf.gyro.mode; + enum inv_icm42600_sensor_mode oldaccel = st->conf.accel.mode; + bool oldtemp = st->conf.temp_en; + unsigned int sleepval; + unsigned int val; + int ret; + + /* if nothing changed, exit */ + if (gyro == oldgyro && accel == oldaccel && temp == oldtemp) + return 0; + + val = INV_ICM42600_PWR_MGMT0_GYRO(gyro) | + INV_ICM42600_PWR_MGMT0_ACCEL(accel); + if (!temp) + val |= INV_ICM42600_PWR_MGMT0_TEMP_DIS; + dev_dbg(regmap_get_device(st->map), "pwr_mgmt0: %#02x\n", val); + ret = regmap_write(st->map, INV_ICM42600_REG_PWR_MGMT0, val); + if (ret) + return ret; + + st->conf.gyro.mode = gyro; + st->conf.accel.mode = accel; + st->conf.temp_en = temp; + + /* compute required wait time for sensors to stabilize */ + sleepval = 0; + /* temperature stabilization time */ + if (temp && !oldtemp) { + if (sleepval < INV_ICM42600_TEMP_STARTUP_TIME_MS) + sleepval = INV_ICM42600_TEMP_STARTUP_TIME_MS; + } + /* accel startup time */ + if (accel != oldaccel && oldaccel == INV_ICM42600_SENSOR_MODE_OFF) { + /* block any register write for at least 200 µs */ + usleep_range(200, 300); + if (sleepval < INV_ICM42600_ACCEL_STARTUP_TIME_MS) + sleepval = INV_ICM42600_ACCEL_STARTUP_TIME_MS; + } + if (gyro != oldgyro) { + /* gyro startup time */ + if (oldgyro == INV_ICM42600_SENSOR_MODE_OFF) { + /* block any register write for at least 200 µs */ + usleep_range(200, 300); + if (sleepval < INV_ICM42600_GYRO_STARTUP_TIME_MS) + sleepval = INV_ICM42600_GYRO_STARTUP_TIME_MS; + /* gyro stop time */ + } else if (gyro == INV_ICM42600_SENSOR_MODE_OFF) { + if (sleepval < INV_ICM42600_GYRO_STOP_TIME_MS) + sleepval = INV_ICM42600_GYRO_STOP_TIME_MS; + } + } + + /* deferred sleep value if sleep pointer is provided or direct sleep */ + if (sleep) + *sleep = sleepval; + else if (sleepval) + msleep(sleepval); + + return 0; +} + +int inv_icm42600_set_accel_conf(struct inv_icm42600_state *st, + struct inv_icm42600_sensor_conf *conf, + unsigned int *sleep) +{ + struct inv_icm42600_sensor_conf *oldconf = &st->conf.accel; + unsigned int val; + int ret; + + /* Sanitize missing values with current values */ + if (conf->mode < 0) + conf->mode = oldconf->mode; + if (conf->fs < 0) + conf->fs = oldconf->fs; + if (conf->odr < 0) + conf->odr = oldconf->odr; + if (conf->filter < 0) + conf->filter = oldconf->filter; + + /* set ACCEL_CONFIG0 register (accel fullscale & odr) */ + if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) { + val = INV_ICM42600_ACCEL_CONFIG0_FS(conf->fs) | + INV_ICM42600_ACCEL_CONFIG0_ODR(conf->odr); + dev_dbg(regmap_get_device(st->map), "accel_config0: %#02x\n", val); + ret = regmap_write(st->map, INV_ICM42600_REG_ACCEL_CONFIG0, val); + if (ret) + return ret; + oldconf->fs = conf->fs; + oldconf->odr = conf->odr; + } + + /* set GYRO_ACCEL_CONFIG0 register (accel filter) */ + if (conf->filter != oldconf->filter) { + val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(conf->filter) | + INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(st->conf.gyro.filter); + dev_dbg(regmap_get_device(st->map), "gyro_accel_config0: %#02x\n", val); + ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val); + if (ret) + return ret; + oldconf->filter = conf->filter; + } + + /* set PWR_MGMT0 register (accel sensor mode) */ + return inv_icm42600_set_pwr_mgmt0(st, st->conf.gyro.mode, conf->mode, + st->conf.temp_en, sleep); +} + +int inv_icm42600_set_gyro_conf(struct inv_icm42600_state *st, + struct inv_icm42600_sensor_conf *conf, + unsigned int *sleep) +{ + struct inv_icm42600_sensor_conf *oldconf = &st->conf.gyro; + unsigned int val; + int ret; + + /* sanitize missing values with current values */ + if (conf->mode < 0) + conf->mode = oldconf->mode; + if (conf->fs < 0) + conf->fs = oldconf->fs; + if (conf->odr < 0) + conf->odr = oldconf->odr; + if (conf->filter < 0) + conf->filter = oldconf->filter; + + /* set GYRO_CONFIG0 register (gyro fullscale & odr) */ + if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) { + val = INV_ICM42600_GYRO_CONFIG0_FS(conf->fs) | + INV_ICM42600_GYRO_CONFIG0_ODR(conf->odr); + dev_dbg(regmap_get_device(st->map), "gyro_config0: %#02x\n", val); + ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_CONFIG0, val); + if (ret) + return ret; + oldconf->fs = conf->fs; + oldconf->odr = conf->odr; + } + + /* set GYRO_ACCEL_CONFIG0 register (gyro filter) */ + if (conf->filter != oldconf->filter) { + val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(st->conf.accel.filter) | + INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(conf->filter); + dev_dbg(regmap_get_device(st->map), "gyro_accel_config0: %#02x\n", val); + ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val); + if (ret) + return ret; + oldconf->filter = conf->filter; + } + + /* set PWR_MGMT0 register (gyro sensor mode) */ + return inv_icm42600_set_pwr_mgmt0(st, conf->mode, st->conf.accel.mode, + st->conf.temp_en, sleep); + + return 0; +} + +int inv_icm42600_set_temp_conf(struct inv_icm42600_state *st, bool enable, + unsigned int *sleep) +{ + return inv_icm42600_set_pwr_mgmt0(st, st->conf.gyro.mode, + st->conf.accel.mode, enable, + sleep); +} + +int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg, + unsigned int writeval, unsigned int *readval) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + mutex_lock(&st->lock); + + if (readval) + ret = regmap_read(st->map, reg, readval); + else + ret = regmap_write(st->map, reg, writeval); + + mutex_unlock(&st->lock); + + return ret; +} + +static int inv_icm42600_set_conf(struct inv_icm42600_state *st, + const struct inv_icm42600_conf *conf) +{ + unsigned int val; + int ret; + + /* set PWR_MGMT0 register (gyro & accel sensor mode, temp enabled) */ + val = INV_ICM42600_PWR_MGMT0_GYRO(conf->gyro.mode) | + INV_ICM42600_PWR_MGMT0_ACCEL(conf->accel.mode); + if (!conf->temp_en) + val |= INV_ICM42600_PWR_MGMT0_TEMP_DIS; + ret = regmap_write(st->map, INV_ICM42600_REG_PWR_MGMT0, val); + if (ret) + return ret; + + /* set GYRO_CONFIG0 register (gyro fullscale & odr) */ + val = INV_ICM42600_GYRO_CONFIG0_FS(conf->gyro.fs) | + INV_ICM42600_GYRO_CONFIG0_ODR(conf->gyro.odr); + ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_CONFIG0, val); + if (ret) + return ret; + + /* set ACCEL_CONFIG0 register (accel fullscale & odr) */ + val = INV_ICM42600_ACCEL_CONFIG0_FS(conf->accel.fs) | + INV_ICM42600_ACCEL_CONFIG0_ODR(conf->accel.odr); + ret = regmap_write(st->map, INV_ICM42600_REG_ACCEL_CONFIG0, val); + if (ret) + return ret; + + /* set GYRO_ACCEL_CONFIG0 register (gyro & accel filters) */ + val = INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(conf->accel.filter) | + INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(conf->gyro.filter); + ret = regmap_write(st->map, INV_ICM42600_REG_GYRO_ACCEL_CONFIG0, val); + if (ret) + return ret; + + /* update internal conf */ + st->conf = *conf; + + return 0; +} + +/** + * inv_icm42600_setup() - check and setup chip. + */ +static int inv_icm42600_setup(struct inv_icm42600_state *st, + inv_icm42600_bus_setup bus_setup) +{ + const struct inv_icm42600_hw *hw = &inv_icm42600_hw[st->chip]; + const struct device *dev = regmap_get_device(st->map); + unsigned int mask, val; + int ret; + + /* check chip self-identification value */ + ret = regmap_read(st->map, INV_ICM42600_REG_WHOAMI, &val); + if (ret) + return ret; + if (val != hw->whoami) { + dev_err(dev, "invalid whoami %#02x expected %#02x (%s)\n", + val, hw->whoami, hw->name); + return -ENODEV; + } + dev_info(dev, "found %s (%#02x)\n", hw->name, hw->whoami); + st->name = hw->name; + + /* reset to make sure previous state are not there */ + ret = regmap_write(st->map, INV_ICM42600_REG_DEVICE_CONFIG, + INV_ICM42600_DEVICE_CONFIG_SOFT_RESET); + if (ret) + return ret; + msleep(INV_ICM42600_RESET_TIME_MS); + ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, &val); + if (ret) + return ret; + if (!(val & INV_ICM42600_INT_STATUS_RESET_DONE)) { + dev_err(dev, "reset error, reset done bit not set\n"); + return -ENODEV; + } + + /* set chip bus configuration */ + ret = bus_setup(st); + if (ret) + return ret; + + /* sensor data in big-endian (default) */ + mask = INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN; + val = INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN; + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0, + mask, val); + if (ret) + return ret; + + return inv_icm42600_set_conf(st, hw->conf); +} + +static int inv_icm42600_enable_regulator_vddio(struct inv_icm42600_state *st) +{ + int ret; + + ret = regulator_enable(st->vddio_supply); + if (ret) + return ret; + + /* wait a little for supply ramp */ + usleep_range(3000, 4000); + + return 0; +} + +static void inv_icm42600_disable_regulators(void *_data) +{ + struct inv_icm42600_state *st = _data; + const struct device *dev = regmap_get_device(st->map); + int ret; + + ret = regulator_disable(st->vddio_supply); + if (ret) + dev_err(dev, "failed to disable vddio error %d\n", ret); + + ret = regulator_disable(st->vdd_supply); + if (ret) + dev_err(dev, "failed to disable vdd error %d\n", ret); +} + +static void inv_icm42600_disable_pm(void *_data) +{ + struct device *dev = _data; + + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); +} + +int inv_icm42600_core_probe(struct regmap *regmap, int chip, + inv_icm42600_bus_setup bus_setup) +{ + struct device *dev = regmap_get_device(regmap); + struct inv_icm42600_state *st; + int ret; + + BUILD_BUG_ON(ARRAY_SIZE(inv_icm42600_hw) != INV_CHIP_NB); + if (chip < 0 || chip >= INV_CHIP_NB) { + dev_err(dev, "invalid chip = %d\n", chip); + return -ENODEV; + } + + st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL); + if (!st) + return -ENOMEM; + dev_set_drvdata(dev, st); + mutex_init(&st->lock); + st->chip = chip; + st->map = regmap; + + ret = iio_read_mount_matrix(dev, "mount-matrix", &st->orientation); + if (ret) { + dev_err(dev, "failed to retrieve mounting matrix %d\n", ret); + return ret; + } + + st->vdd_supply = devm_regulator_get(dev, "vdd"); + if (IS_ERR(st->vdd_supply)) + return PTR_ERR(st->vdd_supply); + + st->vddio_supply = devm_regulator_get(dev, "vddio"); + if (IS_ERR(st->vddio_supply)) + return PTR_ERR(st->vddio_supply); + + ret = regulator_enable(st->vdd_supply); + if (ret) + return ret; + msleep(INV_ICM42600_POWER_UP_TIME_MS); + + ret = inv_icm42600_enable_regulator_vddio(st); + if (ret) { + regulator_disable(st->vdd_supply); + return ret; + } + + ret = devm_add_action_or_reset(dev, inv_icm42600_disable_regulators, + st); + if (ret) + return ret; + + /* setup chip registers */ + ret = inv_icm42600_setup(st, bus_setup); + if (ret) + return ret; + + /* setup runtime power management */ + ret = pm_runtime_set_active(dev); + if (ret) + return ret; + pm_runtime_get_noresume(dev); + pm_runtime_enable(dev); + pm_runtime_set_autosuspend_delay(dev, INV_ICM42600_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(dev); + pm_runtime_put(dev); + + return devm_add_action_or_reset(dev, inv_icm42600_disable_pm, dev); +} +EXPORT_SYMBOL_GPL(inv_icm42600_core_probe); + +static int __maybe_unused inv_icm42600_suspend(struct device *dev) +{ + struct inv_icm42600_state *st = dev_get_drvdata(dev); + int ret; + + mutex_lock(&st->lock); + + st->suspended.gyro = st->conf.gyro.mode; + st->suspended.accel = st->conf.accel.mode; + st->suspended.temp = st->conf.temp_en; + if (pm_runtime_suspended(dev)) { + ret = 0; + goto out_unlock; + } + + ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF, + INV_ICM42600_SENSOR_MODE_OFF, false, + NULL); + if (ret) + goto out_unlock; + + regulator_disable(st->vddio_supply); + +out_unlock: + mutex_unlock(&st->lock); + return ret; +} + +static int __maybe_unused inv_icm42600_resume(struct device *dev) +{ + struct inv_icm42600_state *st = dev_get_drvdata(dev); + int ret; + + mutex_lock(&st->lock); + + ret = inv_icm42600_enable_regulator_vddio(st); + if (ret) + goto out_unlock; + + pm_runtime_disable(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + /* restore sensors state */ + ret = inv_icm42600_set_pwr_mgmt0(st, st->suspended.gyro, + st->suspended.accel, + st->suspended.temp, NULL); + if (ret) + goto out_unlock; + +out_unlock: + mutex_unlock(&st->lock); + return ret; +} + +static int __maybe_unused inv_icm42600_runtime_suspend(struct device *dev) +{ + struct inv_icm42600_state *st = dev_get_drvdata(dev); + int ret; + + mutex_lock(&st->lock); + + /* disable all sensors */ + ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF, + INV_ICM42600_SENSOR_MODE_OFF, false, + NULL); + if (ret) + goto error_unlock; + + regulator_disable(st->vddio_supply); + +error_unlock: + mutex_unlock(&st->lock); + return ret; +} + +static int __maybe_unused inv_icm42600_runtime_resume(struct device *dev) +{ + struct inv_icm42600_state *st = dev_get_drvdata(dev); + int ret; + + mutex_lock(&st->lock); + + ret = inv_icm42600_enable_regulator_vddio(st); + + mutex_unlock(&st->lock); + return ret; +} + +const struct dev_pm_ops inv_icm42600_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(inv_icm42600_suspend, inv_icm42600_resume) + SET_RUNTIME_PM_OPS(inv_icm42600_runtime_suspend, + inv_icm42600_runtime_resume, NULL) +}; +EXPORT_SYMBOL_GPL(inv_icm42600_pm_ops); + +MODULE_AUTHOR("InvenSense, Inc."); +MODULE_DESCRIPTION("InvenSense ICM-426xx device driver"); +MODULE_LICENSE("GPL"); From patchwork Thu May 7 14:42:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Baptiste Maneyrol X-Patchwork-Id: 200946 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, MSGID_FROM_MTA_HEADER,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, UNWANTED_LANGUAGE_BODY, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 183D8C54E49 for ; Thu, 7 May 2020 14:43:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DCC5B20838 for ; Thu, 7 May 2020 14:43:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="mhUze55S"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="LRkYwmlY" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726774AbgEGOnU (ORCPT ); Thu, 7 May 2020 10:43:20 -0400 Received: from mx0a-00328301.pphosted.com ([148.163.145.46]:23002 "EHLO mx0a-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726598AbgEGOnT (ORCPT ); Thu, 7 May 2020 10:43:19 -0400 Received: from pps.filterd (m0156134.ppops.net [127.0.0.1]) by mx0a-00328301.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 047Eegd6005564; Thu, 7 May 2020 07:43:15 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=invensense.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : content-type : mime-version; s=pfpt1; bh=1bOjF4OnTz74NnMsiumNubxHvSGSjvKYI03VWRA74XU=; b=mhUze55Sk5y25snO+6W00wnwxh946shaykrqFAzLrSoRm89sw2E5gHpV3dnTyQToNhuv k0wZhckKoi9tgYkQoSf1RDRyxqlXpeseA9qrcADbjYHHWneR/+NviGc/SexEjbCkj7o+ gBYXimdl7WvYXshsDZ3Ks4u7FSw5QopofBWJptk8KP9eL8GrnRNrMjNJ7SNRZYGqxIri XxepbSyhJrYfZHoVhUJ963lkPev2D5nMhEy/niSDYMOLk1CBjFBXZjXsLExdRzYPEuk3 XzLn00r6jvUzp9Ka+A1shDvBYa2HNVL2B8flHUOOy95+ykNUYNrRaaejr5fJoi4mHkTy 9g== Received: from nam11-dm6-obe.outbound.protection.outlook.com (mail-dm6nam11lp2169.outbound.protection.outlook.com [104.47.57.169]) by mx0a-00328301.pphosted.com with ESMTP id 30sfwdjs8q-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 07 May 2020 07:43:15 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=d/J4roHpgG08xUz++aZUToAEOKlLElCFh83P/KUHrrhfapw6KGoJks5mX7qu+0vT+WdJjmeLIkNYSe8KTBTJBTXrI49yCzno6qlmBhNRbQQ92HXoEH5a96Gi1RCNnbCGCq5tFwhvCbvQLLioOk1Sfqj0mCrcS6xO5ga9NSXJFNgq/fzgU4jIwugyoC1nJlduJloOCBs+Cl4KXhD15pITX0w7h8qKBpnoKKojZTp+zGmctDKrzdrvDc5dy/di5M1TJP8HhlUbiXVVnpd3p+zVaHqSystx4qRQTNx6RDNm8nRAKs98xBpad9VRK6OLHbj7serRMNfQw0luuoK6EISjdA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=1bOjF4OnTz74NnMsiumNubxHvSGSjvKYI03VWRA74XU=; b=ej2CrkeRbFGbFTw1YrRYJ2aG9/fG1RAWW/9DQTBypzYrAdZmo74pZl7KAtWa6bqqjnVwGKjbl2C9iE+X/OG7MLEKWZvV4+OVb7ZsD7LAZdDyIh01OCHhzvxZe/kyz/KBmJYlFcnSwjNRL5QlVpTJQbTT/QDfIH7kRa4zZUA5q/lf5uSXlZ1ST/dsJ8KBDi4VVaiwos6Zrn9FWLKYvoSMohI7HWnPHoiujuVlqcTwVlGY59awnAl4S3D4FHUlsb8MUq6krNJCHRjB6idMZzDEiLvDv6T2nJQz7w1JcnFWVps7tMAWPv8NWWQAPIotXcDCtIWrechUf6IpZc9u02z/XQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=invensense.com; dmarc=pass action=none header.from=invensense.com; dkim=pass header.d=invensense.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=invensense.onmicrosoft.com; s=selector2-invensense-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=1bOjF4OnTz74NnMsiumNubxHvSGSjvKYI03VWRA74XU=; b=LRkYwmlYAdO8VE4wL85bubraBTHMP20qFoOP94R7Zg7oyM0Q8puvoqO0tVlNEteTli2KyKSdi9iBld256T5NGto22LoahFLMP7sBXm0LgthvhEuingXI4ck/JFX4BBaIRDnXUYcr0OJfExIbjP5O4bIFrFoOe20QFkNYDUe97OI= Authentication-Results: kernel.org; dkim=none (message not signed) header.d=none; kernel.org; dmarc=none action=none header.from=invensense.com; Received: from MN2PR12MB4422.namprd12.prod.outlook.com (2603:10b6:208:265::9) by MN2PR12MB4269.namprd12.prod.outlook.com (2603:10b6:208:1d4::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2979.28; Thu, 7 May 2020 14:43:14 +0000 Received: from MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::7471:da8b:8ca1:6af0]) by MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::7471:da8b:8ca1:6af0%4]) with mapi id 15.20.2979.028; Thu, 7 May 2020 14:43:14 +0000 From: Jean-Baptiste Maneyrol To: jic23@kernel.org, robh+dt@kernel.org, robh@kernel.org, mchehab+huawei@kernel.org, davem@davemloft.net, gregkh@linuxfoundation.org Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Jean-Baptiste Maneyrol Subject: [PATCH 04/12] iio: imu: inv_icm42600: add gyroscope IIO device Date: Thu, 7 May 2020 16:42:14 +0200 Message-Id: <20200507144222.20989-5-jmaneyrol@invensense.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200507144222.20989-1-jmaneyrol@invensense.com> References: <20200507144222.20989-1-jmaneyrol@invensense.com> X-ClientProxiedBy: LNXP265CA0048.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:5c::36) To MN2PR12MB4422.namprd12.prod.outlook.com (2603:10b6:208:265::9) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from frgnb-buildozer.invcorp.invensense.com (77.157.193.39) by LNXP265CA0048.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:5c::36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2979.26 via Frontend Transport; Thu, 7 May 2020 14:43:11 +0000 X-Mailer: git-send-email 2.17.1 X-Originating-IP: [77.157.193.39] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 27e96971-22d8-4f7e-149e-08d7f294f82d X-MS-TrafficTypeDiagnostic: MN2PR12MB4269: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:565; X-Forefront-PRVS: 03965EFC76 X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: PjQIsCVxWzvnzUHr3hBJOD1kUKlwyoGxB/yOYrmtKrHWXcWfW2klR2XkHWpUjS40ZsqqbDduq98RKfMDk3dRfAVUI5tjCcA3UbkRjLBMkprdGn/OPWv4iKUR6Y6vE1IIfDB4jaYGDVIuyqOLXGkzvQAe3HcHWROlCw+R+vgWeojBvD35qb8oIoY1yLzTGRPjgW1W68Ktgw3fqgJsyxx50LhuT4cyHazXfbHUbT+uYDn9FWBfptOmHc36g0+koUpZZgHqvCpdni7iItg463vpOzpF1y3GcNU78Qx4FVqEEsufQhCHXW32Di5Uil9yBH9ZH5aSDkkqIxS6wuRJYLshumIpAgX5SH5GG9RvCFd3VTsom1jo40zhrucoYzIX70FCIy1AIq7jHCq4UyTQL1653SSpiKNIitGaVomdHWSUbXyw8Z0jqolc+IpKHgnHQ2fWCkwgzBxMpySB3ubu3YufvlEUcGEMKCFi7KxFwY4wnkNs8WtquqV5jQHv0Tw8AU4tncO+XaMPjKDCFfj1D0z0zQ== X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:MN2PR12MB4422.namprd12.prod.outlook.com; PTR:; CAT:NONE; SFTY:; SFS:(346002)(396003)(136003)(366004)(39850400004)(376002)(33430700001)(186003)(6486002)(478600001)(16526019)(5660300002)(4326008)(33440700001)(30864003)(66556008)(8676002)(1076003)(36756003)(316002)(66946007)(66476007)(52116002)(8936002)(86362001)(2616005)(83280400001)(956004)(83320400001)(83290400001)(83310400001)(26005)(2906002)(7696005)(83300400001)(107886003); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData: J7bDtdj253sIw1hHVbsBVV4g4vR0uz5YJ8py4kk5vMq0suLqBgd+GjqMvJu7bKarXkD5bpgKvofj54QEaiDJNRugSDtGktoxdztK/krO6wWo8lZ29DnbJFd37iKw5AdQaFLOovuVo3Iu8yW6NS1S5mygPJR+ph2YOUw0EahVaBbp9j18Nj8QJbYzRESEz3bkazgkNRxpyLW6z5/qvXMqJuC0dm6WomxqIieQH4JaPF6YWr9fJB0RvEnD+5w36kaAzn26mRatbh0wtShCjQ49PgszEn0nbyWh2iinV2quy30RZvLjC6woUOYZePwkfIMI7PNIQwqgtChNZC/h+xxClHUHBGmc/vgXLZjpVbnC12mOQQHAe/fIyzF5e3bsyt4W/NFXTQ8uWkHMvy1O6UHMZowgRbTE6Uk8REdcFNhsFAU1fxYKPcLLqvTpg60RUjvymdnSk1ubWjpxCrnIhUy3mhJD0pTOHpHFS6WyYQF6+6s/0kFbIqHKonq2BmroWC6LR2Cya6cPCLUNzQlPRHIEpUcPA5Cac1hMzF48n4/3szg7PBeTT+N33a9H2lXmDgcAfXyW7YA6TV3UQBrQ6lo5KHqL5I6InGiG++9W+0Py4pT3cQP8l0f8Ou+9MYx5fGUvRAUudFpamT4+Ca0e0qtqaw5WzSyEWEYRi/YrGRplTAWAqeUmIQsrD8/6rHMxTipbsszB98kjqgTR19cOb0yTuEUYKJiLTP92LmP1UpOfnPMZ1D/kuL5LetU137j7ab6thX/dU8NF6c6xdukfDLjQqJv99h8NLe8JcHgzwZa0yzM= X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: 27e96971-22d8-4f7e-149e-08d7f294f82d X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 May 2020 14:43:14.1584 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 462b3b3b-e42b-47ea-801a-f1581aac892d X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: j7YM6Seu+Pvj5xixFihT7BfWw1499Jn55+LXvE5qnUZrXFTFHpzB4eyuiFIZjraOQhhiYt1xx6oB4MwasyILfmv4KgovD35stE+gYZ0NqmM= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4269 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216, 18.0.676 definitions=2020-05-07_09:2020-05-07,2020-05-07 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 adultscore=0 spamscore=0 impostorscore=0 suspectscore=0 mlxscore=0 phishscore=0 bulkscore=0 malwarescore=0 mlxlogscore=999 clxscore=1015 priorityscore=1501 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2005070118 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add IIO device for gyroscope sensor with data polling interface. Attributes: raw, scale, sampling_frequency, calibbias. Gyroscope in low noise mode. Signed-off-by: Jean-Baptiste Maneyrol --- drivers/iio/imu/inv_icm42600/inv_icm42600.h | 4 + .../iio/imu/inv_icm42600/inv_icm42600_core.c | 5 + .../iio/imu/inv_icm42600/inv_icm42600_gyro.c | 549 ++++++++++++++++++ 3 files changed, 558 insertions(+) create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h b/drivers/iio/imu/inv_icm42600/inv_icm42600.h index 8da4c8249aed..ca41a9d6404a 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h @@ -120,6 +120,7 @@ struct inv_icm42600_suspended { * @orientation: sensor chip orientation relative to main hardware. * @conf: chip sensors configurations. * @suspended: suspended sensors configuration. + * @indio_gyro: gyroscope IIO device. */ struct inv_icm42600_state { struct mutex lock; @@ -131,6 +132,7 @@ struct inv_icm42600_state { struct iio_mount_matrix orientation; struct inv_icm42600_conf conf; struct inv_icm42600_suspended suspended; + struct iio_dev *indio_gyro; }; /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */ @@ -369,4 +371,6 @@ int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg, int inv_icm42600_core_probe(struct regmap *regmap, int chip, inv_icm42600_bus_setup bus_setup); +int inv_icm42600_gyro_init(struct inv_icm42600_state *st); + #endif diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c index 35bdf4f9d31e..151257652ce6 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c @@ -503,6 +503,11 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, if (ret) return ret; + /* create and init gyroscope iio device */ + ret = inv_icm42600_gyro_init(st); + if (ret) + return ret; + /* setup runtime power management */ ret = pm_runtime_set_active(dev); if (ret) diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c new file mode 100644 index 000000000000..74aa2b5fa611 --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c @@ -0,0 +1,549 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "inv_icm42600.h" + +#define INV_ICM42600_GYRO_CHAN(_modifier, _index, _ext_info) \ + { \ + .type = IIO_ANGL_VEL, \ + .modified = 1, \ + .channel2 = _modifier, \ + .info_mask_separate = \ + BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_CALIBBIAS), \ + .info_mask_shared_by_type = \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_type_available = \ + BIT(IIO_CHAN_INFO_SCALE), \ + .info_mask_shared_by_all = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .info_mask_shared_by_all_available = \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .shift = 0, \ + .endianness = IIO_BE, \ + }, \ + .ext_info = _ext_info, \ + } + +enum inv_icm42600_gyro_scan { + INV_ICM42600_GYRO_SCAN_X, + INV_ICM42600_GYRO_SCAN_Y, + INV_ICM42600_GYRO_SCAN_Z, +}; + +static const struct iio_chan_spec_ext_info inv_icm42600_gyro_ext_infos[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42600_get_mount_matrix), + {}, +}; + +static const struct iio_chan_spec inv_icm42600_gyro_channels[] = { + INV_ICM42600_GYRO_CHAN(IIO_MOD_X, INV_ICM42600_GYRO_SCAN_X, + inv_icm42600_gyro_ext_infos), + INV_ICM42600_GYRO_CHAN(IIO_MOD_Y, INV_ICM42600_GYRO_SCAN_Y, + inv_icm42600_gyro_ext_infos), + INV_ICM42600_GYRO_CHAN(IIO_MOD_Z, INV_ICM42600_GYRO_SCAN_Z, + inv_icm42600_gyro_ext_infos), +}; + +static int inv_icm42600_gyro_read_sensor(struct inv_icm42600_state *st, + struct iio_chan_spec const *chan, + int16_t *val) +{ + struct device *dev = regmap_get_device(st->map); + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; + unsigned int reg; + __be16 data; + int ret; + + if (chan->type != IIO_ANGL_VEL) + return -EINVAL; + + switch (chan->channel2) { + case IIO_MOD_X: + reg = INV_ICM42600_REG_GYRO_DATA_X; + break; + case IIO_MOD_Y: + reg = INV_ICM42600_REG_GYRO_DATA_Y; + break; + case IIO_MOD_Z: + reg = INV_ICM42600_REG_GYRO_DATA_Z; + break; + default: + return -EINVAL; + } + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + /* enable gyro sensor */ + conf.mode = INV_ICM42600_SENSOR_MODE_LOW_NOISE; + ret = inv_icm42600_set_gyro_conf(st, &conf, NULL); + if (ret) + goto exit; + + /* read gyro register data */ + ret = regmap_bulk_read(st->map, reg, &data, sizeof(data)); + if (ret) + goto exit; + + *val = (int16_t)be16_to_cpu(data); + if (*val == INV_ICM42600_DATA_INVALID) + ret = -EINVAL; +exit: + mutex_unlock(&st->lock); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + return ret; +} + +/* IIO format int + nano */ +static const int inv_icm42600_gyro_scale[] = { + /* +/- 2000dps => 0.001065264 rad/s */ + [2 * INV_ICM42600_GYRO_FS_2000DPS] = 0, + [2 * INV_ICM42600_GYRO_FS_2000DPS + 1] = 1065264, + /* +/- 1000dps => 0.000532632 rad/s */ + [2 * INV_ICM42600_GYRO_FS_1000DPS] = 0, + [2 * INV_ICM42600_GYRO_FS_1000DPS + 1] = 532632, + /* +/- 500dps => 0.000266316 rad/s */ + [2 * INV_ICM42600_GYRO_FS_500DPS] = 0, + [2 * INV_ICM42600_GYRO_FS_500DPS + 1] = 266316, + /* +/- 250dps => 0.000133158 rad/s */ + [2 * INV_ICM42600_GYRO_FS_250DPS] = 0, + [2 * INV_ICM42600_GYRO_FS_250DPS + 1] = 133158, + /* +/- 125dps => 0.000066579 rad/s */ + [2 * INV_ICM42600_GYRO_FS_125DPS] = 0, + [2 * INV_ICM42600_GYRO_FS_125DPS + 1] = 66579, + /* +/- 62.5dps => 0.000033290 rad/s */ + [2 * INV_ICM42600_GYRO_FS_62_5DPS] = 0, + [2 * INV_ICM42600_GYRO_FS_62_5DPS + 1] = 33290, + /* +/- 31.25dps => 0.000016645 rad/s */ + [2 * INV_ICM42600_GYRO_FS_31_25DPS] = 0, + [2 * INV_ICM42600_GYRO_FS_31_25DPS + 1] = 16645, + /* +/- 15.625dps => 0.000008322 rad/s */ + [2 * INV_ICM42600_GYRO_FS_15_625DPS] = 0, + [2 * INV_ICM42600_GYRO_FS_15_625DPS + 1] = 8322, +}; + +static int inv_icm42600_gyro_read_scale(struct inv_icm42600_state *st, + int *val, int *val2) +{ + unsigned int idx; + + mutex_lock(&st->lock); + idx = st->conf.gyro.fs; + mutex_unlock(&st->lock); + + *val = inv_icm42600_gyro_scale[2 * idx]; + *val2 = inv_icm42600_gyro_scale[2 * idx + 1]; + return IIO_VAL_INT_PLUS_NANO; +} + +static int inv_icm42600_gyro_write_scale(struct inv_icm42600_state *st, + int val, int val2) +{ + struct device *dev = regmap_get_device(st->map); + unsigned int idx; + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; + int ret; + + for (idx = 0; idx < ARRAY_SIZE(inv_icm42600_gyro_scale); idx += 2) { + if (val == inv_icm42600_gyro_scale[idx] && + val2 == inv_icm42600_gyro_scale[idx + 1]) + break; + } + if (idx >= ARRAY_SIZE(inv_icm42600_gyro_scale)) + return -EINVAL; + + /* update gyro fs */ + pm_runtime_get_sync(dev); + + mutex_lock(&st->lock); + conf.fs = idx / 2; + ret = inv_icm42600_set_gyro_conf(st, &conf, NULL); + mutex_unlock(&st->lock); + + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +/* IIO format int + micro */ +static const int inv_icm42600_gyro_odr[] = { + /* 12.5Hz */ + 12, 500000, + /* 25Hz */ + 25, 0, + /* 50Hz */ + 50, 0, + /* 100Hz */ + 100, 0, + /* 200Hz */ + 200, 0, + /* 1kHz */ + 1000, 0, + /* 2kHz */ + 2000, 0, + /* 4kHz */ + 4000, 0, +}; + +static const int inv_icm42600_gyro_odr_conv[] = { + INV_ICM42600_ODR_12_5HZ, + INV_ICM42600_ODR_25HZ, + INV_ICM42600_ODR_50HZ, + INV_ICM42600_ODR_100HZ, + INV_ICM42600_ODR_200HZ, + INV_ICM42600_ODR_1KHZ_LN, + INV_ICM42600_ODR_2KHZ_LN, + INV_ICM42600_ODR_4KHZ_LN, +}; + +static int inv_icm42600_gyro_read_odr(struct inv_icm42600_state *st, + int *val, int *val2) +{ + unsigned int odr; + unsigned int i; + + mutex_lock(&st->lock); + odr = st->conf.gyro.odr; + mutex_unlock(&st->lock); + + for (i = 0; i < ARRAY_SIZE(inv_icm42600_gyro_odr_conv); ++i) { + if (inv_icm42600_gyro_odr_conv[i] == odr) + break; + } + if (i >= ARRAY_SIZE(inv_icm42600_gyro_odr_conv)) + return -EINVAL; + + *val = inv_icm42600_gyro_odr[2 * i]; + *val2 = inv_icm42600_gyro_odr[2 * i + 1]; + + return IIO_VAL_INT_PLUS_MICRO; +} + +static int inv_icm42600_gyro_write_odr(struct inv_icm42600_state *st, + int val, int val2) +{ + struct device *dev = regmap_get_device(st->map); + unsigned int idx; + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; + int ret; + + for (idx = 0; idx < ARRAY_SIZE(inv_icm42600_gyro_odr); idx += 2) { + if (val == inv_icm42600_gyro_odr[idx] && + val2 == inv_icm42600_gyro_odr[idx + 1]) + break; + } + if (idx >= ARRAY_SIZE(inv_icm42600_gyro_odr)) + return -EINVAL; + + /* update gyro odr */ + pm_runtime_get_sync(dev); + + mutex_lock(&st->lock); + conf.odr = inv_icm42600_gyro_odr_conv[idx / 2]; + ret = inv_icm42600_set_gyro_conf(st, &conf, NULL); + mutex_unlock(&st->lock); + + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +static int inv_icm42600_gyro_read_offset(struct inv_icm42600_state *st, + struct iio_chan_spec const *chan, + int16_t *val) +{ + struct device *dev = regmap_get_device(st->map); + unsigned int reg; + uint8_t data[2]; + int ret; + + if (chan->type != IIO_ANGL_VEL) + return -EINVAL; + + switch (chan->channel2) { + case IIO_MOD_X: + reg = INV_ICM42600_REG_OFFSET_USER0; + break; + case IIO_MOD_Y: + reg = INV_ICM42600_REG_OFFSET_USER1; + break; + case IIO_MOD_Z: + reg = INV_ICM42600_REG_OFFSET_USER3; + break; + default: + return -EINVAL; + } + + pm_runtime_get_sync(dev); + + /* read gyro offset data */ + mutex_lock(&st->lock); + ret = regmap_bulk_read(st->map, reg, &data, sizeof(data)); + mutex_unlock(&st->lock); + if (ret) + goto exit; + + switch (chan->channel2) { + case IIO_MOD_X: + *val = (int16_t)(((data[1] & 0x0F) << 8) | data[0]); + break; + case IIO_MOD_Y: + *val = (int16_t)(((data[0] & 0xF0) << 4) | data[1]); + break; + case IIO_MOD_Z: + *val = (int16_t)(((data[1] & 0x0F) << 8) | data[0]); + break; + default: + ret = -EINVAL; + break; + } + +exit: + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + return ret; +} + +static int inv_icm42600_gyro_write_offset(struct inv_icm42600_state *st, + struct iio_chan_spec const *chan, + int val) +{ + struct device *dev = regmap_get_device(st->map); + unsigned int reg, regval; + uint8_t data[2]; + int ret; + + if (chan->type != IIO_ANGL_VEL) + return -EINVAL; + + switch (chan->channel2) { + case IIO_MOD_X: + reg = INV_ICM42600_REG_OFFSET_USER0; + break; + case IIO_MOD_Y: + reg = INV_ICM42600_REG_OFFSET_USER1; + break; + case IIO_MOD_Z: + reg = INV_ICM42600_REG_OFFSET_USER3; + break; + default: + return -EINVAL; + } + + /* value is limited to 12 bits signed */ + if (val < -2048 || val > 2047) + return -EINVAL; + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + switch (chan->channel2) { + case IIO_MOD_X: + /* OFFSET_USER1 register is shared */ + ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER1, + ®val); + if (ret) + goto out_unlock; + data[0] = val & 0xFF; + data[1] = (regval & 0xF0) | ((val & 0xF00) >> 8); + break; + case IIO_MOD_Y: + /* OFFSET_USER1 register is shared */ + ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER1, + ®val); + if (ret) + goto out_unlock; + data[0] = ((val & 0xF00) >> 4) | (regval & 0x0F); + data[1] = val & 0xFF; + break; + case IIO_MOD_Z: + /* OFFSET_USER4 register is shared */ + ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER4, + ®val); + if (ret) + goto out_unlock; + data[0] = val & 0xFF; + data[1] = (regval & 0xF0) | ((val & 0xF00) >> 8); + break; + default: + ret = -EINVAL; + goto out_unlock; + } + + ret = regmap_bulk_write(st->map, reg, data, sizeof(data)); + +out_unlock: + mutex_unlock(&st->lock); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + return ret; +} + +static int inv_icm42600_gyro_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int16_t data; + int ret; + + if (chan->type != IIO_ANGL_VEL) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = inv_icm42600_gyro_read_sensor(st, chan, &data); + iio_device_release_direct_mode(indio_dev); + if (ret) + return ret; + *val = data; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + return inv_icm42600_gyro_read_scale(st, val, val2); + case IIO_CHAN_INFO_SAMP_FREQ: + return inv_icm42600_gyro_read_odr(st, val, val2); + case IIO_CHAN_INFO_CALIBBIAS: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = inv_icm42600_gyro_read_offset(st, chan, &data); + iio_device_release_direct_mode(indio_dev); + if (ret) + return ret; + *val = data; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int inv_icm42600_gyro_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, + int *type, int *length, long mask) +{ + if (chan->type != IIO_ANGL_VEL) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + *vals = inv_icm42600_gyro_scale; + *type = IIO_VAL_INT_PLUS_NANO; + *length = ARRAY_SIZE(inv_icm42600_gyro_scale); + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_SAMP_FREQ: + *vals = inv_icm42600_gyro_odr; + *type = IIO_VAL_INT_PLUS_MICRO; + *length = ARRAY_SIZE(inv_icm42600_gyro_odr); + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + +static int inv_icm42600_gyro_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + if (chan->type != IIO_ANGL_VEL) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = inv_icm42600_gyro_write_scale(st, val, val2); + iio_device_release_direct_mode(indio_dev); + return ret; + case IIO_CHAN_INFO_SAMP_FREQ: + return inv_icm42600_gyro_write_odr(st, val, val2); + case IIO_CHAN_INFO_CALIBBIAS: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = inv_icm42600_gyro_write_offset(st, chan, val); + iio_device_release_direct_mode(indio_dev); + return ret; + default: + return -EINVAL; + } +} + +static int inv_icm42600_gyro_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long mask) +{ + if (chan->type != IIO_ANGL_VEL) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + return IIO_VAL_INT_PLUS_NANO; + case IIO_CHAN_INFO_SAMP_FREQ: + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_CALIBBIAS: + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static const struct iio_info inv_icm42600_gyro_info = { + .read_raw = inv_icm42600_gyro_read_raw, + .read_avail = inv_icm42600_gyro_read_avail, + .write_raw = inv_icm42600_gyro_write_raw, + .write_raw_get_fmt = inv_icm42600_gyro_write_raw_get_fmt, + .debugfs_reg_access = inv_icm42600_debugfs_reg, +}; + +int inv_icm42600_gyro_init(struct inv_icm42600_state *st) +{ + struct device *dev = regmap_get_device(st->map); + const char *name; + struct iio_dev *indio_dev; + + name = devm_kasprintf(dev, GFP_KERNEL, "%s-gyro", st->name); + if (!name) + return -ENOMEM; + + indio_dev = devm_iio_device_alloc(dev, 0); + if (!indio_dev) + return -ENOMEM; + + iio_device_set_drvdata(indio_dev, st); + indio_dev->dev.parent = dev; + indio_dev->name = name; + indio_dev->info = &inv_icm42600_gyro_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = inv_icm42600_gyro_channels; + indio_dev->num_channels = ARRAY_SIZE(inv_icm42600_gyro_channels); + + st->indio_gyro = indio_dev; + return devm_iio_device_register(dev, st->indio_gyro); +} From patchwork Thu May 7 14:42:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jean-Baptiste Maneyrol X-Patchwork-Id: 200945 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, MSGID_FROM_MTA_HEADER, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 08642C54E4A for ; Thu, 7 May 2020 14:43:29 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DDF9020B1F for ; Thu, 7 May 2020 14:43:28 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="FHX889XK"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="KTLmrV/w" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727770AbgEGOn0 (ORCPT ); Thu, 7 May 2020 10:43:26 -0400 Received: from mx0b-00328301.pphosted.com ([148.163.141.47]:36142 "EHLO mx0b-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727032AbgEGOnY (ORCPT ); Thu, 7 May 2020 10:43:24 -0400 Received: from pps.filterd (m0156136.ppops.net [127.0.0.1]) by mx0b-00328301.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 047Eb4lb005942; Thu, 7 May 2020 07:43:19 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=invensense.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : content-type : content-transfer-encoding : mime-version; s=pfpt1; bh=vx8zKfnK39Y2G7jVI/7YNtma6l/Y6g3qWBZ7ad+TqMs=; b=FHX889XKGAn4W99unMe1koCC7N9kJ9nueeUCgxEZpe7o5xUscOixzLPxu4EylLpDiiDn YGprj4979MzabqLbIjcGqMljFLY+D1UrZkQsllwOg/Tkppr6yX8vm6cyegggwMSv1uaT eJ0gZc+7s++dKyKRFkkL2H045mQ7DZv7Oaq+yG4VBvO8RSGqJJJYY6tdzizgciRojC3P ZH5PEIgvGFcpgsWWixE+nE82xC7/cA5VX+SCBkxGAQlsAlRexZ2OZfFQUXVHTNWoUIN7 i+P1mAkAaP/grkwGHSC8/xUNq1EA2KjnQoghe8uEJetHhiaQPsaErN9OzHtwk469A6ZK aQ== Received: from nam12-bn8-obe.outbound.protection.outlook.com (mail-bn8nam12lp2173.outbound.protection.outlook.com [104.47.55.173]) by mx0b-00328301.pphosted.com with ESMTP id 30s4tnatwr-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 07 May 2020 07:43:19 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=TpyROuIoTrJbQLwAGkbY8p0KNFkLA1hGsnyMWYr135Z56YeNOWbHQnSmzPyAV217HwTweFGRrIiqTid8jDogWJUV2DjQXuRCDVmakBtzBOw1kgndDVDY21B3HbXqly5iGaAjz0fbXEkycIQMkpYrCVZiup9ndi+HwczP/49RN++eAjAAAPuJpaAIne1WaJYBTG6CQfec6+R5S+tB9AHuOil1hSw3/Lk36JSRTXF18tUlyHL9tejn4S1x4FthyW+JinF9RqsfJg2wN1pyRVxD9OdqGDI2wG8T6loChmkyQu7aye2jlsh1CKlhoOAXE5GmvOEDt9/D1nbPccadNZ3p5A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=vx8zKfnK39Y2G7jVI/7YNtma6l/Y6g3qWBZ7ad+TqMs=; b=hP2wsvLd31OthoCdJAg/3cTPc4JKbndwMkpCKIuVJt3xAeR2B6Ia+fDlsUY28P5o2vVxN85SXs1FHQz7RMDBpJcfC94cUrEXWSo3M+5UWw8iT8aPWT/BSMVvVnsVJUziSZTmef7E/ECWr6rp7l/v02ZvbazQmsDTfM9hSanFDJbn2y8ufWNTrPCT0lMdG4amleBmfvqFehK7FymaFml2SAUFHSpGuk3u6ut8zMQn9rK2e7BL03/lSDMUoPLLOnB/EthnymUHzoeexuyixxKNGRZsnethHd8Sw6JaDDMvjJVCxcvpSo0u1hgyIAGe1MDjSG+GjNey2ybg2r6M6tpzkw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=invensense.com; dmarc=pass action=none header.from=invensense.com; dkim=pass header.d=invensense.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=invensense.onmicrosoft.com; s=selector2-invensense-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=vx8zKfnK39Y2G7jVI/7YNtma6l/Y6g3qWBZ7ad+TqMs=; b=KTLmrV/wFQxiGXKoSTQViPw1evhYBVOFyDonX7NF6YkCOO6IOjNVccA0BrOCSTPuo5e4ydj83FNQc/2Q1RUxZiGlnLSha7YSZ64m2u2u1LkuqfV3M7HD9rWpvQ6O1+hjaZGUL3hUHnNgFJBhehuDMVqPstGBzAb80O21As6QLfw= Authentication-Results: kernel.org; dkim=none (message not signed) header.d=none; kernel.org; dmarc=none action=none header.from=invensense.com; Received: from MN2PR12MB4422.namprd12.prod.outlook.com (2603:10b6:208:265::9) by MN2PR12MB4269.namprd12.prod.outlook.com (2603:10b6:208:1d4::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2979.28; Thu, 7 May 2020 14:43:18 +0000 Received: from MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::7471:da8b:8ca1:6af0]) by MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::7471:da8b:8ca1:6af0%4]) with mapi id 15.20.2979.028; Thu, 7 May 2020 14:43:18 +0000 From: Jean-Baptiste Maneyrol To: jic23@kernel.org, robh+dt@kernel.org, robh@kernel.org, mchehab+huawei@kernel.org, davem@davemloft.net, gregkh@linuxfoundation.org Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Jean-Baptiste Maneyrol Subject: [PATCH 06/12] iio: imu: inv_icm42600: add temperature sensor support Date: Thu, 7 May 2020 16:42:16 +0200 Message-Id: <20200507144222.20989-7-jmaneyrol@invensense.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200507144222.20989-1-jmaneyrol@invensense.com> References: <20200507144222.20989-1-jmaneyrol@invensense.com> X-ClientProxiedBy: LNXP265CA0048.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:5c::36) To MN2PR12MB4422.namprd12.prod.outlook.com (2603:10b6:208:265::9) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from frgnb-buildozer.invcorp.invensense.com (77.157.193.39) by LNXP265CA0048.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:5c::36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2979.26 via Frontend Transport; Thu, 7 May 2020 14:43:16 +0000 X-Mailer: git-send-email 2.17.1 X-Originating-IP: [77.157.193.39] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: f879c516-b3b5-46a8-65e1-08d7f294fb35 X-MS-TrafficTypeDiagnostic: MN2PR12MB4269: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:8882; X-Forefront-PRVS: 03965EFC76 X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: c6giz5YXjBMB64YoaTGFcu668cm/l/HOzDVGXnEct+u7NR4Ip9vhkJF10W4C9p2ImCjo7NoaPAQub3ipOwQXkz67wDUtI7ZuY+YoBASiT4wPq3X2QOM5hlC/5UK7sTJ7uem7ewdINAKQsTmgczf4HCj50OkCLQdr1c7Sv3VASQPmhKkUPcJZLLNf0x0Ex4nH9Y7PvdEP4uf/+OeAlkLTBK92Q+TM+JW/Zyj72+d3ngcougJU9+YggYJWGUTfxJNf+5x+AZqB1sXIcGX3nze+ccoIdInzSkFLqNB7HLKuZX1zRDHqEtAVLgSVCnZUTyGC23TQ/NB8r8DcRrdiZnPS1DifAZCv9eabegiY2KXzfkBDqtyzFyXv1b3hIWjsZvU3GmyhVZGJgWZCTDp1C0BiSEwwY7On5SYXqCwBsF1jKuzwMUnu0LVGycMZA65Crto9ssmUCVJLA7NlhhWic58WybWJP5HHI8n/H+H9coB5hdFyYDAiKOGDVsi/jrLO/GoJNjogdeO1wq7G9+XW5gj+1g== X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:MN2PR12MB4422.namprd12.prod.outlook.com; PTR:; CAT:NONE; SFTY:; SFS:(346002)(396003)(136003)(366004)(39850400004)(376002)(33430700001)(186003)(6486002)(478600001)(16526019)(5660300002)(4326008)(33440700001)(66556008)(8676002)(1076003)(36756003)(316002)(66946007)(66476007)(52116002)(8936002)(86362001)(2616005)(83280400001)(956004)(83320400001)(83290400001)(83310400001)(26005)(2906002)(7696005)(83300400001)(107886003); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData: +RNptZ1QAUG6MsNLzuspjbmysinzHmqbFANYgxak4KDPCSwRVsKuLM1L1eBihByY4Hr7p1DxVDBrfy4aCHqeNrlxHmWVC4DnmDa0YO5uJbYpp2J8WOF21TifOpJjZLRTj0hhRwA3Wrdky6d+OVpvn2QEZZrbjgJ6xHATA99/MOMajgi2ajKNcNIRiJvWKOAcT2JjnQqHcJwdteV3CWTzgvMsgf72xekmEtqkWYnWYp2JDJPFm46ZXbZ2aY9yW0fYRKgaj9lU+AZQIBTgpOVetAOwQt+DvVGkznZEWW3UeYnp58VrA50v2H+eK/SOzqNxyPLUvYMmQZf5u4qz0uOEchWk/lw2n9vfZ56NkusgFslXIlFZR0BZUnxhRVge0yMV0QM1QGBCbdEWSZr2/ecveGuaisXob3C3i8ZuF2dyQVcFLbsyRWsIEOzy4GNSpM/k35PF+0KaVLQjAQPhif7dr8O4Jmt938t23Qconxt6SDZHCkPl8kcByA4jA71SUD0JCbRIE+VtQDiImyTliNmr8ybwIb0OBcMsy/ecMZd2OKNZzpz4huInWm2WcL/7Naxtjp7fAZQof+YA8slgx8G8V0OhpvTKytp89EFP43oFFZU6FXdB5+sSVibumdH9DJ+wqQ9gQYomrQGYwmDrp6ux1NPc3jXYtZwor6uVN0WQqeF5unoIBi/+l2dqy9nmiG9WLfnUsCtsiqgqZGZ30axqWSztM8ScqY9gecCUsIMl7bVlJ6MziRPPXILahohh2qEToGbiTRhebXluwFgtu6Lq2aTcM9XXQouVb3RS5jej3MY= X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: f879c516-b3b5-46a8-65e1-08d7f294fb35 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 May 2020 14:43:18.2146 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 462b3b3b-e42b-47ea-801a-f1581aac892d X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: FQg9oGEU9Vt2358yxZdsQac2eDHFSbZWCv8Y0b/KgFpv2BjAUJErHaccZtZLy3BdJoOOuZPzY7dgi/P+6QeImEC2HBfCnsjo7a+31p7452E= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4269 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216, 18.0.676 definitions=2020-05-07_09:2020-05-07,2020-05-07 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 adultscore=0 priorityscore=1501 spamscore=0 mlxlogscore=999 impostorscore=0 suspectscore=0 phishscore=0 malwarescore=0 lowpriorityscore=0 bulkscore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2005070118 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add temperature channel in gyroscope and accelerometer devices. Temperature is available in full 16 bits resolution as a processed channel. Scale and offset attributes are also provided for the low 8 bits resolution raw temperature found in the FIFO. Signed-off-by: Jean-Baptiste Maneyrol --- .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 12 ++- .../iio/imu/inv_icm42600/inv_icm42600_gyro.c | 12 ++- .../iio/imu/inv_icm42600/inv_icm42600_temp.c | 86 +++++++++++++++++++ .../iio/imu/inv_icm42600/inv_icm42600_temp.h | 32 +++++++ 4 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c index 397e3d0fd42b..74dac5f283d4 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c @@ -12,6 +12,7 @@ #include #include "inv_icm42600.h" +#include "inv_icm42600_temp.h" #define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info) \ { \ @@ -44,6 +45,7 @@ enum inv_icm42600_accel_scan { INV_ICM42600_ACCEL_SCAN_X, INV_ICM42600_ACCEL_SCAN_Y, INV_ICM42600_ACCEL_SCAN_Z, + INV_ICM42600_ACCEL_SCAN_TEMP, }; static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = { @@ -58,6 +60,7 @@ static const struct iio_chan_spec inv_icm42600_accel_channels[] = { inv_icm42600_accel_ext_infos), INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z, inv_icm42600_accel_ext_infos), + INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP), }; static int inv_icm42600_accel_read_sensor(struct inv_icm42600_state *st, @@ -394,8 +397,15 @@ static int inv_icm42600_accel_read_raw(struct iio_dev *indio_dev, int16_t data; int ret; - if (chan->type != IIO_ACCEL) + switch (chan->type) { + case IIO_ACCEL: + break; + case IIO_TEMP: + return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2, + mask); + default: return -EINVAL; + } switch (mask) { case IIO_CHAN_INFO_RAW: diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c index 74aa2b5fa611..c0164ab2830e 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c @@ -12,6 +12,7 @@ #include #include "inv_icm42600.h" +#include "inv_icm42600_temp.h" #define INV_ICM42600_GYRO_CHAN(_modifier, _index, _ext_info) \ { \ @@ -44,6 +45,7 @@ enum inv_icm42600_gyro_scan { INV_ICM42600_GYRO_SCAN_X, INV_ICM42600_GYRO_SCAN_Y, INV_ICM42600_GYRO_SCAN_Z, + INV_ICM42600_GYRO_SCAN_TEMP, }; static const struct iio_chan_spec_ext_info inv_icm42600_gyro_ext_infos[] = { @@ -58,6 +60,7 @@ static const struct iio_chan_spec inv_icm42600_gyro_channels[] = { inv_icm42600_gyro_ext_infos), INV_ICM42600_GYRO_CHAN(IIO_MOD_Z, INV_ICM42600_GYRO_SCAN_Z, inv_icm42600_gyro_ext_infos), + INV_ICM42600_TEMP_CHAN(INV_ICM42600_GYRO_SCAN_TEMP), }; static int inv_icm42600_gyro_read_sensor(struct inv_icm42600_state *st, @@ -406,8 +409,15 @@ static int inv_icm42600_gyro_read_raw(struct iio_dev *indio_dev, int16_t data; int ret; - if (chan->type != IIO_ANGL_VEL) + switch (chan->type) { + case IIO_ANGL_VEL: + break; + case IIO_TEMP: + return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2, + mask); + default: return -EINVAL; + } switch (mask) { case IIO_CHAN_INFO_RAW: diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c new file mode 100644 index 000000000000..e5407b17c407 --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#include +#include +#include +#include +#include +#include + +#include "inv_icm42600.h" +#include "inv_icm42600_temp.h" + +static int inv_icm42600_temp_read(struct inv_icm42600_state *st, int32_t *temp) +{ + struct device *dev = regmap_get_device(st->map); + __be16 raw; + int16_t val; + int64_t data; + int ret; + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + ret = inv_icm42600_set_temp_conf(st, true, NULL); + if (ret) + goto exit; + + ret = regmap_bulk_read(st->map, INV_ICM42600_REG_TEMP_DATA, + &raw, sizeof(raw)); + if (ret) + goto exit; + + val = (int16_t)be16_to_cpu(raw); + if (val == INV_ICM42600_DATA_INVALID) { + ret = -EINVAL; + goto exit; + } + /* + * T°C = (val / 132.48) + 25 = ((val * 100) / 13248) + 25 + * Tm°C = (val * 100 * 1000) / 13248 + 25000 + */ + data = (int64_t)(val) * 100LL * 1000LL; + *temp = div_s64(data, 13248) + 25000; +exit: + mutex_unlock(&st->lock); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + return ret; +} + +int inv_icm42600_temp_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int32_t temp; + int ret; + + if (chan->type != IIO_TEMP) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_PROCESSED: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = inv_icm42600_temp_read(st, &temp); + iio_device_release_direct_mode(indio_dev); + if (ret) + return ret; + *val = temp; + return IIO_VAL_INT; + case IIO_CHAN_INFO_SCALE: + *val = 483; + *val2 = 91787; + return IIO_VAL_INT_PLUS_MICRO; + case IIO_CHAN_INFO_OFFSET: + *val = 25000; + return IIO_VAL_INT; + default: + return -EINVAL; + } +} diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h new file mode 100644 index 000000000000..7c0854d38e1e --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#ifndef INV_ICM42600_TEMP_H_ +#define INV_ICM42600_TEMP_H_ + +#include +#include + +#define INV_ICM42600_TEMP_CHAN(_index) \ + { \ + .type = IIO_TEMP, \ + .info_mask_separate = \ + BIT(IIO_CHAN_INFO_PROCESSED) | \ + BIT(IIO_CHAN_INFO_OFFSET) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 8, \ + .storagebits = 8, \ + .shift = 0, \ + }, \ + } + +int inv_icm42600_temp_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask); + +#endif From patchwork Thu May 7 14:42:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Baptiste Maneyrol X-Patchwork-Id: 200942 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, MSGID_FROM_MTA_HEADER, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 265F7C54E49 for ; Thu, 7 May 2020 14:44:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 04A2D208DB for ; Thu, 7 May 2020 14:44:03 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="L8BCBt/H"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="LOqqPwc8" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727787AbgEGOnx (ORCPT ); Thu, 7 May 2020 10:43:53 -0400 Received: from mx0b-00328301.pphosted.com ([148.163.141.47]:42036 "EHLO mx0b-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727772AbgEGOn2 (ORCPT ); Thu, 7 May 2020 10:43:28 -0400 Received: from pps.filterd (m0156136.ppops.net [127.0.0.1]) by mx0b-00328301.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 047EeBqA009573; Thu, 7 May 2020 07:43:24 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=invensense.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : content-type : mime-version; s=pfpt1; bh=ih1YAq1tAzzkOsqsEijrLmTMFDUFg046Zw65ZJPQDcA=; b=L8BCBt/HD5Yi1d2OQEWJVhDSXJvSbYAFpXcDzL2J/PUcuLsEgCXujBRdgAZ43UOd6sDS nwrM1CxLHjfZ0FzSovZqpjwduloZdk/x8Ohep4l+X5Xn3O5J8CG0Ip45qjnDmZlHrP8B FI2sv2pGsEiaQqL9N9WRpkGtYCep5iUVUj6xzIcV8+EvhaJLBH/w29YgeJsRfuEvvWGC KBHFXnU+NBHJ0y8TqNIVZ1FnaBztLTD/6c9oapLXGKos0e1xrLSkjlumKmWQ1gpSROMR h3TWQ2xILJc8ZEcQ6T9gm+C+LaT6FaPbZsr+epwui9ntQEu+cexwyv4jL5bUqIdJIy/X NA== Received: from nam11-dm6-obe.outbound.protection.outlook.com (mail-dm6nam11lp2172.outbound.protection.outlook.com [104.47.57.172]) by mx0b-00328301.pphosted.com with ESMTP id 30s4tnatwt-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 07 May 2020 07:43:24 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=TFg60S44u7LiMyLEFD33o1GrLIgfoWh3s9WuhOv/YFKWAVK/F/77J2a08+yrgP3wQFqu4kQlvW1s+hW0felAboLu071zWaZ5kcsR5mK95pGh/6vHuOwp8mBRDvkVCOoo4xPbUg9ytjvJ2jJQX8VdFSSZte6YobNMJNJYiB3egcuQELpAd8VV/UCbnq7BUDVdOZ5D+Dhc59boIL6iK5WlqkThR+/x4+Yt79l8kDzrwxOtICkyuTL4iQKm1cjSdOBPp3D0adjDIZU0KZR6gcZy8ywIgC3xEK3DuY1+2ANPCQCEDvQ3KsU9tAOtRb6cgtgspVhSlvX5gugV3vA/0B1Iyg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=ih1YAq1tAzzkOsqsEijrLmTMFDUFg046Zw65ZJPQDcA=; b=XPPHI7mTboz6FwTY7rhkE17iclkakNa7sLARLaJRTiuhIDHn6xSBiUruCi9MxvUHSawEOpGRxSz2I6U3eWkEwK48cnF3Dcbfhw9SSqzEDHGmIrrV8DPefNtSPx8AjDqL4+sVSUGjvxCnGuZTMMoKqd1eWdNufxR68d/dYJL6cHBixfBFPwKjeA1ulSpw445Xv9yKNdgt/glXhDWoh5QvcyFW3UPpKPYYhzme3WGIsmyOvLcJfn1fXsvrF5/OQhI6NeKBOfKubQ2dvA2XoGbKVEbszxzxGSgvH2HOQNrFRyfI9TpYF/vPaQ2wWR2Cu7s/T4wTiwncsvRrudzVqbfOeg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=invensense.com; dmarc=pass action=none header.from=invensense.com; dkim=pass header.d=invensense.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=invensense.onmicrosoft.com; s=selector2-invensense-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=ih1YAq1tAzzkOsqsEijrLmTMFDUFg046Zw65ZJPQDcA=; b=LOqqPwc8yPOwmt/v1ogCKh6TgfYot3MZ26UO/eXw0AV7trKKomP/Fqpgy8noo+zS+11kaD2a9lz0soys3kgURiFcWrSLEtBFAbvWxSGzlUSrhXQDi4PeNJqbUpPFmHYlohH5hqLKAaKnfPDU/GF4F28hi3vypDx2thSxLCBGRs4= Authentication-Results: kernel.org; dkim=none (message not signed) header.d=none; kernel.org; dmarc=none action=none header.from=invensense.com; Received: from MN2PR12MB4422.namprd12.prod.outlook.com (2603:10b6:208:265::9) by MN2PR12MB4501.namprd12.prod.outlook.com (2603:10b6:208:269::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2979.27; Thu, 7 May 2020 14:43:21 +0000 Received: from MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::7471:da8b:8ca1:6af0]) by MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::7471:da8b:8ca1:6af0%4]) with mapi id 15.20.2979.028; Thu, 7 May 2020 14:43:21 +0000 From: Jean-Baptiste Maneyrol To: jic23@kernel.org, robh+dt@kernel.org, robh@kernel.org, mchehab+huawei@kernel.org, davem@davemloft.net, gregkh@linuxfoundation.org Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Jean-Baptiste Maneyrol Subject: [PATCH 08/12] iio: imu: inv_icm42600: add device interrupt trigger Date: Thu, 7 May 2020 16:42:18 +0200 Message-Id: <20200507144222.20989-9-jmaneyrol@invensense.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200507144222.20989-1-jmaneyrol@invensense.com> References: <20200507144222.20989-1-jmaneyrol@invensense.com> X-ClientProxiedBy: LNXP265CA0048.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:5c::36) To MN2PR12MB4422.namprd12.prod.outlook.com (2603:10b6:208:265::9) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from frgnb-buildozer.invcorp.invensense.com (77.157.193.39) by LNXP265CA0048.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:5c::36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2979.26 via Frontend Transport; Thu, 7 May 2020 14:43:20 +0000 X-Mailer: git-send-email 2.17.1 X-Originating-IP: [77.157.193.39] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: f005aa3b-a0ca-4e9d-46c4-08d7f294fd49 X-MS-TrafficTypeDiagnostic: MN2PR12MB4501: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:1002; X-Forefront-PRVS: 03965EFC76 X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: HyIiqtPdqg5VLOw2UAm9MoEkgH7uH9FfNpvxzKW62wnuwCR77XgeIi9/+zMN4Y/05QHKQlGCrrAJfo3ehwGJtfTvvlM1Ashx46rNUKwfZ+WdLT3o4kPkzyLTSVegGi89gK9l3wFQyXOTzgtl3i2LJo1FSE/JhBUuhT9LRB0PdJSejLYjgAMNioT6R1fwj0Z4wtizhHnepSPFkRfjpsMJL59XxUnSWyAjq3EtbtWHcLXqXlLPWBogN/b3Frv3+vxIwpqHKJKtLeWxjpqDOYCVGdqY9tyv2j/RrEu/Jv31LqiTEADMd3Ep1fCHkSDDmFW9zfoDZ03AN52ByAbzoKG5mN5hzTmXcHxPXjtFlg8HA7e+4ZRNBVX4c7N+srV6506IVeWrQydG4MNaRgsktbRZmh52kTW4WLmATIg2bgOC0czPOJZAdJukrQHtcPcdc8P6uFsJFOuAujjjjew5YqysLA84DH3JVhfGXcTBidYBlCiMPDSXeoDYaGepQCN3TiW7eSvTWCRi7+qq1dx8HDt2gg== X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:MN2PR12MB4422.namprd12.prod.outlook.com; PTR:; CAT:NONE; SFTY:; SFS:(346002)(376002)(136003)(396003)(39850400004)(366004)(33430700001)(30864003)(107886003)(4326008)(8676002)(6486002)(2906002)(316002)(5660300002)(8936002)(1076003)(26005)(7696005)(33440700001)(66946007)(956004)(66476007)(52116002)(2616005)(86362001)(186003)(83320400001)(83280400001)(83310400001)(83290400001)(16526019)(478600001)(36756003)(66556008)(83300400001); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData: pQ2MFB/iJMRP0dyD9fA9JvFXk6r/oO2gC+c7pIMypu6yrWRzvCQY4x3daL5znfrEiS6J284i9DzJmf96dFZ3Txj/VFc1+3XCJp1adLs2eI4sTvSewXqNfpyNssEFxfhyAjw44L61gsyyjdKjhr0fYMi//rhGFKywcEsuGQfaxprys+gb+9sFP94pRpgiOjFmG/b0Ry2lj06i5F2GvWqPg5PsIn8vLHMF8RNcbPPcbCm9FjCjCvgV8nxOmWfhDgfsTugnHRhLYYrlo4DG2RVXYxAPWmRqX6VGRcEq+AqjyxhZ244YBY+XVO7aiLmJynEscNr3xhQ9W+ND8O0nAR+k0fQsZD5ad/FQI25XjeJGgXMYcbAQXBJNitgETBjhqUSaBx9I7omVTl4EfeAdJYVGNjGMQ+MbUAEIm7eLXBvVMECMfwRck8GbpLYGVq8iIbq8U0R//K9mDCvU6Ef120V5o5DPBaS/97D8OHubf10Ykp7mcdyL+ciMbtlWrifdZtTA/SlWHLsan+tCen514vZlJPxlLkCDQAh77jM7U1dP3enS6mzdym++RJBoh1jAvfA7vmjgaWmi/bXHgEHaAV8tD+OjNNaJ5LuEPDIWfslZsR7+yaL+Z7vf73FX477lT5euYCOWKnqrOMZ6GZwRqju+w4jUT28dTQ/G9MH2c3oUrbbGcipuO8fJRaGbGWqAToztyuxYQPrRbw6PemT1zGiMtsu3MuotzaQKabrvftHeBE+ibZgA2mygYjvJVrGrHSYRCqhen0hIbMqhJ3RKgnLMUtf3T5Kr3oZ7xyHfo4WhtSU= X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: f005aa3b-a0ca-4e9d-46c4-08d7f294fd49 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 May 2020 14:43:21.8945 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 462b3b3b-e42b-47ea-801a-f1581aac892d X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: ta1NYNfFrDoQAUUrOVOhssculqqBJctyfefdTkmXZcmcWoMQjY1Q/qQlSB9LDOGeVjqjEixYQvkp7fyYZsWG2/+YebKSUEwE92VANtp2W5o= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4501 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216, 18.0.676 definitions=2020-05-07_09:2020-05-07,2020-05-07 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 adultscore=0 priorityscore=1501 spamscore=0 mlxlogscore=999 impostorscore=0 suspectscore=0 phishscore=0 malwarescore=0 lowpriorityscore=0 bulkscore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2005070118 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add INT1 interrupt support and use it as an iio trigger. Support interrupt edge and level, active high or low. Push-pull configuration only. Trigger enables FIFO and will be useful with buffer support. Signed-off-by: Jean-Baptiste Maneyrol --- drivers/iio/imu/inv_icm42600/Kconfig | 1 + drivers/iio/imu/inv_icm42600/Makefile | 1 + drivers/iio/imu/inv_icm42600/inv_icm42600.h | 8 +- .../iio/imu/inv_icm42600/inv_icm42600_core.c | 19 +- .../iio/imu/inv_icm42600/inv_icm42600_i2c.c | 2 +- .../iio/imu/inv_icm42600/inv_icm42600_spi.c | 2 +- .../imu/inv_icm42600/inv_icm42600_trigger.c | 177 ++++++++++++++++++ 7 files changed, 206 insertions(+), 4 deletions(-) create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_trigger.c diff --git a/drivers/iio/imu/inv_icm42600/Kconfig b/drivers/iio/imu/inv_icm42600/Kconfig index 22390a72f0a3..7b3eaeb2aa4a 100644 --- a/drivers/iio/imu/inv_icm42600/Kconfig +++ b/drivers/iio/imu/inv_icm42600/Kconfig @@ -2,6 +2,7 @@ config INV_ICM42600 tristate + select IIO_TRIGGER config INV_ICM42600_I2C tristate "InvenSense ICM-426xx I2C driver" diff --git a/drivers/iio/imu/inv_icm42600/Makefile b/drivers/iio/imu/inv_icm42600/Makefile index 48965824f00c..e1f2aacbe888 100644 --- a/drivers/iio/imu/inv_icm42600/Makefile +++ b/drivers/iio/imu/inv_icm42600/Makefile @@ -5,6 +5,7 @@ inv-icm42600-y += inv_icm42600_core.o inv-icm42600-y += inv_icm42600_gyro.o inv-icm42600-y += inv_icm42600_accel.o inv-icm42600-y += inv_icm42600_temp.o +inv-icm42600-y += inv_icm42600_trigger.o obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o inv-icm42600-i2c-y += inv_icm42600_i2c.o diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h b/drivers/iio/imu/inv_icm42600/inv_icm42600.h index bc963b3d1800..175c1f67faee 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h @@ -13,6 +13,7 @@ #include #include #include +#include enum inv_icm42600_chip { INV_CHIP_ICM42600, @@ -122,6 +123,7 @@ struct inv_icm42600_suspended { * @suspended: suspended sensors configuration. * @indio_gyro: gyroscope IIO device. * @indio_accel: accelerometer IIO device. + * @trigger: device internal interrupt trigger */ struct inv_icm42600_state { struct mutex lock; @@ -135,6 +137,7 @@ struct inv_icm42600_state { struct inv_icm42600_suspended suspended; struct iio_dev *indio_gyro; struct iio_dev *indio_accel; + struct iio_trigger *trigger; }; /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */ @@ -370,11 +373,14 @@ int inv_icm42600_set_temp_conf(struct inv_icm42600_state *st, bool enable, int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg, unsigned int writeval, unsigned int *readval); -int inv_icm42600_core_probe(struct regmap *regmap, int chip, +int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, inv_icm42600_bus_setup bus_setup); int inv_icm42600_gyro_init(struct inv_icm42600_state *st); int inv_icm42600_accel_init(struct inv_icm42600_state *st); +int inv_icm42600_trigger_init(struct inv_icm42600_state *st, int irq, + int irq_type); + #endif diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c index 4e33f263d3ea..1102c54396e3 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c @@ -447,11 +447,13 @@ static void inv_icm42600_disable_pm(void *_data) pm_runtime_disable(dev); } -int inv_icm42600_core_probe(struct regmap *regmap, int chip, +int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, inv_icm42600_bus_setup bus_setup) { struct device *dev = regmap_get_device(regmap); struct inv_icm42600_state *st; + struct irq_data *irq_desc; + int irq_type; int ret; BUILD_BUG_ON(ARRAY_SIZE(inv_icm42600_hw) != INV_CHIP_NB); @@ -460,6 +462,16 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, return -ENODEV; } + /* get irq data, set trigger falling by default */ + irq_desc = irq_get_irq_data(irq); + if (!irq_desc) { + dev_err(dev, "could not find IRQ %d\n", irq); + return -EINVAL; + } + irq_type = irqd_get_trigger_type(irq_desc); + if (!irq_type) + irq_type = IRQF_TRIGGER_FALLING; + st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL); if (!st) return -ENOMEM; @@ -503,6 +515,11 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, if (ret) return ret; + /* setup interrupt trigger */ + ret = inv_icm42600_trigger_init(st, irq, irq_type); + if (ret) + return ret; + /* create and init gyroscope iio device */ ret = inv_icm42600_gyro_init(st); if (ret) diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c index b61f993beacf..b1478ece43f6 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c @@ -70,7 +70,7 @@ static int inv_icm42600_probe(struct i2c_client *client, if (IS_ERR(regmap)) return PTR_ERR(regmap); - return inv_icm42600_core_probe(regmap, chip, + return inv_icm42600_core_probe(regmap, chip, client->irq, inv_icm42600_i2c_bus_setup); } diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c index 835ced68a3a3..ec784f9e3c2c 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c @@ -70,7 +70,7 @@ static int inv_icm42600_probe(struct spi_device *spi) if (IS_ERR(regmap)) return PTR_ERR(regmap); - return inv_icm42600_core_probe(regmap, chip, + return inv_icm42600_core_probe(regmap, chip, spi->irq, inv_icm42600_spi_bus_setup); } diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_trigger.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_trigger.c new file mode 100644 index 000000000000..7a5e76305f0b --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_trigger.c @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "inv_icm42600.h" + +static irqreturn_t inv_icm42600_trigger_timestamp(int irq, void *_data) +{ + struct inv_icm42600_state *st = _data; + + if (st->indio_gyro) + iio_pollfunc_store_time(irq, st->indio_gyro->pollfunc); + if (st->indio_accel) + iio_pollfunc_store_time(irq, st->indio_accel->pollfunc); + + return IRQ_WAKE_THREAD; +} + +static irqreturn_t inv_icm42600_trigger_int_handler(int irq, void *_data) +{ + struct inv_icm42600_state *st = _data; + struct device *dev = regmap_get_device(st->map); + unsigned int status; + int ret; + + mutex_lock(&st->lock); + + ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, &status); + if (ret) + goto out_unlock; + dev_dbg(dev, "int_status = %#02x\n", status); + + /* FIFO full */ + if (status & INV_ICM42600_INT_STATUS_FIFO_FULL) + dev_warn(dev, "FIFO full data lost!\n"); + + /* FIFO threshold reached */ + if (status & INV_ICM42600_INT_STATUS_FIFO_THS) + iio_trigger_poll_chained(st->trigger); + +out_unlock: + mutex_unlock(&st->lock); + return IRQ_HANDLED; +} + +static int inv_icm42600_trigger_set_state(struct iio_trigger *trig, bool state) +{ + struct inv_icm42600_state *st = iio_trigger_get_drvdata(trig); + unsigned int val; + uint16_t dummy; + int ret; + + mutex_lock(&st->lock); + + /* + * IIO buffers preenable and postdisable are managing power on/off. + * update_scan_mode is setting data FIFO enabled. + */ + if (state) { + /* set FIFO threshold interrupt */ + val = INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN; + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0, + val, val); + if (ret) + goto out_unlock; + /* flush FIFO data */ + ret = regmap_write(st->map, INV_ICM42600_REG_SIGNAL_PATH_RESET, + INV_ICM42600_SIGNAL_PATH_RESET_FIFO_FLUSH); + if (ret) + goto out_unlock; + /* set FIFO in streaming mode */ + ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG, + INV_ICM42600_FIFO_CONFIG_STREAM); + if (ret) + goto out_unlock; + /* workaround: dummy read of FIFO count */ + ret = regmap_bulk_read(st->map, INV_ICM42600_REG_FIFO_COUNT, + &dummy, sizeof(dummy)); + } else { + /* set FIFO in bypass mode */ + ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG, + INV_ICM42600_FIFO_CONFIG_BYPASS); + if (ret) + goto out_unlock; + /* flush FIFO data */ + ret = regmap_write(st->map, INV_ICM42600_REG_SIGNAL_PATH_RESET, + INV_ICM42600_SIGNAL_PATH_RESET_FIFO_FLUSH); + if (ret) + goto out_unlock; + /* disable FIFO threshold interrupt */ + val = INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN; + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0, + val, 0); + } + +out_unlock: + mutex_unlock(&st->lock); + return ret; +} + +static int inv_icm42600_trigger_validate(struct iio_trigger *trig, + struct iio_dev *indio_dev) +{ + struct inv_icm42600_state *st = iio_trigger_get_drvdata(trig); + + if (iio_device_get_drvdata(indio_dev) != st) + return -ENODEV; + + return 0; +} + +static const struct iio_trigger_ops inv_icm42600_trigger_ops = { + .set_trigger_state = &inv_icm42600_trigger_set_state, + .validate_device = &inv_icm42600_trigger_validate, +}; + +int inv_icm42600_trigger_init(struct inv_icm42600_state *st, int irq, + int irq_type) +{ + struct device *dev = regmap_get_device(st->map); + unsigned int val; + int ret; + + st->trigger = devm_iio_trigger_alloc(dev, "%s-dev", st->name); + if (!st->trigger) + return -ENOMEM; + + st->trigger->dev.parent = dev; + st->trigger->ops = &inv_icm42600_trigger_ops; + iio_trigger_set_drvdata(st->trigger, st); + + /* configure INT1 with correct mode */ + /* falling or both-edge */ + if (irq_type & IRQF_TRIGGER_FALLING) { + val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_LOW; + } else if (irq_type == IRQF_TRIGGER_RISING) { + val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_HIGH; + } else if (irq_type == IRQF_TRIGGER_LOW) { + val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_LOW | + INV_ICM42600_INT_CONFIG_INT1_LATCHED; + } else if (irq_type == IRQF_TRIGGER_HIGH) { + val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_LOW | + INV_ICM42600_INT_CONFIG_INT1_LATCHED; + } else { + dev_err(dev, "invalid interrupt type %#x\n", irq_type); + return -EINVAL; + } + val |= INV_ICM42600_INT_CONFIG_INT1_PUSH_PULL; + ret = regmap_write(st->map, INV_ICM42600_REG_INT_CONFIG, val); + if (ret) + return ret; + + /* Deassert async reset for proper INT pin operation (cf datasheet) */ + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_CONFIG1, + INV_ICM42600_INT_CONFIG1_ASYNC_RESET, 0); + if (ret) + return ret; + + ret = devm_request_threaded_irq(dev, irq, + inv_icm42600_trigger_timestamp, + inv_icm42600_trigger_int_handler, + irq_type, "inv_icm42600", st); + if (ret) + return ret; + + return devm_iio_trigger_register(dev, st->trigger); +} From patchwork Thu May 7 14:42:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Baptiste Maneyrol X-Patchwork-Id: 200943 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, MSGID_FROM_MTA_HEADER,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, UNWANTED_LANGUAGE_BODY,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 00009C47247 for ; Thu, 7 May 2020 14:43:49 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BFA7E208D6 for ; Thu, 7 May 2020 14:43:49 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="F8fnmZoi"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="bxABE7Pt" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728053AbgEGOns (ORCPT ); Thu, 7 May 2020 10:43:48 -0400 Received: from mx0a-00328301.pphosted.com ([148.163.145.46]:36510 "EHLO mx0a-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727787AbgEGOna (ORCPT ); Thu, 7 May 2020 10:43:30 -0400 Received: from pps.filterd (m0156134.ppops.net [127.0.0.1]) by mx0a-00328301.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 047Eegd7005564; Thu, 7 May 2020 07:43:25 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=invensense.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : content-type : mime-version; s=pfpt1; bh=E4/9MNCKw3gAe5FzYl5LeaML9JToSDiY4KYE8GjysP8=; b=F8fnmZoij68TX2owuC2+6Y1T1vC2CdbAMQCSnix+/gzeCcUUSVD38A0dZDs5Vb00ofGm 6OYYxYgvsG4vG2b3PLAmfBGMteCp/KiQRb+Tg5KukhjjnUhJCOt1kuRr1KKSS2raLcza Yr631Qwhm/HytZc2ppMIXUM40pBgtFBTikSdVuE/DgvmjPXk7dxV0XLHErmpbbYc1GMA mWU2bbwJDm49IS6fLe73HsVKwCrp9CddGJ45i9zK2k9pKt+Gn7mQSZrzj06+xtZQDUBx IrCF5s/pGep9yOxPqV3aNs9S3JnrKlhTj2rjsOYFSucDIpeIRpS8UZx2SABjDSYdCYaa hA== Received: from nam11-dm6-obe.outbound.protection.outlook.com (mail-dm6nam11lp2170.outbound.protection.outlook.com [104.47.57.170]) by mx0a-00328301.pphosted.com with ESMTP id 30sfwdjs8x-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 07 May 2020 07:43:25 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=YIw7LKylCEh+x0/l3VaNqTU8YZmJaZYdSURV0fZKOjXXO/jSKY+i1YB1DyLRLdB+RWUPNVFR+SSB7Eiffpqn97BuZ/1XHoAnXvlIAO5klnHfzEah6MJpXRPllPMG6eOhCvZ9YyFAlwQUxxc7K4yIB1zpFd73bdXLp1E6jREie0kyDTudO3msItKaNcJIxu4GrBcD+Zem8RN0LEX6S93uJPerK4TbNdpnLuFbANy/Uza2uoR7LkvR+Mm2ryp05+Dcn5gYoazyXXhHLwDaHW4wPSqIdnDrIH0mAlkHseTFlvoP+7/bdmUaR/Vf2Fx6kFqUYFixO5rJWwiRKxvcwW6IRg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=E4/9MNCKw3gAe5FzYl5LeaML9JToSDiY4KYE8GjysP8=; b=X/rNCsVst5bNwm3Y5GFjoiE+uFItmFwnpAeoFgAe0Z78dFQpVXwtBTcEddkjoaYRsMhcWHImx1XRC6UBNmyQC4D8/KuwzL5d2kBbk/kySSpt7+K9GZtfMoq2Ln2lNxON21Boz+NAR2mGg4E1Li5DGEmaJ52VIlhrWtF21AFjbC62+F6Bg6o2LlHOtioHFZqnR/lawll2hGuweZKQjQR/laU/i0l9oLhrZBWrVuJsCFGiDsYsYRx1VrdpRT9/EbohvUJosbSpf2/v9eeLbGzDUM0cA19W+HpJ3YoVbGuCSeVTV4KrQKcqghybXDC6GrtK53PToTD0PExApby8071FYg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=invensense.com; dmarc=pass action=none header.from=invensense.com; dkim=pass header.d=invensense.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=invensense.onmicrosoft.com; s=selector2-invensense-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=E4/9MNCKw3gAe5FzYl5LeaML9JToSDiY4KYE8GjysP8=; b=bxABE7PtrMiaRVX1IJf0OMoXwVSj0SDiJh5wd5j7ctebwesbQKFIPKFTRB8iAaJAsNAvX8dMA3ecmpSUDeQzmQVtOWX3I5/eqOfpEBj0Ldu86xq+LTbTmSqjx9ZwaPzFaHDyDIZvPr/wdPOoQ4mH0mXj05DmLc5GyHAOJp/qoAA= Authentication-Results: kernel.org; dkim=none (message not signed) header.d=none; kernel.org; dmarc=none action=none header.from=invensense.com; Received: from MN2PR12MB4422.namprd12.prod.outlook.com (2603:10b6:208:265::9) by MN2PR12MB4501.namprd12.prod.outlook.com (2603:10b6:208:269::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2979.27; Thu, 7 May 2020 14:43:23 +0000 Received: from MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::7471:da8b:8ca1:6af0]) by MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::7471:da8b:8ca1:6af0%4]) with mapi id 15.20.2979.028; Thu, 7 May 2020 14:43:23 +0000 From: Jean-Baptiste Maneyrol To: jic23@kernel.org, robh+dt@kernel.org, robh@kernel.org, mchehab+huawei@kernel.org, davem@davemloft.net, gregkh@linuxfoundation.org Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Jean-Baptiste Maneyrol Subject: [PATCH 09/12] iio: imu: inv_icm42600: add buffer support in iio devices Date: Thu, 7 May 2020 16:42:19 +0200 Message-Id: <20200507144222.20989-10-jmaneyrol@invensense.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200507144222.20989-1-jmaneyrol@invensense.com> References: <20200507144222.20989-1-jmaneyrol@invensense.com> X-ClientProxiedBy: LNXP265CA0048.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:5c::36) To MN2PR12MB4422.namprd12.prod.outlook.com (2603:10b6:208:265::9) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from frgnb-buildozer.invcorp.invensense.com (77.157.193.39) by LNXP265CA0048.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:5c::36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2979.26 via Frontend Transport; Thu, 7 May 2020 14:43:22 +0000 X-Mailer: git-send-email 2.17.1 X-Originating-IP: [77.157.193.39] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 9ef73221-038d-431a-c6af-08d7f294fe69 X-MS-TrafficTypeDiagnostic: MN2PR12MB4501: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:86; X-Forefront-PRVS: 03965EFC76 X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: +bLM10Mdg9qA9y0ByvTTBxE+gB6vLRsygmWae2J36iqJXsdDmGqSHivk5rjXAhO4RPVjGJ2PANvcfohZ11IHZHG6OB/pCgMwGBLJUvl4mcFSNU0J8vPaaiWnV8kNnYFWNSTIk2qvy8HDhme6GxTFCGuM+wV961C6m6DB1t9n/qUrJhh6NQtX81c7w4bfAhMSApIpula80h6qrhyRTi5YROP9zmrbigzfqjdgrjAVymBXDDSlRjtS9l8L8dZwI2g2KjcvAatT6lOUOsXI0WIIq2Ejec4VAjqegqYxaCgZtQSkmwltvmmPc+wwBqzF52ioYOHXXg2IEwsyHfx8WWPkxED2D8NBerqsWAEwEUhFBbq1ZpwU00m2iwSd0y6l3GoSWKVcp+S0zgyHZxbcws7jgjCJD//vtCVEGWMG/Vk0dHI5yHCfMarQAc7DAVzn7Gaj7qUlcjs5K5HtHk14nhvwyZGQMKRBaHBn3u8pZPnrdKh/ib+593bG2QuYTnUtudhft2h1meduenkDkfzJfvKUTA== X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:MN2PR12MB4422.namprd12.prod.outlook.com; PTR:; CAT:NONE; SFTY:; SFS:(346002)(376002)(136003)(396003)(39850400004)(366004)(33430700001)(30864003)(107886003)(4326008)(8676002)(6486002)(2906002)(316002)(5660300002)(8936002)(1076003)(26005)(7696005)(33440700001)(66946007)(956004)(66476007)(52116002)(2616005)(86362001)(186003)(83320400001)(83280400001)(83310400001)(83290400001)(16526019)(478600001)(6666004)(36756003)(66556008)(83300400001); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData: 3aAiZNoC8vcV3btvAFZ5yGcafNBgPnWZ3IqggzYErDUQSxn0grnouBK4nUtBTfcRM9FLPh+jr28zBirSeRMCaziR70PBH00k/1XvcUaeIWn8ws2Ox7qKqLaUR+uHz3JZX2gwYRR5KS65UyjiC+VZ8stMbiRk+Op9fOnMo5cGhrCS7sMyXDzHKalhajAxfpnE6hFxkDvNSqNtZ3d0U13UNSl/GPTQsebru+0CHrM5FFVadwBi7fUswTHOI4honDDP0meJXob58pFO5TMs1Ig5y+I1lAA6L8uu/+6PMNHF3cM42GK/49o/qyG4TyQ6KqXNcATEiWB5rtCXvG/F4+PkFRLO4yzckMe2/+DeHe40ZbeCiTwRR9CCcZm0aU/z8K0ekz84Poca9yGYcgpnD2fkR9ttS2Dachnap6Uw4FiZGtCRcoiCgSCCIdDpdpmjyqg3Z2Ue+R7G/NxQYiy2eOkE8/zcLKjVV8XF2t/2APeEzaYUDgmvwTcf7q2hYBedME1VEOdVN+ljtCtWyYDgMffjSAn7wKWdjL64AWrhOlQ/HQ0ccwA5t8a0Nf4DkX2/boXNGn+FXFiWjO56MTsD7IGTfC583qwtRAnZUQgWCN7tlPhRF1z3ErgM6P50UMzXe+vJQc0b1qptwd04qRsq6IpbmhRDjH9bZUtVf119ERTDAwJ2+kOeOqWHseRSJGbUtZzCgK5rpSAIH32abJMThUgEElB7JZCnhbt8Tp5FnoGMe3Wz8Xz7ByBZWjzAxMccAidhO1Pwo+vnfrZ8ghzNpIeNsgqmV7vS8P297644pzwIn4Q= X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: 9ef73221-038d-431a-c6af-08d7f294fe69 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 May 2020 14:43:23.5990 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 462b3b3b-e42b-47ea-801a-f1581aac892d X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: S7McbcaDRQjGx5iqtkJj65mKF2mDhgUfi5FsbhEM0oPk7r7gTpaAxyzn5xcCkIQBqXwkCds25XU0JwZMa1v1TzMbNbUXnBiaY4VE3E6sW+0= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4501 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216, 18.0.676 definitions=2020-05-07_09:2020-05-07,2020-05-07 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 adultscore=0 spamscore=0 impostorscore=0 suspectscore=0 mlxscore=0 phishscore=0 bulkscore=0 malwarescore=0 mlxlogscore=999 clxscore=1015 priorityscore=1501 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2005070118 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Use triggered buffer by parsing FIFO data read in device trigger. Support hwfifo watermark by multiplexing gyro and accel settings. Support hwfifo flush. Simply use interrupt timestamp first. Signed-off-by: Jean-Baptiste Maneyrol --- drivers/iio/imu/inv_icm42600/Kconfig | 3 +- drivers/iio/imu/inv_icm42600/Makefile | 1 + drivers/iio/imu/inv_icm42600/inv_icm42600.h | 8 + .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 183 +++++++++ .../imu/inv_icm42600/inv_icm42600_buffer.c | 353 ++++++++++++++++++ .../imu/inv_icm42600/inv_icm42600_buffer.h | 162 ++++++++ .../iio/imu/inv_icm42600/inv_icm42600_core.c | 23 ++ .../iio/imu/inv_icm42600/inv_icm42600_gyro.c | 183 +++++++++ .../imu/inv_icm42600/inv_icm42600_trigger.c | 15 +- 9 files changed, 928 insertions(+), 3 deletions(-) create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h diff --git a/drivers/iio/imu/inv_icm42600/Kconfig b/drivers/iio/imu/inv_icm42600/Kconfig index 7b3eaeb2aa4a..8c0969319c49 100644 --- a/drivers/iio/imu/inv_icm42600/Kconfig +++ b/drivers/iio/imu/inv_icm42600/Kconfig @@ -2,7 +2,8 @@ config INV_ICM42600 tristate - select IIO_TRIGGER + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER config INV_ICM42600_I2C tristate "InvenSense ICM-426xx I2C driver" diff --git a/drivers/iio/imu/inv_icm42600/Makefile b/drivers/iio/imu/inv_icm42600/Makefile index e1f2aacbe888..d6732118010c 100644 --- a/drivers/iio/imu/inv_icm42600/Makefile +++ b/drivers/iio/imu/inv_icm42600/Makefile @@ -6,6 +6,7 @@ inv-icm42600-y += inv_icm42600_gyro.o inv-icm42600-y += inv_icm42600_accel.o inv-icm42600-y += inv_icm42600_temp.o inv-icm42600-y += inv_icm42600_trigger.o +inv-icm42600-y += inv_icm42600_buffer.o obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o inv-icm42600-i2c-y += inv_icm42600_i2c.o diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h b/drivers/iio/imu/inv_icm42600/inv_icm42600.h index 175c1f67faee..947ca4dd245b 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h @@ -15,6 +15,8 @@ #include #include +#include "inv_icm42600_buffer.h" + enum inv_icm42600_chip { INV_CHIP_ICM42600, INV_CHIP_ICM42602, @@ -124,6 +126,7 @@ struct inv_icm42600_suspended { * @indio_gyro: gyroscope IIO device. * @indio_accel: accelerometer IIO device. * @trigger: device internal interrupt trigger + * @fifo: FIFO management structure. */ struct inv_icm42600_state { struct mutex lock; @@ -138,6 +141,7 @@ struct inv_icm42600_state { struct iio_dev *indio_gyro; struct iio_dev *indio_accel; struct iio_trigger *trigger; + struct inv_icm42600_fifo fifo; }; /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */ @@ -378,8 +382,12 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, int inv_icm42600_gyro_init(struct inv_icm42600_state *st); +int inv_icm42600_gyro_parse_fifo(struct iio_dev *indio_dev, int64_t ts); + int inv_icm42600_accel_init(struct inv_icm42600_state *st); +int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev, int64_t ts); + int inv_icm42600_trigger_init(struct inv_icm42600_state *st, int irq, int irq_type); diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c index 74dac5f283d4..4206be54d057 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c @@ -10,9 +10,13 @@ #include #include #include +#include +#include +#include #include "inv_icm42600.h" #include "inv_icm42600_temp.h" +#include "inv_icm42600_buffer.h" #define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info) \ { \ @@ -46,6 +50,7 @@ enum inv_icm42600_accel_scan { INV_ICM42600_ACCEL_SCAN_Y, INV_ICM42600_ACCEL_SCAN_Z, INV_ICM42600_ACCEL_SCAN_TEMP, + INV_ICM42600_ACCEL_SCAN_TIMESTAMP, }; static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = { @@ -61,8 +66,100 @@ static const struct iio_chan_spec inv_icm42600_accel_channels[] = { INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z, inv_icm42600_accel_ext_infos), INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP), + IIO_CHAN_SOFT_TIMESTAMP(INV_ICM42600_ACCEL_SCAN_TIMESTAMP), }; +/* IIO buffer data */ +struct inv_icm42600_accel_buffer { + struct inv_icm42600_fifo_sensor_data accel; + int8_t temp; + int64_t timestamp; +}; + +#define INV_ICM42600_SCAN_MASK_ACCEL_3AXIS \ + (BIT(INV_ICM42600_ACCEL_SCAN_X) | \ + BIT(INV_ICM42600_ACCEL_SCAN_Y) | \ + BIT(INV_ICM42600_ACCEL_SCAN_Z)) + +#define INV_ICM42600_SCAN_MASK_TEMP BIT(INV_ICM42600_ACCEL_SCAN_TEMP) + +static const unsigned long inv_icm42600_accel_scan_masks[] = { + /* 3-axis accel + temperature */ + INV_ICM42600_SCAN_MASK_ACCEL_3AXIS | INV_ICM42600_SCAN_MASK_TEMP, + 0, +}; + +static irqreturn_t inv_icm42600_accel_handler(int irq, void *_data) +{ + struct iio_poll_func *pf = _data; + struct iio_dev *indio_dev = pf->indio_dev; + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + const size_t fifo_nb = st->fifo.nb.total; + int ret; + + /* exit if no sample */ + if (fifo_nb == 0) + goto out; + + ret = inv_icm42600_accel_parse_fifo(indio_dev, pf->timestamp); + if (ret) + dev_err(regmap_get_device(st->map), "accel fifo error %d\n", + ret); + +out: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + +/* enable accelerometer sensor and FIFO write */ +static int inv_icm42600_accel_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; + unsigned int fifo_en = 0; + unsigned int sleep_temp = 0; + unsigned int sleep_accel = 0; + unsigned int sleep; + int ret; + + mutex_lock(&st->lock); + + if (*scan_mask & INV_ICM42600_SCAN_MASK_TEMP) { + /* enable temp sensor */ + ret = inv_icm42600_set_temp_conf(st, true, &sleep_temp); + if (ret) + goto out_unlock; + fifo_en |= INV_ICM42600_SENSOR_TEMP; + } + + if (*scan_mask & INV_ICM42600_SCAN_MASK_ACCEL_3AXIS) { + /* enable accel sensor */ + conf.mode = INV_ICM42600_SENSOR_MODE_LOW_NOISE; + ret = inv_icm42600_set_accel_conf(st, &conf, &sleep_accel); + if (ret) + goto out_unlock; + fifo_en |= INV_ICM42600_SENSOR_ACCEL; + } + + /* update data FIFO write and FIFO watermark */ + ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en); + if (ret) + goto out_unlock; + ret = inv_icm42600_buffer_update_watermark(st); + +out_unlock: + mutex_unlock(&st->lock); + /* sleep maximum required time */ + if (sleep_accel > sleep_temp) + sleep = sleep_accel; + else + sleep = sleep_temp; + if (sleep) + msleep(sleep); + return ret; +} + static int inv_icm42600_accel_read_sensor(struct inv_icm42600_state *st, struct iio_chan_spec const *chan, int16_t *val) @@ -250,6 +347,8 @@ static int inv_icm42600_accel_write_odr(struct inv_icm42600_state *st, mutex_lock(&st->lock); conf.odr = inv_icm42600_accel_odr_conv[idx / 2]; ret = inv_icm42600_set_accel_conf(st, &conf, NULL); + inv_icm42600_buffer_update_fifo_period(st); + inv_icm42600_buffer_update_watermark(st); mutex_unlock(&st->lock); pm_runtime_mark_last_busy(dev); @@ -512,12 +611,51 @@ static int inv_icm42600_accel_write_raw_get_fmt(struct iio_dev *indio_dev, } } +static int inv_icm42600_accel_hwfifo_set_watermark(struct iio_dev *indio_dev, + unsigned int val) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + mutex_lock(&st->lock); + + st->fifo.watermark.accel = val; + ret = inv_icm42600_buffer_update_watermark(st); + + mutex_unlock(&st->lock); + + return ret; +} + +static int inv_icm42600_accel_hwfifo_flush(struct iio_dev *indio_dev, + unsigned int count) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + if (count == 0) + return 0; + + mutex_lock(&st->lock); + + ret = inv_icm42600_buffer_hwfifo_flush(st, count); + if (!ret) + ret = st->fifo.nb.accel; + + mutex_unlock(&st->lock); + + return ret; +} + static const struct iio_info inv_icm42600_accel_info = { .read_raw = inv_icm42600_accel_read_raw, .read_avail = inv_icm42600_accel_read_avail, .write_raw = inv_icm42600_accel_write_raw, .write_raw_get_fmt = inv_icm42600_accel_write_raw_get_fmt, .debugfs_reg_access = inv_icm42600_debugfs_reg, + .update_scan_mode = inv_icm42600_accel_update_scan_mode, + .hwfifo_set_watermark = inv_icm42600_accel_hwfifo_set_watermark, + .hwfifo_flush_to_buffer = inv_icm42600_accel_hwfifo_flush, }; int inv_icm42600_accel_init(struct inv_icm42600_state *st) @@ -525,6 +663,7 @@ int inv_icm42600_accel_init(struct inv_icm42600_state *st) struct device *dev = regmap_get_device(st->map); const char *name; struct iio_dev *indio_dev; + int ret; name = devm_kasprintf(dev, GFP_KERNEL, "%s-accel", st->name); if (!name) @@ -541,7 +680,51 @@ int inv_icm42600_accel_init(struct inv_icm42600_state *st) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = inv_icm42600_accel_channels; indio_dev->num_channels = ARRAY_SIZE(inv_icm42600_accel_channels); + indio_dev->available_scan_masks = inv_icm42600_accel_scan_masks; + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, + inv_icm42600_accel_handler, + &inv_icm42600_buffer_ops); + if (ret) + return ret; + + indio_dev->trig = iio_trigger_get(st->trigger); st->indio_accel = indio_dev; return devm_iio_device_register(dev, st->indio_accel); } + +int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev, int64_t ts) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + const size_t accel_nb = st->fifo.nb.accel; + ssize_t i, size; + const void *accel, *gyro, *temp, *timestamp; + unsigned int odr; + struct inv_icm42600_accel_buffer buffer; + + /* exit if no accel sample */ + if (accel_nb == 0) + return 0; + + /* parse all fifo packets */ + for (i = 0; i < st->fifo.count; i += size) { + size = inv_icm42600_fifo_decode_packet(&st->fifo.data[i], + &accel, &gyro, &temp, ×tamp, &odr); + dev_dbg(regmap_get_device(st->map), "accel packet size = %zd\n", + size); + /* quit if error or FIFO is empty */ + if (size <= 0) + return size; + /* skip packet if no accel data or data is invalid */ + if (accel == NULL || !inv_icm42600_fifo_is_data_valid(accel)) { + dev_dbg(regmap_get_device(st->map), "skip accel data\n"); + continue; + } + memcpy(&buffer.accel, accel, sizeof(buffer.accel)); + memcpy(&buffer.temp, temp, sizeof(buffer.temp)); + iio_push_to_buffers_with_timestamp(indio_dev, &buffer, ts); + } + + return 0; +} diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c new file mode 100644 index 000000000000..b428abdc92ee --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c @@ -0,0 +1,353 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "inv_icm42600.h" +#include "inv_icm42600_buffer.h" + +void inv_icm42600_buffer_update_fifo_period(struct inv_icm42600_state *st) +{ + uint32_t period_gyro, period_accel, period; + + if (st->fifo.en & INV_ICM42600_SENSOR_GYRO) + period_gyro = inv_icm42600_odr_to_period(st->conf.gyro.odr); + else + period_gyro = U32_MAX; + + if (st->fifo.en & INV_ICM42600_SENSOR_ACCEL) + period_accel = inv_icm42600_odr_to_period(st->conf.accel.odr); + else + period_accel = U32_MAX; + + if (period_gyro <= period_accel) + period = period_gyro; + else + period = period_accel; + + st->fifo.period = period; +} + +int inv_icm42600_buffer_set_fifo_en(struct inv_icm42600_state *st, + unsigned int fifo_en) +{ + unsigned int mask, val; + int ret; + + /* update only FIFO EN bits */ + mask = INV_ICM42600_FIFO_CONFIG1_TMST_FSYNC_EN | + INV_ICM42600_FIFO_CONFIG1_TEMP_EN | + INV_ICM42600_FIFO_CONFIG1_GYRO_EN | + INV_ICM42600_FIFO_CONFIG1_ACCEL_EN; + + val = 0; + if (fifo_en & INV_ICM42600_SENSOR_GYRO) + val |= INV_ICM42600_FIFO_CONFIG1_GYRO_EN; + if (fifo_en & INV_ICM42600_SENSOR_ACCEL) + val |= INV_ICM42600_FIFO_CONFIG1_ACCEL_EN; + if (fifo_en & INV_ICM42600_SENSOR_TEMP) + val |= INV_ICM42600_FIFO_CONFIG1_TEMP_EN; + + ret = regmap_update_bits(st->map, INV_ICM42600_REG_FIFO_CONFIG1, + mask, val); + if (ret) + return ret; + + st->fifo.en = fifo_en; + inv_icm42600_buffer_update_fifo_period(st); + + return 0; +} + +static size_t inv_icm42600_get_packet_size(unsigned int fifo_en) +{ + size_t packet_size; + + if ((fifo_en & INV_ICM42600_SENSOR_GYRO) && + (fifo_en & INV_ICM42600_SENSOR_ACCEL)) + packet_size = INV_ICM42600_FIFO_2SENSORS_PACKET_SIZE; + else + packet_size = INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE; + + return packet_size; +} + +static unsigned int inv_icm42600_wm_truncate(unsigned int watermark, + size_t packet_size) +{ + size_t wm_size; + unsigned int wm; + + wm_size = watermark * packet_size; + if (wm_size > INV_ICM42600_FIFO_WATERMARK_MAX) + wm_size = INV_ICM42600_FIFO_WATERMARK_MAX; + + wm = wm_size / packet_size; + + return wm; +} + +int inv_icm42600_buffer_update_watermark(struct inv_icm42600_state *st) +{ + size_t packet_size, wm_size; + unsigned int wm_gyro, wm_accel, watermark; + uint32_t period_gyro, period_accel, period; + int64_t latency_gyro, latency_accel, latency; + unsigned int mask, val; + bool restore; + __le16 raw_wm; + int ret; + + packet_size = inv_icm42600_get_packet_size(st->fifo.en); + + /* get minimal latency, depending on sensor watermark and odr */ + wm_gyro = inv_icm42600_wm_truncate(st->fifo.watermark.gyro, + packet_size); + wm_accel = inv_icm42600_wm_truncate(st->fifo.watermark.accel, + packet_size); + period_gyro = inv_icm42600_odr_to_period(st->conf.gyro.odr); + period_accel = inv_icm42600_odr_to_period(st->conf.accel.odr); + latency_gyro = (int64_t)period_gyro * (int64_t)wm_gyro; + latency_accel = (int64_t)period_accel * (int64_t)wm_accel; + if (latency_gyro == 0) { + latency = latency_accel; + watermark = wm_accel; + } else if (latency_accel == 0) { + latency = latency_gyro; + watermark = wm_gyro; + } else { + /* compute the smallest latency that is a multiple of both */ + if (latency_gyro <= latency_accel) { + latency = latency_gyro; + latency -= latency_accel % latency_gyro; + } else { + latency = latency_accel; + latency -= latency_gyro % latency_accel; + } + /* use the shortest period */ + if (period_gyro <= period_accel) + period = period_gyro; + else + period = period_accel; + /* all this works because periods are multiple of each others */ + watermark = div_s64(latency, period); + if (watermark < 1) + watermark = 1; + } + wm_size = watermark * packet_size; + dev_dbg(regmap_get_device(st->map), "watermark: %u (%zu)\n", + watermark, wm_size); + + /* changing FIFO watermark requires to turn off watermark interrupt */ + mask = INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN; + val = 0; + ret = regmap_update_bits_check(st->map, INV_ICM42600_REG_INT_SOURCE0, + mask, val, &restore); + if (ret) + return ret; + + raw_wm = INV_ICM42600_FIFO_WATERMARK_VAL(wm_size); + ret = regmap_bulk_write(st->map, INV_ICM42600_REG_FIFO_WATERMARK, + &raw_wm, sizeof(raw_wm)); + if (ret) + return ret; + + /* restore watermark interrupt */ + if (restore) { + mask = INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN; + val = INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN; + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0, + mask, val); + if (ret) + return ret; + } + + return 0; +} + +static int inv_icm42600_buffer_preenable(struct iio_dev *indio_dev) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct device *dev = regmap_get_device(st->map); + + pm_runtime_get_sync(dev); + + return 0; +} + +static int inv_icm42600_buffer_postdisable(struct iio_dev *indio_dev) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct device *dev = regmap_get_device(st->map); + unsigned int sensor; + unsigned int *watermark; + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; + unsigned int sleep = 0; + int ret; + + if (indio_dev == st->indio_gyro) { + sensor = INV_ICM42600_SENSOR_GYRO; + watermark = &st->fifo.watermark.gyro; + } else if (indio_dev == st->indio_accel) { + sensor = INV_ICM42600_SENSOR_ACCEL; + watermark = &st->fifo.watermark.accel; + } else { + return -EINVAL; + } + + mutex_lock(&st->lock); + + ret = inv_icm42600_buffer_set_fifo_en(st, st->fifo.en & ~sensor); + if (ret) + goto out_unlock; + + *watermark = 0; + ret = inv_icm42600_buffer_update_watermark(st); + if (ret) + goto out_unlock; + + conf.mode = INV_ICM42600_SENSOR_MODE_OFF; + if (sensor == INV_ICM42600_SENSOR_GYRO) + ret = inv_icm42600_set_gyro_conf(st, &conf, &sleep); + else + ret = inv_icm42600_set_accel_conf(st, &conf, &sleep); + +out_unlock: + mutex_unlock(&st->lock); + if (sleep) + msleep(sleep); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +const struct iio_buffer_setup_ops inv_icm42600_buffer_ops = { + .preenable = inv_icm42600_buffer_preenable, + .postenable = iio_triggered_buffer_postenable, + .predisable = iio_triggered_buffer_predisable, + .postdisable = inv_icm42600_buffer_postdisable, +}; + +int inv_icm42600_buffer_fifo_read(struct inv_icm42600_state *st, + unsigned int max) +{ + struct device *dev = regmap_get_device(st->map); + __be16 raw_fifo_count; + size_t max_count; + ssize_t i, size; + const void *accel, *gyro, *temp, *timestamp; + unsigned int odr; + int ret; + + /* reset all samples counters */ + st->fifo.count = 0; + st->fifo.nb.gyro = 0; + st->fifo.nb.accel = 0; + st->fifo.nb.total = 0; + + /* compute maximum FIFO read size */ + if (max == 0) + max_count = sizeof(st->fifo.data); + else + max_count = max * inv_icm42600_get_packet_size(st->fifo.en); + + /* read FIFO count value */ + ret = regmap_bulk_read(st->map, INV_ICM42600_REG_FIFO_COUNT, + &raw_fifo_count, sizeof(raw_fifo_count)); + if (ret) + return ret; + st->fifo.count = be16_to_cpu(raw_fifo_count); + dev_dbg(dev, "FIFO count = %zu\n", st->fifo.count); + + /* check and sanitize FIFO count value */ + if (st->fifo.count == 0) + return 0; + if (st->fifo.count > max_count) + st->fifo.count = max_count; + + /* read all FIFO data in internal buffer */ + ret = regmap_noinc_read(st->map, INV_ICM42600_REG_FIFO_DATA, + st->fifo.data, st->fifo.count); + if (ret) + return ret; + + /* compute number of samples for each sensor */ + for (i = 0; i < st->fifo.count; i += size) { + size = inv_icm42600_fifo_decode_packet(&st->fifo.data[i], + &accel, &gyro, &temp, ×tamp, &odr); + if (size <= 0) + break; + if (gyro != NULL && inv_icm42600_fifo_is_data_valid(gyro)) + st->fifo.nb.gyro++; + if (accel != NULL && inv_icm42600_fifo_is_data_valid(accel)) + st->fifo.nb.accel++; + st->fifo.nb.total++; + } + + return 0; +} + +int inv_icm42600_buffer_hwfifo_flush(struct inv_icm42600_state *st, + unsigned int count) +{ + int64_t ts_gyro, ts_accel; + int ret; + + dev_dbg(regmap_get_device(st->map), "FIFO flush %u\n", count); + + ts_gyro = iio_get_time_ns(st->indio_gyro); + ts_accel = iio_get_time_ns(st->indio_accel); + ret = inv_icm42600_buffer_fifo_read(st, count); + if (ret) + return ret; + + if (st->fifo.nb.total == 0) + return 0; + + ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro, ts_gyro); + if (ret) + return ret; + + return inv_icm42600_accel_parse_fifo(st->indio_accel, ts_accel); +} + +int inv_icm42600_buffer_init(struct inv_icm42600_state *st) +{ + unsigned int mask, val; + int ret; + + /* + * Default FIFO configuration (bits 7 to 5) + * - use invalid value + * - FIFO count in bytes + * - FIFO count in big endian + */ + mask = GENMASK(7, 5); + val = INV_ICM42600_INTF_CONFIG0_FIFO_COUNT_ENDIAN; + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0, + mask, val); + if (ret) + return ret; + + /* + * Enable FIFO partial read and continuous watermark interrupt. + * Disable all FIFO EN bits. + */ + mask = GENMASK(6, 5) | GENMASK(3, 0); + val = INV_ICM42600_FIFO_CONFIG1_RESUME_PARTIAL_RD | + INV_ICM42600_FIFO_CONFIG1_WM_GT_TH; + return regmap_update_bits(st->map, INV_ICM42600_REG_FIFO_CONFIG1, + mask, val); +} diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h new file mode 100644 index 000000000000..74b91c0e664b --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h @@ -0,0 +1,162 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#ifndef INV_ICM42600_BUFFER_H_ +#define INV_ICM42600_BUFFER_H_ + +#include +#include + +struct inv_icm42600_state; + +#define INV_ICM42600_SENSOR_GYRO BIT(0) +#define INV_ICM42600_SENSOR_ACCEL BIT(1) +#define INV_ICM42600_SENSOR_TEMP BIT(2) + +struct inv_icm42600_fifo { + unsigned int en; + uint32_t period; + struct { + unsigned int gyro; + unsigned int accel; + } watermark; + size_t count; + struct { + size_t gyro; + size_t accel; + size_t total; + } nb; + uint8_t data[2080]; +}; + +/* FIFO header: 1 byte */ +#define INV_ICM42600_FIFO_HEADER_MSG BIT(7) +#define INV_ICM42600_FIFO_HEADER_ACCEL BIT(6) +#define INV_ICM42600_FIFO_HEADER_GYRO BIT(5) +#define INV_ICM42600_FIFO_HEADER_TMST_FSYNC GENMASK(3, 2) +#define INV_ICM42600_FIFO_HEADER_ODR_ACCEL BIT(1) +#define INV_ICM42600_FIFO_HEADER_ODR_GYRO BIT(0) + +/* FIFO data packet */ +struct inv_icm42600_fifo_sensor_data { + __be16 x; + __be16 y; + __be16 z; +} __packed; +#define INV_ICM42600_FIFO_DATA_INVALID -32768 + +struct inv_icm42600_fifo_1sensor_packet { + uint8_t header; + struct inv_icm42600_fifo_sensor_data data; + int8_t temp; +} __packed; +#define INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE 8 + +struct inv_icm42600_fifo_2sensors_packet { + uint8_t header; + struct inv_icm42600_fifo_sensor_data accel; + struct inv_icm42600_fifo_sensor_data gyro; + int8_t temp; + __be16 timestamp; +} __packed; +#define INV_ICM42600_FIFO_2SENSORS_PACKET_SIZE 16 + +static inline int16_t inv_icm42600_fifo_get_sensor_data(__be16 d) +{ + return be16_to_cpu(d); +} + +static inline bool +inv_icm42600_fifo_is_data_valid(const struct inv_icm42600_fifo_sensor_data *s) +{ + int16_t x, y, z; + + x = inv_icm42600_fifo_get_sensor_data(s->x); + y = inv_icm42600_fifo_get_sensor_data(s->y); + z = inv_icm42600_fifo_get_sensor_data(s->z); + + if (x == INV_ICM42600_FIFO_DATA_INVALID && + y == INV_ICM42600_FIFO_DATA_INVALID && + z == INV_ICM42600_FIFO_DATA_INVALID) + return false; + + return true; +} + +static inline ssize_t inv_icm42600_fifo_decode_packet(const void *packet, + const void **accel, const void **gyro, const void **temp, + const void **timestamp, unsigned int *odr) +{ + const struct inv_icm42600_fifo_1sensor_packet *pack1 = packet; + const struct inv_icm42600_fifo_2sensors_packet *pack2 = packet; + uint8_t header = *((const uint8_t *)packet); + + /* FIFO empty */ + if (header & INV_ICM42600_FIFO_HEADER_MSG) { + *accel = NULL; + *gyro = NULL; + *temp = NULL; + *timestamp = NULL; + *odr = 0; + return 0; + } + + /* handle odr flags */ + *odr = 0; + if (header & INV_ICM42600_FIFO_HEADER_ODR_GYRO) + *odr |= INV_ICM42600_SENSOR_GYRO; + if (header & INV_ICM42600_FIFO_HEADER_ODR_ACCEL) + *odr |= INV_ICM42600_SENSOR_ACCEL; + + /* accel + gyro */ + if ((header & INV_ICM42600_FIFO_HEADER_ACCEL) && + (header & INV_ICM42600_FIFO_HEADER_GYRO)) { + *accel = &pack2->accel; + *gyro = &pack2->gyro; + *temp = &pack2->temp; + *timestamp = &pack2->timestamp; + return INV_ICM42600_FIFO_2SENSORS_PACKET_SIZE; + } + + /* accel only */ + if (header & INV_ICM42600_FIFO_HEADER_ACCEL) { + *accel = &pack1->data; + *gyro = NULL; + *temp = &pack1->temp; + *timestamp = NULL; + return INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE; + } + + /* gyro only */ + if (header & INV_ICM42600_FIFO_HEADER_GYRO) { + *accel = NULL; + *gyro = &pack1->data; + *temp = &pack1->temp; + *timestamp = NULL; + return INV_ICM42600_FIFO_1SENSOR_PACKET_SIZE; + } + + /* invalid packet if here */ + return -EINVAL; +} + +extern const struct iio_buffer_setup_ops inv_icm42600_buffer_ops; + +int inv_icm42600_buffer_init(struct inv_icm42600_state *st); + +void inv_icm42600_buffer_update_fifo_period(struct inv_icm42600_state *st); + +int inv_icm42600_buffer_set_fifo_en(struct inv_icm42600_state *st, + unsigned int fifo_en); + +int inv_icm42600_buffer_update_watermark(struct inv_icm42600_state *st); + +int inv_icm42600_buffer_fifo_read(struct inv_icm42600_state *st, + unsigned int max); + +int inv_icm42600_buffer_hwfifo_flush(struct inv_icm42600_state *st, + unsigned int count); + +#endif diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c index 1102c54396e3..689089065ff9 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c @@ -14,6 +14,7 @@ #include #include "inv_icm42600.h" +#include "inv_icm42600_buffer.h" static const struct regmap_range_cfg inv_icm42600_regmap_ranges[] = { { @@ -515,6 +516,11 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, if (ret) return ret; + /* setup FIFO buffer */ + ret = inv_icm42600_buffer_init(st); + if (ret) + return ret; + /* setup interrupt trigger */ ret = inv_icm42600_trigger_init(st, irq, irq_type); if (ret) @@ -559,6 +565,16 @@ static int __maybe_unused inv_icm42600_suspend(struct device *dev) goto out_unlock; } + /* disable FIFO data streaming */ + if (iio_buffer_enabled(st->indio_gyro) || + iio_buffer_enabled(st->indio_accel)) { + /* set FIFO in bypass mode */ + ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG, + INV_ICM42600_FIFO_CONFIG_BYPASS); + if (ret) + goto out_unlock; + } + ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF, INV_ICM42600_SENSOR_MODE_OFF, false, NULL); @@ -594,6 +610,13 @@ static int __maybe_unused inv_icm42600_resume(struct device *dev) if (ret) goto out_unlock; + /* restore FIFO data streaming */ + if (iio_buffer_enabled(st->indio_gyro) || + iio_buffer_enabled(st->indio_accel)) { + ret = regmap_write(st->map, INV_ICM42600_REG_FIFO_CONFIG, + INV_ICM42600_FIFO_CONFIG_STREAM); + } + out_unlock: mutex_unlock(&st->lock); return ret; diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c index c0164ab2830e..dafb104abc77 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c @@ -10,9 +10,13 @@ #include #include #include +#include +#include +#include #include "inv_icm42600.h" #include "inv_icm42600_temp.h" +#include "inv_icm42600_buffer.h" #define INV_ICM42600_GYRO_CHAN(_modifier, _index, _ext_info) \ { \ @@ -46,6 +50,7 @@ enum inv_icm42600_gyro_scan { INV_ICM42600_GYRO_SCAN_Y, INV_ICM42600_GYRO_SCAN_Z, INV_ICM42600_GYRO_SCAN_TEMP, + INV_ICM42600_GYRO_SCAN_TIMESTAMP, }; static const struct iio_chan_spec_ext_info inv_icm42600_gyro_ext_infos[] = { @@ -61,8 +66,100 @@ static const struct iio_chan_spec inv_icm42600_gyro_channels[] = { INV_ICM42600_GYRO_CHAN(IIO_MOD_Z, INV_ICM42600_GYRO_SCAN_Z, inv_icm42600_gyro_ext_infos), INV_ICM42600_TEMP_CHAN(INV_ICM42600_GYRO_SCAN_TEMP), + IIO_CHAN_SOFT_TIMESTAMP(INV_ICM42600_GYRO_SCAN_TIMESTAMP), }; +/* IIO buffer data */ +struct inv_icm42600_gyro_buffer { + struct inv_icm42600_fifo_sensor_data gyro; + int8_t temp; + int64_t timestamp; +}; + +#define INV_ICM42600_SCAN_MASK_GYRO_3AXIS \ + (BIT(INV_ICM42600_GYRO_SCAN_X) | \ + BIT(INV_ICM42600_GYRO_SCAN_Y) | \ + BIT(INV_ICM42600_GYRO_SCAN_Z)) + +#define INV_ICM42600_SCAN_MASK_TEMP BIT(INV_ICM42600_GYRO_SCAN_TEMP) + +static const unsigned long inv_icm42600_gyro_scan_masks[] = { + /* 3-axis gyro + temperature */ + INV_ICM42600_SCAN_MASK_GYRO_3AXIS | INV_ICM42600_SCAN_MASK_TEMP, + 0, +}; + +static irqreturn_t inv_icm42600_gyro_handler(int irq, void *_data) +{ + struct iio_poll_func *pf = _data; + struct iio_dev *indio_dev = pf->indio_dev; + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + const size_t fifo_nb = st->fifo.nb.total; + int ret; + + /* exit if no sample */ + if (fifo_nb == 0) + goto out; + + ret = inv_icm42600_gyro_parse_fifo(indio_dev, pf->timestamp); + if (ret) + dev_err(regmap_get_device(st->map), "gyro fifo error %d\n", + ret); + +out: + iio_trigger_notify_done(indio_dev->trig); + return IRQ_HANDLED; +} + +/* enable gyroscope sensor and FIFO write */ +static int inv_icm42600_gyro_update_scan_mode(struct iio_dev *indio_dev, + const unsigned long *scan_mask) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; + unsigned int fifo_en = 0; + unsigned int sleep_gyro = 0; + unsigned int sleep_temp = 0; + unsigned int sleep; + int ret; + + mutex_lock(&st->lock); + + if (*scan_mask & INV_ICM42600_SCAN_MASK_TEMP) { + /* enable temp sensor */ + ret = inv_icm42600_set_temp_conf(st, true, &sleep_temp); + if (ret) + goto out_unlock; + fifo_en |= INV_ICM42600_SENSOR_TEMP; + } + + if (*scan_mask & INV_ICM42600_SCAN_MASK_GYRO_3AXIS) { + /* enable gyro sensor */ + conf.mode = INV_ICM42600_SENSOR_MODE_LOW_NOISE; + ret = inv_icm42600_set_gyro_conf(st, &conf, &sleep_gyro); + if (ret) + goto out_unlock; + fifo_en |= INV_ICM42600_SENSOR_GYRO; + } + + /* update data FIFO write and FIFO watermark */ + ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en); + if (ret) + goto out_unlock; + ret = inv_icm42600_buffer_update_watermark(st); + +out_unlock: + mutex_unlock(&st->lock); + /* sleep maximum required time */ + if (sleep_gyro > sleep_temp) + sleep = sleep_gyro; + else + sleep = sleep_temp; + if (sleep) + msleep(sleep); + return ret; +} + static int inv_icm42600_gyro_read_sensor(struct inv_icm42600_state *st, struct iio_chan_spec const *chan, int16_t *val) @@ -262,6 +359,8 @@ static int inv_icm42600_gyro_write_odr(struct inv_icm42600_state *st, mutex_lock(&st->lock); conf.odr = inv_icm42600_gyro_odr_conv[idx / 2]; ret = inv_icm42600_set_gyro_conf(st, &conf, NULL); + inv_icm42600_buffer_update_fifo_period(st); + inv_icm42600_buffer_update_watermark(st); mutex_unlock(&st->lock); pm_runtime_mark_last_busy(dev); @@ -524,12 +623,51 @@ static int inv_icm42600_gyro_write_raw_get_fmt(struct iio_dev *indio_dev, } } +static int inv_icm42600_gyro_hwfifo_set_watermark(struct iio_dev *indio_dev, + unsigned int val) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + mutex_lock(&st->lock); + + st->fifo.watermark.gyro = val; + ret = inv_icm42600_buffer_update_watermark(st); + + mutex_unlock(&st->lock); + + return ret; +} + +static int inv_icm42600_gyro_hwfifo_flush(struct iio_dev *indio_dev, + unsigned int count) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + if (count == 0) + return 0; + + mutex_lock(&st->lock); + + ret = inv_icm42600_buffer_hwfifo_flush(st, count); + if (!ret) + ret = st->fifo.nb.gyro; + + mutex_unlock(&st->lock); + + return ret; +} + static const struct iio_info inv_icm42600_gyro_info = { .read_raw = inv_icm42600_gyro_read_raw, .read_avail = inv_icm42600_gyro_read_avail, .write_raw = inv_icm42600_gyro_write_raw, .write_raw_get_fmt = inv_icm42600_gyro_write_raw_get_fmt, .debugfs_reg_access = inv_icm42600_debugfs_reg, + .update_scan_mode = inv_icm42600_gyro_update_scan_mode, + .hwfifo_set_watermark = inv_icm42600_gyro_hwfifo_set_watermark, + .hwfifo_flush_to_buffer = inv_icm42600_gyro_hwfifo_flush, }; int inv_icm42600_gyro_init(struct inv_icm42600_state *st) @@ -537,6 +675,7 @@ int inv_icm42600_gyro_init(struct inv_icm42600_state *st) struct device *dev = regmap_get_device(st->map); const char *name; struct iio_dev *indio_dev; + int ret; name = devm_kasprintf(dev, GFP_KERNEL, "%s-gyro", st->name); if (!name) @@ -553,7 +692,51 @@ int inv_icm42600_gyro_init(struct inv_icm42600_state *st) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->channels = inv_icm42600_gyro_channels; indio_dev->num_channels = ARRAY_SIZE(inv_icm42600_gyro_channels); + indio_dev->available_scan_masks = inv_icm42600_gyro_scan_masks; + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, + inv_icm42600_gyro_handler, + &inv_icm42600_buffer_ops); + if (ret) + return ret; + + indio_dev->trig = iio_trigger_get(st->trigger); st->indio_gyro = indio_dev; return devm_iio_device_register(dev, st->indio_gyro); } + +int inv_icm42600_gyro_parse_fifo(struct iio_dev *indio_dev, int64_t ts) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + const size_t gyro_nb = st->fifo.nb.gyro; + ssize_t i, size; + const void *accel, *gyro, *temp, *timestamp; + unsigned int odr; + struct inv_icm42600_gyro_buffer buffer; + + /* exit if no gyro sample */ + if (gyro_nb == 0) + return 0; + + /* parse all fifo packets */ + for (i = 0; i < st->fifo.count; i += size) { + size = inv_icm42600_fifo_decode_packet(&st->fifo.data[i], + &accel, &gyro, &temp, ×tamp, &odr); + dev_dbg(regmap_get_device(st->map), "gyro packet size = %zd\n", + size); + /* quit if error or FIFO is empty */ + if (size <= 0) + return size; + /* skip packet if no gyro data or data is invalid */ + if (gyro == NULL || !inv_icm42600_fifo_is_data_valid(gyro)) { + dev_dbg(regmap_get_device(st->map), "skip gyro data\n"); + continue; + } + memcpy(&buffer.gyro, gyro, sizeof(buffer.gyro)); + memcpy(&buffer.temp, temp, sizeof(buffer.temp)); + iio_push_to_buffers_with_timestamp(indio_dev, &buffer, ts); + } + + return 0; +} diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_trigger.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_trigger.c index 7a5e76305f0b..5667e0204722 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_trigger.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_trigger.c @@ -13,6 +13,7 @@ #include #include "inv_icm42600.h" +#include "inv_icm42600_buffer.h" static irqreturn_t inv_icm42600_trigger_timestamp(int irq, void *_data) { @@ -45,8 +46,18 @@ static irqreturn_t inv_icm42600_trigger_int_handler(int irq, void *_data) dev_warn(dev, "FIFO full data lost!\n"); /* FIFO threshold reached */ - if (status & INV_ICM42600_INT_STATUS_FIFO_THS) - iio_trigger_poll_chained(st->trigger); + if (status & INV_ICM42600_INT_STATUS_FIFO_THS) { + ret = inv_icm42600_buffer_fifo_read(st, 0); + if (ret) + dev_err(dev, "FIFO read error %d\n", ret); + } else { + st->fifo.count = 0; + st->fifo.nb.gyro = 0; + st->fifo.nb.accel = 0; + st->fifo.nb.total = 0; + } + + iio_trigger_poll_chained(st->trigger); out_unlock: mutex_unlock(&st->lock); From patchwork Thu May 7 14:42:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Baptiste Maneyrol X-Patchwork-Id: 200944 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, MSGID_FROM_MTA_HEADER, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 32E12C47247 for ; Thu, 7 May 2020 14:43:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0CDC3208D6 for ; Thu, 7 May 2020 14:43:47 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="iQC7hIwZ"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="Ayp+xS08" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727942AbgEGOng (ORCPT ); Thu, 7 May 2020 10:43:36 -0400 Received: from mx0b-00328301.pphosted.com ([148.163.141.47]:49462 "EHLO mx0b-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727857AbgEGOne (ORCPT ); Thu, 7 May 2020 10:43:34 -0400 Received: from pps.filterd (m0156136.ppops.net [127.0.0.1]) by mx0b-00328301.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 047Ebhbf006057; Thu, 7 May 2020 07:43:30 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=invensense.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : content-type : mime-version; s=pfpt1; bh=fEwmw9ER5fwbE7/630gcavOolHhI9ezXUsNWuYkyYSg=; b=iQC7hIwZ6pydHDAR0Pgm7WyUi+02kCJrJ2OKRZKWomBi+l777W8F0UzeZn3NqHnRi6yQ wSBoJHuJ4z6xKkTgMY4qK5GN5GOShYf/KCiuWi1lHFInuuRRtti1gz7jgQqlTNeZpTLq 7i9yIqhboLwVm/bho/e38fRWANpEfJX73JwP/SZo8xQR8t4JdPM16QFyrqx5s8oU8SZx dad+q+QS3JvBPFTBxOGOJXvRh2eH6eb2+/CsFtX2dlTpY+NrZpowHEeQxsf0LNQURQdg 2rQm6IOjDrCPLGWvC4K1VpEi1HGfEHekFQuUR4tTvMCBi2YQUszPCn5jQZt1oWYnhKbp 2A== Received: from nam12-mw2-obe.outbound.protection.outlook.com (mail-mw2nam12lp2040.outbound.protection.outlook.com [104.47.66.40]) by mx0b-00328301.pphosted.com with ESMTP id 30s4tnatww-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 07 May 2020 07:43:29 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=nchpGGhKnoY6rsQnliL7SilrzTPnqnNijhl5ZZUYNWRD2P3xY80vK2SsheusNFqb4V/l4CIAHgfT9FVqLh6jcUcTFIdslmApCUH6vNqlur5iGcfVFQr9tyc4zjqKsLaMMK2CJ2DiHFZdYFChOMGsJZLGrj2jmGRYgG4h5sJ/dZfvKGSidGMkR0BNKOzkg2MDwyG8HZPyq9yIBXZh/38YeL/vQdrejpSLEB3OCgI2NA7oo/QJTOtjEh8SW16Fey7qiFCmV/NcuC8Qw/smDGfR0afdDOFCqBgYwl+WyUAPYALnhuAEObeeMD9xEkgn7ci8xcZ9vrDZWgFPyNLxYnbL5A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=fEwmw9ER5fwbE7/630gcavOolHhI9ezXUsNWuYkyYSg=; b=MkdAhZwBfZ59wd4N4CMuEML6hT/iodIRYLNTjmM9qe1xdISo/Ixs2DoR5rM6FxDTG5UebKezf3RBU/DFc2YWLsCpmnV/QzBZobqZHx+8I7Wawwy9OkvTnZcLFFUpQBYPQEs99s/PoUjll12d6UUKE1YPjJIE6F63t2Vefpkn8sYZpANC2Hs2zPUTzOZ3ZFBAsRXndDVXvEFkuWPL2p+PofO5TUu/hdFL80hV+llsW4FHrSYeHVM0JDw/N02BEt16U03g930bUAyrEDlXmzIPyeLM8Evrr3lo2FEEAGwPvbaW/UVxmgJbnu5rf0LuiLfRRbCy7YHN6mu3ZcVpD+LRMw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=invensense.com; dmarc=pass action=none header.from=invensense.com; dkim=pass header.d=invensense.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=invensense.onmicrosoft.com; s=selector2-invensense-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=fEwmw9ER5fwbE7/630gcavOolHhI9ezXUsNWuYkyYSg=; b=Ayp+xS08CizKyQLVV7390d0yKAI5qQPnDCQp2wVlSoXTsK6bYfT7EvI73NJ4K3+1eykfu9GMVPE2Xm4fwFF5kQauf+WdmjvkugQStWP6/qbaJ/sbjE2ziNUp+1GTkofor7iQYXtXpMcDuWqh3xdqrmi/IohVW1V2XZKiscNttdM= Authentication-Results: kernel.org; dkim=none (message not signed) header.d=none; kernel.org; dmarc=none action=none header.from=invensense.com; Received: from MN2PR12MB4422.namprd12.prod.outlook.com (2603:10b6:208:265::9) by MN2PR12MB4501.namprd12.prod.outlook.com (2603:10b6:208:269::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2979.27; Thu, 7 May 2020 14:43:29 +0000 Received: from MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::7471:da8b:8ca1:6af0]) by MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::7471:da8b:8ca1:6af0%4]) with mapi id 15.20.2979.028; Thu, 7 May 2020 14:43:29 +0000 From: Jean-Baptiste Maneyrol To: jic23@kernel.org, robh+dt@kernel.org, robh@kernel.org, mchehab+huawei@kernel.org, davem@davemloft.net, gregkh@linuxfoundation.org Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Jean-Baptiste Maneyrol Subject: [PATCH 12/12] MAINTAINERS: add entry for inv_icm42600 6-axis imu sensor Date: Thu, 7 May 2020 16:42:22 +0200 Message-Id: <20200507144222.20989-13-jmaneyrol@invensense.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200507144222.20989-1-jmaneyrol@invensense.com> References: <20200507144222.20989-1-jmaneyrol@invensense.com> X-ClientProxiedBy: LNXP265CA0048.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:5c::36) To MN2PR12MB4422.namprd12.prod.outlook.com (2603:10b6:208:265::9) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from frgnb-buildozer.invcorp.invensense.com (77.157.193.39) by LNXP265CA0048.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:5c::36) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2979.26 via Frontend Transport; Thu, 7 May 2020 14:43:27 +0000 X-Mailer: git-send-email 2.17.1 X-Originating-IP: [77.157.193.39] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: cf2f4123-155e-41bd-d99e-08d7f295019d X-MS-TrafficTypeDiagnostic: MN2PR12MB4501: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:1079; X-Forefront-PRVS: 03965EFC76 X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 2tIfo+rg3TeQfbiJBhZNPtIM4yhSo7GvAJ9c/pPjLd26Hq+qyltQ/5A5DRP7ooVJ6R31dhD9Ugav2gZW9TQhz3l78u4X3TFgZCa+bb+XsnHPYtTyse+v0rvtJ5Su1Hd08p3zWpXgiJxfxw7EXPyaGRo6S6JJd03njyxFXu/qdAAaNf/4jCS558Jlgsp9ww2rclxVUxwVhl8Kn2k+KRQ6Otn5J4fSTbmDueDexUdAGbXXfc+oPtehSBU92pO5YrGO30KeufELtZTp9BjkwKQZ5I2s6rSR1Fc6IlM6d7uapwJfHc0TsxHY5UPjHSVWEjZPXmHgNPSPMxYT4s/v2TkEVRZ5DuOKCl1XGboipQw6xgCDshW4nlO4sFqYkrsYdzbooJkFaGL0oHzBLjuOk6eql4NUTNgKboKlRnW7+TpjCO9tigiuQqjvLU3z2hx/ZfzxLwPLlIkOAXyJcNiXATibQ3dQUIYVwPfL6jKeDXkqE3fqhS10Wf2YHa9ceV9G0zs9GadAIXTbAaKf8sL6T3Nwk0MQDwEEz85b+X6cUuqMzxl/AuuJExxemaK7FgaqyaXLSgSnBCmLt/cQjQ1PugPyIDnjAC8aJqNSu6Oj3oG1Ln0= X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:MN2PR12MB4422.namprd12.prod.outlook.com; PTR:; CAT:NONE; SFTY:; SFS:(346002)(376002)(136003)(396003)(39850400004)(366004)(33430700001)(966005)(107886003)(4326008)(8676002)(6486002)(2906002)(316002)(5660300002)(8936002)(1076003)(26005)(7696005)(33440700001)(66946007)(956004)(66476007)(52116002)(2616005)(86362001)(186003)(83320400001)(83280400001)(83310400001)(83290400001)(16526019)(478600001)(6666004)(36756003)(4744005)(66556008)(83300400001); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData: 8Finn44NzEpmZo1n6xEKRDAnLHo4LdBDVBHqwQ4QYiMD8uYcibSGOjFqqsVUrKAtQ21nl3ateOCcWDp2ewMbra6PCEYbJZ7nFq+4LpRvimO7wKjkHRSNyR98aLl/+C3QvZ5kyDLkKcyrGj+8jY8oDJdQrKuYWSOUiLGNCpZdJKHhAQfnfFxjxkDNiOvDNvpL5aQE2STOsBl3UJoTPGf3Y7GLWr87d3qEn6HDlcdV7U5Zp/pqf7fX2IPjEZeEBfMpmziaqdk0rSSXTtkq1vQxQ3vNr7NPf1z04IQGumsnlWO7Bn5DuBmRJL/ZCunidZVkKGMy5hH+CrIEyGuuJ7r7eqo0VcD8jVF1QuaT3ATPVTUbKL9ascjoeV+v+MWomk7q+84hQ2Y+4IL5rjgwJ6GpN0krjXniBYOXx+2mMlgvY1x66VWKQTVjrV2kys+hGt0EetdYmO1lXMXWKog3oeL+NF/s5M2S47S912ansZDyaC7KRa/5EAtkhuJrorRyxZ3uZKDy7OVlOdBE1EzLoCNyOEAatFR5eQ07BTQAYN4FiZjieqZjmjqe4xqyJnOvco4s791QcSzy9DgLrwiyQXP3j3zCu4sYahSY9UhnK6XrNIIpKuZIqlddRizDlyY2uGmFfOLscW/1ZgXvmEFFB170/7nHl1qTj09iIdyyz8b+AdUTWn3Ek/vugB27gLoE7lKgHfKRJDlx4Y5V4EshNBLlIgJVjahSuYDcqkqSvm+A1kZeDOF9Bh7WDVzCgxCj8DjoRsoLy+Fs3GkrD8WwDdpA3k8yxKVvG0UDcHJh/6E/v1U= X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: cf2f4123-155e-41bd-d99e-08d7f295019d X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 May 2020 14:43:29.0252 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 462b3b3b-e42b-47ea-801a-f1581aac892d X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 0gaTtrGRGO45yKmhpRN5PtKCblu0wodWVe3cP/paUxOEUvHdSjs5vTL8u+32Gp2czQxweyYagcy6w4OF1l/Z0D0sL8RLkew+4zsMtnHjEkE= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4501 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216, 18.0.676 definitions=2020-05-07_09:2020-05-07,2020-05-07 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 adultscore=0 priorityscore=1501 spamscore=0 mlxlogscore=999 impostorscore=0 suspectscore=0 phishscore=0 malwarescore=0 lowpriorityscore=0 bulkscore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2003020000 definitions=main-2005070118 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add MAINTAINERS entry for InvenSense ICM-426xx IMU device. Signed-off-by: Jean-Baptiste Maneyrol --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 10eb348c801c..1714390e2721 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8864,6 +8864,14 @@ F: include/dt-bindings/interconnect/ F: include/linux/interconnect-provider.h F: include/linux/interconnect.h +INVENSENSE ICM-426xx IMU DRIVER +M: Jean-Baptiste Maneyrol +L: linux-iio@vger.kernel.org +S: Maintained +W https://invensense.tdk.com/ +F: Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml +F: drivers/iio/imu/inv_icm42600/ + INVENSENSE MPU-3050 GYROSCOPE DRIVER M: Linus Walleij L: linux-iio@vger.kernel.org