From patchwork Thu Aug 29 15:18:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Baptiste Maneyrol X-Patchwork-Id: 11121739 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 14B7714D5 for ; Thu, 29 Aug 2019 15:37:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C852A20828 for ; Thu, 29 Aug 2019 15:37:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=invensense.com header.i=@invensense.com header.b="xwmXgVOQ"; dkim=pass (1024-bit key) header.d=invensense.onmicrosoft.com header.i=@invensense.onmicrosoft.com header.b="gFqGZSZe" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727860AbfH2Ph1 (ORCPT ); Thu, 29 Aug 2019 11:37:27 -0400 Received: from mx0b-00328301.pphosted.com ([148.163.141.47]:56170 "EHLO mx0b-00328301.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726283AbfH2Ph1 (ORCPT ); Thu, 29 Aug 2019 11:37:27 -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 x7TF9ren001995; Thu, 29 Aug 2019 08:18:48 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=invensense.com; h=from : to : cc : subject : date : message-id : references : in-reply-to : content-type : content-transfer-encoding : mime-version; s=pfpt1; bh=udsw7c3C+8DqbLgrH6g/o7PRZLWKMoCB96VTql8/46c=; b=xwmXgVOQlA1oZjc99Itft6jWVUyOLtxPzKiNJNsaxm5fl87ZZABjvWREGVGo25YRWKxn OKJpdGCs94tXaF/gKu+jC1S5VT/xcS3+C5v0e+90pOMXlXfVb4oFJXWCUKXjA05ynIYW G8QSFfKaLLxekgrAVuS5thQXP1UOpwitArPb8ACDxyvh5tnmt+bK2MYTBcxzHqtkevY4 VW/QLRzrV7AEJpt4/lixbSTXp3nK9x0FPBgyTmjPFTMaIZEzbqtITY+vKDUX48mfxJlF AnT5rcFEfgASLckgio9kRZRHvchk2KFhuXUdZbMGVVZ3wZZbWzvEqErtvahZiNYOGLaQ 8g== Received: from nam05-co1-obe.outbound.protection.outlook.com (mail-co1nam05lp2050.outbound.protection.outlook.com [104.47.48.50]) by mx0b-00328301.pphosted.com with ESMTP id 2ukyymt18t-2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 29 Aug 2019 08:18:47 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=AD+BASoyx+3WI5kaQNY6nodtGqIdvl50D3BVpRnHa0KYbmt7v7z601UVkunMBvggvMCiaz93feDzwgHFJVRxhRSjtZqAZyF9jzPCHg2gB2cOVk42/kVNpCa8h0U62hZmno8Q1vSxmZcc513M7FQA065IJXJJ2RUkQskEF6jjhOjlxd5rG0xPL7oPYMx4BQ+BlcPJOVjA5NaJlC1U/XnkAs8ouM6x1FUoVrNAg+2QOVrrWfxc8F3fVSof+gXXBjdI4jdGAyB4U1y4kXUghgiEZXu37BNvcdU9A8F0YrtGGKSuZcC6gnHV4yn4ZFgt6zMKa6dNHbFSRKSAQA/BnRsQfg== 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=udsw7c3C+8DqbLgrH6g/o7PRZLWKMoCB96VTql8/46c=; b=lxwk/H/V2DjeAQUX4b69tzFBCrfDWmkvi4etG2X0q4neH7P4J2VZGWLbldu1h/v9ye0woZhSbFs6lw9oU0AjNtadW7zO3qUa+OnpSdFuFzYUIQFs+GNm11OWvbXeJkaZ1dyFVFWxEZrvSA4AyQ/w2L2JMJToGfGPGsaI+YgZ8K72QYUHGFgo3Zq7ieQunyx8rriQHI8ncHam4M1wU5FDFdD33zaHt41tPsqZmdCB1aiDGRDFwpWGtTrLgVpGZu5ukVUeih86zjcRVo8UfSTIXHz3y1wp8fcD2J7k3WfJud47ufAwU/kNACDdikLz8OKxkxpy8MRT7c6poS2B5dR6QQ== 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=udsw7c3C+8DqbLgrH6g/o7PRZLWKMoCB96VTql8/46c=; b=gFqGZSZeFKQyTaarP5V62/tLVZx+Eu4Kr1f/0qoh3J1mmUNJeeEfxb8g/E2x1bpx8jUPkq0H++fAKGhhJYF1nrtfmnaZHtFkJPEYWvbOyMvh5WfQTenmoONQB3cVc6ej1bN0ASidw2bF4AEfXgnsylztLbTZZfJYbf4Z3A2ZL4M= Received: from BYAPR12MB3366.namprd12.prod.outlook.com (20.178.55.207) by BYAPR12MB3638.namprd12.prod.outlook.com (20.178.54.87) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2220.16; Thu, 29 Aug 2019 15:18:45 +0000 Received: from BYAPR12MB3366.namprd12.prod.outlook.com ([fe80::24a1:e93b:cc7:5861]) by BYAPR12MB3366.namprd12.prod.outlook.com ([fe80::24a1:e93b:cc7:5861%7]) with mapi id 15.20.2199.021; Thu, 29 Aug 2019 15:18:45 +0000 From: Jean-Baptiste Maneyrol To: "jic23@kernel.org" CC: "linux-iio@vger.kernel.org" , Jean-Baptiste Maneyrol Subject: [PATCH 7/8] iio: imu: inv_mpu6050: add magnetometer support inside mpu driver Thread-Topic: [PATCH 7/8] iio: imu: inv_mpu6050: add magnetometer support inside mpu driver Thread-Index: AQHVXn0MYpJzl4x+WUecu/G2bHQLjw== Date: Thu, 29 Aug 2019 15:18:45 +0000 Message-ID: <20190829151801.13014-8-jmaneyrol@invensense.com> References: <20190829151801.13014-1-jmaneyrol@invensense.com> In-Reply-To: <20190829151801.13014-1-jmaneyrol@invensense.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-clientproxiedby: PR0P264CA0137.FRAP264.PROD.OUTLOOK.COM (2603:10a6:100:1a::29) To BYAPR12MB3366.namprd12.prod.outlook.com (2603:10b6:a03:a9::15) x-originating-ip: [77.157.193.39] x-ms-exchange-messagesentrepresentingtype: 1 x-mailer: git-send-email 2.17.1 x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: cd3601aa-ed6a-4cbd-03cc-08d72c942ed4 x-microsoft-antispam: BCL:0;PCL:0;RULEID:(2390118)(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600166)(711020)(4605104)(1401327)(2017052603328)(7193020);SRVR:BYAPR12MB3638; x-ms-traffictypediagnostic: BYAPR12MB3638: x-ms-exchange-transport-forked: True x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:9508; x-forefront-prvs: 0144B30E41 x-forefront-antispam-report: SFV:NSPM;SFS:(10009020)(396003)(366004)(376002)(346002)(39850400004)(136003)(199004)(189003)(4326008)(6486002)(256004)(14454004)(1076003)(14444005)(316002)(26005)(102836004)(81166006)(66066001)(81156014)(386003)(6506007)(305945005)(86362001)(2351001)(6916009)(186003)(30864003)(2501003)(80792005)(7736002)(36756003)(50226002)(2616005)(6512007)(8676002)(478600001)(71190400001)(71200400001)(64756008)(54906003)(66946007)(2906002)(66446008)(6116002)(52116002)(76176011)(66476007)(99286004)(66556008)(8936002)(446003)(486006)(107886003)(5640700003)(53936002)(11346002)(476003)(6436002)(5660300002)(3846002)(25786009);DIR:OUT;SFP:1101;SCL:1;SRVR:BYAPR12MB3638;H:BYAPR12MB3366.namprd12.prod.outlook.com;FPR:;SPF:None;LANG:en;PTR:InfoNoRecords;A:1;MX:1; received-spf: None (protection.outlook.com: invensense.com does not designate permitted sender hosts) x-ms-exchange-senderadcheck: 1 x-microsoft-antispam-message-info: b5F2U2X+Wcz+6xACixEUGlwgt/lAu6pxxHUJ255C6MVAQd+c0T12fzgTJ5dfSlVjyzZK/r6BrgR2gaBR2Pz2p2G9nGH+9dPfICZZC/2mw/YUiKjY4Q9RqyrLouN7CeUKiaockaMTj60ZJ/nJO2pfuu0cG96v7oRQIcrYKusH1a+HkiwnSawzg5i1q3JxXundTWhbmHEZo40pUlAvOVAzFVGaCrgwg6p1a+njmFBUb1JdhyFJwPZRLDsCa5sCqKRoXghSNa+kEfZ7LXNNRDxer9o+uiICoC/Zu6az88KME5H3eu72oIYg1A7qWkq1suNDpHHEt29eXc7wxYPgLRuvJQdlak5sGIpV/V1Ln25wO+zr6DcsUAZrhMSeG+mKcmk6bojCXelJ/u1uNjb9FwguCsSTllHfJ/p7bGuNXfYKKgU= MIME-Version: 1.0 X-OriginatorOrg: invensense.com X-MS-Exchange-CrossTenant-Network-Message-Id: cd3601aa-ed6a-4cbd-03cc-08d72c942ed4 X-MS-Exchange-CrossTenant-originalarrivaltime: 29 Aug 2019 15:18:45.2660 (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: zetAYztGTdbgIfLcitZDsjKxS0rEB/ForIr9OF7zaNRrauOWguCfonbAHvHLQexHL4uk8vYN2Wbx87yGSr9dZvkGSvIDeGQzSJGtLWKS3ZM= X-MS-Exchange-Transport-CrossTenantHeadersStamped: BYAPR12MB3638 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.70,1.0.8 definitions=2019-08-29_07:2019-08-29,2019-08-29 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 adultscore=0 clxscore=1015 lowpriorityscore=0 phishscore=0 suspectscore=0 impostorscore=0 spamscore=0 malwarescore=0 bulkscore=0 mlxscore=0 mlxlogscore=999 priorityscore=1501 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-1906280000 definitions=main-1908290164 Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org Add inv_mpu_magn layer to manage several chip specific implementations and be noop when Kconfig option is not set. Signed-off-by: Jean-Baptiste Maneyrol --- drivers/iio/imu/inv_mpu6050/Makefile | 3 +- drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 140 ++++++++++++++++++++- drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 2 + drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c | 120 ++++++++++++++++++ drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h | 107 ++++++++++++++++ 5 files changed, 368 insertions(+), 4 deletions(-) create mode 100644 drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c create mode 100644 drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h diff --git a/drivers/iio/imu/inv_mpu6050/Makefile b/drivers/iio/imu/inv_mpu6050/Makefile index fee41415ebdb..6f5baac29f81 100644 --- a/drivers/iio/imu/inv_mpu6050/Makefile +++ b/drivers/iio/imu/inv_mpu6050/Makefile @@ -5,7 +5,8 @@ obj-$(CONFIG_INV_MPU6050_IIO) += inv-mpu6050.o inv-mpu6050-y := inv_mpu_core.o inv_mpu_ring.o inv_mpu_trigger.o -inv-mpu6050-$(CONFIG_INV_MPU6050_MAGN) += inv_mpu_aux.o inv_mpu9250_magn.o +inv-mpu6050-$(CONFIG_INV_MPU6050_MAGN) += inv_mpu_aux.o inv_mpu_magn.o \ + inv_mpu9250_magn.o obj-$(CONFIG_INV_MPU6050_I2C) += inv-mpu6050-i2c.o inv-mpu6050-i2c-y := inv_mpu_i2c.o inv_mpu_acpi.o diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c index b17f060b52fc..d08cec6a8a7a 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c @@ -16,7 +16,9 @@ #include #include #include + #include "inv_mpu_iio.h" +#include "inv_mpu_magn.h" /* * this is the gyro scale translated from dynamic range plus/minus @@ -332,6 +334,11 @@ static int inv_mpu6050_init_config(struct iio_dev *indio_dev) */ st->chip_period = NSEC_PER_MSEC; + /* magn chip init, noop if not present in the chip */ + result = inv_mpu_magn_probe(st); + if (result) + goto error_power_off; + return inv_mpu6050_set_power_itg(st, false); error_power_off: @@ -411,6 +418,9 @@ static int inv_mpu6050_read_channel_data(struct iio_dev *indio_dev, ret = inv_mpu6050_sensor_show(st, st->reg->temperature, IIO_MOD_X, val); break; + case IIO_MAGN: + ret = inv_mpu_magn_read(st, chan->channel2, val); + break; default: ret = -EINVAL; break; @@ -469,6 +479,8 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev, *val2 = INV_MPU6050_TEMP_SCALE; return IIO_VAL_INT_PLUS_MICRO; + case IIO_MAGN: + return inv_mpu_magn_get_scale(st, chan, val, val2); default: return -EINVAL; } @@ -710,6 +722,11 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr, if (result) goto fifo_rate_fail_power_off; + /* update rate for magn, noop if not present in chip */ + result = inv_mpu_magn_set_rate(st, fifo_rate); + if (result) + goto fifo_rate_fail_power_off; + fifo_rate_fail_power_off: result |= inv_mpu6050_set_power_itg(st, false); fifo_rate_fail_unlock: @@ -795,8 +812,13 @@ inv_get_mount_matrix(const struct iio_dev *indio_dev, const struct iio_chan_spec *chan) { struct inv_mpu6050_state *data = iio_priv(indio_dev); + const struct iio_mount_matrix *matrix = &data->orientation; - return &data->orientation; +#ifdef CONFIG_INV_MPU6050_MAGN + if (chan->type == IIO_MAGN) + matrix = &data->magn_orient; +#endif + return matrix; } static const struct iio_chan_spec_ext_info inv_ext_info[] = { @@ -864,6 +886,102 @@ static const unsigned long inv_mpu_scan_masks[] = { 0, }; +#ifdef CONFIG_INV_MPU6050_MAGN + +#define INV_MPU9X50_MAGN_CHAN(_chan2, _bits, _index) \ + { \ + .type = IIO_MAGN, \ + .modified = 1, \ + .channel2 = _chan2, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_RAW), \ + .scan_index = _index, \ + .scan_type = { \ + .sign = 's', \ + .realbits = _bits, \ + .storagebits = 16, \ + .shift = 0, \ + .endianness = IIO_BE, \ + }, \ + .ext_info = inv_ext_info, \ + } + +static const struct iio_chan_spec inv_mpu9250_channels[] = { + IIO_CHAN_SOFT_TIMESTAMP(INV_MPU9X50_SCAN_TIMESTAMP), + /* + * Note that temperature should only be via polled reading only, + * not the final scan elements output. + */ + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) + | BIT(IIO_CHAN_INFO_OFFSET) + | BIT(IIO_CHAN_INFO_SCALE), + .scan_index = -1, + }, + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_MPU9X50_SCAN_GYRO_X), + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_MPU9X50_SCAN_GYRO_Y), + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_MPU9X50_SCAN_GYRO_Z), + + INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_X, INV_MPU9X50_SCAN_ACCL_X), + INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Y, INV_MPU9X50_SCAN_ACCL_Y), + INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU9X50_SCAN_ACCL_Z), + + /* Magnetometer resolution is 16 bits */ + INV_MPU9X50_MAGN_CHAN(IIO_MOD_X, 16, INV_MPU9X50_SCAN_MAGN_X), + INV_MPU9X50_MAGN_CHAN(IIO_MOD_Y, 16, INV_MPU9X50_SCAN_MAGN_Y), + INV_MPU9X50_MAGN_CHAN(IIO_MOD_Z, 16, INV_MPU9X50_SCAN_MAGN_Z), +}; + +static const unsigned long inv_mpu9x50_scan_masks[] = { + /* 3-axis accel */ + BIT(INV_MPU9X50_SCAN_ACCL_X) + | BIT(INV_MPU9X50_SCAN_ACCL_Y) + | BIT(INV_MPU9X50_SCAN_ACCL_Z), + /* 3-axis gyro */ + BIT(INV_MPU9X50_SCAN_GYRO_X) + | BIT(INV_MPU9X50_SCAN_GYRO_Y) + | BIT(INV_MPU9X50_SCAN_GYRO_Z), + /* 3-axis magn */ + BIT(INV_MPU9X50_SCAN_MAGN_X) + | BIT(INV_MPU9X50_SCAN_MAGN_Y) + | BIT(INV_MPU9X50_SCAN_MAGN_Z), + /* 6-axis accel + gyro */ + BIT(INV_MPU9X50_SCAN_ACCL_X) + | BIT(INV_MPU9X50_SCAN_ACCL_Y) + | BIT(INV_MPU9X50_SCAN_ACCL_Z) + | BIT(INV_MPU9X50_SCAN_GYRO_X) + | BIT(INV_MPU9X50_SCAN_GYRO_Y) + | BIT(INV_MPU9X50_SCAN_GYRO_Z), + /* 6-axis accel + magn */ + BIT(INV_MPU9X50_SCAN_ACCL_X) + | BIT(INV_MPU9X50_SCAN_ACCL_Y) + | BIT(INV_MPU9X50_SCAN_ACCL_Z) + | BIT(INV_MPU9X50_SCAN_MAGN_X) + | BIT(INV_MPU9X50_SCAN_MAGN_Y) + | BIT(INV_MPU9X50_SCAN_MAGN_Z), + /* 6-axis gyro + magn */ + BIT(INV_MPU9X50_SCAN_GYRO_X) + | BIT(INV_MPU9X50_SCAN_GYRO_Y) + | BIT(INV_MPU9X50_SCAN_GYRO_Z) + | BIT(INV_MPU9X50_SCAN_MAGN_X) + | BIT(INV_MPU9X50_SCAN_MAGN_Y) + | BIT(INV_MPU9X50_SCAN_MAGN_Z), + /* 9-axis accel + gyro + magn */ + BIT(INV_MPU9X50_SCAN_ACCL_X) + | BIT(INV_MPU9X50_SCAN_ACCL_Y) + | BIT(INV_MPU9X50_SCAN_ACCL_Z) + | BIT(INV_MPU9X50_SCAN_GYRO_X) + | BIT(INV_MPU9X50_SCAN_GYRO_Y) + | BIT(INV_MPU9X50_SCAN_GYRO_Z) + | BIT(INV_MPU9X50_SCAN_MAGN_X) + | BIT(INV_MPU9X50_SCAN_MAGN_Y) + | BIT(INV_MPU9X50_SCAN_MAGN_Z), + 0, +}; + +#endif + static const struct iio_chan_spec inv_icm20602_channels[] = { IIO_CHAN_SOFT_TIMESTAMP(INV_ICM20602_SCAN_TIMESTAMP), { @@ -1145,6 +1263,11 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, return result; } + /* fill magnetometer orientation */ + result = inv_mpu_magn_set_orient(st); + if (result) + return result; + /* power is turned on inside check chip type*/ result = inv_check_and_setup_chip(st); if (result) @@ -1167,14 +1290,25 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, else indio_dev->name = dev_name(dev); - if (chip_type == INV_ICM20602) { + switch (chip_type) { +#ifdef CONFIG_INV_MPU6050_MAGN + case INV_MPU9250: + case INV_MPU9255: + indio_dev->channels = inv_mpu9250_channels; + indio_dev->num_channels = ARRAY_SIZE(inv_mpu9250_channels); + indio_dev->available_scan_masks = inv_mpu9x50_scan_masks; + break; +#endif + case INV_ICM20602: indio_dev->channels = inv_icm20602_channels; indio_dev->num_channels = ARRAY_SIZE(inv_icm20602_channels); indio_dev->available_scan_masks = inv_icm20602_scan_masks; - } else { + break; + default: indio_dev->channels = inv_mpu_channels; indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels); indio_dev->available_scan_masks = inv_mpu_scan_masks; + break; } indio_dev->info = &mpu_info; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h index 5b462672bbcb..cfc11cb0a36c 100644 --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h @@ -130,6 +130,7 @@ struct inv_mpu6050_hw { * @data_timestamp: timestamp for next data sample. * @vddio_supply voltage regulator for the chip. * @magn_raw_to_gauss: coefficient to convert mag raw value to Gauss. + * @magn_orient: magnetometer sensor chip orientation if available. */ struct inv_mpu6050_state { struct mutex lock; @@ -153,6 +154,7 @@ struct inv_mpu6050_state { struct regulator *vddio_supply; #ifdef CONFIG_INV_MPU6050_MAGN s32 magn_raw_to_gauss[3]; + struct iio_mount_matrix magn_orient; #endif }; diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c new file mode 100644 index 000000000000..2bb40dae0429 --- /dev/null +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 TDK-InvenSense, Inc. + */ + +#include +#include +#include + +#include "inv_mpu_iio.h" +#include "inv_mpu_aux.h" +#include "inv_mpu9250_magn.h" + +int inv_mpu_magn_probe(struct inv_mpu6050_state *st) +{ + int ret; + + /* probe and init mag chip */ + switch (st->chip_type) { + case INV_MPU9250: + case INV_MPU9255: + /* configure i2c master aux port */ + ret = inv_mpu_aux_init(st); + if (ret) + return ret; + return inv_mpu9250_magn_probe(st); + default: + break; + } + + return 0; +} + +int inv_mpu_magn_set_rate(const struct inv_mpu6050_state *st, int fifo_rate) +{ + int max_freq; + uint8_t d; + + switch (st->chip_type) { + case INV_MPU9250: + case INV_MPU9255: + max_freq = INV_MPU9250_MAGN_FREQ_HZ_MAX; + break; + default: + return 0; + } + + /* + * update i2c master delay to limit mag sampling to max frequency + * compute fifo_rate divider d: rate = fifo_rate / (d + 1) + */ + if (fifo_rate > max_freq) + d = fifo_rate / max_freq - 1; + else + d = 0; + + return regmap_write(st->map, INV_MPU6050_REG_I2C_SLV4_CTRL, d); +} + +int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st) +{ + const char *orient; + char *str; + int i; + + /* fill magnetometer orientation */ + switch (st->chip_type) { + case INV_MPU9250: + case INV_MPU9255: + /* x <- y */ + st->magn_orient.rotation[0] = st->orientation.rotation[3]; + st->magn_orient.rotation[1] = st->orientation.rotation[4]; + st->magn_orient.rotation[2] = st->orientation.rotation[5]; + /* y <- x */ + st->magn_orient.rotation[3] = st->orientation.rotation[0]; + st->magn_orient.rotation[4] = st->orientation.rotation[1]; + st->magn_orient.rotation[5] = st->orientation.rotation[2]; + /* z <- -z */ + for (i = 0; i < 3; ++i) { + orient = st->orientation.rotation[6 + i]; + /* use length + 2 for adding minus sign if needed */ + str = devm_kzalloc(regmap_get_device(st->map), + strlen(orient) + 2, GFP_KERNEL); + if (str == NULL) + return -ENOMEM; + if (strcmp(orient, "0") == 0) { + strcpy(str, orient); + } else if (orient[0] == '-') { + strcpy(str, &orient[1]); + } else { + str[0] = '-'; + strcpy(&str[1], orient); + } + st->magn_orient.rotation[6 + i] = str; + } + break; + default: + st->magn_orient = st->orientation; + break; + } + + return 0; +} + +int inv_mpu_magn_read(const struct inv_mpu6050_state *st, int axis, int *val) +{ + int ret; + + switch (st->chip_type) { + case INV_MPU9250: + case INV_MPU9255: + ret = inv_mpu9250_magn_read(st, axis, val); + break; + default: + ret = -ENODEV; + break; + } + + return ret; +} diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h new file mode 100644 index 000000000000..efa2ec1b3b2f --- /dev/null +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_magn.h @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2019 TDK-InvenSense, Inc. + */ + +#ifndef INV_MPU_MAGN_H_ +#define INV_MPU_MAGN_H_ + +#include + +#include "inv_mpu_iio.h" + +#ifdef CONFIG_INV_MPU6050_MAGN + +/** + * inv_mpu_magn_probe() - probe and setup magnetometer chip + * @st: driver internal state + * + * Returns 0 on success, a negative error code otherwise + * + * It is probing the chip and setting up all needed i2c transfers. + * Noop if there is no magnetometer in the chip. + */ +int inv_mpu_magn_probe(struct inv_mpu6050_state *st); + +/** + * inv_mpu_magn_get_scale() - get magnetometer scale value + * @st: driver internal state + * + * Returns IIO data format. + */ +static inline int inv_mpu_magn_get_scale(const struct inv_mpu6050_state *st, + const struct iio_chan_spec *chan, + int *val, int *val2) +{ + *val = 0; + *val2 = st->magn_raw_to_gauss[chan->address]; + return IIO_VAL_INT_PLUS_MICRO; +} + +/** + * inv_mpu_magn_set_rate() - set magnetometer sampling rate + * @st: driver internal state + * @fifo_rate: mpu set fifo rate + * + * Returns 0 on success, a negative error code otherwise + * + * Limit sampling frequency to the maximum value supported by the + * magnetometer chip. Resulting in duplicated data for higher frequencies. + * Noop if there is no magnetometer in the chip. + */ +int inv_mpu_magn_set_rate(const struct inv_mpu6050_state *st, int fifo_rate); + +/** + * inv_mpu_magn_set_orient() - fill magnetometer mounting matrix + * @st: driver internal state + * + * Returns 0 on success, a negative error code otherwise + * + * Fill magnetometer mounting matrix using the provided chip matrix. + */ +int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st); + +/** + * inv_mpu_magn_read() - read magnetometer data + * @st: driver internal state + * @axis: IIO modifier axis value + * @val: store corresponding axis value + * + * Returns 0 on success, a negative error code otherwise + */ +int inv_mpu_magn_read(const struct inv_mpu6050_state *st, int axis, int *val); + +#else /* CONFIG_INV_MPU6050_MAGN */ + +static inline int inv_mpu_magn_probe(struct inv_mpu6050_state *st) +{ + return 0; +} + +static inline int inv_mpu_magn_get_scale(const struct inv_mpu6050_state *st, + const struct iio_chan_spec *chan, + int *val, int *val2) +{ + return -EINVAL; +} + +static inline int inv_mpu_magn_set_rate(const struct inv_mpu6050_state *st, + int fifo_rate) +{ + return 0; +} + +static inline int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st) +{ + return 0; +} + +static inline int inv_mpu_magn_read(const struct inv_mpu6050_state *st, int axis, + int *val) +{ + return 0; +} + +#endif /* CONFIG_INV_MPU6050_MAGN */ + +#endif /* INV_MPU_MAGN_H_ */