From patchwork Mon Jun 22 15:37:17 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: 11618255 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0415160D for ; Mon, 22 Jun 2020 15:38:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CDA5E20760 for ; Mon, 22 Jun 2020 15:38:53 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="a3Ra+4Om"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="GeIfnSh9" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729655AbgFVPiI (ORCPT ); Mon, 22 Jun 2020 11:38:08 -0400 Received: from mx0b-00328301.pphosted.com ([148.163.141.47]:29754 "EHLO mx0b-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729494AbgFVPiG (ORCPT ); Mon, 22 Jun 2020 11:38:06 -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 05MFWDw5004965; Mon, 22 Jun 2020 08:37:57 -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=LY5NdeeP3Ldra1mgDwQdeSQtqJcmWkNwZWxEd8R3JOQ=; b=a3Ra+4OmuzvopwITbxIHpKGvHfAoHAAbftNEY1CZczYJF7LMSz2nJc5jTExz5ZBRb/sW AHkSI4Exv/gBUCErV7DJGGtZMvmSdUH1E0lCuAYDgOMJZeq43pvqsoHoLUSbY/+EVmmY mQ2D+8Ot6gAAjN8u8cuiImjvtkSFqxEUYJF0x7uedUFBNabp/rxiUxgPoGkIsP7Zs93f ChfKu836PINcrdhE40eyL9CbUR300JB+0zWIcK4kO5ROefYgBjP4pK/aB5twU+8XgKBz okkaPAy3RS2XlMGh3O61ql+ZrsKz77L0Qjzx/v6sCkrX1rkQPDyrVNZ8O4R2nTHUmu4Z 4Q== Received: from nam04-sn1-obe.outbound.protection.outlook.com (mail-sn1nam04lp2055.outbound.protection.outlook.com [104.47.44.55]) by mx0b-00328301.pphosted.com with ESMTP id 31sedp0ukd-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 22 Jun 2020 08:37:57 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Vf9qcz5ael6pl8kd2MczLTZXrbUrzAY6/vuWpTkY+TOUAUthumaKdlUZHLzgBaW3TkhjOiZy74/cy9TSmiWKra5mf08Eq9FW//9kJQ2agvXuDx72zH3vRlNeijZDcbclzAQ9dDy3dt9EXsLhMAr17P+UtOgzF1/PTA9mSCJOYcz4e0X21/VqWWXo7Hn9ZOAelW5SAKhkK8Wjsu5gel2MzhT2pQvXxFPBOxCgpONFj6I7S5CHYNy8Qczmv98uuF4fj/Zy+FIc9rQQtZ/nGWLkrrn5XkV3QZqLIaQGdbc3HC9O7OpR7v5DMK0Fjf1zjBkpUgOul/D+8BnYfl4O2XD+qA== 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=LY5NdeeP3Ldra1mgDwQdeSQtqJcmWkNwZWxEd8R3JOQ=; b=aIitEY1tLGZOvrKV70mSP2XkYZzWlWRRnROJUtsAvSixxZROFK4qj6KVQ6hPGQP6fn6UUmb/vpoZultgT+FS83Za7n/w/IVsqVVdXbdcETIGZVX9FJp6OUV2VfxQyqcdU70eyXI2zco36DBHJxXx+6Y4rR81u/oKswQXmV7R7J+d4zI1yXL9xS6PD6MJ2IPHiWfPhJ8gubNkLwjtyMT2agpdD9lZWh1QGnuY+/3HP7sDvAtpTd0zywZEV97AsNYb/7OoDUtDB0ucpmpUbOs1gI7sU34zA1aETHlTdVBXHAoYj11dMb8UyAc87ZsfHdK7yXpaZdvesoeYJB3UzNfBnw== 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=LY5NdeeP3Ldra1mgDwQdeSQtqJcmWkNwZWxEd8R3JOQ=; b=GeIfnSh9orBPSUcJywT3GhJReidvi3seL9W0i1ONl/G8xsP7CbWyixQILZkY8pGdBttGSufY0SS5M9Xhxwoec96YFBfa9uzOwNahxOy8PdNt5IrFSlBeCUxga5Ww/fRApkwGwEAAHXNGyn2d/PrELvf4MGKdFkCd7uMMLtTjXBY= 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.3109.22; Mon, 22 Jun 2020 15:37:55 +0000 Received: from MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0]) by MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0%7]) with mapi id 15.20.3109.027; Mon, 22 Jun 2020 15:37:55 +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 v4 01/13] iio: imu: inv_icm42600: add core of new inv_icm42600 driver Date: Mon, 22 Jun 2020 17:37:17 +0200 Message-Id: <20200622153729.12702-2-jmaneyrol@invensense.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200622153729.12702-1-jmaneyrol@invensense.com> References: <20200622153729.12702-1-jmaneyrol@invensense.com> X-ClientProxiedBy: LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) 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 LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3109.21 via Frontend Transport; Mon, 22 Jun 2020 15:37:54 +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: 283b5e5a-a0eb-43ea-0c48-08d816c23bcf X-MS-TrafficTypeDiagnostic: MN2PR12MB4501: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:211; X-Forefront-PRVS: 0442E569BC X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 5wHeyz9Hu1F+UGo9PS04ndQufJOcV3ST67fYvDTj32NB0n6QspKNgboXeUk/i9/B7YYRouE52j+erESEY8rIs7fD/3yyqpYVk4Ap7AfVxxLAbR24393RKBahngEciHWLoF68mVrTY3LDDEjZvZ2rOasZq+495S8YT3ayuriK6Z2ifmHmILPXbbBJXhgGhSKDi4QaFM0MTqID9mnyP+EL1W3IORnO+8OqbPayOfe2wQ8TrrcQIfN+g744QNy5P5tg34vz0VIp7kYha9zBh1W1iGbOuk9XSNCEFH1gZBXI7dourCDHvD0Bu6iKK/bBIzI/tbCW39aZSpDKHgOGBTBiNA== 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)(39850400004)(136003)(366004)(396003)(4326008)(66946007)(7696005)(52116002)(8676002)(66476007)(66556008)(956004)(2616005)(1076003)(83380400001)(107886003)(86362001)(36756003)(30864003)(478600001)(6486002)(6666004)(26005)(316002)(8936002)(16526019)(5660300002)(2906002)(186003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: Z/XW4Xh+CBLtV2KPSukrs+g1o+h5ot7GRVoz9Z2oeYrytRf/0AaB67Muwsj6UQwoavDJxADFGbpiMT/Gg5k3tSWbngHp79ohNJOUcCZ3Rwa0c9cHXS2Ux994+Dq6UQcEZuU4md1VkJE3wl/O8wIhZlUd5NcWsW+U/zDAHiNHe4+hHoSp8GkOxgzqouhX/4hPAInsFT7tU3A/xOkmblbejbYU7ZJtEXpKiXZtmFO3/WmailhFc1gl6yT/e7mCaQfIrD2DozlV1WQtORshhyYnHP6xMg/+oDFTmqTTc9xBNE9zob3fIQpggRylGF8X4n7GiT29gLbrv8FMF12nuDVQIQ33TWpOrzlpo4/YB4zquQFn0eu3p0Vg9xQ3+H+oJwuoP6Gm3StaK3CuTLabzwO+gSsGDN9b0/hPB4KCatkCRss4FWMSyHYd16ZpMfm2c4uVTKcLQkfAOs7nREq1PaTmYpWC25RUy4fMZ3BymoLY+u0= X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: 283b5e5a-a0eb-43ea-0c48-08d816c23bcf X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Jun 2020 15:37:55.8594 (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: gfPmEo6PMgtJk28mbmU+CZsj3Hf2hKR7oqYvfq/d4o24zUjdhtZMBgJpFBjMUF53WvSSicd5rMyLBvJyoykizFYoU/Cte0gLJ4EMA5SvtbY= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4501 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216,18.0.687 definitions=2020-06-22_09:2020-06-22,2020-06-22 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 clxscore=1015 adultscore=0 mlxlogscore=999 spamscore=0 mlxscore=0 lowpriorityscore=0 phishscore=0 priorityscore=1501 bulkscore=0 cotscore=-2147483648 malwarescore=0 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006220116 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@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 | 634 ++++++++++++++++++ 2 files changed, 1006 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..14c8ef152418 --- /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: lock for serializing multiple registers access. + * @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_ms); + +int inv_icm42600_set_gyro_conf(struct inv_icm42600_state *st, + struct inv_icm42600_sensor_conf *conf, + unsigned int *sleep_ms); + +int inv_icm42600_set_temp_conf(struct inv_icm42600_state *st, bool enable, + unsigned int *sleep_ms); + +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..2eb25c5f77f8 --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c @@ -0,0 +1,634 @@ +// 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" + +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_NB] = { + [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(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_ms) +{ + 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; + 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_ms) + *sleep_ms = 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_ms) +{ + 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); + 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); + 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_ms); +} + +int inv_icm42600_set_gyro_conf(struct inv_icm42600_state *st, + struct inv_icm42600_sensor_conf *conf, + unsigned int *sleep_ms) +{ + 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); + 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); + 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_ms); + + return 0; +} + +int inv_icm42600_set_temp_conf(struct inv_icm42600_state *st, bool enable, + unsigned int *sleep_ms) +{ + return inv_icm42600_set_pwr_mgmt0(st, st->conf.gyro.mode, + st->conf.accel.mode, enable, + sleep_ms); +} + +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 + * @st: driver internal state + * @bus_setup: callback for setting up bus specific registers + * + * Returns 0 on success, a negative error code otherwise. + */ +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 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; + } + 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) */ + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0, + INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN, + INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN); + 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_vdd_reg(void *_data) +{ + struct inv_icm42600_state *st = _data; + const struct device *dev = regmap_get_device(st->map); + int 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_vddio_reg(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); +} + +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; + + 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 = devm_add_action_or_reset(dev, inv_icm42600_disable_vdd_reg, st); + if (ret) + return ret; + + ret = inv_icm42600_enable_regulator_vddio(st); + if (ret) + return ret; + + ret = devm_add_action_or_reset(dev, inv_icm42600_disable_vddio_reg, 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); + +/* + * Suspend saves sensors state and turns everything off. + * Check first if runtime suspend has not already done the job. + */ +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; +} + +/* + * System resume gets the system back on and restores the sensors state. + * Manually put runtime power management in system active state. + */ +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; +} + +/* Runtime suspend will turn off sensors that are enabled by iio devices. */ +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; +} + +/* Sensors are enabled by iio devices, no need to turn them back on here. */ +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 Mon Jun 22 15:37: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: 11618265 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2CAD860D for ; Mon, 22 Jun 2020 15:39:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0EAAF2074D for ; Mon, 22 Jun 2020 15:39:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="IxgputHS"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="bcxhBcgJ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729563AbgFVPiC (ORCPT ); Mon, 22 Jun 2020 11:38:02 -0400 Received: from mx0a-00328301.pphosted.com ([148.163.145.46]:49866 "EHLO mx0a-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729444AbgFVPiB (ORCPT ); Mon, 22 Jun 2020 11:38:01 -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 05MFa4C6021446; Mon, 22 Jun 2020 08:37:59 -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=+jiMf8sqcLDdqCWqdv5GNr9Gk062vMMjfJOvpD2p59M=; b=IxgputHStiLFZYyJ1ETCr3q7u0cHydS9FUAPyRtppueuNzekUAQAbQxIbpG4EK1hfSze WhXv7XcqExLO6drf8dmuh5tiw9MwDyk/Ci6P7lY4IGSnDlhDYvR6FhVa0RgYOZ6/qFpl cn7yP9yxML9HrrFq9cufwV3Z+akqajcETVu2g2UgDwCcXQdUopXtfZO1n6mXDGUASSEU rmLixXR3TGyYs7yUqXBW+suBMwQg5qkCwVH6TtXrvtTOfCaj7ee9U5YoVy9UlYN9x4y/ r03ekWPOOJF5uEec2tkObs0iKzHJlHifHbxsIPW+oFEop9SvPD3HGQFEtyb26lumSGLt xg== Received: from nam04-sn1-obe.outbound.protection.outlook.com (mail-sn1nam04lp2054.outbound.protection.outlook.com [104.47.44.54]) by mx0a-00328301.pphosted.com with ESMTP id 31sdxnrtxw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 22 Jun 2020 08:37:59 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=OGWGlREWvEoqu4iGWETqWCfcJ0ynCe0Il7oE9Ne7xdNnuSolxFv/tOpKNdevnjJ2PNenLKpJf0MApShm4fpzZYKVYji6Wpq0h7UReFRtI+RWkgiLvPk54Ams9R0e9+VkqLjxGR/S6GjLLL+esFW7QpPqIb+vpVtZdc2NFzYmaV3pFFJspFgB40i68knBgjmmKb+vFlQg/VNYCctEfE5oVS8ZWKqqr5KZmR5HW1O9MVq8htF4GmchaU4VeA32hTe1NrWm/nMb0Rz2lePkZEOIKXUNUSidkpyW3n/ecRO8IT+5vt+3TEYVH/mHPSCsWbc/8pggMfcJBP0IShFzbuOG0w== 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=+jiMf8sqcLDdqCWqdv5GNr9Gk062vMMjfJOvpD2p59M=; b=luPeIYeTGrEa9gfnjiNV8u1gCsHjnWlxaB3wJpfgYQpEQeuyvI/l4qk0ZTzhlATyqyC0xChOSCbEGP7C1roxdMjVYDHF/mWw8glvyq5jvDMsaGL/MPlNWKPBFy8vnbISoXv1nCStxcBdK+v2ME/T2bRUFWZM2SReIDwjV1jMaIGVdhUKAUe3l3O1H55vbofNx1QCnGFF2Npa2p68XvJ4kMypTXV9R3dN7TRE0spwHfq34W8S43rhJenbVHU0bHGBqV4QI5HAEssWX3/5a4YWuKWBMzjcdpG6HH+SlxlTpMQ1bOV7OEP8aVATBC/OQBHw9Zi+bI9hNNZ/yy2yGpoT9w== 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=+jiMf8sqcLDdqCWqdv5GNr9Gk062vMMjfJOvpD2p59M=; b=bcxhBcgJHJyIoXZ0AN1kjTk+WH2NAarDMONF8h83GQkb7Xk+OosHRXG2R9oskIBr1zB503CjPl0ozEoEc5liB56x5rqN0XXoVUXO/BJ66k2gcWxvjlV/dmfp+4nSoJoeZGiHQOpfuuDdUbqlValiCs4QDeog35wgeKebjY/hJGk= 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.3109.22; Mon, 22 Jun 2020 15:37:57 +0000 Received: from MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0]) by MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0%7]) with mapi id 15.20.3109.027; Mon, 22 Jun 2020 15:37:57 +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 v4 02/13] iio: imu: inv_icm42600: add I2C driver for inv_icm42600 driver Date: Mon, 22 Jun 2020 17:37:18 +0200 Message-Id: <20200622153729.12702-3-jmaneyrol@invensense.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200622153729.12702-1-jmaneyrol@invensense.com> References: <20200622153729.12702-1-jmaneyrol@invensense.com> X-ClientProxiedBy: LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) 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 LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3109.21 via Frontend Transport; Mon, 22 Jun 2020 15:37:56 +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: f867b15a-5430-4bab-9b4a-08d816c23cd8 X-MS-TrafficTypeDiagnostic: MN2PR12MB4501: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:843; X-Forefront-PRVS: 0442E569BC X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: ZHjCUouwXIitHhhao1hW2N0gdxvjEEUXeabIcO47YrBsztHDo+olLXFjkvtp1BPqeD7FvhCyqTvM4x3NqR1UrjVVBcV+x1fDWleV3spyCRoZbuYvqQPT9wP1ls66RBGPn6EBNaBvg8reC+50WnwAAy+xMzv2cEBA9/9fDW5iBnLUFkOHweiQIMoEy7ytyTdkgl6fLkIykUjoeElkftT0Wb1ZoCTJgNkcfxRDQHMPx7wthvfl0ZlKIm4uY1BejFWjc3Q4A++pXsKp91mDjk+3blhPrKAzch158xwFQynXB7aMSAewz2A4ebnkvwWbwkCYyPhPnh0npCGy3v7mMye+sg== 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)(39850400004)(136003)(366004)(396003)(4326008)(66946007)(7696005)(52116002)(8676002)(66476007)(66556008)(956004)(2616005)(1076003)(83380400001)(107886003)(86362001)(36756003)(478600001)(6486002)(6666004)(26005)(316002)(8936002)(16526019)(5660300002)(2906002)(186003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: K2GkLKvVi0slqp9lkmxSRQuoYfZpYLOYwhtlisWwVYc+Q5MI3mffSe8q1/wHEy6SAO4BqGC6UHSZIytsoXvdCo2kc+pBRM18nD3cJmFjdquJuP41tGZwB4S6UOv8sUteP7cd88ovfxtqsy3icQu/9vs2Phn+/GgXe60XVUsdvPvzuZ0lFum6g0zslTTE0zNTtxAduzvZorRaMad7X3nLphziBS31EW+BaM+d129+DsemtuV2WCfSMlzIGL7UHNJIpgH5p6jNRccQgyl8WzKdAZa1eweOXJw9XnCFLjb7QxxSf5xwhupTYZhBUfgCw9JbDQSjwQ1D/UuosVTv+zPIa1uop5IyIiI1Lef+oPBEH8SQUVFI3r0Zh0yL3IOyUUVK/7vy87w0yw1gN0K6JPQnQf1PBfNZKBjUbU6t42/HP+orepTMAC5O16PHETE7btITK90YLfSxy37JWPyOT/ANqvYW5e8w6umOfClN2fhujys= X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: f867b15a-5430-4bab-9b4a-08d816c23cd8 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Jun 2020 15:37:57.5072 (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: XSzwqBAHZVScaeLjHd7QY1h3AFQws9YFI4o3uv6C/11PD8wqNUl03oPyyElRK+hhVq2E6zqxw70CvzRtXHB4S/G1YkTad2uBqDrmC8iUjCk= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4501 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216,18.0.687 definitions=2020-06-22_09:2020-06-22,2020-06-22 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 mlxscore=0 phishscore=0 clxscore=1015 bulkscore=0 cotscore=-2147483648 suspectscore=0 impostorscore=0 spamscore=0 mlxlogscore=999 malwarescore=0 adultscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006220116 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add I2C driver for InvenSense ICM-426xxx devices. Configure bus signal slew rates as indicated in the datasheet. Signed-off-by: Jean-Baptiste Maneyrol --- .../iio/imu/inv_icm42600/inv_icm42600_i2c.c | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c new file mode 100644 index 000000000000..4789cead23b3 --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 InvenSense, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "inv_icm42600.h" + +static int inv_icm42600_i2c_bus_setup(struct inv_icm42600_state *st) +{ + unsigned int mask, val; + int ret; + + /* setup interface registers */ + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6, + INV_ICM42600_INTF_CONFIG6_MASK, + INV_ICM42600_INTF_CONFIG6_I3C_EN); + if (ret) + return ret; + + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4, + INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY, 0); + if (ret) + return ret; + + /* set slew rates for I2C and SPI */ + mask = INV_ICM42600_DRIVE_CONFIG_I2C_MASK | + INV_ICM42600_DRIVE_CONFIG_SPI_MASK; + val = INV_ICM42600_DRIVE_CONFIG_I2C(INV_ICM42600_SLEW_RATE_12_36NS) | + INV_ICM42600_DRIVE_CONFIG_SPI(INV_ICM42600_SLEW_RATE_12_36NS); + ret = regmap_update_bits(st->map, INV_ICM42600_REG_DRIVE_CONFIG, + mask, val); + if (ret) + return ret; + + /* disable SPI bus */ + return regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0, + INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK, + INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_SPI_DIS); +} + +static int inv_icm42600_probe(struct i2c_client *client) +{ + const void *match; + enum inv_icm42600_chip chip; + struct regmap *regmap; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) + return -ENOTSUPP; + + match = device_get_match_data(&client->dev); + if (!match) + return -EINVAL; + chip = (enum inv_icm42600_chip)match; + + regmap = devm_regmap_init_i2c(client, &inv_icm42600_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return inv_icm42600_core_probe(regmap, chip, inv_icm42600_i2c_bus_setup); +} + +static const struct of_device_id inv_icm42600_of_matches[] = { + { + .compatible = "invensense,icm42600", + .data = (void *)INV_CHIP_ICM42600, + }, { + .compatible = "invensense,icm42602", + .data = (void *)INV_CHIP_ICM42602, + }, { + .compatible = "invensense,icm42605", + .data = (void *)INV_CHIP_ICM42605, + }, { + .compatible = "invensense,icm42622", + .data = (void *)INV_CHIP_ICM42622, + }, + {} +}; +MODULE_DEVICE_TABLE(of, inv_icm42600_of_matches); + +static struct i2c_driver inv_icm42600_driver = { + .driver = { + .name = "inv-icm42600-i2c", + .of_match_table = inv_icm42600_of_matches, + .pm = &inv_icm42600_pm_ops, + }, + .probe_new = inv_icm42600_probe, +}; +module_i2c_driver(inv_icm42600_driver); + +MODULE_AUTHOR("InvenSense, Inc."); +MODULE_DESCRIPTION("InvenSense ICM-426xx I2C driver"); +MODULE_LICENSE("GPL"); From patchwork Mon Jun 22 15:37: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: 11618239 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E21F790 for ; Mon, 22 Jun 2020 15:38:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id BE1832073E for ; Mon, 22 Jun 2020 15:38:05 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="BkxwiGta"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="KH4lzREU" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729605AbgFVPiE (ORCPT ); Mon, 22 Jun 2020 11:38:04 -0400 Received: from mx0a-00328301.pphosted.com ([148.163.145.46]:51456 "EHLO mx0a-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729539AbgFVPiC (ORCPT ); Mon, 22 Jun 2020 11:38:02 -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 05MFaviq023511; Mon, 22 Jun 2020 08:38:00 -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=yobIXnKmHVtQN55oixDDsZx17pu/hx9Y5m9OJf2mIOA=; b=BkxwiGta2O63HOavmOs9pPiDbYIF4BewDnimn6GJoc5BBYwZEE2M5PbusT/zniPHcfEw Oc63rcvSLhxPm4BdcNArE612TMzP+HavRUk0g0H9fhRVAsY1RtvkWYpigJK1LJdYrWf0 dnogql4G7FbZb44e+ZXAMsotKM9EN3N4L+F3sGxtPFjCOXuH3fmvVh2IPSawIvn0HUn5 wthhW9qmqaWbjApeR6ThejZxjRhc0XVx4XqwDRH6y39WY33vSl72OiiGHApba06WGkV7 KPpWqOubRvtXOl8DiGO5rS3koQZugPISmBv31OjzfkGct6fx8L0CDigZxCnfgFaT+jse cA== Received: from nam04-sn1-obe.outbound.protection.outlook.com (mail-sn1nam04lp2057.outbound.protection.outlook.com [104.47.44.57]) by mx0a-00328301.pphosted.com with ESMTP id 31sdxnrtxx-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 22 Jun 2020 08:38:00 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=nFtRVxNmM24Clyb9Y2gaLTBqW7W3lnzFuCgwYemFXNFx+B7TfTbJw5z6znAMKAUKJlznaJoLXAV5KB6MfM6RC4NGCMhWBC1OUHAvACJVxICKHOHZLQcXGKTkxqryLReDSeYGUm/kOPK5a5tZwAGBLMu6hzLESlEDhKVT26y3ia680HbTmAdssQYrnbTIixuJ6aRZEkZQ34XotoK9PrdPwurTrwxVlVF6nQ2CrWRzeyJAHJl6YNvje9wZsuZJy05kCHz3liDjuHExayNJ/uf8ie6LAw3UtV1C4JQJy4QT+V7HIdwvqy+Kz+extzccqq6s9AjtqoV7nwx2BMXCtvOWvA== 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=yobIXnKmHVtQN55oixDDsZx17pu/hx9Y5m9OJf2mIOA=; b=XMY4FEVenYnSAMOjHQjxpAv2fMqG8GmFA1vjGID8suUwh6Q6TWlJ1mpT3ZWMgHbr4965ok5Z6V4QlDuhcxLmd8nuk7rJxnSx02FZCDc7AagElg1MO857rzxQA9AJPjF/3GyrJ5GsNPF47c3tmEM/0Q4AkDzBp15ff2cLs+I6ameN6yVExUk5Yg1T6iTErhHD3VTPKcYFfJlOgeTHb09OpqCFnzQVLzSSMYgowsTdt7U/DeDf1r+ijqasX17y0ZCY2MMVz9Epr9CrLu7IgNHKf+sVTmU2cMsNMJMpkZAOI41adB3lwtKDPcit+eAb7pUaIF+c8vA123CEPcXFH3O8rg== 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=yobIXnKmHVtQN55oixDDsZx17pu/hx9Y5m9OJf2mIOA=; b=KH4lzREUsYUK0A0Xex1FrBxCwB6NukacPewM6gE4ST9m/GfCS9daO0vkhhnmMJ45ta0aPN57gSHvaI05mUmvr1DBy8JrN4av9bY1GqM6ejUJ2xEzdYn/a+N5V0z9ebejDK87XX84uboUPJe1mlqY9wPI7X5l5mw01oXxUAH5olA= 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.3109.22; Mon, 22 Jun 2020 15:37:59 +0000 Received: from MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0]) by MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0%7]) with mapi id 15.20.3109.027; Mon, 22 Jun 2020 15:37:59 +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 v4 03/13] iio: imu: inv_icm42600: add SPI driver for inv_icm42600 driver Date: Mon, 22 Jun 2020 17:37:19 +0200 Message-Id: <20200622153729.12702-4-jmaneyrol@invensense.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200622153729.12702-1-jmaneyrol@invensense.com> References: <20200622153729.12702-1-jmaneyrol@invensense.com> X-ClientProxiedBy: LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) 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 LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3109.21 via Frontend Transport; Mon, 22 Jun 2020 15:37:57 +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: 75f20469-9b8e-43bf-9816-08d816c23dd8 X-MS-TrafficTypeDiagnostic: MN2PR12MB4501: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:843; X-Forefront-PRVS: 0442E569BC X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: gOemBcCU9wbFh3qYX33ArjNQBa7A5NDNiST6Bat0pPw0JGl0SfyKFGTzr7Oy/XCZQgYpDfnkCLzdAGEMFFEKmtIXtLdYohFSr+73coVYbTE/KGwyqc4d8IPayq2ol3JhRgz/CnKjYtHlIs7r0BXcTPx+4tSjZ1amQlCNe5pUGBsb3dr/fGwmva7EtsObLEblT+l1Qd3cNhfZgQvB9BjPeF9bMd1kMJ/eScfqybErAWjsyQVKDI+2zoOUaTfK/QjIZk/m2atK0Qvh+t3Bb1Nw6tvQN7VIrLJgdBqjgk595nw0XW8/eEbNNTcq64tk06TwZOfq6GzxFDnQ2AmwniyiwQ== 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)(39850400004)(136003)(366004)(396003)(4326008)(66946007)(7696005)(52116002)(8676002)(66476007)(66556008)(956004)(2616005)(1076003)(83380400001)(107886003)(86362001)(36756003)(478600001)(6486002)(6666004)(26005)(316002)(8936002)(16526019)(5660300002)(2906002)(186003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: 9JhKM/feFZLAXou9+F0mi+J0BQKsoo16O1zdUYJuLINNjvS/M1CGAIHCopnSS7jwaGUrQ0LADJAj1qT2oWWBulKxUf41IqQUtLyZxK3Gc90U+t7ovKf4F4YuuXwWCh7dAGQUU6ILwVwrWzAKEaGUvtMeqsp4FGGsI1KGwgglEe3yH0RFlcJIU94exdFuKQvElDO+0jVh0uC3Fm+FNkVho1sgR4o5XpB5c/Qels0UUVgTFgWwqBM0gfVrm4MXkw9OZlxPS8guJwMuHyepH/ogjrZz0Op20/lGuL9KSbaPZcDOpeVhkZqY6FaYW0Eh14lhyMdl1dGvTT2VDur4I0N6kLvxCALKbyxtUlYEVpQUFqz7jTxGegRGVASClyZiwJ5hGvvLjnLjlJRhXxqACLen11Q7c5k/6RN0yYW6RSiL4UJYEmYCRgwt2C92aCyP7hC8izfVMRDM5ZKHCs64ubjwTuIAMM6kTkMdMNtTOEVyFR8= X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: 75f20469-9b8e-43bf-9816-08d816c23dd8 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Jun 2020 15:37:59.1529 (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: zQP/E0zSgeg/fX29jIN8pc0cc7sLC1wmbitJoBejVgyBM+bN8VL6F/TDCKk2HZNutIcr3VajvLRVSd+8rWKyX+P0XdD92Ru2pbs2QJMdcBk= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4501 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216,18.0.687 definitions=2020-06-22_09:2020-06-22,2020-06-22 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 mlxscore=0 phishscore=0 clxscore=1015 bulkscore=0 cotscore=-2147483648 suspectscore=0 impostorscore=0 spamscore=0 mlxlogscore=999 malwarescore=0 adultscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006220116 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add SPI driver for InvenSense ICM-426xxx devices. Configure bus signal slew rates as indicated in the datasheet. Signed-off-by: Jean-Baptiste Maneyrol --- .../iio/imu/inv_icm42600/inv_icm42600_spi.c | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c new file mode 100644 index 000000000000..a9c5e2fdbe2a --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 InvenSense, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "inv_icm42600.h" + +static int inv_icm42600_spi_bus_setup(struct inv_icm42600_state *st) +{ + unsigned int mask, val; + int ret; + + /* setup interface registers */ + val = INV_ICM42600_INTF_CONFIG6_I3C_EN | + INV_ICM42600_INTF_CONFIG6_I3C_SDR_EN | + INV_ICM42600_INTF_CONFIG6_I3C_DDR_EN; + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6, + INV_ICM42600_INTF_CONFIG6_MASK, val); + if (ret) + return ret; + + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4, + INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY, 0); + if (ret) + return ret; + + /* set slew rates for I2C and SPI */ + mask = INV_ICM42600_DRIVE_CONFIG_I2C_MASK | + INV_ICM42600_DRIVE_CONFIG_SPI_MASK; + val = INV_ICM42600_DRIVE_CONFIG_I2C(INV_ICM42600_SLEW_RATE_20_60NS) | + INV_ICM42600_DRIVE_CONFIG_SPI(INV_ICM42600_SLEW_RATE_INF_2NS); + ret = regmap_update_bits(st->map, INV_ICM42600_REG_DRIVE_CONFIG, + mask, val); + if (ret) + return ret; + + /* disable i2c bus */ + return regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0, + INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK, + INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS); +} + +static int inv_icm42600_probe(struct spi_device *spi) +{ + const void *match; + enum inv_icm42600_chip chip; + struct regmap *regmap; + + match = device_get_match_data(&spi->dev); + if (!match) + return -EINVAL; + chip = (enum inv_icm42600_chip)match; + + regmap = devm_regmap_init_spi(spi, &inv_icm42600_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return inv_icm42600_core_probe(regmap, chip, inv_icm42600_spi_bus_setup); +} + +static const struct of_device_id inv_icm42600_of_matches[] = { + { + .compatible = "invensense,icm42600", + .data = (void *)INV_CHIP_ICM42600, + }, { + .compatible = "invensense,icm42602", + .data = (void *)INV_CHIP_ICM42602, + }, { + .compatible = "invensense,icm42605", + .data = (void *)INV_CHIP_ICM42605, + }, { + .compatible = "invensense,icm42622", + .data = (void *)INV_CHIP_ICM42622, + }, + {} +}; +MODULE_DEVICE_TABLE(of, inv_icm42600_of_matches); + +static struct spi_driver inv_icm42600_driver = { + .driver = { + .name = "inv-icm42600-spi", + .of_match_table = inv_icm42600_of_matches, + .pm = &inv_icm42600_pm_ops, + }, + .probe = inv_icm42600_probe, +}; +module_spi_driver(inv_icm42600_driver); + +MODULE_AUTHOR("InvenSense, Inc."); +MODULE_DESCRIPTION("InvenSense ICM-426xx SPI driver"); +MODULE_LICENSE("GPL"); From patchwork Mon Jun 22 15:37:20 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: 11618259 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1DD4190 for ; Mon, 22 Jun 2020 15:38:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EE25D20760 for ; Mon, 22 Jun 2020 15:38:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="FlkiNypq"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="FjDNJfhW" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729877AbgFVPix (ORCPT ); Mon, 22 Jun 2020 11:38:53 -0400 Received: from mx0a-00328301.pphosted.com ([148.163.145.46]:54794 "EHLO mx0a-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729444AbgFVPiH (ORCPT ); Mon, 22 Jun 2020 11:38:07 -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 05MFa4C7021446; Mon, 22 Jun 2020 08:38:03 -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=JIkqp9s/Sl5PfSgpALjiZFm+rdbKd6fIXw3v6jjwm10=; b=FlkiNypqEkPiF6qlZA5/N9zonh7n1Ws/gh84N2Afwoy+Qfxr0ag+cOYwsjCdPHB1I4ji vLV81t+l43MaEySQoj0DCZZZlNNGjqK/l4M9SDqyEVcNscr6Vkb7FvmLv57ZaSuwHBCD ijjBij94RWZaXKLJVNrYXLn69Q5wrvIqTwuDqpmPa2gdxWXouu2OOLh8cQiF8om+thRu NerN3jlZVtDuzF4ceKiPRuOPUhCpRnrjDiSK6vKyp3oE453RPcISmG7rVHiyfg+dP55p U3/VB8XrVywdlFXhdYE1Kw7hAOSbCYhnGQlLYldmMi8FSVqKWc/tvanekCMcwIkU4+qf Ew== Received: from nam04-sn1-obe.outbound.protection.outlook.com (mail-sn1nam04lp2059.outbound.protection.outlook.com [104.47.44.59]) by mx0a-00328301.pphosted.com with ESMTP id 31sdxnrtxy-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 22 Jun 2020 08:38:02 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=gXFuWZ1VBxXxhOXm0tMst6MBMB7PYTDpwdSq7/ZU398tbx30eKVb943I8j8djNUnBSKKNj0J+ZeuwQPliEHCp68DlCj+JVJ1W5mXZkSWrH4rDVK96DBirv0Uj6Z+Unlsd9HKq8S6W/pWnSspt2xSrGcre91X7EK/n7v2oUNPzgLjSLkT3RBK2vqPGKfNYbzwxAisRDou4xf9OR4z14gTYfZOBUNxo7Bkk4galoXrKEE/NPWrQxsQFmZVY5aIQL0VIehzJehxLsNiStpVOnl2nqO/1W+7tX3xDU3MLSrY2hF8SkSm4MkxD60EQ6WvlEAjSg/NdcrVPMmO275hIeGo9Q== 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=JIkqp9s/Sl5PfSgpALjiZFm+rdbKd6fIXw3v6jjwm10=; b=O/jJYho9tNrbhLFBG7XrIsbP6Ekp1+N45elzxSrM1/iLuCEjn5Am6Bq4NWe1zWDKj/9WRaq1Ou5mwd/nToUuMLeSJOUZqMqpd9mDBeFzSvC/82vH1ywvZlHBX7JfhHsoJOxXN6b8HSqFQn2mzTMRgth3MhxQqN2NXriEh1+uQkUkO/tYcFUowhzHPV+91V8+UjUZeFqEZKXWnTeAAiO1OH2ymYZSv9b3wq0zZDT4ckCGfcvYaWQd5li9nrpeeZKVqImFcIkE/f5mvRvFsKGD9RONuE9sljP2cUXSBxDJvvQ4Aj1nfsnant2nV3jKDgPvQKbRdM4fALGj6qPx79gsCA== 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=JIkqp9s/Sl5PfSgpALjiZFm+rdbKd6fIXw3v6jjwm10=; b=FjDNJfhWaLoTBuER2H2LIksy1X77jDn8MOTEXCP7fJWSSVUW3LEb6/ePdhoGOgnIGy1MQM73FFVFvMzsEeTRpLu/pgJo4a0ciicKX128S1TlM2d8uXPhs1VwdMxxdBuuePVizK4AR4QmvgCllnFRwB2BQZcs7Ggv/elu6g5ySlA= 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.3109.22; Mon, 22 Jun 2020 15:38:01 +0000 Received: from MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0]) by MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0%7]) with mapi id 15.20.3109.027; Mon, 22 Jun 2020 15:38:00 +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 v4 04/13] iio: imu: inv_icm42600: add gyroscope IIO device Date: Mon, 22 Jun 2020 17:37:20 +0200 Message-Id: <20200622153729.12702-5-jmaneyrol@invensense.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200622153729.12702-1-jmaneyrol@invensense.com> References: <20200622153729.12702-1-jmaneyrol@invensense.com> X-ClientProxiedBy: LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) 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 LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3109.21 via Frontend Transport; Mon, 22 Jun 2020 15:37:59 +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: fd1f3df2-a95f-458f-671b-08d816c23ece X-MS-TrafficTypeDiagnostic: MN2PR12MB4501: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:409; X-Forefront-PRVS: 0442E569BC X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 7eGj6aoSYjafI70Hv7AXt7v/SnEohBQHjBMO0KDPvunJxYbArApsPqgXWL5vZ+C0umX7JVf/kRpZevWs2/wNvHx52clrVKOB5+qPtEKqaMlAbXrY2nhJdQRArbF7aUkVCu9RAdXh9/YA2ClFUNovviGtrqZ5UABngeUlubwRsK9MQ6QdeBKAb+TZTzf80Gh7sFN41D70se0DBFQCrDqkOP5HWeS6d+hb3EoUtHnJAJ91m1ahHTvJg9oQTr7L0iUQWicaFEdMyrLDLu6OsW9HO1+PWHV/3NuScyjKKz6M/dbbicY1U82lQzraTvOs8Kpy8aXPRt9LEt+xrORreVs3gg== 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)(39850400004)(136003)(366004)(396003)(4326008)(66946007)(7696005)(52116002)(8676002)(66476007)(66556008)(956004)(2616005)(1076003)(83380400001)(107886003)(86362001)(36756003)(30864003)(478600001)(6486002)(6666004)(26005)(316002)(8936002)(16526019)(5660300002)(2906002)(186003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: sxXQ2mSSPGzsPtAVWYSD0l/qJWXzhEUVwJISwFu4eEyWVvpbYIdg8Pkv6Jzzx+EwpKFz4jFx9PGemc5B8I45WTndF2dIQB37OoDQ0o/UDoQ9+l/9yJxrew9TNjkVEXlbM7waK0xVNriF0pEoF1KoABsUXGxeHfh9mpLpqXL6NqyFiN6sjjj/nv7NNisiOyTg/7TDngASD9Z1mkJpNhMihfgY9/tjvM0wrxdpZJjsXGNsCU/aG0+ytvg+bMhiSCjfYjMy1+kb8XLdOIvHB8ywdO0hAej/gU0R/HG6HPsow8S7LM1kq4V1sazJxd1l2im7IgAxPV/WrS2LAFEzMSYLbDPS1W44YL47t67xtNKuIjWIgyqNuXKzTVzWpdt8mOUiGkSe22oGfe/ijYyPrAXU/5b7gAOFRj2fTGqsKrOIsFZyIoce+gcq2z3lB575rw4OF02kuvKt4RsQOCvlot2JNluXCxQu132RTnOoe22EUO8= X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: fd1f3df2-a95f-458f-671b-08d816c23ece X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Jun 2020 15:38:00.8405 (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: /1/S0qpQ/OKJ4VT5lcAlEYZo9GFgnJmyFjI3kvUedL95MiTXIA9krHGigMJsqcs18L35Akwzod1yvZLCd3kkPKeOLDkggawcQZZ3Xw7kqqo= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4501 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216,18.0.687 definitions=2020-06-22_09:2020-06-22,2020-06-22 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 mlxscore=0 phishscore=0 clxscore=1015 bulkscore=0 cotscore=-2147483648 suspectscore=0 impostorscore=0 spamscore=0 mlxlogscore=999 malwarescore=0 adultscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006220116 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@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 | 6 + .../iio/imu/inv_icm42600/inv_icm42600_core.c | 4 + .../iio/imu/inv_icm42600/inv_icm42600_gyro.c | 603 ++++++++++++++++++ 3 files changed, 613 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 14c8ef152418..d155470d770a 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h @@ -120,6 +120,8 @@ 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. + * @buffer: data transfer buffer aligned for DMA. */ struct inv_icm42600_state { struct mutex lock; @@ -131,6 +133,8 @@ struct inv_icm42600_state { struct iio_mount_matrix orientation; struct inv_icm42600_conf conf; struct inv_icm42600_suspended suspended; + struct iio_dev *indio_gyro; + uint8_t buffer[2] ____cacheline_aligned; }; /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */ @@ -369,4 +373,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); +struct iio_dev *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 2eb25c5f77f8..84e9ff320b3b 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c @@ -509,6 +509,10 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, if (ret) return ret; + st->indio_gyro = inv_icm42600_gyro_init(st); + if (IS_ERR(st->indio_gyro)) + return PTR_ERR(st->indio_gyro); + /* 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..3875ecbee67e --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c @@ -0,0 +1,603 @@ +// 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" + +#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) | \ + BIT(IIO_CHAN_INFO_CALIBBIAS), \ + .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, \ + .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 */ + data = (__be16 *)&st->buffer[0]; + ret = regmap_bulk_read(st->map, reg, data, sizeof(*data)); + if (ret) + goto exit; + + *val = (int16_t)be16_to_cpup(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; + + idx = st->conf.gyro.fs; + + *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; + + conf.fs = idx / 2; + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + 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; + + odr = st->conf.gyro.odr; + + 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; + + conf.odr = inv_icm42600_gyro_odr_conv[idx / 2]; + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + 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; +} + +/* + * Calibration bias values, IIO range format int + nano. + * Value is limited to +/-64dps coded on 12 bits signed. Step is 1/32 dps. + */ +static int inv_icm42600_gyro_calibbias[] = { + -1, 117010721, /* min: -1.117010721 rad/s */ + 0, 545415, /* step: 0.000545415 rad/s */ + 1, 116465306, /* max: 1.116465306 rad/s */ +}; + +static int inv_icm42600_gyro_read_offset(struct inv_icm42600_state *st, + struct iio_chan_spec const *chan, + int *val, int *val2) +{ + struct device *dev = regmap_get_device(st->map); + int64_t val64; + int32_t bias; + unsigned int reg; + int16_t offset; + 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); + mutex_lock(&st->lock); + + ret = regmap_bulk_read(st->map, reg, st->buffer, sizeof(data)); + memcpy(data, st->buffer, sizeof(data)); + + mutex_unlock(&st->lock); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + if (ret) + return ret; + + /* 12 bits signed value */ + switch (chan->channel2) { + case IIO_MOD_X: + offset = sign_extend32(((data[1] & 0x0F) << 8) | data[0], 11); + break; + case IIO_MOD_Y: + offset = sign_extend32(((data[0] & 0xF0) << 4) | data[1], 11); + break; + case IIO_MOD_Z: + offset = sign_extend32(((data[1] & 0x0F) << 8) | data[0], 11); + break; + default: + return -EINVAL; + } + + /* + * convert raw offset to dps then to rad/s + * 12 bits signed raw max 64 to dps: 64 / 2048 + * dps to rad: Pi / 180 + * result in nano (1000000000) + * (offset * 64 * Pi * 1000000000) / (2048 * 180) + */ + val64 = (int64_t)offset * 64LL * 3141592653LL; + /* for rounding, add + or - divisor (2048 * 180) divided by 2 */ + if (val64 >= 0) + val64 += 2048 * 180 / 2; + else + val64 -= 2048 * 180 / 2; + bias = div_s64(val64, 2048 * 180); + *val = bias / 1000000000L; + *val2 = bias % 1000000000L; + + return IIO_VAL_INT_PLUS_NANO; +} + +static int inv_icm42600_gyro_write_offset(struct inv_icm42600_state *st, + struct iio_chan_spec const *chan, + int val, int val2) +{ + struct device *dev = regmap_get_device(st->map); + int64_t val64, min, max; + unsigned int reg, regval; + int16_t offset; + 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; + } + + /* inv_icm42600_gyro_calibbias: min - step - max in nano */ + min = (int64_t)inv_icm42600_gyro_calibbias[0] * 1000000000LL + + (int64_t)inv_icm42600_gyro_calibbias[1]; + max = (int64_t)inv_icm42600_gyro_calibbias[4] * 1000000000LL + + (int64_t)inv_icm42600_gyro_calibbias[5]; + val64 = (int64_t)val * 1000000000LL + (int64_t)val2; + if (val64 < min || val64 > max) + return -EINVAL; + + /* + * convert rad/s to dps then to raw value + * rad to dps: 180 / Pi + * dps to raw 12 bits signed, max 64: 2048 / 64 + * val in nano (1000000000) + * val * 180 * 2048 / (Pi * 1000000000 * 64) + */ + val64 = val64 * 180LL * 2048LL; + /* for rounding, add + or - divisor (3141592653 * 64) divided by 2 */ + if (val64 >= 0) + val64 += 3141592653LL * 64LL / 2LL; + else + val64 -= 3141592653LL * 64LL / 2LL; + offset = div64_s64(val64, 3141592653LL * 64LL); + + /* clamp value limited to 12 bits signed */ + if (offset < -2048) + offset = -2048; + else if (offset > 2047) + offset = 2047; + + 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; + st->buffer[0] = offset & 0xFF; + st->buffer[1] = (regval & 0xF0) | ((offset & 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; + st->buffer[0] = ((offset & 0xF00) >> 4) | (regval & 0x0F); + st->buffer[1] = offset & 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; + st->buffer[0] = offset & 0xFF; + st->buffer[1] = (regval & 0xF0) | ((offset & 0xF00) >> 8); + break; + default: + ret = -EINVAL; + goto out_unlock; + } + + ret = regmap_bulk_write(st->map, reg, st->buffer, 2); + +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: + return inv_icm42600_gyro_read_offset(st, chan, val, val2); + 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; + case IIO_CHAN_INFO_CALIBBIAS: + *vals = inv_icm42600_gyro_calibbias; + *type = IIO_VAL_INT_PLUS_NANO; + return IIO_AVAIL_RANGE; + 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, val2); + 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_PLUS_NANO; + 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, +}; + +struct iio_dev *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) + return ERR_PTR(-ENOMEM); + + indio_dev = devm_iio_device_alloc(dev, 0); + if (!indio_dev) + return ERR_PTR(-ENOMEM); + + iio_device_set_drvdata(indio_dev, st); + 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); + + ret = devm_iio_device_register(dev, indio_dev); + if (ret) + return ERR_PTR(ret); + + return indio_dev; +} From patchwork Mon Jun 22 15:37:21 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: 11618261 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 30DB090 for ; Mon, 22 Jun 2020 15:39:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 071802074D for ; Mon, 22 Jun 2020 15:39:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="p4Cj1cTd"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="Zpmu+oK8" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729881AbgFVPiy (ORCPT ); Mon, 22 Jun 2020 11:38:54 -0400 Received: from mx0a-00328301.pphosted.com ([148.163.145.46]:55710 "EHLO mx0a-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729612AbgFVPiG (ORCPT ); Mon, 22 Jun 2020 11:38:06 -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 05MFa4C8021446; Mon, 22 Jun 2020 08:38:03 -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=kU+IuaD+USzK+7Uf0WSkAmmVYqlub7tjrL28klwo1KI=; b=p4Cj1cTdWOoj0Oj2gNBXsqKXdBRZIOUvGibN8oNNz/HCheKgmYwAXoybOtTdPqlPfMw4 a2hkjRrdo2oCuWw7r0wENlnkMhtiadhJeb2RgSTVpb4lPy370mYZONFXATBG0yprTiev 31iwQ8uJZNg/gAq7vOYLHXLgzUtbHoijAJDA7LyNNfSH68H7eUOeCmFAP5i/vtXl0aOw M02w1eyxLp1DvVshTs9bIL18dzC5HS4sXE8Pfy1/beBfyqQ1GcoTF1VooqFvLUkUC1w4 MWDOrBCGsThbKaX3BGST1Csagiy1IidV03gJu0yDSzUMvfznRxB8/mQgk7N+6a806zV5 TA== Received: from nam04-sn1-obe.outbound.protection.outlook.com (mail-sn1nam04lp2059.outbound.protection.outlook.com [104.47.44.59]) by mx0a-00328301.pphosted.com with ESMTP id 31sdxnrtxy-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 22 Jun 2020 08:38:03 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=A9Zv+f0zFGvxwhZUCACDRNV24D+JWyKw7Jmfzc8ldKazqnqshSf0gg2piWV+YC4GpxbJsAGmUSJ5Wzs/WAML9yPkuxjDG9pahdDvQhWDjyugFYbW+sH5FuTFMi638rMCZE2gu2RatN18inCArx+0dF1W/a/LoitG1gQBGsM/QxmA8wBUXowyu70jLQSx96rR4m0KB0e8tsB1vdKYGPKrQkjWMUHlpNowHMaiAOVTwE3Nqy6ep80gFjDd6cN5OEYE/O+NNmH+aGyvweyOp8hQjIWniN2keYTQ5lS/H10Aoq9luKooDvqGDXuEvZf2/Ak55BH8DyQykdCBzeA2dh4WZQ== 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=kU+IuaD+USzK+7Uf0WSkAmmVYqlub7tjrL28klwo1KI=; b=fHMKtgaiWM8fO1YeFZx7w+C0KpO6pdMieVQoMksSqFZstJitXqvWMiAtNCvJgoencCOTcc7M4dlFEoZ8xIYweDr8Ekgnu2KgbWmN6YqClGIv1lV4BZ3YEg5Cr6tvdqG2HWew1VKTjeFLex3pyUHTJ1663bNPp2r4nnBMTL2SGAi7wYxOKZ5MYpMyzfyrBvNPqydfJtWj+xR4LpPdUtgb4qH6A1ebnw/fjsiAksoCrDGXf5tG9z4AlGK2X/zel2wdURuylWhrDF53+sMU2q+hYqTx+OKAX6aJPefZ3AsoE3BcJ1M65WQplBOxolu8nBA63LB7Hwma/ELaFzJVjOskOQ== 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=kU+IuaD+USzK+7Uf0WSkAmmVYqlub7tjrL28klwo1KI=; b=Zpmu+oK8sHrU6JUqVM4V0aSYghP9NgL1jLMvVin+h8LigEuGLAIqw5lWfK7JYgRYzmLqMRRu6boEUToyXr7fLTflqtNH3no0UQJ5gsl3CE3k2pG7ig4GcFgaY/78QLpubrc23FYrmfp/UXBgTPPpW7rB7W635opSsCRy/syFnQY= 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.3109.22; Mon, 22 Jun 2020 15:38:02 +0000 Received: from MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0]) by MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0%7]) with mapi id 15.20.3109.027; Mon, 22 Jun 2020 15:38:02 +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 v4 05/13] iio: imu: inv_icm42600: add accelerometer IIO device Date: Mon, 22 Jun 2020 17:37:21 +0200 Message-Id: <20200622153729.12702-6-jmaneyrol@invensense.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200622153729.12702-1-jmaneyrol@invensense.com> References: <20200622153729.12702-1-jmaneyrol@invensense.com> X-ClientProxiedBy: LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) 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 LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3109.21 via Frontend Transport; Mon, 22 Jun 2020 15:38:01 +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: 3e7366be-83e1-4eac-0fba-08d816c23fd0 X-MS-TrafficTypeDiagnostic: MN2PR12MB4501: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:3968; X-Forefront-PRVS: 0442E569BC X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 6Q2bIa3OYfXTSO2Ex0nehkHAe6BK1HsgokUH8ulu30gEs7Y6VyKJTYYMvg7mndcS+ijA6zPsg00GQlq8qc1uOFcvH14GXeQXS6kGJVBAVAW0CAVIf9mpdCld3f6XimQYSoazs6h8AcD+uGNmDI/9GYPNE6o861YZ/IMTIJmLt1RAc/m5tY9XxRHNunq5Nia9Pb2Izu4VKyGw9vJHU4J6OhIVcm8XXw0iNAIR5lPtC+k4B7b5aCdBxDm7KDov03KAHPtiLudNX2RG77WWBnML9Vw66RD3llYnqBVYqDhzCRVp+U09R2eS8BQKBIAupu68kD6VOfOPFaBiBv28tHGRrA== 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)(39850400004)(136003)(366004)(396003)(4326008)(66946007)(7696005)(52116002)(8676002)(66476007)(66556008)(956004)(2616005)(1076003)(83380400001)(107886003)(86362001)(36756003)(30864003)(478600001)(6486002)(6666004)(26005)(316002)(8936002)(16526019)(5660300002)(2906002)(186003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: OdHZGWRtAIpvLZmGYUS9dY6w+I8ED/QAJak9vFHXdfDvs1QqLKFOTpegFh7xsq+hdlSyzummiELXZiqb0whrEJc/3+eQ5YMIyX47BIsTH69rVeTnoItNqhq8n6BYQPE7IMVJPqrv8g5j3LyAr9qv89Yh/FyDsTPuIG1RpYxZGsNFpjwRcdQpKztrpqhvyYsgqXs8tz850DebC2TzLDtvibqPv7D2NxTMTXmbsrbHe+je3LSQuV9Nt/4O1/ueTuIG9qf7naudsjPY07/fSuYjwtVh2YY8VFVz4/a10dXT3k4N51nc0fzn3mkYY7nxg4/KmeR1F35KjmUswZ6vTZJDVzlGTRyvSDFDs38BOiaqIuuE2WAanXheC4StQYvm168GeL5V2A/kc/nmGv9IHE+e9tuRGVhWS9+2cn7FRv2GC+R846l75YavF2K2wxSH9puL1KnDi9uT78bM56GZ/7bvCt6GF+8xMQYI/J/Ph7a3VP8= X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: 3e7366be-83e1-4eac-0fba-08d816c23fd0 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Jun 2020 15:38:02.4873 (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: GYD0IZ5aw0VwAr+IlIsS3qNrf0amIKEcjKabnv/KkVpiyauNedu0bVfZ6auKbJBxl6VvgpIYFusvnixjwk7Lnhej71Yy7+oaK09RSWSaYAg= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4501 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216,18.0.687 definitions=2020-06-22_09:2020-06-22,2020-06-22 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 mlxscore=0 phishscore=0 clxscore=1015 bulkscore=0 cotscore=-2147483648 suspectscore=0 impostorscore=0 spamscore=0 mlxlogscore=999 malwarescore=0 adultscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006220116 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add IIO device for accelerometer sensor with data polling interface. Attributes: raw, scale, sampling_frequency, calibbias. Accelerometer 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_accel.c | 592 ++++++++++++++++++ .../iio/imu/inv_icm42600/inv_icm42600_core.c | 4 + 3 files changed, 600 insertions(+) create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h b/drivers/iio/imu/inv_icm42600/inv_icm42600.h index d155470d770a..3b190461a2b6 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h @@ -121,6 +121,7 @@ struct inv_icm42600_suspended { * @conf: chip sensors configurations. * @suspended: suspended sensors configuration. * @indio_gyro: gyroscope IIO device. + * @indio_accel: accelerometer IIO device. * @buffer: data transfer buffer aligned for DMA. */ struct inv_icm42600_state { @@ -134,6 +135,7 @@ struct inv_icm42600_state { struct inv_icm42600_conf conf; struct inv_icm42600_suspended suspended; struct iio_dev *indio_gyro; + struct iio_dev *indio_accel; uint8_t buffer[2] ____cacheline_aligned; }; @@ -375,4 +377,6 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st); +struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st); + #endif diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c new file mode 100644 index 000000000000..717c6b0869fc --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c @@ -0,0 +1,592 @@ +// 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" + +#define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info) \ + { \ + .type = IIO_ACCEL, \ + .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) | \ + BIT(IIO_CHAN_INFO_CALIBBIAS), \ + .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, \ + .endianness = IIO_BE, \ + }, \ + .ext_info = _ext_info, \ + } + +enum inv_icm42600_accel_scan { + INV_ICM42600_ACCEL_SCAN_X, + INV_ICM42600_ACCEL_SCAN_Y, + INV_ICM42600_ACCEL_SCAN_Z, +}; + +static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = { + IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42600_get_mount_matrix), + {}, +}; + +static const struct iio_chan_spec inv_icm42600_accel_channels[] = { + INV_ICM42600_ACCEL_CHAN(IIO_MOD_X, INV_ICM42600_ACCEL_SCAN_X, + inv_icm42600_accel_ext_infos), + INV_ICM42600_ACCEL_CHAN(IIO_MOD_Y, INV_ICM42600_ACCEL_SCAN_Y, + inv_icm42600_accel_ext_infos), + INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z, + inv_icm42600_accel_ext_infos), +}; + +static int inv_icm42600_accel_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_ACCEL) + return -EINVAL; + + switch (chan->channel2) { + case IIO_MOD_X: + reg = INV_ICM42600_REG_ACCEL_DATA_X; + break; + case IIO_MOD_Y: + reg = INV_ICM42600_REG_ACCEL_DATA_Y; + break; + case IIO_MOD_Z: + reg = INV_ICM42600_REG_ACCEL_DATA_Z; + break; + default: + return -EINVAL; + } + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + /* enable accel sensor */ + conf.mode = INV_ICM42600_SENSOR_MODE_LOW_NOISE; + ret = inv_icm42600_set_accel_conf(st, &conf, NULL); + if (ret) + goto exit; + + /* read accel register data */ + data = (__be16 *)&st->buffer[0]; + ret = regmap_bulk_read(st->map, reg, data, sizeof(*data)); + if (ret) + goto exit; + + *val = (int16_t)be16_to_cpup(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_accel_scale[] = { + /* +/- 16G => 0.004788403 m/s-2 */ + [2 * INV_ICM42600_ACCEL_FS_16G] = 0, + [2 * INV_ICM42600_ACCEL_FS_16G + 1] = 4788403, + /* +/- 8G => 0.002394202 m/s-2 */ + [2 * INV_ICM42600_ACCEL_FS_8G] = 0, + [2 * INV_ICM42600_ACCEL_FS_8G + 1] = 2394202, + /* +/- 4G => 0.001197101 m/s-2 */ + [2 * INV_ICM42600_ACCEL_FS_4G] = 0, + [2 * INV_ICM42600_ACCEL_FS_4G + 1] = 1197101, + /* +/- 2G => 0.000598550 m/s-2 */ + [2 * INV_ICM42600_ACCEL_FS_2G] = 0, + [2 * INV_ICM42600_ACCEL_FS_2G + 1] = 598550, +}; + +static int inv_icm42600_accel_read_scale(struct inv_icm42600_state *st, + int *val, int *val2) +{ + unsigned int idx; + + idx = st->conf.accel.fs; + + *val = inv_icm42600_accel_scale[2 * idx]; + *val2 = inv_icm42600_accel_scale[2 * idx + 1]; + return IIO_VAL_INT_PLUS_NANO; +} + +static int inv_icm42600_accel_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_accel_scale); idx += 2) { + if (val == inv_icm42600_accel_scale[idx] && + val2 == inv_icm42600_accel_scale[idx + 1]) + break; + } + if (idx >= ARRAY_SIZE(inv_icm42600_accel_scale)) + return -EINVAL; + + conf.fs = idx / 2; + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + ret = inv_icm42600_set_accel_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_accel_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_accel_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_accel_read_odr(struct inv_icm42600_state *st, + int *val, int *val2) +{ + unsigned int odr; + unsigned int i; + + odr = st->conf.accel.odr; + + for (i = 0; i < ARRAY_SIZE(inv_icm42600_accel_odr_conv); ++i) { + if (inv_icm42600_accel_odr_conv[i] == odr) + break; + } + if (i >= ARRAY_SIZE(inv_icm42600_accel_odr_conv)) + return -EINVAL; + + *val = inv_icm42600_accel_odr[2 * i]; + *val2 = inv_icm42600_accel_odr[2 * i + 1]; + + return IIO_VAL_INT_PLUS_MICRO; +} + +static int inv_icm42600_accel_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_accel_odr); idx += 2) { + if (val == inv_icm42600_accel_odr[idx] && + val2 == inv_icm42600_accel_odr[idx + 1]) + break; + } + if (idx >= ARRAY_SIZE(inv_icm42600_accel_odr)) + return -EINVAL; + + conf.odr = inv_icm42600_accel_odr_conv[idx / 2]; + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + ret = inv_icm42600_set_accel_conf(st, &conf, NULL); + + mutex_unlock(&st->lock); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + + return ret; +} + +/* + * Calibration bias values, IIO range format int + micro. + * Value is limited to +/-1g coded on 12 bits signed. Step is 0.5mg. + */ +static int inv_icm42600_accel_calibbias[] = { + -10, 42010, /* min: -10.042010 m/s² */ + 0, 4903, /* step: 0.004903 m/s² */ + 10, 37106, /* max: 10.037106 m/s² */ +}; + +static int inv_icm42600_accel_read_offset(struct inv_icm42600_state *st, + struct iio_chan_spec const *chan, + int *val, int *val2) +{ + struct device *dev = regmap_get_device(st->map); + int64_t val64; + int32_t bias; + unsigned int reg; + int16_t offset; + uint8_t data[2]; + int ret; + + if (chan->type != IIO_ACCEL) + return -EINVAL; + + switch (chan->channel2) { + case IIO_MOD_X: + reg = INV_ICM42600_REG_OFFSET_USER4; + break; + case IIO_MOD_Y: + reg = INV_ICM42600_REG_OFFSET_USER6; + break; + case IIO_MOD_Z: + reg = INV_ICM42600_REG_OFFSET_USER7; + break; + default: + return -EINVAL; + } + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + ret = regmap_bulk_read(st->map, reg, st->buffer, sizeof(data)); + memcpy(data, st->buffer, sizeof(data)); + + mutex_unlock(&st->lock); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + if (ret) + return ret; + + /* 12 bits signed value */ + switch (chan->channel2) { + case IIO_MOD_X: + offset = sign_extend32(((data[0] & 0xF0) << 4) | data[1], 11); + break; + case IIO_MOD_Y: + offset = sign_extend32(((data[1] & 0x0F) << 8) | data[0], 11); + break; + case IIO_MOD_Z: + offset = sign_extend32(((data[0] & 0xF0) << 4) | data[1], 11); + break; + default: + return -EINVAL; + } + + /* + * convert raw offset to g then to m/s² + * 12 bits signed raw step 0.5mg to g: 5 / 10000 + * g to m/s²: 9.806650 + * result in micro (1000000) + * (offset * 5 * 9.806650 * 1000000) / 10000 + */ + val64 = (int64_t)offset * 5LL * 9806650LL; + /* for rounding, add + or - divisor (10000) divided by 2 */ + if (val64 >= 0) + val64 += 10000LL / 2LL; + else + val64 -= 10000LL / 2LL; + bias = div_s64(val64, 10000L); + *val = bias / 1000000L; + *val2 = bias % 1000000L; + + return IIO_VAL_INT_PLUS_MICRO; +} + +static int inv_icm42600_accel_write_offset(struct inv_icm42600_state *st, + struct iio_chan_spec const *chan, + int val, int val2) +{ + struct device *dev = regmap_get_device(st->map); + int64_t val64; + int32_t min, max; + unsigned int reg, regval; + int16_t offset; + int ret; + + if (chan->type != IIO_ACCEL) + return -EINVAL; + + switch (chan->channel2) { + case IIO_MOD_X: + reg = INV_ICM42600_REG_OFFSET_USER4; + break; + case IIO_MOD_Y: + reg = INV_ICM42600_REG_OFFSET_USER6; + break; + case IIO_MOD_Z: + reg = INV_ICM42600_REG_OFFSET_USER7; + break; + default: + return -EINVAL; + } + + /* inv_icm42600_accel_calibbias: min - step - max in micro */ + min = inv_icm42600_accel_calibbias[0] * 1000000L + + inv_icm42600_accel_calibbias[1]; + max = inv_icm42600_accel_calibbias[4] * 1000000L + + inv_icm42600_accel_calibbias[5]; + val64 = (int64_t)val * 1000000LL + (int64_t)val2; + if (val64 < min || val64 > max) + return -EINVAL; + + /* + * convert m/s² to g then to raw value + * m/s² to g: 1 / 9.806650 + * g to raw 12 bits signed, step 0.5mg: 10000 / 5 + * val in micro (1000000) + * val * 10000 / (9.806650 * 1000000 * 5) + */ + val64 = val64 * 10000LL; + /* for rounding, add + or - divisor (9806650 * 5) divided by 2 */ + if (val64 >= 0) + val64 += 9806650 * 5 / 2; + else + val64 -= 9806650 * 5 / 2; + offset = div_s64(val64, 9806650 * 5); + + /* clamp value limited to 12 bits signed */ + if (offset < -2048) + offset = -2048; + else if (offset > 2047) + offset = 2047; + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + switch (chan->channel2) { + case IIO_MOD_X: + /* OFFSET_USER4 register is shared */ + ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER4, + ®val); + if (ret) + goto out_unlock; + st->buffer[0] = ((offset & 0xF00) >> 4) | (regval & 0x0F); + st->buffer[1] = offset & 0xFF; + break; + case IIO_MOD_Y: + /* OFFSET_USER7 register is shared */ + ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER7, + ®val); + if (ret) + goto out_unlock; + st->buffer[0] = offset & 0xFF; + st->buffer[1] = ((offset & 0xF00) >> 8) | (regval & 0xF0); + break; + case IIO_MOD_Z: + /* OFFSET_USER7 register is shared */ + ret = regmap_read(st->map, INV_ICM42600_REG_OFFSET_USER7, + ®val); + if (ret) + goto out_unlock; + st->buffer[0] = ((offset & 0xF00) >> 4) | (regval & 0x0F); + st->buffer[1] = offset & 0xFF; + break; + default: + ret = -EINVAL; + goto out_unlock; + } + + ret = regmap_bulk_write(st->map, reg, st->buffer, 2); + +out_unlock: + mutex_unlock(&st->lock); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + return ret; +} + +static int inv_icm42600_accel_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_ACCEL) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = inv_icm42600_accel_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_accel_read_scale(st, val, val2); + case IIO_CHAN_INFO_SAMP_FREQ: + return inv_icm42600_accel_read_odr(st, val, val2); + case IIO_CHAN_INFO_CALIBBIAS: + return inv_icm42600_accel_read_offset(st, chan, val, val2); + default: + return -EINVAL; + } +} + +static int inv_icm42600_accel_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_ACCEL) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + *vals = inv_icm42600_accel_scale; + *type = IIO_VAL_INT_PLUS_NANO; + *length = ARRAY_SIZE(inv_icm42600_accel_scale); + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_SAMP_FREQ: + *vals = inv_icm42600_accel_odr; + *type = IIO_VAL_INT_PLUS_MICRO; + *length = ARRAY_SIZE(inv_icm42600_accel_odr); + return IIO_AVAIL_LIST; + case IIO_CHAN_INFO_CALIBBIAS: + *vals = inv_icm42600_accel_calibbias; + *type = IIO_VAL_INT_PLUS_MICRO; + return IIO_AVAIL_RANGE; + default: + return -EINVAL; + } +} + +static int inv_icm42600_accel_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_ACCEL) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_SCALE: + ret = iio_device_claim_direct_mode(indio_dev); + if (ret) + return ret; + ret = inv_icm42600_accel_write_scale(st, val, val2); + iio_device_release_direct_mode(indio_dev); + return ret; + case IIO_CHAN_INFO_SAMP_FREQ: + return inv_icm42600_accel_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_accel_write_offset(st, chan, val, val2); + iio_device_release_direct_mode(indio_dev); + return ret; + default: + return -EINVAL; + } +} + +static int inv_icm42600_accel_write_raw_get_fmt(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + long mask) +{ + if (chan->type != IIO_ACCEL) + 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_PLUS_MICRO; + default: + return -EINVAL; + } +} + +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, +}; + +struct iio_dev *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) + return ERR_PTR(-ENOMEM); + + indio_dev = devm_iio_device_alloc(dev, 0); + if (!indio_dev) + return ERR_PTR(-ENOMEM); + + iio_device_set_drvdata(indio_dev, st); + indio_dev->name = name; + indio_dev->info = &inv_icm42600_accel_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = inv_icm42600_accel_channels; + indio_dev->num_channels = ARRAY_SIZE(inv_icm42600_accel_channels); + + ret = devm_iio_device_register(dev, indio_dev); + if (ret) + return ERR_PTR(ret); + + return indio_dev; +} diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c index 84e9ff320b3b..a35ff21f50bb 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c @@ -513,6 +513,10 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, if (IS_ERR(st->indio_gyro)) return PTR_ERR(st->indio_gyro); + st->indio_accel = inv_icm42600_accel_init(st); + if (IS_ERR(st->indio_accel)) + return PTR_ERR(st->indio_accel); + /* setup runtime power management */ ret = pm_runtime_set_active(dev); if (ret) From patchwork Mon Jun 22 15:37:22 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: 11618257 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4180E90 for ; Mon, 22 Jun 2020 15:38:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 1BA6620760 for ; Mon, 22 Jun 2020 15:38:54 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="SCdAfj8i"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="Bx3tiP1n" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729683AbgFVPiw (ORCPT ); Mon, 22 Jun 2020 11:38:52 -0400 Received: from mx0b-00328301.pphosted.com ([148.163.141.47]:40534 "EHLO mx0b-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729647AbgFVPiK (ORCPT ); Mon, 22 Jun 2020 11:38:10 -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 05MFWD46004964; Mon, 22 Jun 2020 08:38:06 -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=GX+Z39CAjHCmycLvaMK+oUDm9TWzQpYNu+xxcfbCTv4=; b=SCdAfj8iMnHb2nMjuHSDsB8FSXafPZy8FowNsTsV7/e/QgK+j8aJPH5HAuBnw0NAkOne l7cQH2gYMIU7AQHjvZ2LzcY3829PP6lCypKd/3h9tAGMVX01Bzz0Re831cTbz9wQ+D0H 2LktveSx/SQK+AZY4DK9+O48SMXUVQLuHNBwImUmhqE647sdy5cTz9EkHkzm/srbX2ag C1CdYQBdQhJlrSrr3h7fvpdDsLYvw7RWQw0w82diKjNN7fOEN2M/DngYKfWxwd5XRFLm LxTdeANuNlZPdSWl4+3r9f5BeMC2BEMY8Z38IXQ3KPwll5pLkYON5iF4FXl/EeftzoVW 6w== Received: from nam04-sn1-obe.outbound.protection.outlook.com (mail-sn1nam04lp2052.outbound.protection.outlook.com [104.47.44.52]) by mx0b-00328301.pphosted.com with ESMTP id 31sedp0ukj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 22 Jun 2020 08:38:05 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=N8oMUySjTxYk/TtXk/QQzYRj8MOStdD22go+HAYQd7IEz5O5HPCE9K3zeNdke2MMVSyt2CAk3bvtzHh2PlY87w+85Z2K2F9adW+BV1oPN6seo185DgDQYJgfMQO2jBO5UU1TKmeLwJQv3QFXscKShF6z8dw0nRU/ns/H9Gaf+yxM48muHu4eKukN6C1rGK/SoN9m0brqj8H95Vb6OoOW8DcvjXmRFSCgmZkyzw7gqJrCyD+W26IVKp3T6iqYDUkiQxDO3QlpDwqRfb/PUBj0ZqHsr8rFH6JTzOxalhwL6bUnZIECAozxrZteBM7urNb3paRuiCFToby4+JwE/Jcffw== 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=GX+Z39CAjHCmycLvaMK+oUDm9TWzQpYNu+xxcfbCTv4=; b=Nwu4JoNOldFYCWKZANaacpxIqbIDo1gD2JccIev4zDw3snMQkapQChom8d2zzokU7oDExjb0X2DmVWZEoN3C7wyvMigxGQ1mbYV6wefmQ+4vdUGKkLm5Cm9+EvIaYYy2E+ppBB62KyBinMYx3O7Br/5XifP8T9He2F2Pl+AB/DHM3M7nGWz68BDoltjl1RsToS7NserUka/e31MDpNl9hKCi06lqD/T2y7QpIJ1rOGJE/E1DDU4q7ru4j0I2IQYtXeHTjHn+A0xeOeOjmo/aCSkWMPJ8vnWIG86GvzRDiUPrMBqwzfmOv0TaU4E0kw28NHgrv0jfL3Gg142VxSicrA== 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=GX+Z39CAjHCmycLvaMK+oUDm9TWzQpYNu+xxcfbCTv4=; b=Bx3tiP1nPMOhDz4D8zPELLs1Y8ADfKFGQM9Hr6EhiphyXFgNC1cWCEBsY97zBntUEj+HkQlAmoj2pDFXX1aGNjkebaDCR8RxqRdG2yZlJQRWJOA7Y8VVey5zLlcEv9ez+2SPM4WSeRUvA7L1nRT4VxXHf8plt/MPBk6bqWvLxfc= 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.3109.22; Mon, 22 Jun 2020 15:38:04 +0000 Received: from MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0]) by MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0%7]) with mapi id 15.20.3109.027; Mon, 22 Jun 2020 15:38:04 +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 v4 06/13] iio: imu: inv_icm42600: add temperature sensor support Date: Mon, 22 Jun 2020 17:37:22 +0200 Message-Id: <20200622153729.12702-7-jmaneyrol@invensense.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200622153729.12702-1-jmaneyrol@invensense.com> References: <20200622153729.12702-1-jmaneyrol@invensense.com> X-ClientProxiedBy: LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) 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 LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3109.21 via Frontend Transport; Mon, 22 Jun 2020 15:38:02 +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: 3e07611e-25b7-4f4d-403d-08d816c240cc X-MS-TrafficTypeDiagnostic: MN2PR12MB4501: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:7691; X-Forefront-PRVS: 0442E569BC X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: SnF/O0GP88UIdIYl41kmb95cVDSo9xDo90uER/RByozSpVfIvbLaXRas+CzYOJfaqsrXDTkSEDYHMX02FxkxvK3tUNlohmaB49aFB3afwJyKlvf+I7O8+Hz3e7jSDx0R/rjdmvVnaZ9b4dAsbRn+FB4fiB6wXsCzY54ePUuJ1GebzL8MdlNFW1Ht1z9pyFDuOn7Clszcw7DW4V7dPhBryyfIC2qLE3ZSnv+cVVQ/x08bgSpLNwMzeO5CrRhMDJKKf0JDYmgtWNIkcIBTCtoVYvM4lSMPWUf+zexXkgN1Em98H16+pOR3TloaRNqOfhDY 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)(39850400004)(136003)(366004)(396003)(4326008)(66946007)(7696005)(52116002)(8676002)(66476007)(66556008)(956004)(2616005)(1076003)(83380400001)(107886003)(86362001)(36756003)(478600001)(6486002)(6666004)(26005)(316002)(8936002)(16526019)(5660300002)(2906002)(186003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: wia8Neb6Gvqqvzg4gpB6D9tR3dI3TRYBqUMDmXQDoiz0SzbMGSPSCWS+sJOoVWL1J2ldK1AyEV4+eG61BemHgWH2WnOWmQfSxfTyL+NcycMH7w7nM0xKc4LFQ71Qt/gEUGXuHx0vyR08BQ+sYzz2EpQODN2a1EaygngKwunEP+Ey6oCWqERkXy8wZB086L09mqwwXX+nU8RK7gH0qSEQ6nll2Jg1ctrhV0ICTZ2M1CUAMiGSwNMct17hOqR5+csZS3Y6hriuxstoohT4i5w5BkO0qySeZgwYfZa5yH0efXZDEvQdSuRWeVq2I7TS5Glbkml635q/B5AZTovomUAdpdjmwAhpwV4sixfpRRh8XS5GhRKkMd3vFHnHuMvN/WOk/CJqE9GkuQsBgHMFaMbPMRku4MADQwcLKttwk+qALgqgOK5MS/grGRS4GGHfX2q4wXFlAO9dtdWV2Q6oITMZjmwU+kXTAAXGetHXeNeja2o= X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: 3e07611e-25b7-4f4d-403d-08d816c240cc X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Jun 2020 15:38:04.1072 (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: QLM5ovDPCsjkYg/iYQjYs/ppGHqv6p2ojVtKlYI9ZiD60aCCIY5rc9/AivNYP7nFOwc87/5KOFop1/suc7Pi4+hgYo1hR9caQQaxZdtK6jc= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4501 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216,18.0.687 definitions=2020-06-22_09:2020-06-22,2020-06-22 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 clxscore=1015 adultscore=0 mlxlogscore=999 spamscore=0 mlxscore=0 lowpriorityscore=0 phishscore=0 priorityscore=1501 bulkscore=0 cotscore=-2147483648 malwarescore=0 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006220116 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add temperature channel in gyroscope and accelerometer devices. Temperature is available in full 16 bits resolution when reading register and in low 8 bits resolution in the FIFO. Return full precision raw temperature with corresponding scale and offset. Signed-off-by: Jean-Baptiste Maneyrol --- .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 11 ++- .../iio/imu/inv_icm42600/inv_icm42600_gyro.c | 11 ++- .../iio/imu/inv_icm42600/inv_icm42600_temp.c | 84 +++++++++++++++++++ .../iio/imu/inv_icm42600/inv_icm42600_temp.h | 30 +++++++ 4 files changed, 134 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 717c6b0869fc..3f214df44093 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c @@ -13,6 +13,7 @@ #include #include "inv_icm42600.h" +#include "inv_icm42600_temp.h" #define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info) \ { \ @@ -45,6 +46,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[] = { @@ -59,6 +61,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, @@ -450,8 +453,14 @@ 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 3875ecbee67e..6a0e7661fa48 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c @@ -13,6 +13,7 @@ #include #include "inv_icm42600.h" +#include "inv_icm42600_temp.h" #define INV_ICM42600_GYRO_CHAN(_modifier, _index, _ext_info) \ { \ @@ -45,6 +46,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[] = { @@ -59,6 +61,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, @@ -461,8 +464,14 @@ 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..213cce1c3111 --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c @@ -0,0 +1,84 @@ +// 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, int16_t *temp) +{ + struct device *dev = regmap_get_device(st->map); + __be16 *raw; + int ret; + + pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + + ret = inv_icm42600_set_temp_conf(st, true, NULL); + if (ret) + goto exit; + + raw = (__be16 *)&st->buffer[0]; + ret = regmap_bulk_read(st->map, INV_ICM42600_REG_TEMP_DATA, raw, sizeof(*raw)); + if (ret) + goto exit; + + *temp = (int16_t)be16_to_cpup(raw); + if (*temp == INV_ICM42600_DATA_INVALID) + ret = -EINVAL; + +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); + int16_t temp; + int ret; + + if (chan->type != IIO_TEMP) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + 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; + /* + * T°C = (temp / 132.48) + 25 + * Tm°C = 1000 * ((temp * 100 / 13248) + 25) + * scale: 100000 / 13248 ~= 7.548309 + * offset: 25000 + */ + case IIO_CHAN_INFO_SCALE: + *val = 7; + *val2 = 548309; + 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..3941186512fb --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#ifndef INV_ICM42600_TEMP_H_ +#define INV_ICM42600_TEMP_H_ + +#include + +#define INV_ICM42600_TEMP_CHAN(_index) \ + { \ + .type = IIO_TEMP, \ + .info_mask_separate = \ + BIT(IIO_CHAN_INFO_RAW) | \ + BIT(IIO_CHAN_INFO_OFFSET) | \ + BIT(IIO_CHAN_INFO_SCALE), \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + }, \ + } + +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 Mon Jun 22 15:37:23 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: 11618241 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7344760D for ; Mon, 22 Jun 2020 15:38:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 52CCB2074D for ; Mon, 22 Jun 2020 15:38:16 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="e4/4rAJe"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="IXT0e5tc" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729296AbgFVPiP (ORCPT ); Mon, 22 Jun 2020 11:38:15 -0400 Received: from mx0b-00328301.pphosted.com ([148.163.141.47]:42252 "EHLO mx0b-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729253AbgFVPiL (ORCPT ); Mon, 22 Jun 2020 11:38:11 -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 05MFWD47004964; Mon, 22 Jun 2020 08:38:07 -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=QBf2HMHj1/eKnonntrdhRRALP8UmjKyNHNknL468b6U=; b=e4/4rAJeLeL+expAwpQI1u2vgDkycWFpOtISOSc0SsI2baFkb+BknE8JjdgNXl7CLPLw fOi37yWblczAq21129Qk6x0nCxPVs9AwQFURP0IB02LM318zanRxi0tSCzPV23bl1OwZ KHXkJ2g7tNqW7oE5NcSi9eBLwdgzCC3zvqjXRX7akUeyN0lE/TSMx1NqG5fXGEJ7Bh89 YMFIjJpgQ7xq0LCbyR6KHzpWsr6GxUmXbZY6u/pJ0Ai6xKaHqvq9YvQeqnyBEiVII2y8 msl7OdlwFXmxotNKPRIgsHKe/+00X0QyIfEcVDskw3usCS52wTqWLN8ZKhknSR/1j1fE aw== Received: from nam04-sn1-obe.outbound.protection.outlook.com (mail-sn1nam04lp2056.outbound.protection.outlook.com [104.47.44.56]) by mx0b-00328301.pphosted.com with ESMTP id 31sedp0ukm-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 22 Jun 2020 08:38:07 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=QaNWVkBGBZL+3xB8cxgsTXgrUqOikUoiSdxP2YzQz8FVOPoqW+CEKbhMYe3LVEPXxLAnf6sz2tg6nvgy9/+DUwodwSavCvk6eLlMABBAJ821kn5EqTZNUHeEs5cHJzuZrojmzPJNNsfhvyY+4oabr4XoGIQFu4XCeyBKtZz7LOeQTJY7ksJvDFCKGnoZwPg0EC7hSDdB1cFTyTXwyQy/hhe6kaVo1liEPzZTBu6U2ou9PaFPIRox9k4rulCCOlYRhZU8JlkrSrDkT4P5bF64qNxURGQ2T5APPH8ZNhuWhhiLLMQlHt7dqTVwpp2o8Pks9OS1jEUhQdI8shvTYaLe2w== 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=QBf2HMHj1/eKnonntrdhRRALP8UmjKyNHNknL468b6U=; b=kX+gcgm0Kko6qzduxVYZ1PkQhT0lbKrZHFRH/Cjtz9W3WMoAzPbZoCa2W3GLdHI0cYmH3SddVkVUTGiTn94LSvE23CZtPWMddwpdMJmSgK6LrBF3Ru9wjGueS/0RZY1dJxFAB4FVeZOpDgAyxOdOSEpFpGz2M+qK6eJKGTGcg4V58G43cu6E73N4WUvr53Lu3nwa/HjBqC9eKEWhnDZ0U1lf7SDUJgBa4qwYqVCX66ZDSjSZ7uHuJl4wAP9rEA3/jXY3U2CfTrkyjlq3cS+T7W/mfhtK9oOnI2GLpRtDzdE8RJ+E0djpq6KLADDgE0BbI+DYu+P+0AOY/fcIl1FZqA== 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=QBf2HMHj1/eKnonntrdhRRALP8UmjKyNHNknL468b6U=; b=IXT0e5tcBtxYc6kr1n9mcjUPqCg8nBPIvSR7EKn1zbZLUPGLjn7kH16vIpluFr1PtP0xDTXmZ43GbT2f6qTExjsCLdPaiQl3jju4ej4aULe9JMZr4ijfGY8t0at+w1C+viWKb88LQOfnHzM7f/oHXGRgVofPB1L+N3zdRABJTWg= 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.3109.22; Mon, 22 Jun 2020 15:38:06 +0000 Received: from MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0]) by MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0%7]) with mapi id 15.20.3109.027; Mon, 22 Jun 2020 15:38:05 +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 v4 07/13] iio: imu: add Kconfig and Makefile for inv_icm42600 driver Date: Mon, 22 Jun 2020 17:37:23 +0200 Message-Id: <20200622153729.12702-8-jmaneyrol@invensense.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200622153729.12702-1-jmaneyrol@invensense.com> References: <20200622153729.12702-1-jmaneyrol@invensense.com> X-ClientProxiedBy: LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) 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 LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3109.21 via Frontend Transport; Mon, 22 Jun 2020 15:38:04 +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: 92e30dea-ae75-4d9b-5043-08d816c241c6 X-MS-TrafficTypeDiagnostic: MN2PR12MB4501: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:2803; X-Forefront-PRVS: 0442E569BC X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: VrP/9H9KCdyTuCyJPP1Lx3dIdvCrHjlLzCURD1gR2TMs/YRqSX/sfBtkX2NtvjnBNADibaWD4SSMlML6SLeB3+mVhwigMVM/DN/2RC7yh8rEaHzqfalEMgVv600swCg56bSRYWoDcxrIEfNGBx0OAAj/hkuQ9k4K6b1oywfWu1vTH57MxJZ9k825xsMJPx/3iw9/sFlWFGRP1pGBNNmGegJTKLmQFgYViGy/0cujLhby6y4iB4CxyNgyPni30Z8vb5aPn+08wUE/L58wQM0gph0eg62QZraKSccN9CUmCiXxoUhKb6O+fNvEU7NAyJRW 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)(39850400004)(136003)(366004)(396003)(4326008)(66946007)(7696005)(52116002)(8676002)(66476007)(66556008)(956004)(2616005)(1076003)(107886003)(86362001)(36756003)(478600001)(6486002)(6666004)(26005)(316002)(8936002)(16526019)(5660300002)(2906002)(186003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: qOM1gGb8QSmkF8nnp9llxAkcJjCCcse7O0rzuXR3hjF2vzd+LOpTiJx3fiR6PVKMo9GqnNHAujSS/VNVJfZWYtqMzIDTUz1dftHp2tNDgbLjN/EbV8yb+Ku+7nqTkBk14+jXZXlo7yliP28NrKTJdee7/xC/kOSzlVlI4pOLXuyLcgtLWyneZrfZgoTk5CsygNqmcHqhsKY4EE6szIv5mtunPmDZ/T+S4TU3K6wc5efFbcNClsE5jTGKYz1cheqd4Xw6ibZeza6WSKDPZWgrQH/7HjCMdMIpLs7i0AQtzbpFCDiIyx4k3gkRms/uCB/yw1dtFWHTJJsWxI7p9U9bu07jt7bFMJdQT/iwnjorEjOPqkV6rWsOOkCeLVPyO/1jgoGCXebJzTrwPZtCaDjVheMmw4SSmfmzj3giC/Ej43CM8lMnGLE8AZQ9JE+Z/uLLdBrQThB9bWd4z67H4gjTCE9XSJTy1bpRLJmMZvtAH7k= X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: 92e30dea-ae75-4d9b-5043-08d816c241c6 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Jun 2020 15:38:05.8247 (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: 8kg99BzAke0vQ+MaJ8sqQkBnI6pAviwYrb9Fdo+7JzncvjVrX13sk6k47JV3moYeH6zzVtPw8JcnHS224Ix2gyG3/9XwvmIO8K01WsEBSEQ= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4501 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216,18.0.687 definitions=2020-06-22_09:2020-06-22,2020-06-22 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 clxscore=1015 adultscore=0 mlxlogscore=972 spamscore=0 mlxscore=0 lowpriorityscore=0 phishscore=0 priorityscore=1501 bulkscore=0 cotscore=-2147483648 malwarescore=0 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006220116 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add 3 modules: inv-icm42600, inv-icm42600-i2c, inv-icm42600-spi. Signed-off-by: Jean-Baptiste Maneyrol --- drivers/iio/imu/Kconfig | 1 + drivers/iio/imu/Makefile | 1 + drivers/iio/imu/inv_icm42600/Kconfig | 28 +++++++++++++++++++++++++++ drivers/iio/imu/inv_icm42600/Makefile | 13 +++++++++++++ 4 files changed, 43 insertions(+) create mode 100644 drivers/iio/imu/inv_icm42600/Kconfig create mode 100644 drivers/iio/imu/inv_icm42600/Makefile diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig index fc4123d518bc..f02883b08480 100644 --- a/drivers/iio/imu/Kconfig +++ b/drivers/iio/imu/Kconfig @@ -91,6 +91,7 @@ config KMX61 To compile this driver as module, choose M here: the module will be called kmx61. +source "drivers/iio/imu/inv_icm42600/Kconfig" source "drivers/iio/imu/inv_mpu6050/Kconfig" source "drivers/iio/imu/st_lsm6dsx/Kconfig" diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile index 88b2c4555230..13e9ff442b11 100644 --- a/drivers/iio/imu/Makefile +++ b/drivers/iio/imu/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_FXOS8700) += fxos8700_core.o obj-$(CONFIG_FXOS8700_I2C) += fxos8700_i2c.o obj-$(CONFIG_FXOS8700_SPI) += fxos8700_spi.o +obj-y += inv_icm42600/ obj-y += inv_mpu6050/ obj-$(CONFIG_KMX61) += kmx61.o diff --git a/drivers/iio/imu/inv_icm42600/Kconfig b/drivers/iio/imu/inv_icm42600/Kconfig new file mode 100644 index 000000000000..22390a72f0a3 --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/Kconfig @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +config INV_ICM42600 + tristate + +config INV_ICM42600_I2C + tristate "InvenSense ICM-426xx I2C driver" + depends on I2C + select INV_ICM42600 + select REGMAP_I2C + help + This driver supports the InvenSense ICM-426xx motion tracking + devices over I2C. + + This driver can be built as a module. The module will be called + inv-icm42600-i2c. + +config INV_ICM42600_SPI + tristate "InvenSense ICM-426xx SPI driver" + depends on SPI_MASTER + select INV_ICM42600 + select REGMAP_SPI + help + This driver supports the InvenSense ICM-426xx motion tracking + devices over SPI. + + This driver can be built as a module. The module will be called + inv-icm42600-spi. diff --git a/drivers/iio/imu/inv_icm42600/Makefile b/drivers/iio/imu/inv_icm42600/Makefile new file mode 100644 index 000000000000..48965824f00c --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/Makefile @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +obj-$(CONFIG_INV_ICM42600) += inv-icm42600.o +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 + +obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o +inv-icm42600-i2c-y += inv_icm42600_i2c.o + +obj-$(CONFIG_INV_ICM42600_SPI) += inv-icm42600-spi.o +inv-icm42600-spi-y += inv_icm42600_spi.o From patchwork Mon Jun 22 15:37:24 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: 11618253 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B66B290 for ; Mon, 22 Jun 2020 15:38:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 96ED020767 for ; Mon, 22 Jun 2020 15:38:47 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="GtCRx8Fk"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="cJGkFAPl" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729716AbgFVPiq (ORCPT ); Mon, 22 Jun 2020 11:38:46 -0400 Received: from mx0b-00328301.pphosted.com ([148.163.141.47]:44290 "EHLO mx0b-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729683AbgFVPiM (ORCPT ); Mon, 22 Jun 2020 11:38:12 -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 05MFWuqh005880; Mon, 22 Jun 2020 08:38: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 : mime-version; s=pfpt1; bh=ts7RgAAzhzPOnSMR0uB3yQL4tELJfE/5U3WAV+hW0JY=; b=GtCRx8Fk+QVCBEdqXTCy/7v6I050brwq8fTdr6tv09q59hq3jxi7NV+Ul6RTTlDN8RwM CL3GVN+vngVlpOscc9BrYswZ+c6DZaZ+9fG2vH+Rf6c+HUBSpSb7qDR8yrEN+B01vwVk ZpISumDrHvRTEuBuke2Tw2YfCIQDEmmUiBQqwERvr0G+Bo/UYpr9G6I5spd6aGYrhBTY yw8H1Qo71xhKtqFT2TFzxdqmM7q0sPaw+j1bRIdPllGZqgrp9bvLNKZlF84Md368wBHI Bb6P1HrjDoz/8Nv7L9aFC4QseJ+0YlgWMTcwRo4SWWbWdmlc6JDgnjM78ahxJho5Pzeb hg== Received: from nam04-sn1-obe.outbound.protection.outlook.com (mail-sn1nam04lp2058.outbound.protection.outlook.com [104.47.44.58]) by mx0b-00328301.pphosted.com with ESMTP id 31sedp0ukn-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 22 Jun 2020 08:38:08 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=iPSiXkrZdwu+e8NvvbT4wEzKniLPwvzxZnv6lZyps3QX3sb5RV4l2Gtaq0ynTuIDKSUtp1hO6c5i+Lrn6wVETdt8lif+GEXzf80XCj1fCphBs36ID4GlH82bO+Jf5+H5S/7ICHt+xD3mL4quENmd2imwzSUdTcHjVhrVDWOAUN908PzUabZgyyltLeFTdU9Q6lp7mAeRmMK1T1TXY5GJ1mAEPOqS06HvVKmILdTeC6xF6znBQk6IIrmtKm/MxrLGQMwPdburamFXHir7QGpWkv4JmXO4uBtmAmewxay2tqfKjAcezyBwtYablnu4xrNoT40za7iGEbBdecnF1Pwc8A== 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=ts7RgAAzhzPOnSMR0uB3yQL4tELJfE/5U3WAV+hW0JY=; b=jVBWf9Oiw1GH3ICG9gDVnwm251xAhvq7hP3jx0cmutRWY1slUTMvXC+JUrb7j0I0wfnU3bm+V4MqABjbpK861Lhdptdf6A2n14H+b6ogx0Dw6g4kinyAWQnnBx2EdfCf9paQJ+yUNmZiiiOqPyAOlxwQiJkbX/OWePStmNZEC3hMP0FpVbxkkqEx/I443CHF79zBhWcDnQC2miV43grqXDet6+vq6Yf5O/AQL8vHHOuIRqny9LkC7DqPoibAutRg/97uApZbQRsYLSiPlVl1iY+7Y4wSZWGd1bJOl/qGB8UKvv6aOCM80kjiz5vf1l+QgFBQZB+wVaEK+/2DdRmnPQ== 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=ts7RgAAzhzPOnSMR0uB3yQL4tELJfE/5U3WAV+hW0JY=; b=cJGkFAPlG7rusPOON8jF9329r3umQ1ak3/U8W0YCEIqB3WCRR0XOmE4278Xs5tebC7xDYjnbt9LMAr63NTbaUh+8+X6GOk6HStgN4KghyqTFKLgVis1P5fz5zZToVDWG4gOwOVQpLZ9Kp2piykvBCC7iLtB12adnetp0N5/KN9I= 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.3109.22; Mon, 22 Jun 2020 15:38:07 +0000 Received: from MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0]) by MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0%7]) with mapi id 15.20.3109.027; Mon, 22 Jun 2020 15:38: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 v4 08/13] Documentation: ABI: add specific icm42600 documentation Date: Mon, 22 Jun 2020 17:37:24 +0200 Message-Id: <20200622153729.12702-9-jmaneyrol@invensense.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200622153729.12702-1-jmaneyrol@invensense.com> References: <20200622153729.12702-1-jmaneyrol@invensense.com> X-ClientProxiedBy: LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) 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 LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3109.21 via Frontend Transport; Mon, 22 Jun 2020 15:38:06 +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: 4f84b97b-0e19-43e0-9465-08d816c242c8 X-MS-TrafficTypeDiagnostic: MN2PR12MB4501: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:337; X-Forefront-PRVS: 0442E569BC X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: hO2pA6KSqcnvPC8SVx1Urx3Mt3cIqf3IEsANz5BLt0I9vPZb1aOxPpge/aIvIqiOBvFUcdVgJpDGtlenm5vJiaZHOEP4p76q8di87NUbmsiI0z5BZ7wxzwxXqdSNCUDJEW2+CszD9/eCMJ9eA/1a+OFtIYwlO2SJmhFcPhCUF+Md1kmZvvVjHNAV7qscnkNKizNyPWk/Kq4J941pWPYT5EEcLsz7XTNGleNJt+yoQ6HSmxS4we/mIgHOA7Wl/CLh84+8QbaP2U48f93IwQaJJ9GBmkqaBpDUy9l58YeWLs9UjbYkWHRAAls+DBY4v94sN1f7u1pyT5U35/r/OkRrcw== 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)(39850400004)(136003)(366004)(396003)(4326008)(66946007)(7696005)(52116002)(8676002)(66476007)(66556008)(956004)(2616005)(1076003)(107886003)(86362001)(36756003)(478600001)(6486002)(6666004)(19627235002)(26005)(316002)(8936002)(16526019)(5660300002)(2906002)(186003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: YBMRXrfqqh2G0yQGO8eKr5V0LrCYIPUeiguZIxfFy+nzJmLCfqdsR+4dYF7Gl2sMzp6drF/FKTRUJRdSZoesiZNjmdk+EAQ2AxGA66yZJ4W/t9zCqkYhVwYkiozFd5gs/UP5EZDwugLOJoacYGCdvA4GjddMn0ezrJYEPqK2ZcEP+j7IODP+0eGFtb+y+6HjwmsVikuPLKsDvGe0HPZUK3qg8Q4RnfC2QsNg/32unU9SUmNK11pcp1J/TpioMkVir+11jpSS9WX5XaSXO9Vugg1mALo52dmvHX5HeVQSt2+XHHBrG51mLPTMJiErTf5ZdVzo3qjkVQ729D+fGnJxTV0UqI2ja/RdUI/6yasEl01YgHHVr+qg0e5DYPVMWgqqnFyO4pg0rNs2UkYXr2cAi0rIIRv5bonLTLIVWw8fE56IOEZVIF8omrvXL0DIp1Y29vNjLVOO2orOKWVXC/2Wb3jQfLFg1epCSf0iUFRVdRs= X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: 4f84b97b-0e19-43e0-9465-08d816c242c8 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Jun 2020 15:38:07.4615 (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: aK6DMhVCcGkXZvUNU8AtMbJcBJXY13zQk3Ru2kUbNpqWQDnkWW7bUO7d0R6sjS5ti9tPWb43SWVcSl0Z4bqd1RmP94K+dWZLkATS+uoF19w= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4501 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216,18.0.687 definitions=2020-06-22_09:2020-06-22,2020-06-22 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 clxscore=1015 adultscore=0 mlxlogscore=999 spamscore=0 mlxscore=0 lowpriorityscore=0 phishscore=0 priorityscore=1501 bulkscore=0 cotscore=-2147483648 malwarescore=0 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006220116 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Hardware offset available as calibscale sysfs attributes are real physical values exprimed in SI units. calibscale_available sysfs attributes represents the range of acceptable values. Signed-off-by: Jean-Baptiste Maneyrol --- .../ABI/testing/sysfs-bus-iio-icm42600 | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-icm42600 diff --git a/Documentation/ABI/testing/sysfs-bus-iio-icm42600 b/Documentation/ABI/testing/sysfs-bus-iio-icm42600 new file mode 100644 index 000000000000..0bf1fd4f5bf1 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-iio-icm42600 @@ -0,0 +1,20 @@ +What: /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibbias +What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibbias +What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibbias +What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibbias +What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibbias +What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibbias +KernelVersion: 5.8 +Contact: linux-iio@vger.kernel.org +Description: + Hardware applied calibration offset (assumed to fix production + inaccuracies). Values represent a real physical offset expressed + in SI units (m/s^2 for accelerometer and rad/s for gyroscope). + +What: /sys/bus/iio/devices/iio:deviceX/in_accel_calibbias_available +What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_calibbias_available +KernelVersion: 5.8 +Contact: linux-iio@vger.kernel.org +Description: + Range of available values for hardware offset. Values in SI + units (m/s^2 for accelerometer and rad/s for gyroscope). From patchwork Mon Jun 22 15:37:25 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: 11618243 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A363090 for ; Mon, 22 Jun 2020 15:38:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 803B02071A for ; Mon, 22 Jun 2020 15:38:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="F5XJcxyG"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="dsFlVUkm" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729746AbgFVPiR (ORCPT ); Mon, 22 Jun 2020 11:38:17 -0400 Received: from mx0b-00328301.pphosted.com ([148.163.141.47]:45900 "EHLO mx0b-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729705AbgFVPiP (ORCPT ); Mon, 22 Jun 2020 11:38:15 -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 05MFWDw6004965; Mon, 22 Jun 2020 08:38:10 -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=Ac9eFAx/Ik/+xmRjOSD3b/jAUbqE30hJuuy6dHCep44=; b=F5XJcxyGcmhowe5lA+hrhMiYGeA7MesDgMxAlgO58DGfgJLOeuflEYkFgXsQKMC7HruH 9KYnqXW2R5+EbgB3bB9ZXNOC0FA9jPAknMbyTYbmcnLusAscBvQX6SiXXybsYHrLoOH8 GqM72wxHipsFmEagta3pQhDXVG+GQZVspcvE9LZuSP1IldUbAA0q9xaTMXgPHb3FaZaT 4IeCVJN+fL179BhCRg8CGSnPT43LlflFAIacK4SGvzToP5O5w7t9vfx/ogzbkFFSz7pM dByApfje5FsIZPLfmPRifkXUKEPczQUxEkwHLs0Cl1bc2uLAhbp31ST3POvOcdEcTrT7 Lg== Received: from nam04-sn1-obe.outbound.protection.outlook.com (mail-sn1nam04lp2056.outbound.protection.outlook.com [104.47.44.56]) by mx0b-00328301.pphosted.com with ESMTP id 31sedp0ukp-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 22 Jun 2020 08:38:10 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=G0uON07tI78TqIBb5y0YVD5nHdtv6fnwIABeJaDt/YgJyDVTUBR449hdDcPYBJIRTHIR7c9Eptt4lfI8dr7bf5y/Tck3cRSjK9fYB/UuuQC47tX0ENDm3ebuEGjOQgznNBAy41pZYjgbQk2y/QrN5uswfkS4rLjDu2zw8+923iK9EsBFMrd9mF5qMxHvkPjtSKkQWSj+tE+lZKFn8lbIOFfJeq2x4x9vcsCqmM5dy9ENAPMvVXepiqUYmkh2jheELFpyHZqcnKTAJhPUtDsC9AFauuAB+8l/t74HHqcL7duec95ujvlW6OJBsP80h0sTFYiLw7kYYxijbCCRCbVOfA== 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=Ac9eFAx/Ik/+xmRjOSD3b/jAUbqE30hJuuy6dHCep44=; b=R3aPp8WnnE04hi1/TE675zmP/mD/AGA53ZPskhlFjW6EqCCEpSgj562jOIjUKe8+eMuQ1svKf/dhHmpQUe9UG5XoQRuD7AjLcz32BQlX5da2n1BqbwXLNq0BiO2czNQhcMthuo1rJbQH5Bd/viNEP98VLLJsKrW30bDLi11U/EHxVrW8VOiIQSgd0NOs85MME4NJl3gRFKxRvPu0yWm2OHu/pnXlay+EnpAJsAmXqcdu4vKDQtd9sHA9dYwdRIrjlIw9x5ckqbHdWU4bdAD59yY4I/PG34z9m1eYaz9SxFZzBQHzQkMcUubx1/jjGBdQDgcOhL4Kyw/CwlaY645bmQ== 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=Ac9eFAx/Ik/+xmRjOSD3b/jAUbqE30hJuuy6dHCep44=; b=dsFlVUkmIoDJ+u0VUT1YicF80OjlBlqAL89iENGDYKI4M5arALnz57u1aUSnLxKbeleyKxYfDaEO+0KIlmfCChcSeNEAun3ZmaKt0FC/VoqwsNM9Nwi5cDeuwVAo+WcK7tN6XbAarkTR3JPiMX16GJc0HROgXMN0G/Emu0VHJpI= 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.3109.22; Mon, 22 Jun 2020 15:38:09 +0000 Received: from MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0]) by MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0%7]) with mapi id 15.20.3109.027; Mon, 22 Jun 2020 15:38:09 +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 v4 09/13] iio: imu: inv_icm42600: add device interrupt Date: Mon, 22 Jun 2020 17:37:25 +0200 Message-Id: <20200622153729.12702-10-jmaneyrol@invensense.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200622153729.12702-1-jmaneyrol@invensense.com> References: <20200622153729.12702-1-jmaneyrol@invensense.com> X-ClientProxiedBy: LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) 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 LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3109.21 via Frontend Transport; Mon, 22 Jun 2020 15:38:07 +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: 12f004a1-32e7-413c-e56c-08d816c243c6 X-MS-TrafficTypeDiagnostic: MN2PR12MB4501: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:5236; X-Forefront-PRVS: 0442E569BC X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: UD/5XdHUzKtwyZw4mJ2PeL5qN7ANHWEBApk5VfJYSXBDqCZoUhPeZHfzz21VM94oQlpLImriTlhUOZrujB5eSmUq1tOP8S0SgscNRAlzV6HaTRN0ZG1FdvMWz8TweH/pRiN101yJ1giRga9au19ZesZAalK5VNAweZXtkGzi9gPcOXJjCNpJyiBYxtTlRxGs0ZnEysa/OgLxqnCHDyIp2f1u7++/NUJwGKNMXMaxBLR0ix3cPxTgjSwdVFbPJ1Nlwy4d8a5DGeAac4Kcyc4Z6iut8MK+0OtjiroB57A8k608N2yo9P7+mebs9lB9AR49OXwx7EBtFyAtuvPW3mJg+g== 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)(39850400004)(136003)(366004)(396003)(4326008)(66946007)(7696005)(52116002)(8676002)(66476007)(66556008)(956004)(2616005)(1076003)(83380400001)(107886003)(86362001)(36756003)(478600001)(6486002)(6666004)(26005)(316002)(8936002)(16526019)(5660300002)(2906002)(186003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: JIe+w8duWVtepRQShBbV6pmz9E8hdpE5bQKU48MJFapr7TqwDpy2T3eVqXr3U4IohdYgGXFWZCPFFt96/EnK2nBQ3z8cLf2+gzfvyVDZUcoIg4UXcDhiVmQIFgp4rBy+dSVCvKgjoYsc7OEuEiOn59Wy9E2U69bQL3L6au8cT6GfshXtdIDyXoEQkCdoS0lJRaeHjninPvWupndzQHua7U5fM8FGt9pf5hqn/mHwWjXgGpHJsYoR4bzdzNdBrlZjMb37FbrZU2g33ujWcxlX8Z+Jwjp5n6+QEF1YPVq/3NnT1UCV6kOU5673W6e55cJ+bi0qv3PofL4lGUgQQPS0iEdSc3B9VIWMnVNllJmUXjQM1laUVBoDZX2mL40x4SJ3P3UUdm5j+SmKQNxQO0Hfluuby7XC8XeOFfKvr2qYXeboiy8Yvvap424M+odSHPq7aZ5mdJtzJZeU93wqiROntA9dmi31RRG2lj4t9okxkYc= X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: 12f004a1-32e7-413c-e56c-08d816c243c6 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Jun 2020 15:38:09.1232 (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: 6Kv2szDFGS6+mXiYUgZkhLPozhCaf6P3Eah8Q4TPcNIG4Ku+y7BXcCtplBesL/Pu1zRAKDFMqQJaJ5Ga+3qJ45b3cHNTx2+l1ySsJeQhYsk= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4501 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216,18.0.687 definitions=2020-06-22_09:2020-06-22,2020-06-22 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 clxscore=1015 adultscore=0 mlxlogscore=999 spamscore=0 mlxscore=0 lowpriorityscore=0 phishscore=0 priorityscore=1501 bulkscore=0 cotscore=-2147483648 malwarescore=0 impostorscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006220116 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add INT1 interrupt support. Support interrupt edge and level, active high or low. Push-pull or open-drain configurations. Interrupt will be used to read data from the FIFO. Signed-off-by: Jean-Baptiste Maneyrol --- drivers/iio/imu/inv_icm42600/inv_icm42600.h | 2 +- .../iio/imu/inv_icm42600/inv_icm42600_core.c | 101 +++++++++++++++++- .../iio/imu/inv_icm42600/inv_icm42600_i2c.c | 3 +- .../iio/imu/inv_icm42600/inv_icm42600_spi.c | 3 +- 4 files changed, 105 insertions(+), 4 deletions(-) diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h b/drivers/iio/imu/inv_icm42600/inv_icm42600.h index 3b190461a2b6..148894c888cc 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h @@ -372,7 +372,7 @@ 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); struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st); diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c index a35ff21f50bb..95b2a6d91e5b 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c @@ -9,8 +9,11 @@ #include #include #include +#include +#include #include #include +#include #include #include @@ -408,6 +411,82 @@ static int inv_icm42600_setup(struct inv_icm42600_state *st, return inv_icm42600_set_conf(st, hw->conf); } +static irqreturn_t inv_icm42600_irq_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; + + /* FIFO full */ + if (status & INV_ICM42600_INT_STATUS_FIFO_FULL) + dev_warn(dev, "FIFO full data lost!\n"); + +out_unlock: + mutex_unlock(&st->lock); + return IRQ_HANDLED; +} + +/** + * inv_icm42600_irq_init() - initialize int pin and interrupt handler + * @st: driver internal state + * @irq: irq number + * @irq_type: irq trigger type + * @open_drain: true if irq is open drain, false for push-pull + * + * Returns 0 on success, a negative error code otherwise. + */ +static int inv_icm42600_irq_init(struct inv_icm42600_state *st, int irq, + int irq_type, bool open_drain) +{ + struct device *dev = regmap_get_device(st->map); + unsigned int val; + int ret; + + /* configure INT1 interrupt: default is active low on edge */ + switch (irq_type) { + case IRQF_TRIGGER_RISING: + case IRQF_TRIGGER_HIGH: + val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_HIGH; + break; + default: + val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_LOW; + break; + } + + switch (irq_type) { + case IRQF_TRIGGER_LOW: + case IRQF_TRIGGER_HIGH: + val |= INV_ICM42600_INT_CONFIG_INT1_LATCHED; + break; + default: + break; + } + + if (!open_drain) + 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; + + return devm_request_threaded_irq(dev, irq, NULL, + inv_icm42600_irq_handler, irq_type, + "inv_icm42600", st); +} + static int inv_icm42600_enable_regulator_vddio(struct inv_icm42600_state *st) { int ret; @@ -452,11 +531,14 @@ 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; + bool open_drain; int ret; if (chip < 0 || chip >= INV_CHIP_NB) { @@ -464,6 +546,19 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, return -ENODEV; } + /* get irq properties, 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; + + open_drain = device_property_read_bool(dev, "drive-open-drain"); + st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL); if (!st) return -ENOMEM; @@ -517,6 +612,10 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, if (IS_ERR(st->indio_accel)) return PTR_ERR(st->indio_accel); + ret = inv_icm42600_irq_init(st, irq, irq_type, open_drain); + 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_i2c.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c index 4789cead23b3..85b1934cec60 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c @@ -64,7 +64,8 @@ static int inv_icm42600_probe(struct i2c_client *client) if (IS_ERR(regmap)) return PTR_ERR(regmap); - return inv_icm42600_core_probe(regmap, chip, inv_icm42600_i2c_bus_setup); + return inv_icm42600_core_probe(regmap, chip, client->irq, + inv_icm42600_i2c_bus_setup); } static const struct of_device_id inv_icm42600_of_matches[] = { diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c index a9c5e2fdbe2a..323789697a08 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c @@ -63,7 +63,8 @@ static int inv_icm42600_probe(struct spi_device *spi) if (IS_ERR(regmap)) return PTR_ERR(regmap); - return inv_icm42600_core_probe(regmap, chip, inv_icm42600_spi_bus_setup); + return inv_icm42600_core_probe(regmap, chip, spi->irq, + inv_icm42600_spi_bus_setup); } static const struct of_device_id inv_icm42600_of_matches[] = { From patchwork Mon Jun 22 15:37:26 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: 11618251 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1A91390 for ; Mon, 22 Jun 2020 15:38:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D682420760 for ; Mon, 22 Jun 2020 15:38:44 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="g0ruazAp"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="b15J0QGm" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729828AbgFVPif (ORCPT ); Mon, 22 Jun 2020 11:38:35 -0400 Received: from mx0a-00328301.pphosted.com ([148.163.145.46]:3092 "EHLO mx0a-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729716AbgFVPiS (ORCPT ); Mon, 22 Jun 2020 11:38:18 -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 05MFaLZk021513; Mon, 22 Jun 2020 08:38:13 -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=RxG78sBbjwxGmklGd8mcrvGQRUNOJxBrhHDSD7D3jec=; b=g0ruazApDSgaxgMQcEpJe4whu6+37Bj2GNGPPO4KBW+f1VJu/hveJO+kl+2bXFzKKHS8 ZscaOQiz+pPavshPcmFFpEOr+q042/keyYXwK5RWv3qQaYg+kOWV3AvEGIZ94Dswe3/B xGane9CbwuYfJpEIwRQyvPs4+0a8XTMDo4zqaM36LNE4S4t9mO5Nsfre/AbhsOg5pWgb nZ+nrxJPQWIzxxKXbBdcoi6znjz7sKvs6Lg0upppZB4KegS2EvvdxzCwc611nuKH3PB3 e1iFINilzNff0sNlH1dnsZ+1KjNQSHF/f/uvWw3QeLX3KcmmO09mn+9Pl237mVb3iiVx bQ== Received: from nam04-sn1-obe.outbound.protection.outlook.com (mail-sn1nam04lp2055.outbound.protection.outlook.com [104.47.44.55]) by mx0a-00328301.pphosted.com with ESMTP id 31sdxnrty1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 22 Jun 2020 08:38:12 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=CaNjl4I95kW9yMGhP1m9/Ey33XWuY7guEeuzkbbkg/kIhs0kn3n8qoatjeANwLvRgRQO15xAVGFcmRulMZyKPnU8+zrP7BAyRL19KieAoVlrSUis9DnDyhbQvg0BM++ZfSlihQjaWynGO6J5ZvhniGsVqmzJyhH/ghpK5uKM6l1fDRuC5ca52az2qJ3ImvE+e4m+7EGBC6VMQQ2j20G1FJ4bulUMHW7i8ITKcvAfdPWldgxVQRmnVyvDulwATCn0D7eD3TPEjpD9OKGGcML4Z+qU7AcUJYueO+bnxGY0nJ2axO9SStnXl2dSfPwNpFKT67dd/XmH13zP5zsFt8QOUA== 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=RxG78sBbjwxGmklGd8mcrvGQRUNOJxBrhHDSD7D3jec=; b=CSnzfO0gWLHxYaYSM8hds3JX6vnxIs6Rm71+cYo0Uz9zpsJZJ+AM7EZAJxjuP1nM64s9ZQTgfzP7oRbKl6y7Butfp59FBCu64V49ARBkp6qujJatkgJ1OnHWjAOmTm8q7UP/idkrnrs3cvTq27tgrTeeSGHzUlnvxycyE7Q6M7HewPYGaCITvMTWyZq+ezpu8JAlFjeh2OOfRsopqQf89ZVxw3ZifP6pcCljhfWbeVi1PRp3XMWxsinsOz1fmaq0oOy9i7VplQ8IPvRy1fs9Jq5GiaWpAQtI1OWDqtnEFLE/y+6CJ9XcI3jz4uOjDYTMPUg3u3UFhxXqPr6KMUlzJg== 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=RxG78sBbjwxGmklGd8mcrvGQRUNOJxBrhHDSD7D3jec=; b=b15J0QGmOiGtp4y3lZN//m3sC3A7dZPwXhRU59lopw4HjKG1S76np6f4HBZmYDu2dYf4SB+ij7kucb1/1lG2DWhvoi7HqFK2W9qObkRyKZUTqsmIoKVm0LqNzoQfIwMul/kfriAfK2S6IVaXL31k+vPWs9hlPavTQPXMXropc2o= 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.3109.22; Mon, 22 Jun 2020 15:38:11 +0000 Received: from MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0]) by MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0%7]) with mapi id 15.20.3109.027; Mon, 22 Jun 2020 15:38:11 +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 v4 10/13] iio: imu: inv_icm42600: add buffer support in iio devices Date: Mon, 22 Jun 2020 17:37:26 +0200 Message-Id: <20200622153729.12702-11-jmaneyrol@invensense.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200622153729.12702-1-jmaneyrol@invensense.com> References: <20200622153729.12702-1-jmaneyrol@invensense.com> X-ClientProxiedBy: LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) 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 LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3109.21 via Frontend Transport; Mon, 22 Jun 2020 15:38:09 +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: dae994d8-1fce-4cc6-dec4-08d816c244c1 X-MS-TrafficTypeDiagnostic: MN2PR12MB4501: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:4125; X-Forefront-PRVS: 0442E569BC X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: /ivP+bC4OF93y4/5RT+/e4ziUbLol139UDu54dF+7vzmy/ltnyAd2OSNLezJYuFYCXu1OeEVJdmfz0dIk6Kf2MO0hUSXPHLGBhyBIeG01Tb20+Jq/yItVbdePKCQc33vKrUxFmHxCb1DmzbVUxuZa6squyZxhusFLtZBRJuYWE41hLvNbHmNAzMO1hcpg/+/trDdvTHQ9e8kaq5l3YuCN3slnU3KS13oDlBUCLwe3VGM+EzA6b7kTrmG+rsZBjFrTnuLcisX1CPfWMfmOl9MT5Div5vT7mr6Xs+FWt1gvpYMf8jPWipksuE8tLKQ/KV7iHQYYvhVZL/RgwtQEFH4YA== 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)(39850400004)(136003)(366004)(396003)(4326008)(66946007)(7696005)(52116002)(8676002)(66476007)(66556008)(956004)(2616005)(1076003)(83380400001)(107886003)(86362001)(36756003)(30864003)(478600001)(6486002)(6666004)(26005)(316002)(8936002)(16526019)(5660300002)(2906002)(186003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: qskaQdK1ufi2Ae/+W254uxvM+mTtxd3Eo3Wx4FDfHgralk4zaDOOW+U0kuPPqgryjBM5wjN0zkn8IDsyWKYjoSIyxYBL1V6B3sRrEHV+ikQW2ZgtLtCkORJfbbgnRHdZaPdrQ6m7xW2GNMsd0Ij6I/ySTH2fh7M3bnX0LtcH1pgOZN2XU59cbfth2szjpNJ6lBLegTcnR8RruAkJsRG08It2JI5ygEjnY9sgYMrUScAzsrI49BJuQHZVFU54dSgTdvl5mcao1PH6e1KkDSNRq09A/bNRfr0j9m1RUtjzvQISTmqubPxNyDdLun/iyEuRxyzQE1Txc2YchwMhB6RI/TeiIYUpLEW+pcp+f7W8OnHoLYpWIo72MQ4mVDvmJIX9I2cvwD5z8A7E2Q3361pJeSM1jyclt41REH8/bBruixauBH6fr9apTS7YbKa5Y7DyDoBxjWaC0tKZ3oOj2ZXu4r99nO6Z236dvtqD98OXewk= X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: dae994d8-1fce-4cc6-dec4-08d816c244c1 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Jun 2020 15:38:10.8496 (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: vfB4FTYvxst+LLue8BECB48EMOlCXV76Pi3KNh/UmqojY+c390AA+5FI28wHVkDc977gJ39uBEu22/DY/tfqQ4aqMorqe20JdUE9Yt/PQT8= X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB4501 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216,18.0.687 definitions=2020-06-22_09:2020-06-22,2020-06-22 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 mlxscore=0 phishscore=0 clxscore=1015 bulkscore=0 cotscore=-2147483648 suspectscore=0 impostorscore=0 spamscore=0 mlxlogscore=999 malwarescore=0 adultscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006220116 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add all FIFO parsing and reading functions. Add accel and gyro kfifo buffer and FIFO data parsing. Use device interrupt for reading data FIFO and launching accel and gyro parsing. Support hwfifo watermark by multiplexing gyro and accel settings. Support hwfifo flush. 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_accel.c | 162 ++++- .../imu/inv_icm42600/inv_icm42600_buffer.c | 573 ++++++++++++++++++ .../imu/inv_icm42600/inv_icm42600_buffer.h | 98 +++ .../iio/imu/inv_icm42600/inv_icm42600_core.c | 30 + .../iio/imu/inv_icm42600/inv_icm42600_gyro.c | 162 ++++- 8 files changed, 1033 insertions(+), 2 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 22390a72f0a3..50cbcfcb6cf1 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_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 48965824f00c..0f49f6df3647 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_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 148894c888cc..7b52d92739c3 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h @@ -14,6 +14,8 @@ #include #include +#include "inv_icm42600_buffer.h" + enum inv_icm42600_chip { INV_CHIP_ICM42600, INV_CHIP_ICM42602, @@ -123,6 +125,7 @@ struct inv_icm42600_suspended { * @indio_gyro: gyroscope IIO device. * @indio_accel: accelerometer IIO device. * @buffer: data transfer buffer aligned for DMA. + * @fifo: FIFO management structure. */ struct inv_icm42600_state { struct mutex lock; @@ -137,6 +140,7 @@ struct inv_icm42600_state { struct iio_dev *indio_gyro; struct iio_dev *indio_accel; uint8_t buffer[2] ____cacheline_aligned; + struct inv_icm42600_fifo fifo; }; /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */ @@ -377,6 +381,10 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st); +int inv_icm42600_gyro_parse_fifo(struct iio_dev *indio_dev); + struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st); +int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev); + #endif diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c index 3f214df44093..fbc029bd6e72 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c @@ -11,9 +11,12 @@ #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) \ { \ @@ -64,6 +67,78 @@ static const struct iio_chan_spec inv_icm42600_accel_channels[] = { INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP), }; +/* + * IIO buffer data: size must be a power of 2 + * 8 bytes: 6 bytes acceleration and 2 bytes temperature + */ +struct inv_icm42600_accel_buffer { + struct inv_icm42600_fifo_sensor_data accel; + int16_t temp; +}; + +#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, +}; + +/* 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 */ + 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) @@ -248,7 +323,12 @@ static int inv_icm42600_accel_write_odr(struct inv_icm42600_state *st, mutex_lock(&st->lock); ret = inv_icm42600_set_accel_conf(st, &conf, NULL); + if (ret) + goto out_unlock; + inv_icm42600_buffer_update_fifo_period(st); + inv_icm42600_buffer_update_watermark(st); +out_unlock: mutex_unlock(&st->lock); pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); @@ -563,12 +643,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, }; struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st) @@ -576,6 +695,7 @@ struct iio_dev *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; + struct iio_buffer *buffer; int ret; name = devm_kasprintf(dev, GFP_KERNEL, "%s-accel", st->name); @@ -586,12 +706,20 @@ struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st) if (!indio_dev) return ERR_PTR(-ENOMEM); + buffer = devm_iio_kfifo_allocate(dev); + if (!buffer) + return ERR_PTR(-ENOMEM); + iio_device_set_drvdata(indio_dev, st); indio_dev->name = name; indio_dev->info = &inv_icm42600_accel_info; - indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; 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; + indio_dev->setup_ops = &inv_icm42600_buffer_ops; + + iio_device_attach_buffer(indio_dev, buffer); ret = devm_iio_device_register(dev, indio_dev); if (ret) @@ -599,3 +727,35 @@ struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st) return indio_dev; } + +int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + ssize_t i, size; + const void *accel, *gyro, *timestamp; + const int8_t *temp; + unsigned int odr; + struct inv_icm42600_accel_buffer buffer; + + /* 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); + /* 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)) + continue; + + /* buffer is copied to userspace, zeroing it to avoid any data leak */ + memset(&buffer, 0, sizeof(buffer)); + memcpy(&buffer.accel, accel, sizeof(buffer.accel)); + /* convert 8 bits FIFO temperature in high resolution format */ + buffer.temp = temp ? (*temp * 64) : 0; + iio_push_to_buffers(indio_dev, &buffer); + } + + 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..e58e6f0c5698 --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c @@ -0,0 +1,573 @@ +// 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" +#include "inv_icm42600_buffer.h" + +/* 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) + +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 + +ssize_t inv_icm42600_fifo_decode_packet(const void *packet, const void **accel, + const void **gyro, const int8_t **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; +} + +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; +} + +/** + * inv_icm42600_buffer_update_watermark - update watermark FIFO threshold + * @st: driver internal state + * + * Returns 0 on success, a negative error code otherwise. + * + * FIFO watermark threshold is computed based on the required watermark values + * set for gyro and accel sensors. Since watermark is all about acceptable data + * latency, use the smallest setting between the 2. It means choosing the + * smallest latency but this is not as simple as choosing the smallest watermark + * value. Latency depends on watermark and ODR. It requires several steps: + * 1) compute gyro and accel latencies and choose the smallest value. + * 2) adapt the choosen latency so that it is a multiple of both gyro and accel + * ones. Otherwise it is possible that you don't meet a requirement. (for + * example with gyro @100Hz wm 4 and accel @100Hz with wm 6, choosing the + * value of 4 will not meet accel latency requirement because 6 is not a + * multiple of 4. You need to use the value 2.) + * 3) Since all periods are multiple of each others, watermark is computed by + * dividing this computed latency by the smallest period, which corresponds + * to the FIFO frequency. Beware that this is only true because we are not + * using 500Hz frequency which is not a multiple of the others. + */ +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; + uint32_t latency_gyro, latency_accel, latency; + bool restore; + __le16 raw_wm; + int ret; + + packet_size = inv_icm42600_get_packet_size(st->fifo.en); + + /* compute sensors 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); + /* use us for odr to avoid overflow using 32 bits values */ + period_gyro = inv_icm42600_odr_to_period(st->conf.gyro.odr) / 1000UL; + period_accel = inv_icm42600_odr_to_period(st->conf.accel.odr) / 1000UL; + latency_gyro = period_gyro * wm_gyro; + latency_accel = period_accel * wm_accel; + + /* 0 value for watermark means that the sensor is turned off */ + if (latency_gyro == 0) { + watermark = wm_accel; + } else if (latency_accel == 0) { + watermark = wm_gyro; + } else { + /* compute the smallest latency that is a multiple of both */ + if (latency_gyro <= latency_accel) + latency = latency_gyro - (latency_accel % latency_gyro); + else + latency = latency_accel - (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 = latency / period; + if (watermark < 1) + watermark = 1; + } + + /* compute watermark value in bytes */ + wm_size = watermark * packet_size; + + /* changing FIFO watermark requires to turn off watermark interrupt */ + ret = regmap_update_bits_check(st->map, INV_ICM42600_REG_INT_SOURCE0, + INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN, + 0, &restore); + if (ret) + return ret; + + raw_wm = INV_ICM42600_FIFO_WATERMARK_VAL(wm_size); + memcpy(st->buffer, &raw_wm, sizeof(raw_wm)); + ret = regmap_bulk_write(st->map, INV_ICM42600_REG_FIFO_WATERMARK, + st->buffer, sizeof(raw_wm)); + if (ret) + return ret; + + /* restore watermark interrupt */ + if (restore) { + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0, + INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN, + INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN); + 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; +} + +/* + * update_scan_mode callback is turning sensors on and setting data FIFO enable + * bits. + */ +static int inv_icm42600_buffer_postenable(struct iio_dev *indio_dev) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + mutex_lock(&st->lock); + + /* exit if FIFO is already on */ + if (st->fifo.on) { + ret = 0; + goto out_on; + } + + /* set FIFO threshold interrupt */ + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0, + INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN, + INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN); + 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: first read of FIFO count after reset is always 0 */ + ret = regmap_bulk_read(st->map, INV_ICM42600_REG_FIFO_COUNT, st->buffer, 2); + if (ret) + goto out_unlock; + +out_on: + /* increase FIFO on counter */ + st->fifo.on++; +out_unlock: + mutex_unlock(&st->lock); + return ret; +} + +static int inv_icm42600_buffer_predisable(struct iio_dev *indio_dev) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + int ret; + + mutex_lock(&st->lock); + + /* exit if there are several sensors using the FIFO */ + if (st->fifo.on > 1) { + ret = 0; + goto out_off; + } + + /* 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 */ + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_SOURCE0, + INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN, 0); + if (ret) + goto out_unlock; + +out_off: + /* decrease FIFO on counter */ + st->fifo.on--; +out_unlock: + mutex_unlock(&st->lock); + return ret; +} + +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_temp = 0; + unsigned int sleep_sensor = 0; + unsigned int sleep; + 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_sensor); + else + ret = inv_icm42600_set_accel_conf(st, &conf, &sleep_sensor); + if (ret) + goto out_unlock; + + /* if FIFO is off, turn temperature off */ + if (!st->fifo.on) + ret = inv_icm42600_set_temp_conf(st, false, &sleep_temp); + +out_unlock: + mutex_unlock(&st->lock); + + /* sleep maximum required time */ + if (sleep_sensor > sleep_temp) + sleep = sleep_sensor; + else + sleep = sleep_temp; + 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 = inv_icm42600_buffer_postenable, + .predisable = inv_icm42600_buffer_predisable, + .postdisable = inv_icm42600_buffer_postdisable, +}; + +int inv_icm42600_buffer_fifo_read(struct inv_icm42600_state *st, + unsigned int max) +{ + size_t max_count; + __be16 *raw_fifo_count; + ssize_t i, size; + const void *accel, *gyro, *timestamp; + const int8_t *temp; + 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 */ + raw_fifo_count = (__be16 *)st->buffer; + 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_cpup(raw_fifo_count); + + /* check and clamp 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_fifo_parse(struct inv_icm42600_state *st) +{ + int ret; + + if (st->fifo.nb.total == 0) + return 0; + + if (st->fifo.nb.gyro > 0) { + ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro); + if (ret) + return ret; + } + + if (st->fifo.nb.accel > 0) { + ret = inv_icm42600_accel_parse_fifo(st->indio_accel); + if (ret) + return ret; + } + + return 0; +} + +int inv_icm42600_buffer_hwfifo_flush(struct inv_icm42600_state *st, + unsigned int count) +{ + int ret; + + ret = inv_icm42600_buffer_fifo_read(st, count); + if (ret) + return ret; + + if (st->fifo.nb.total == 0) + return 0; + + if (st->fifo.nb.gyro > 0) { + ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro); + if (ret) + return ret; + } + + if (st->fifo.nb.accel > 0) { + ret = inv_icm42600_accel_parse_fifo(st->indio_accel); + if (ret) + return ret; + } + + return 0; +} + +int inv_icm42600_buffer_init(struct inv_icm42600_state *st) +{ + unsigned int val; + int ret; + + /* + * Default FIFO configuration (bits 7 to 5) + * - use invalid value + * - FIFO count in bytes + * - FIFO count in big endian + */ + val = INV_ICM42600_INTF_CONFIG0_FIFO_COUNT_ENDIAN; + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0, + GENMASK(7, 5), val); + if (ret) + return ret; + + /* + * Enable FIFO partial read and continuous watermark interrupt. + * Disable all FIFO EN bits. + */ + 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, + GENMASK(6, 5) | GENMASK(3, 0), 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..de2a3949dcc7 --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h @@ -0,0 +1,98 @@ +/* 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 - FIFO state variables + * @on: reference counter for FIFO on. + * @en: bits field of INV_ICM42600_SENSOR_* for FIFO EN bits. + * @period: FIFO internal period. + * @watermark: watermark configuration values for accel and gyro. + * @count: number of bytes in the FIFO data buffer. + * @nb: gyro, accel and total samples in the FIFO data buffer. + * @data: FIFO data buffer aligned for DMA (2kB + 32 bytes of read cache). + */ +struct inv_icm42600_fifo { + unsigned int on; + 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] ____cacheline_aligned; +}; + +/* FIFO data packet */ +struct inv_icm42600_fifo_sensor_data { + __be16 x; + __be16 y; + __be16 z; +} __packed; +#define INV_ICM42600_FIFO_DATA_INVALID -32768 + +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; +} + +ssize_t inv_icm42600_fifo_decode_packet(const void *packet, const void **accel, + const void **gyro, const int8_t **temp, + const void **timestamp, unsigned int *odr); + +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_fifo_parse(struct inv_icm42600_state *st); + +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 95b2a6d91e5b..9e1f6e65fd45 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c @@ -18,6 +18,7 @@ #include #include "inv_icm42600.h" +#include "inv_icm42600_buffer.h" static const struct regmap_range_cfg inv_icm42600_regmap_ranges[] = { { @@ -428,6 +429,18 @@ static irqreturn_t inv_icm42600_irq_handler(int irq, void *_data) 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) { + ret = inv_icm42600_buffer_fifo_read(st, 0); + if (ret) { + dev_err(dev, "FIFO read error %d\n", ret); + goto out_unlock; + } + ret = inv_icm42600_buffer_fifo_parse(st); + if (ret) + dev_err(dev, "FIFO parsing error %d\n", ret); + } + out_unlock: mutex_unlock(&st->lock); return IRQ_HANDLED; @@ -604,6 +617,10 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, if (ret) return ret; + ret = inv_icm42600_buffer_init(st); + if (ret) + return ret; + st->indio_gyro = inv_icm42600_gyro_init(st); if (IS_ERR(st->indio_gyro)) return PTR_ERR(st->indio_gyro); @@ -649,6 +666,14 @@ static int __maybe_unused inv_icm42600_suspend(struct device *dev) goto out_unlock; } + /* disable FIFO data streaming */ + if (st->fifo.on) { + 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); @@ -688,6 +713,11 @@ static int __maybe_unused inv_icm42600_resume(struct device *dev) if (ret) goto out_unlock; + /* restore FIFO data streaming */ + if (st->fifo.on) + 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 6a0e7661fa48..3b1f7594b60b 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c @@ -11,9 +11,12 @@ #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) \ { \ @@ -64,6 +67,78 @@ static const struct iio_chan_spec inv_icm42600_gyro_channels[] = { INV_ICM42600_TEMP_CHAN(INV_ICM42600_GYRO_SCAN_TEMP), }; +/* + * IIO buffer data: size must be a power of 2 + * 8 bytes: 6 bytes angular velocity and 2 bytes temperature + */ +struct inv_icm42600_gyro_buffer { + struct inv_icm42600_fifo_sensor_data gyro; + int16_t temp; +}; + +#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, +}; + +/* 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 */ + 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) @@ -260,7 +335,12 @@ static int inv_icm42600_gyro_write_odr(struct inv_icm42600_state *st, mutex_lock(&st->lock); ret = inv_icm42600_set_gyro_conf(st, &conf, NULL); + if (ret) + goto out_unlock; + inv_icm42600_buffer_update_fifo_period(st); + inv_icm42600_buffer_update_watermark(st); +out_unlock: mutex_unlock(&st->lock); pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); @@ -574,12 +654,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, }; struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st) @@ -587,6 +706,7 @@ struct iio_dev *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; + struct iio_buffer *buffer; int ret; name = devm_kasprintf(dev, GFP_KERNEL, "%s-gyro", st->name); @@ -597,12 +717,20 @@ struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st) if (!indio_dev) return ERR_PTR(-ENOMEM); + buffer = devm_iio_kfifo_allocate(dev); + if (!buffer) + return ERR_PTR(-ENOMEM); + iio_device_set_drvdata(indio_dev, st); indio_dev->name = name; indio_dev->info = &inv_icm42600_gyro_info; - indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE; 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; + indio_dev->setup_ops = &inv_icm42600_buffer_ops; + + iio_device_attach_buffer(indio_dev, buffer); ret = devm_iio_device_register(dev, indio_dev); if (ret) @@ -610,3 +738,35 @@ struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st) return indio_dev; } + +int inv_icm42600_gyro_parse_fifo(struct iio_dev *indio_dev) +{ + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + ssize_t i, size; + const void *accel, *gyro, *timestamp; + const int8_t *temp; + unsigned int odr; + struct inv_icm42600_gyro_buffer buffer; + + /* 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); + /* 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)) + continue; + + /* buffer is copied to userspace, zeroing it to avoid any data leak */ + memset(&buffer, 0, sizeof(buffer)); + memcpy(&buffer.gyro, gyro, sizeof(buffer.gyro)); + /* convert 8 bits FIFO temperature in high resolution format */ + buffer.temp = temp ? (*temp * 64) : 0; + iio_push_to_buffers(indio_dev, &buffer); + } + + return 0; +} From patchwork Mon Jun 22 15:37:27 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: 11618247 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1734090 for ; Mon, 22 Jun 2020 15:38:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DB7E42075A for ; Mon, 22 Jun 2020 15:38:33 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="PeX3D6Ax"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="QMrmQhFv" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729804AbgFVPiZ (ORCPT ); Mon, 22 Jun 2020 11:38:25 -0400 Received: from mx0a-00328301.pphosted.com ([148.163.145.46]:5618 "EHLO mx0a-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729742AbgFVPiU (ORCPT ); Mon, 22 Jun 2020 11:38:20 -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 05MFa4C9021446; Mon, 22 Jun 2020 08:38: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=XHIDrMlShwcYhMmtooXywMhG5BaU+fNN6M8/5X7z1QA=; b=PeX3D6AxFu81kF2UBd+4uQcIVtw4/RlgkPFNVzggUDPa2MCZ035Hej/fD+clMyek83dd aa98SjyjfpC8N0uakvCQJonP/0yHLRXXKtq3VqZ6jB1bh9XI/Xj+bC0LNZRzdB5muzWh UMJDgZ6CvbGjCyzXKvAnDoDk8l2B/UbzWVesOJ0eXk2Dh4aEf9KsRNeU7EwiuUIwE4HZ fMlVeDLcsad5b4gIET7jONbbf+O2F1E9DZwNngD6xbQ5cKgZU4ECQO/I8azfblOfiilv h3FytTB0qVchBI/JnBxvV6eop/Yb3sQxMa4LPNaT2cnAq3O1xKDUq3A7wrjOkkckrqa+ cQ== Received: from nam04-co1-obe.outbound.protection.outlook.com (mail-co1nam04lp2055.outbound.protection.outlook.com [104.47.45.55]) by mx0a-00328301.pphosted.com with ESMTP id 31sdxnrty5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 22 Jun 2020 08:38:15 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=FxmHnYSaXwAHVwwdU6m7tDyNcafZJF3iF0KJN/fWhzcLYxyQ6QTu9tS1c2GHCe7T5eY3G/sHqdP0d2AJabDd24iqb8gmHzWCbCCBsQpL4z+80kn+NGLu2RspfQ7c4cYgV4f6GoCxOJ5yxYETnGBCD+8CwH0uCsMDIfGFvey/D7e1lYXv5kRuynI4v6c4ms5hzL2RHhBJWXbB+nEAFr+uyFTZIdcZcuo+SNbb6t1JT+CNH06TbKkh/MMVmNXdvmmysbyyFWntw+QGReDA3oeQlEXcwkTegdAovJgjRUwrlMMyss251NvbMZ/3nbkUxnpcIAUsB+oibSDXPV1NV6xaPA== 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=XHIDrMlShwcYhMmtooXywMhG5BaU+fNN6M8/5X7z1QA=; b=k5M8DALnzWTO5IIiawd5eBLg89oS5XN3Ly3tLB5oinSNTcnPudMJmqy+jI5c8sFNFgCM0dvB87k9s/eH7BxiI3UArov5BX/f3XS0WA1iFfFHCI4tGMKUwUUppNKl6kCrFcvt8oPh05bB1qXmhe1YRDCJeYd0lXA1oZF2cXoWjNKgETMt+RUm0XBxQo6PKq8lqHjUYmUWLOo9MTWA1b61qo5jH91/PVvd5kw7v/RLfvdpUN0VnCAabeFeA+3p2ZULGQ4LIp6kQ1kFrvPhkaCn05a7lnnzLJASfdAISR6p20xT5dJAh/IAmI3rZXHX5Vk0Us7Zt/gBK/S/8VNHQvWoVg== 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=XHIDrMlShwcYhMmtooXywMhG5BaU+fNN6M8/5X7z1QA=; b=QMrmQhFvbjO2HVU9ejpZkhoPCeGbzUlUqpuYStk1eaYmt4seOXzFFieoEGL/stel1SVZNBYQE1HqnYFmrJRFjfttPaIJ9VA6wA+KYEYSFJXqD3zMjVjveaIwdW/hpDW5oIjFfV2urmKuVyL9jJdRVegYs/KebWFOTJweK4PfkQw= 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 BL0PR12MB2338.namprd12.prod.outlook.com (2603:10b6:207:4c::28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3109.22; Mon, 22 Jun 2020 15:38:13 +0000 Received: from MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0]) by MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0%7]) with mapi id 15.20.3109.027; Mon, 22 Jun 2020 15:38:12 +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 v4 11/13] iio: imu: inv_icm42600: add accurate timestamping Date: Mon, 22 Jun 2020 17:37:27 +0200 Message-Id: <20200622153729.12702-12-jmaneyrol@invensense.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200622153729.12702-1-jmaneyrol@invensense.com> References: <20200622153729.12702-1-jmaneyrol@invensense.com> X-ClientProxiedBy: LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) 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 LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3109.21 via Frontend Transport; Mon, 22 Jun 2020 15:38: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: ed8a655c-0ada-4753-3d0f-08d816c245c8 X-MS-TrafficTypeDiagnostic: BL0PR12MB2338: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:9508; X-Forefront-PRVS: 0442E569BC X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: x6LTTRsJHJC+BethotsL7f+V7YydfaxjDZj5cbI2UXZcLeiQct47ZZkdzIfEx6APIcXOK7RCbD8d8+8Z4i4T6UeKcCYaNMbKbdxC+1R9vD52CJuEbTkRR1ao9fpna1DZIlVNLOgARv64yDo5bbwLfL9p07MlbloRNZ6lHfOemShoDfpXhfABoOsjUmEbCUPvHGJFFI8BIo1HKpbtx3FwiWflDoSRLBt1OhTe/gWwljdLQ6VcP+U289asaOfOngz/vlPwBexeiMO2mq9vxGAu9IYiouQfqDqRQs2uRjyj8/TiYxW5BYz5xWQHrsPIbYcJta2ZbM68BknGpFc8Tx88uA== 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:(396003)(346002)(366004)(136003)(376002)(39850400004)(6486002)(36756003)(2906002)(30864003)(107886003)(16526019)(186003)(8936002)(956004)(2616005)(83380400001)(26005)(8676002)(6666004)(478600001)(86362001)(1076003)(66556008)(52116002)(7696005)(66476007)(5660300002)(4326008)(316002)(66946007);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: W39hTG1Da6V7gWjKdYfcFcTeG+5OoNOaZLPd7hAUjj+98u8+PDd8bIi2NZIRc4hj3SMNFxN2FNHcTidwhvBBPLtt1j6UfUozvsXkSxh97xnUc4eQ7aeh2aecQN4pn1CIGLE6Req0YWsbm1BmVWU3ck9z3+SN9XITdCZ567jcRiH0PrEud67G8AAr1mnF7UvMdlA7AeUrLhl2Su2Wg+Qa6qgpvivVW8c6DeZXXTOP2uLSS0K71O17iyuL+yxWPpmz3stnOhwbRLRhVwWGXjXBeJa7i2GPmX9iz9SLpxBtf3qfl+ypSYkF4cInXjLAFkCQpxxgPyuXyKQzbq6mNT8SoJnN11aa+AnI78BAdZYTgqIFusvpovXfmxVr8E6L/h7II8uX946AIYibpOFyP75Iy5A0FJYwlIZSPw32YSSVIrSBZx4tQ2WP/dLxFo/tNhvyjU3RzDajhDZKZH2KHNndc1TKwLfBKwZThWHkXwhkwkw= X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: ed8a655c-0ada-4753-3d0f-08d816c245c8 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Jun 2020 15:38:12.5322 (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: 6PmMUdv/a88N9z9t2nWLacFmQ4mokIlNpQCAxGOX0/8Wj0RZ+oSQLLCfnvhn/aivujZa0j4L0RybotqmIQFyAL3ZqDcJRiY0rjbBtMt6tKg= X-MS-Exchange-Transport-CrossTenantHeadersStamped: BL0PR12MB2338 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216,18.0.687 definitions=2020-06-22_09:2020-06-22,2020-06-22 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 mlxscore=0 phishscore=0 clxscore=1015 bulkscore=0 cotscore=-2147483648 suspectscore=2 impostorscore=0 spamscore=0 mlxlogscore=999 malwarescore=0 adultscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006220116 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add a timestamping mechanism for buffer that provides accurate event timestamps when using watermark. This mechanism estimates device internal clock by comparing FIFO interrupts delta time and device elapsed time computed by parsing FIFO data. Take interrupt timestamp in hard irq handler and add IIO device specific timestamp structures in device private allocation. Signed-off-by: Jean-Baptiste Maneyrol --- drivers/iio/imu/inv_icm42600/Makefile | 1 + drivers/iio/imu/inv_icm42600/inv_icm42600.h | 5 + .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 40 +++- .../imu/inv_icm42600/inv_icm42600_buffer.c | 28 +++ .../iio/imu/inv_icm42600/inv_icm42600_core.c | 17 +- .../iio/imu/inv_icm42600/inv_icm42600_gyro.c | 40 +++- .../imu/inv_icm42600/inv_icm42600_timestamp.c | 195 ++++++++++++++++++ .../imu/inv_icm42600/inv_icm42600_timestamp.h | 85 ++++++++ 8 files changed, 396 insertions(+), 15 deletions(-) create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h diff --git a/drivers/iio/imu/inv_icm42600/Makefile b/drivers/iio/imu/inv_icm42600/Makefile index 0f49f6df3647..291714d9aa54 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_buffer.o +inv-icm42600-y += inv_icm42600_timestamp.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 7b52d92739c3..c0f5059b13b3 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h @@ -126,6 +126,7 @@ struct inv_icm42600_suspended { * @indio_accel: accelerometer IIO device. * @buffer: data transfer buffer aligned for DMA. * @fifo: FIFO management structure. + * @timestamp: interrupt timestamps. */ struct inv_icm42600_state { struct mutex lock; @@ -141,6 +142,10 @@ struct inv_icm42600_state { struct iio_dev *indio_accel; uint8_t buffer[2] ____cacheline_aligned; struct inv_icm42600_fifo fifo; + struct { + int64_t gyro; + int64_t accel; + } timestamp; }; /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */ diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c index fbc029bd6e72..3441b0d61c5d 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c @@ -17,6 +17,7 @@ #include "inv_icm42600.h" #include "inv_icm42600_temp.h" #include "inv_icm42600_buffer.h" +#include "inv_icm42600_timestamp.h" #define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info) \ { \ @@ -50,6 +51,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[] = { @@ -65,15 +67,17 @@ 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: size must be a power of 2 - * 8 bytes: 6 bytes acceleration and 2 bytes temperature + * IIO buffer data: size must be a power of 2 and timestamp aligned + * 16 bytes: 6 bytes acceleration, 2 bytes temperature, 8 bytes timestamp */ struct inv_icm42600_accel_buffer { struct inv_icm42600_fifo_sensor_data accel; int16_t temp; + int64_t timestamp __aligned(8); }; #define INV_ICM42600_SCAN_MASK_ACCEL_3AXIS \ @@ -94,6 +98,7 @@ 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_timestamp *ts = iio_priv(indio_dev); struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; unsigned int fifo_en = 0; unsigned int sleep_temp = 0; @@ -121,6 +126,7 @@ static int inv_icm42600_accel_update_scan_mode(struct iio_dev *indio_dev, } /* update data FIFO write */ + inv_icm42600_timestamp_apply_odr(ts, 0, 0, 0); ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en); if (ret) goto out_unlock; @@ -301,9 +307,11 @@ static int inv_icm42600_accel_read_odr(struct inv_icm42600_state *st, return IIO_VAL_INT_PLUS_MICRO; } -static int inv_icm42600_accel_write_odr(struct inv_icm42600_state *st, +static int inv_icm42600_accel_write_odr(struct iio_dev *indio_dev, int val, int val2) { + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42600_timestamp *ts = iio_priv(indio_dev); struct device *dev = regmap_get_device(st->map); unsigned int idx; struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; @@ -322,6 +330,11 @@ static int inv_icm42600_accel_write_odr(struct inv_icm42600_state *st, pm_runtime_get_sync(dev); mutex_lock(&st->lock); + ret = inv_icm42600_timestamp_update_odr(ts, inv_icm42600_odr_to_period(conf.odr), + iio_buffer_enabled(indio_dev)); + if (ret) + goto out_unlock; + ret = inv_icm42600_set_accel_conf(st, &conf, NULL); if (ret) goto out_unlock; @@ -611,7 +624,7 @@ static int inv_icm42600_accel_write_raw(struct iio_dev *indio_dev, iio_device_release_direct_mode(indio_dev); return ret; case IIO_CHAN_INFO_SAMP_FREQ: - return inv_icm42600_accel_write_odr(st, val, val2); + return inv_icm42600_accel_write_odr(indio_dev, val, val2); case IIO_CHAN_INFO_CALIBBIAS: ret = iio_device_claim_direct_mode(indio_dev); if (ret) @@ -694,6 +707,7 @@ struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st) { struct device *dev = regmap_get_device(st->map); const char *name; + struct inv_icm42600_timestamp *ts; struct iio_dev *indio_dev; struct iio_buffer *buffer; int ret; @@ -702,7 +716,7 @@ struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st) if (!name) return ERR_PTR(-ENOMEM); - indio_dev = devm_iio_device_alloc(dev, 0); + indio_dev = devm_iio_device_alloc(dev, sizeof(*ts)); if (!indio_dev) return ERR_PTR(-ENOMEM); @@ -710,6 +724,9 @@ struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st) if (!buffer) return ERR_PTR(-ENOMEM); + ts = iio_priv(indio_dev); + inv_icm42600_timestamp_init(ts, inv_icm42600_odr_to_period(st->conf.accel.odr)); + iio_device_set_drvdata(indio_dev, st); indio_dev->name = name; indio_dev->info = &inv_icm42600_accel_info; @@ -731,14 +748,17 @@ struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st) int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev) { struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42600_timestamp *ts = iio_priv(indio_dev); ssize_t i, size; + unsigned int no; const void *accel, *gyro, *timestamp; const int8_t *temp; unsigned int odr; + int64_t ts_val; struct inv_icm42600_accel_buffer buffer; /* parse all fifo packets */ - for (i = 0; i < st->fifo.count; i += size) { + for (i = 0, no = 0; i < st->fifo.count; i += size, ++no) { size = inv_icm42600_fifo_decode_packet(&st->fifo.data[i], &accel, &gyro, &temp, ×tamp, &odr); /* quit if error or FIFO is empty */ @@ -749,12 +769,18 @@ int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev) if (accel == NULL || !inv_icm42600_fifo_is_data_valid(accel)) continue; + /* update odr */ + if (odr & INV_ICM42600_SENSOR_ACCEL) + inv_icm42600_timestamp_apply_odr(ts, st->fifo.period, + st->fifo.nb.total, no); + /* buffer is copied to userspace, zeroing it to avoid any data leak */ memset(&buffer, 0, sizeof(buffer)); memcpy(&buffer.accel, accel, sizeof(buffer.accel)); /* convert 8 bits FIFO temperature in high resolution format */ buffer.temp = temp ? (*temp * 64) : 0; - iio_push_to_buffers(indio_dev, &buffer); + ts_val = inv_icm42600_timestamp_pop(ts); + iio_push_to_buffers_with_timestamp(indio_dev, &buffer, ts_val); } return 0; diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c index e58e6f0c5698..99576b2c171f 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c @@ -13,6 +13,7 @@ #include #include "inv_icm42600.h" +#include "inv_icm42600_timestamp.h" #include "inv_icm42600_buffer.h" /* FIFO header: 1 byte */ @@ -374,6 +375,7 @@ static int inv_icm42600_buffer_postdisable(struct iio_dev *indio_dev) struct device *dev = regmap_get_device(st->map); unsigned int sensor; unsigned int *watermark; + struct inv_icm42600_timestamp *ts; struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; unsigned int sleep_temp = 0; unsigned int sleep_sensor = 0; @@ -383,9 +385,11 @@ static int inv_icm42600_buffer_postdisable(struct iio_dev *indio_dev) if (indio_dev == st->indio_gyro) { sensor = INV_ICM42600_SENSOR_GYRO; watermark = &st->fifo.watermark.gyro; + ts = iio_priv(st->indio_gyro); } else if (indio_dev == st->indio_accel) { sensor = INV_ICM42600_SENSOR_ACCEL; watermark = &st->fifo.watermark.accel; + ts = iio_priv(st->indio_accel); } else { return -EINVAL; } @@ -413,6 +417,8 @@ static int inv_icm42600_buffer_postdisable(struct iio_dev *indio_dev) if (!st->fifo.on) ret = inv_icm42600_set_temp_conf(st, false, &sleep_temp); + inv_icm42600_timestamp_reset(ts); + out_unlock: mutex_unlock(&st->lock); @@ -498,17 +504,26 @@ int inv_icm42600_buffer_fifo_read(struct inv_icm42600_state *st, int inv_icm42600_buffer_fifo_parse(struct inv_icm42600_state *st) { + struct inv_icm42600_timestamp *ts; int ret; if (st->fifo.nb.total == 0) return 0; + /* handle gyroscope timestamp and FIFO data parsing */ + ts = iio_priv(st->indio_gyro); + inv_icm42600_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total, + st->fifo.nb.gyro, st->timestamp.gyro); if (st->fifo.nb.gyro > 0) { ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro); if (ret) return ret; } + /* handle accelerometer timestamp and FIFO data parsing */ + ts = iio_priv(st->indio_accel); + inv_icm42600_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total, + st->fifo.nb.accel, st->timestamp.accel); if (st->fifo.nb.accel > 0) { ret = inv_icm42600_accel_parse_fifo(st->indio_accel); if (ret) @@ -521,8 +536,13 @@ int inv_icm42600_buffer_fifo_parse(struct inv_icm42600_state *st) int inv_icm42600_buffer_hwfifo_flush(struct inv_icm42600_state *st, unsigned int count) { + struct inv_icm42600_timestamp *ts; + int64_t gyro_ts, accel_ts; int ret; + gyro_ts = iio_get_time_ns(st->indio_gyro); + accel_ts = iio_get_time_ns(st->indio_accel); + ret = inv_icm42600_buffer_fifo_read(st, count); if (ret) return ret; @@ -531,12 +551,20 @@ int inv_icm42600_buffer_hwfifo_flush(struct inv_icm42600_state *st, return 0; if (st->fifo.nb.gyro > 0) { + ts = iio_priv(st->indio_gyro); + inv_icm42600_timestamp_interrupt(ts, st->fifo.period, + st->fifo.nb.total, st->fifo.nb.gyro, + gyro_ts); ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro); if (ret) return ret; } if (st->fifo.nb.accel > 0) { + ts = iio_priv(st->indio_accel); + inv_icm42600_timestamp_interrupt(ts, st->fifo.period, + st->fifo.nb.total, st->fifo.nb.accel, + accel_ts); ret = inv_icm42600_accel_parse_fifo(st->indio_accel); if (ret) return ret; diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c index 9e1f6e65fd45..8bd77185ccb7 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c @@ -19,6 +19,7 @@ #include "inv_icm42600.h" #include "inv_icm42600_buffer.h" +#include "inv_icm42600_timestamp.h" static const struct regmap_range_cfg inv_icm42600_regmap_ranges[] = { { @@ -412,6 +413,16 @@ static int inv_icm42600_setup(struct inv_icm42600_state *st, return inv_icm42600_set_conf(st, hw->conf); } +static irqreturn_t inv_icm42600_irq_timestamp(int irq, void *_data) +{ + struct inv_icm42600_state *st = _data; + + st->timestamp.gyro = iio_get_time_ns(st->indio_gyro); + st->timestamp.accel = iio_get_time_ns(st->indio_accel); + + return IRQ_WAKE_THREAD; +} + static irqreturn_t inv_icm42600_irq_handler(int irq, void *_data) { struct inv_icm42600_state *st = _data; @@ -495,7 +506,7 @@ static int inv_icm42600_irq_init(struct inv_icm42600_state *st, int irq, if (ret) return ret; - return devm_request_threaded_irq(dev, irq, NULL, + return devm_request_threaded_irq(dev, irq, inv_icm42600_irq_timestamp, inv_icm42600_irq_handler, irq_type, "inv_icm42600", st); } @@ -617,6 +628,10 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq, if (ret) return ret; + ret = inv_icm42600_timestamp_setup(st); + if (ret) + return ret; + ret = inv_icm42600_buffer_init(st); if (ret) 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 3b1f7594b60b..aee7b9ff4bf4 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c @@ -17,6 +17,7 @@ #include "inv_icm42600.h" #include "inv_icm42600_temp.h" #include "inv_icm42600_buffer.h" +#include "inv_icm42600_timestamp.h" #define INV_ICM42600_GYRO_CHAN(_modifier, _index, _ext_info) \ { \ @@ -50,6 +51,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[] = { @@ -65,15 +67,17 @@ 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: size must be a power of 2 - * 8 bytes: 6 bytes angular velocity and 2 bytes temperature + * IIO buffer data: size must be a power of 2 and timestamp aligned + * 16 bytes: 6 bytes angular velocity, 2 bytes temperature, 8 bytes timestamp */ struct inv_icm42600_gyro_buffer { struct inv_icm42600_fifo_sensor_data gyro; int16_t temp; + int64_t timestamp __aligned(8); }; #define INV_ICM42600_SCAN_MASK_GYRO_3AXIS \ @@ -94,6 +98,7 @@ 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_timestamp *ts = iio_priv(indio_dev); struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; unsigned int fifo_en = 0; unsigned int sleep_gyro = 0; @@ -121,6 +126,7 @@ static int inv_icm42600_gyro_update_scan_mode(struct iio_dev *indio_dev, } /* update data FIFO write */ + inv_icm42600_timestamp_apply_odr(ts, 0, 0, 0); ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en); if (ret) goto out_unlock; @@ -313,9 +319,11 @@ static int inv_icm42600_gyro_read_odr(struct inv_icm42600_state *st, return IIO_VAL_INT_PLUS_MICRO; } -static int inv_icm42600_gyro_write_odr(struct inv_icm42600_state *st, +static int inv_icm42600_gyro_write_odr(struct iio_dev *indio_dev, int val, int val2) { + struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42600_timestamp *ts = iio_priv(indio_dev); struct device *dev = regmap_get_device(st->map); unsigned int idx; struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; @@ -334,6 +342,11 @@ static int inv_icm42600_gyro_write_odr(struct inv_icm42600_state *st, pm_runtime_get_sync(dev); mutex_lock(&st->lock); + ret = inv_icm42600_timestamp_update_odr(ts, inv_icm42600_odr_to_period(conf.odr), + iio_buffer_enabled(indio_dev)); + if (ret) + goto out_unlock; + ret = inv_icm42600_set_gyro_conf(st, &conf, NULL); if (ret) goto out_unlock; @@ -622,7 +635,7 @@ static int inv_icm42600_gyro_write_raw(struct iio_dev *indio_dev, iio_device_release_direct_mode(indio_dev); return ret; case IIO_CHAN_INFO_SAMP_FREQ: - return inv_icm42600_gyro_write_odr(st, val, val2); + return inv_icm42600_gyro_write_odr(indio_dev, val, val2); case IIO_CHAN_INFO_CALIBBIAS: ret = iio_device_claim_direct_mode(indio_dev); if (ret) @@ -705,6 +718,7 @@ struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st) { struct device *dev = regmap_get_device(st->map); const char *name; + struct inv_icm42600_timestamp *ts; struct iio_dev *indio_dev; struct iio_buffer *buffer; int ret; @@ -713,7 +727,7 @@ struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st) if (!name) return ERR_PTR(-ENOMEM); - indio_dev = devm_iio_device_alloc(dev, 0); + indio_dev = devm_iio_device_alloc(dev, sizeof(*ts)); if (!indio_dev) return ERR_PTR(-ENOMEM); @@ -721,6 +735,9 @@ struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st) if (!buffer) return ERR_PTR(-ENOMEM); + ts = iio_priv(indio_dev); + inv_icm42600_timestamp_init(ts, inv_icm42600_odr_to_period(st->conf.gyro.odr)); + iio_device_set_drvdata(indio_dev, st); indio_dev->name = name; indio_dev->info = &inv_icm42600_gyro_info; @@ -742,14 +759,17 @@ struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st) int inv_icm42600_gyro_parse_fifo(struct iio_dev *indio_dev) { struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); + struct inv_icm42600_timestamp *ts = iio_priv(indio_dev); ssize_t i, size; + unsigned int no; const void *accel, *gyro, *timestamp; const int8_t *temp; unsigned int odr; + int64_t ts_val; struct inv_icm42600_gyro_buffer buffer; /* parse all fifo packets */ - for (i = 0; i < st->fifo.count; i += size) { + for (i = 0, no = 0; i < st->fifo.count; i += size, ++no) { size = inv_icm42600_fifo_decode_packet(&st->fifo.data[i], &accel, &gyro, &temp, ×tamp, &odr); /* quit if error or FIFO is empty */ @@ -760,12 +780,18 @@ int inv_icm42600_gyro_parse_fifo(struct iio_dev *indio_dev) if (gyro == NULL || !inv_icm42600_fifo_is_data_valid(gyro)) continue; + /* update odr */ + if (odr & INV_ICM42600_SENSOR_GYRO) + inv_icm42600_timestamp_apply_odr(ts, st->fifo.period, + st->fifo.nb.total, no); + /* buffer is copied to userspace, zeroing it to avoid any data leak */ memset(&buffer, 0, sizeof(buffer)); memcpy(&buffer.gyro, gyro, sizeof(buffer.gyro)); /* convert 8 bits FIFO temperature in high resolution format */ buffer.temp = temp ? (*temp * 64) : 0; - iio_push_to_buffers(indio_dev, &buffer); + ts_val = inv_icm42600_timestamp_pop(ts); + iio_push_to_buffers_with_timestamp(indio_dev, &buffer, ts_val); } return 0; diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c new file mode 100644 index 000000000000..7f2dc41f807b --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#include +#include +#include + +#include "inv_icm42600.h" +#include "inv_icm42600_timestamp.h" + +/* internal chip period is 32kHz, 31250ns */ +#define INV_ICM42600_TIMESTAMP_PERIOD 31250 +/* allow a jitter of +/- 2% */ +#define INV_ICM42600_TIMESTAMP_JITTER 2 +/* compute min and max periods accepted */ +#define INV_ICM42600_TIMESTAMP_MIN_PERIOD(_p) \ + (((_p) * (100 - INV_ICM42600_TIMESTAMP_JITTER)) / 100) +#define INV_ICM42600_TIMESTAMP_MAX_PERIOD(_p) \ + (((_p) * (100 + INV_ICM42600_TIMESTAMP_JITTER)) / 100) + +/* Add a new value inside an accumulator and update the estimate value */ +static void inv_update_acc(struct inv_icm42600_timestamp_acc *acc, uint32_t val) +{ + uint64_t sum = 0; + size_t i; + + acc->values[acc->idx++] = val; + if (acc->idx >= ARRAY_SIZE(acc->values)) + acc->idx = 0; + + /* compute the mean of all stored values, use 0 as empty slot */ + for (i = 0; i < ARRAY_SIZE(acc->values); ++i) { + if (acc->values[i] == 0) + break; + sum += acc->values[i]; + } + + acc->val = div_u64(sum, i); +} + +void inv_icm42600_timestamp_init(struct inv_icm42600_timestamp *ts, + uint32_t period) +{ + /* initial odr for sensor after reset is 1kHz */ + const uint32_t default_period = 1000000; + + /* current multiplier and period values after reset */ + ts->mult = default_period / INV_ICM42600_TIMESTAMP_PERIOD; + ts->period = default_period; + /* new set multiplier is the one from chip initialization */ + ts->new_mult = period / INV_ICM42600_TIMESTAMP_PERIOD; + + /* use theoretical value for chip period */ + inv_update_acc(&ts->chip_period, INV_ICM42600_TIMESTAMP_PERIOD); +} + +int inv_icm42600_timestamp_setup(struct inv_icm42600_state *st) +{ + unsigned int val; + + /* enable timestamp register */ + val = INV_ICM42600_TMST_CONFIG_TMST_TO_REGS_EN | + INV_ICM42600_TMST_CONFIG_TMST_EN; + return regmap_update_bits(st->map, INV_ICM42600_REG_TMST_CONFIG, + INV_ICM42600_TMST_CONFIG_MASK, val); +} + +int inv_icm42600_timestamp_update_odr(struct inv_icm42600_timestamp *ts, + uint32_t period, bool fifo) +{ + /* when FIFO is on, prevent odr change if one is already pending */ + if (fifo && ts->new_mult != 0) + return -EAGAIN; + + ts->new_mult = period / INV_ICM42600_TIMESTAMP_PERIOD; + + return 0; +} + +static bool inv_validate_period(uint32_t period, uint32_t mult) +{ + const uint32_t chip_period = INV_ICM42600_TIMESTAMP_PERIOD; + uint32_t period_min, period_max; + + /* check that period is acceptable */ + period_min = INV_ICM42600_TIMESTAMP_MIN_PERIOD(chip_period) * mult; + period_max = INV_ICM42600_TIMESTAMP_MAX_PERIOD(chip_period) * mult; + if (period > period_min && period < period_max) + return true; + else + return false; +} + +static bool inv_compute_chip_period(struct inv_icm42600_timestamp *ts, + uint32_t mult, uint32_t period) +{ + uint32_t new_chip_period; + + if (!inv_validate_period(period, mult)) + return false; + + /* update chip internal period estimation */ + new_chip_period = period / mult; + inv_update_acc(&ts->chip_period, new_chip_period); + + return true; +} + +void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts, + uint32_t fifo_period, size_t fifo_nb, + size_t sensor_nb, int64_t timestamp) +{ + struct inv_icm42600_timestamp_interval *it; + int64_t delta, interval; + const uint32_t fifo_mult = fifo_period / INV_ICM42600_TIMESTAMP_PERIOD; + uint32_t period = ts->period; + int32_t m; + bool valid = false; + + if (fifo_nb == 0) + return; + + /* update interrupt timestamp and compute chip and sensor periods */ + it = &ts->it; + it->lo = it->up; + it->up = timestamp; + delta = it->up - it->lo; + if (it->lo != 0) { + /* compute period: delta time divided by number of samples */ + period = div_s64(delta, fifo_nb); + valid = inv_compute_chip_period(ts, fifo_mult, period); + /* update sensor period if chip internal period is updated */ + if (valid) + ts->period = ts->mult * ts->chip_period.val; + } + + /* no previous data, compute theoritical value from interrupt */ + if (ts->timestamp == 0) { + /* elapsed time: sensor period * sensor samples number */ + interval = (int64_t)ts->period * (int64_t)sensor_nb; + ts->timestamp = it->up - interval; + return; + } + + /* if interrupt interval is valid, sync with interrupt timestamp */ + if (valid) { + /* compute measured fifo_period */ + fifo_period = fifo_mult * ts->chip_period.val; + /* delta time between last sample and last interrupt */ + delta = it->lo - ts->timestamp; + /* if there are multiple samples, go back to first one */ + while (delta >= (fifo_period * 3 / 2)) + delta -= fifo_period; + /* compute maximal adjustment value */ + m = INV_ICM42600_TIMESTAMP_MAX_PERIOD(ts->period) - ts->period; + if (delta > m) + delta = m; + else if (delta < -m) + delta = -m; + ts->timestamp += delta; + } +} + +void inv_icm42600_timestamp_apply_odr(struct inv_icm42600_timestamp *ts, + uint32_t fifo_period, size_t fifo_nb, + unsigned int fifo_no) +{ + int64_t interval; + uint32_t fifo_mult; + + if (ts->new_mult == 0) + return; + + /* update to new multiplier and update period */ + ts->mult = ts->new_mult; + ts->new_mult = 0; + ts->period = ts->mult * ts->chip_period.val; + + /* + * After ODR change the time interval with the previous sample is + * undertermined (depends when the change occures). So we compute the + * timestamp from the current interrupt using the new FIFO period, the + * total number of samples and the current sample numero. + */ + if (ts->timestamp != 0) { + /* compute measured fifo period */ + fifo_mult = fifo_period / INV_ICM42600_TIMESTAMP_PERIOD; + fifo_period = fifo_mult * ts->chip_period.val; + /* computes time interval between interrupt and this sample */ + interval = (int64_t)(fifo_nb - fifo_no) * (int64_t)fifo_period; + ts->timestamp = ts->it.up - interval; + } +} diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h b/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h new file mode 100644 index 000000000000..4e4f331d4fe4 --- /dev/null +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2020 Invensense, Inc. + */ + +#ifndef INV_ICM42600_TIMESTAMP_H_ +#define INV_ICM42600_TIMESTAMP_H_ + +#include + +struct inv_icm42600_state; + +/** + * struct inv_icm42600_timestamp_interval - timestamps interval + * @lo: interval lower bound + * @up: interval upper bound + */ +struct inv_icm42600_timestamp_interval { + int64_t lo; + int64_t up; +}; + +/** + * struct inv_icm42600_timestamp_acc - accumulator for computing an estimation + * @val: current estimation of the value, the mean of all values + * @idx: current index of the next free place in values table + * @values: table of all measured values, use for computing the mean + */ +struct inv_icm42600_timestamp_acc { + uint32_t val; + size_t idx; + uint32_t values[32]; +}; + +/** + * struct inv_icm42600_timestamp - timestamp management states + * @it: interrupts interval timestamps + * @timestamp: store last timestamp for computing next data timestamp + * @mult: current internal period multiplier + * @new_mult: new set internal period multiplier (not yet effective) + * @period: measured current period of the sensor + * @chip_period: accumulator for computing internal chip period + */ +struct inv_icm42600_timestamp { + struct inv_icm42600_timestamp_interval it; + int64_t timestamp; + uint32_t mult; + uint32_t new_mult; + uint32_t period; + struct inv_icm42600_timestamp_acc chip_period; +}; + +void inv_icm42600_timestamp_init(struct inv_icm42600_timestamp *ts, + uint32_t period); + +int inv_icm42600_timestamp_setup(struct inv_icm42600_state *st); + +int inv_icm42600_timestamp_update_odr(struct inv_icm42600_timestamp *ts, + uint32_t period, bool fifo); + +void inv_icm42600_timestamp_interrupt(struct inv_icm42600_timestamp *ts, + uint32_t fifo_period, size_t fifo_nb, + size_t sensor_nb, int64_t timestamp); + +static inline int64_t +inv_icm42600_timestamp_pop(struct inv_icm42600_timestamp *ts) +{ + ts->timestamp += ts->period; + return ts->timestamp; +} + +void inv_icm42600_timestamp_apply_odr(struct inv_icm42600_timestamp *ts, + uint32_t fifo_period, size_t fifo_nb, + unsigned int fifo_no); + +static inline void +inv_icm42600_timestamp_reset(struct inv_icm42600_timestamp *ts) +{ + const struct inv_icm42600_timestamp_interval interval_init = {0LL, 0LL}; + + ts->it = interval_init; + ts->timestamp = 0; +} + +#endif From patchwork Mon Jun 22 15:37:28 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: 11618249 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AF31490 for ; Mon, 22 Jun 2020 15:38:35 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 912BC2075A for ; Mon, 22 Jun 2020 15:38:35 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="PUcmN6TI"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="fs9I+t9+" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729742AbgFVPie (ORCPT ); Mon, 22 Jun 2020 11:38:34 -0400 Received: from mx0a-00328301.pphosted.com ([148.163.145.46]:6264 "EHLO mx0a-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729765AbgFVPiS (ORCPT ); Mon, 22 Jun 2020 11:38:18 -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 05MFa4CA021446; Mon, 22 Jun 2020 08:38:16 -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=z4XX+knfiodO8hOSVV8DxC+eo2Lr5g39QXayM+Rj/MM=; b=PUcmN6TIP7Ul03HuXo0TDvLuasVHV+z8Sf8y/0T0c6NFqvea3j9JOuuWizKLrUgg7VQS EFaIuU8j2l8XpklJVHLLt2e3D1WPp4aLL/eoBcxxVweMNaU/G7sWNh/oq0QU0ITNYF+t AzCkOB/08VbJe4GJa4ZmJlhtekkNKXKeLbK/tnvg6xo2jFR810RBTImVk7swOwRdALI6 wSmqJAZzqgL3GwQeC8mPqyem4INq8221czkrlny1AVof5orbGof/eEVjn9/8uC0RiRVi cI2swRZz6vhl/6dLJu6TXNadx9CH5W41kqQEJzDNIow5uY4m6XTFBJfMlR6FMqGkTroc 9A== Received: from nam04-co1-obe.outbound.protection.outlook.com (mail-co1nam04lp2055.outbound.protection.outlook.com [104.47.45.55]) by mx0a-00328301.pphosted.com with ESMTP id 31sdxnrty5-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 22 Jun 2020 08:38:16 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Fu4C8vZkkI6r4+fqyFUdXPDj60IUAYiREoj6rxlyuHIo0vC2DyfyWSAzRGXMatlwmwwlCTmQpdGd4Y3Qx24YJXiqS2aYb5WHJiSYRs0T5/39Bu3eacvLsxl//rJRSqIFgJd+l799NMJWVUXhBnm6LAqE/fF3vwID39KqlKslqaUVZXwdueY05czx/Xi21VOi/Df94QMuc5Ci7o29/JnAL6TeDr/ndhYlbnmjy+DWvbrODKO4GhRzRA21aBLtsC/qCVPCfnODHlKSBYRUxKYZZBV32IQk5VM4Fl8n6Hw4DsIwz5o0btAraz3Hmh46MDTi0GRpFzuvbCoLkcz/18WdEA== 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=z4XX+knfiodO8hOSVV8DxC+eo2Lr5g39QXayM+Rj/MM=; b=MVQrJYuzagC8yRz1FoebgD8k3ETSImE0HkBBBySG1fC5ve+WvqQX8Am6uXBDH3YtMfN6gLJ/HB+atKCOZzjnmqdpHggYlv0+ArOvHvKpokkhMvorM1iTVNkr0fNar/EEO9NnPv/+Nn+ftslV+hBP7ehsx7i+xAgAwSnfFs5i7osoBkunaYQ0qg79b9jBLzE4M8UF2841G6pJtiiT4uep/L0SWprhh03+2fs7dW9lKEx1HHj30BjLlHMG1rOvF9ijUtjlzXMkpmcUd+C3K7X2MVmm0YQGQf1mLFO6vAvMWf5jtZbz2GOoE7AEFLZWoFRTCEMW/kH2jrvh+651K+sWyQ== 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=z4XX+knfiodO8hOSVV8DxC+eo2Lr5g39QXayM+Rj/MM=; b=fs9I+t9+QR8cw6MN+2psEK4UJst6OpH2twys/J5MaAuRn28SwyG1ti0PlZxBV1QxPGfh7uhvHakAyIScaUCtrmmLwg4KBdYRwVoQ5eg2kiWMfXwbVdMUgNSEcyBsCxtOPdRrkuQBfdgPltY4AMc1l0Eh9EahivliQM7uwpYWoiU= 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 BL0PR12MB2338.namprd12.prod.outlook.com (2603:10b6:207:4c::28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3109.22; Mon, 22 Jun 2020 15:38:14 +0000 Received: from MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0]) by MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0%7]) with mapi id 15.20.3109.027; Mon, 22 Jun 2020 15:38: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 v4 12/13] dt-bindings: iio: imu: Add inv_icm42600 documentation Date: Mon, 22 Jun 2020 17:37:28 +0200 Message-Id: <20200622153729.12702-13-jmaneyrol@invensense.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200622153729.12702-1-jmaneyrol@invensense.com> References: <20200622153729.12702-1-jmaneyrol@invensense.com> X-ClientProxiedBy: LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) 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 LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3109.21 via Frontend Transport; Mon, 22 Jun 2020 15:38:12 +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: fb0a923f-8fd5-44aa-5a7f-08d816c246ca X-MS-TrafficTypeDiagnostic: BL0PR12MB2338: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:5236; X-Forefront-PRVS: 0442E569BC X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: oDCybIjZ9OhrBOYCFyQK15klgpjMEogPR0HQp/BbPifaeFre/oShVg9bJjq53mLmAwlbaQ1LZ56UuyB5lMsVRfkKtTurCzC/V7ggtiPEtKi2WdSODBQ1XJiQiOIHWrhX3iGUknxhKzBL3YpSSiqO8raeIjXr+jxgkJEUeXvkXqbYqBxEkouICH3Uzjd8DPnCdGhdALXO6XcVCTSf01exZzR+HH8Ldany3/FtZJt4XkqNzAecSByO1CcZCNxzoaCmVMxWaK9G5J08i8sXGdrAEJ8nB28T1Ix4v3o0wOL/W4oLsP/ObYNNCM0haLenD7ityX3IukHL43DDix21qRwccIfMuoCh3kg3AiQHYLifekW5MACQr8au6fwCxcpHd6gbY4+JckhXEGRa4B4tGHVNjtLGbpQKWz5LU2nJ+QHF2xVkVQq9/2K+km5xqv3y32yIIiQjIFPasXGA1iGKTjVmostNyCGJ/V3Sd4VTTRTatpQ= 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:(396003)(346002)(366004)(136003)(376002)(39850400004)(6486002)(36756003)(2906002)(107886003)(16526019)(186003)(8936002)(956004)(2616005)(26005)(8676002)(6666004)(478600001)(86362001)(1076003)(66556008)(966005)(52116002)(7696005)(66476007)(5660300002)(4326008)(316002)(66946007)(15398625002)(43620500001);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: TX1erQstpWKnJkYof/kF3n+7cYfzp7WyKSfnARuDVhFNG29eSC5VJRqShmB8QoqKeUIf2N6WJYiNoO0DvRiNtVfD1XeddEoZ3+jltBkuo/HfHorU1xn3dgo9iJ7wnJFbjItwJQDqMweVzSvxtGSxqwiaocrJ2+eEF6l9MRj3PjZvMvt5F1xnSRKjex/K6nGOiOOkoGWVcJSAkWgPDvPEgpnt5+2ot4vm6AU538oKV0viGreIkM4BNgRgH2aZ4383C/qz0zUdeR0rG4LSS9vBW29xHT6qQk609Ytp2Er+a3KtKV+sNvq74hwsPJ0YZX0KXcdUk6LclCwPHryID4GUkXDS/gN3aQ8RLjFYi8cI8GgLqy2tn6DCst7XPCiQMcSdVJajTpM1ehS1fF0QipOwm7sVvIDcdn9Tl90FzwA12JyjNng0CTekN14zRg76GLRXJEgR5cJZrQaNFr/RtuZ97xDKCqfnxBY8mSZy3pZT2OA= X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: fb0a923f-8fd5-44aa-5a7f-08d816c246ca X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Jun 2020 15:38:14.1661 (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: jZjFpXBDztCd5FQZ3i+ToKFySG23gR5ynDDUx8EA29dX6DNHk2P94/CPvY6dN3zg/5FUC8MUinPgqX1Zdprzvp4fhSMoq2Y0T1VouObvVmM= X-MS-Exchange-Transport-CrossTenantHeadersStamped: BL0PR12MB2338 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216,18.0.687 definitions=2020-06-22_09:2020-06-22,2020-06-22 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 mlxscore=0 phishscore=0 clxscore=1015 bulkscore=0 cotscore=-2147483648 suspectscore=0 impostorscore=0 spamscore=0 mlxlogscore=999 malwarescore=0 adultscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006220116 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Document the ICM-426xxx devices devicetree bindings. Signed-off-by: Jean-Baptiste Maneyrol --- .../bindings/iio/imu/invensense,icm42600.yaml | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml diff --git a/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml new file mode 100644 index 000000000000..abd8d25e1136 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml @@ -0,0 +1,90 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/imu/invensense,icm42600.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: InvenSense ICM-426xx Inertial Measurement Unit + +maintainers: + - Jean-Baptiste Maneyrol + +description: | + 6-axis MotionTracking device that combines a 3-axis gyroscope and a 3-axis + accelerometer. + + It has a configurable host interface that supports I3C, I2C and SPI serial + communication, features a 2kB FIFO and 2 programmable interrupts with + ultra-low-power wake-on-motion support to minimize system power consumption. + + Other industry-leading features include InvenSense on-chip APEX Motion + Processing engine for gesture recognition, activity classification, and + pedometer, along with programmable digital filters, and an embedded + temperature sensor. + + https://invensense.tdk.com/wp-content/uploads/2020/03/DS-000292-ICM-42605-v1.4.pdf + +properties: + compatible: + enum: + - invensense,icm42600 + - invensense,icm42602 + - invensense,icm42605 + - invensense,icm42622 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + drive-open-drain: + type: boolean + + vdd-supply: + description: Regulator that provides power to the sensor + + vddio-supply: + description: Regulator that provides power to the bus + +required: + - compatible + - reg + - interrupts + +examples: + - | + #include + #include + i2c0 { + #address-cells = <1>; + #size-cells = <0>; + + icm42605@68 { + compatible = "invensense,icm42605"; + reg = <0x68>; + interrupt-parent = <&gpio2>; + interrupts = <7 IRQ_TYPE_EDGE_FALLING>; + vdd-supply = <&vdd>; + vddio-supply = <&vddio>; + }; + }; + - | + #include + #include + spi0 { + #address-cells = <1>; + #size-cells = <0>; + + icm42602@0 { + compatible = "invensense,icm42602"; + reg = <0>; + spi-max-frequency = <24000000>; + spi-cpha; + spi-cpol; + interrupt-parent = <&gpio1>; + interrupts = <2 IRQ_TYPE_EDGE_FALLING>; + vdd-supply = <&vdd>; + vddio-supply = <&vddio>; + }; + }; From patchwork Mon Jun 22 15:37:29 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: 11618245 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 43BB890 for ; Mon, 22 Jun 2020 15:38:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2491C2074D for ; Mon, 22 Jun 2020 15:38:26 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="afeZuzGo"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="lvvTpdpy" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729799AbgFVPiZ (ORCPT ); Mon, 22 Jun 2020 11:38:25 -0400 Received: from mx0a-00328301.pphosted.com ([148.163.145.46]:8204 "EHLO mx0a-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729776AbgFVPiT (ORCPT ); Mon, 22 Jun 2020 11:38: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 05MFaLZl021513; Mon, 22 Jun 2020 08:38:17 -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=MHpK3KpBI5HFazc9yGkFuEHR+MVVUd+m8NSjI6iqEgY=; b=afeZuzGoKQl+PxcO1u0VtpPy3Mbtvaa4YnqytXsbSokET/P2PYlNl8M+uxrMn092MLOH iU9OlQtKoD7OQweZK7vciLAHyNG1FO8L+lr/i1fTGWdpxQ1ZwelQHXwIv/mz1qFgJTmR JcUHXJFvT8GehV4grD+8Zu+ajl6hELXJgifrWL/QsG2s/QRPp6FBBCvK+00hX3pNTnEX wRi8qfo6DDtq+Warlyv2HwdRSdY56dC9/Us2AmclVLGB5VnXi/aswdx4AB2Ak+KMXeI+ H+6VrsF2wq4aS36J5o4lfs3RT8nkSswWoo3TvnzUtIF8qkxWL3UaUFtUc5WrnLiUylg7 CQ== Received: from nam04-co1-obe.outbound.protection.outlook.com (mail-co1nam04lp2055.outbound.protection.outlook.com [104.47.45.55]) by mx0a-00328301.pphosted.com with ESMTP id 31sdxnrty6-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 22 Jun 2020 08:38:17 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=JODoiyzfAD2I5eB4t3mRjV+CnwP1VyFdxi+kGkP7V+GY112owdm9w18BeN8g9YfeLZXWLsKHsLWfPW3vhWerMOZf4SU0klt0lx5OXwL48bhEv+KiVUUIaOF5P/Xx7hNrTIwTczUzqaagZC8mkhKXoKa3RQwQTIoLkuIujhlpuAXGMR+Hd46RD6gw1U8iJQsj5WcEAfDiphNupeItJgZ1gmD/6kdPme1jImmAip/rKdqUDGxoyhFMAdYdrYtc7JaHLgMJzXVPHDHPHxpq05wfm0aiJebdVw5CZcWpStEKDtaQwd+9f1sUDpEDYIc1itqvoYPrRjdjH05dzYNoCFG7UQ== 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=MHpK3KpBI5HFazc9yGkFuEHR+MVVUd+m8NSjI6iqEgY=; b=ektfnJ/XeDBhevFETYhAR5HtKdudEaCf90wyZp8RRft7+4ykL7oa5hVtNW5ZcOPhTDIiTYKGyXK51WGwr6VMQ7pn/VIgGOZBdFOYGVA3vMhhBoZZ3tRgkB7uz/xlbyP0sstWiPSfaL9kPoK/B7BWSuCFKmU1NxVBDqFXngqRGTiMxIh6PGopeNEPsbEXBtKOWW5f9O3s7zzIMaSUVPkzpStSLQFozm17lN99BfIiofnhy0W3oUibGbpZ7MuZpMWGVkfanFT4PugiHUqsNthZFn7t/j1WEkdnP/oomMby4qSnPRvDYfQKv7pFXje8oME53TzD48HuwrUf8ZUKbccvyg== 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=MHpK3KpBI5HFazc9yGkFuEHR+MVVUd+m8NSjI6iqEgY=; b=lvvTpdpydaFST0CyadwDOIDDXTiGW6kv0uLG3suIo9u5auD83HLk8Alwsf6fCc+ZG7EnJpHW9dE79SXWfEGNOrxuWWMuhRClp8SHju+gMf2XwRjv/KktnndrG/s4kQXwQtd/OZsyBZlhpyQ5BhoqA3KU/GSITt4GYmyP71CS9+Y= 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 BL0PR12MB2338.namprd12.prod.outlook.com (2603:10b6:207:4c::28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3109.22; Mon, 22 Jun 2020 15:38:16 +0000 Received: from MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0]) by MN2PR12MB4422.namprd12.prod.outlook.com ([fe80::8940:8e95:6996:cc0%7]) with mapi id 15.20.3109.027; Mon, 22 Jun 2020 15:38:16 +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 v4 13/13] MAINTAINERS: add entry for inv_icm42600 6-axis imu sensor Date: Mon, 22 Jun 2020 17:37:29 +0200 Message-Id: <20200622153729.12702-14-jmaneyrol@invensense.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200622153729.12702-1-jmaneyrol@invensense.com> References: <20200622153729.12702-1-jmaneyrol@invensense.com> X-ClientProxiedBy: LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) 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 LO2P265CA0054.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:60::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3109.21 via Frontend Transport; Mon, 22 Jun 2020 15:38:14 +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: c67dde2a-ea1a-4b78-1c94-08d816c247c4 X-MS-TrafficTypeDiagnostic: BL0PR12MB2338: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:1079; X-Forefront-PRVS: 0442E569BC X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 0gyr68mGUANOQ5Grm3iRx/MKfXVb1VGAebiBoG8nyJQ391pJxiAF9ANVzTpkziEN6NUBMCvXHIjlRowubdaFhNnOPMHpHbU1pwrrpNg1Twm6ig0pXIiP83gdx94O8qU+//vhkstLtKFfJhkw0ao9vURNZUTDGsEjN7cOhp9eeBmG0sr8riYPmZrEx8H0n/kCvbCsc7K6yFY6o2v5ny1xQJMi6ZVe1+A06pI5KMYPBaPLkVt2kfOALO9FzWAKME+QdAjtF9XEB7+BqzOaV7aqUe7yWZr4t9K20Q4tFWAstnGEd5YwTAnYRXwkDPmyZfX68UvWG7F4DReh7faQ+XEzxRBLcZWHdP/eg64xXXj1vNWiTPhGiwQsz3toTTfq/JpO4NQiK+0Qfuaq68DFB7jVvQ== 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:(396003)(346002)(366004)(136003)(376002)(39850400004)(6486002)(36756003)(2906002)(107886003)(16526019)(4744005)(186003)(8936002)(956004)(2616005)(26005)(8676002)(6666004)(478600001)(86362001)(1076003)(66556008)(966005)(52116002)(7696005)(66476007)(5660300002)(4326008)(316002)(66946007);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData: Jyvil5/gNHUksUUNHWZdOwo8VG3vq2TB3xrV5fpubShEEfZRjJOO6dow7HpV/dJXUpPkJjOiuoVNxb+rvSUqOLChvDA5xEFijb4Qsqn7+hLi4ukoFUO/R1OBn/VjKfUVafMtd6M+rgt57/e2gXC9n1y5VEWtZWDgsU61Fcl9SG2fVRZ2M0l9OlYIdOfIcB1/3q/qMasWOm484jxwUcL8MBMKj6VE53Oth46GUtJwiD4NkKAWudD7FNJiHhue5q9VMbQtvFLRCeKhx6aDHsCo1N9TW2pw6Im/f7OYRPk6juqCbHmyPQbdtXhlAyU2/vZ0+W2QojHlY5X1pA/z46vOsqGsAS91apIHXtzErBhqm9PoUqO1XWvWXmHWBcdZg52hUwjKgjlgScUzQaxzcaoqsCjkCqPhDJ8eGnku905HZitoiGoQaZ7g2/STaLQtm6W9sL1n2rPoT8aydg5usPUmmGtoH98MQFHVXXDVs7/h92Q= X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: c67dde2a-ea1a-4b78-1c94-08d816c247c4 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Jun 2020 15:38:15.9283 (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: uPpHXpph1k3x2NZX4oLjHyfqTPhAOQpDQQ+ysOUf2uYadShW9s0GMHiiCkTnAI/8gdmx+q23qVuQO6JG5u4cbeGDAsywscRUpBwVAo7qsWU= X-MS-Exchange-Transport-CrossTenantHeadersStamped: BL0PR12MB2338 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216,18.0.687 definitions=2020-06-22_09:2020-06-22,2020-06-22 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 mlxscore=0 phishscore=0 clxscore=1015 bulkscore=0 cotscore=-2147483648 suspectscore=0 impostorscore=0 spamscore=0 mlxlogscore=999 malwarescore=0 adultscore=0 lowpriorityscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2006220116 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@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 510fa7f7c756..a65771cfc506 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8979,6 +8979,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