From patchwork Tue Feb 5 17:43:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rui Miguel Silva X-Patchwork-Id: 157505 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp5445175jaa; Tue, 5 Feb 2019 09:43:52 -0800 (PST) X-Google-Smtp-Source: AHgI3IZMUBSKFVjKXNfkmYHjb1dbtGZ7WDV1kjrGv3SSPaJAza1eyCLmXmznzAcgHQsVNlQv4EVg X-Received: by 2002:a63:d810:: with SMTP id b16mr618763pgh.220.1549388632285; Tue, 05 Feb 2019 09:43:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549388632; cv=none; d=google.com; s=arc-20160816; b=ilC8IXjx3fS/0AqrBIaOCNFFk5SQO4iQfYOlyYbpTnw89SwzqN7YHAMpIdG/PfzZRm 9E1q1g73wRbZt4W78H9PvEPQlrzI7PsV60h+t82cBRMavJY427qJ3o5gdAzY+Zzve5zc n7Bd0wa5dHvtbTt/YuBaXVqymp+eU1hVSHiSPZLpXGAQMXQpKo9bk7uEqpQ8utcz+y9z a0rpGN/jaSkog8v+IGCpb2mD4fxqTPbJ96N2nEZ2IigMqUs6rb9KPYZ3mXJR1peZKByN M57VwxNLx/8tTDDiHtUgES1tDZl3FPqhruLXScbM7VQbiCM6Cb46Go3hQknhvfJWH4gr cAsg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=ERTGWcj2mXhrs1MM5n+vI6FIpImhaTERquVn+K2Zjrc=; b=JHvekjDS53MUCg1x6Uv1vWpFwWeDpPPLIBhv0U0O17iCJlUbKImKXD+Cpa/GycfERW AXfcP/foRP+mLBr2WraC6TIoRHZxWtCqAmi1zVnyL7yeyrE25Jhpl4raiqh5SyvJC3G2 yx5b0Luk7lQksVr1BQ2NJ/LxtHtO081SDoArFaBPe2vhsPI5KilHiz3vEYioalK7ommU LEYIBpZu4bPiwL0y+Bgy8fAQYVLN61WV5hFZF4LF5rq/NbJiU66SDcqlWfTEOlV13bde dU7AotMAWtkK8urabQHMHDFiOt1TxVxxlVybbOGhXmXByBRCjkGgnrrRsf7TBHvKY5cL +FCw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="X/1RzFo9"; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g8si3413699pgb.128.2019.02.05.09.43.52; Tue, 05 Feb 2019 09:43:52 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="X/1RzFo9"; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728634AbfBERnv (ORCPT + 7 others); Tue, 5 Feb 2019 12:43:51 -0500 Received: from mail-wr1-f65.google.com ([209.85.221.65]:41604 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726742AbfBERnv (ORCPT ); Tue, 5 Feb 2019 12:43:51 -0500 Received: by mail-wr1-f65.google.com with SMTP id x10so4579097wrs.8 for ; Tue, 05 Feb 2019 09:43:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ERTGWcj2mXhrs1MM5n+vI6FIpImhaTERquVn+K2Zjrc=; b=X/1RzFo9umi69PDUybyvJ2T04C1op+H6HZMzjMexVLQNCGfMomxfkr4xM9L0QVnRnJ b/0mlHXHOXD/dnZXucCjOv2u3Xa4KExxO3IClyioYogd9G/Rc7vMhJb6D52LPyHAQTwA FdlUlg5brXcZX6tunn5F4sba8bZImt4IHpD5yFeEDxvK055I4NN9GLxUNnJWuFh6IOHG 8SvvFPmiDOJDIvMJT9rZX3QvBrObdmhgK/3FbYhgfr/nH0hhmaeHDkTy5zXB2DPLgHHd OSiJSZERNJ4vOaxrquS6JqH2zJP0SDLgxwmtz+6UamsXeWRx5eu9PiB61alelf+Gcd7o qPvA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ERTGWcj2mXhrs1MM5n+vI6FIpImhaTERquVn+K2Zjrc=; b=RqkJqAkprFwUtdvp56CALM6FoLT9nI906I9G+ePK7VRnlqCaLQ1ifqA0F8V5VoQJhO KYjIYM+++jwmOznTomnMZ3nyLZBOvY19B5mHuJl5ig3cZ0xZA8jc8scXC5rQ33baj5WA l86ZOdZJtBLbZKJ/ToXxgxAg7QXHfKdoGcJno25EKexrcEVDPFyWZKmOfP/DTjilYK7w s6TeNy/RFR61z7dGE/03rp7ixQM2A+ADx/0nRHErj0CqY8czKYpEgM+NJvDaUCRSCbqK Etete7Vim2leHRhtOqosdqH0ox1NUvTt9C4xcl94gCOf9qxAOXDXr5PrQTXwXOzNukTB yl6w== X-Gm-Message-State: AHQUAubZWIXJy1X+sz+gErDmMaSyg5FN8mRiTRkIEetwSQluUMLSQtEe ua7c1GqcIk8lTT5eJpXn5Pkq7A== X-Received: by 2002:a5d:4a85:: with SMTP id o5mr4674567wrq.54.1549388629255; Tue, 05 Feb 2019 09:43:49 -0800 (PST) Received: from arch-late.local (a109-49-46-234.cpe.netcabo.pt. [109.49.46.234]) by smtp.gmail.com with ESMTPSA id s132sm12225751wmf.28.2019.02.05.09.43.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 05 Feb 2019 09:43:48 -0800 (PST) From: Rui Miguel Silva To: Jonathan Cameron , Hartmut Knaack , Lars-Peter Clausen , Peter Meerwald-Stadler , Shawn Guo , Rob Herring , Fabio Estevam Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, Rui Miguel Silva Subject: [PATCH v2 1/5] iio: gyro: add DT bindings to fxas21002 Date: Tue, 5 Feb 2019 17:43:29 +0000 Message-Id: <20190205174333.17672-2-rui.silva@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190205174333.17672-1-rui.silva@linaro.org> References: <20190205174333.17672-1-rui.silva@linaro.org> MIME-Version: 1.0 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add device tree bindings for the FXAS21002 gyroscope. Signed-off-by: Rui Miguel Silva --- .../bindings/iio/gyroscope/fxas2100x.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/gyroscope/fxas2100x.txt -- 2.20.1 Reviewed-by: Rob Herring diff --git a/Documentation/devicetree/bindings/iio/gyroscope/fxas2100x.txt b/Documentation/devicetree/bindings/iio/gyroscope/fxas2100x.txt new file mode 100644 index 000000000000..df10a60aa533 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/gyroscope/fxas2100x.txt @@ -0,0 +1,18 @@ +* NXP FXAS2100X Gyroscope device tree bindings + +http://www.nxp.com/products/sensors/gyroscopes/3-axis-digital-gyroscope:FXAS21002C + +Required properties: + - compatible : should be "nxp,fxas21002" + - reg : the I2C address of the sensor + - vdd-supply: phandle to the regulator that provides power to the sensor. + - vddio-supply: phandle to the regulator that provides power to the bus. + +Example: + +fxas21002@20 { + compatible = "nxp,fxas21002"; + reg = <0x20>; + vdd-supply = <®_peri_3p15v>; + vddio-supply = <®_peri_3p15v>; +}; From patchwork Tue Feb 5 17:43:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rui Miguel Silva X-Patchwork-Id: 157506 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp5445238jaa; Tue, 5 Feb 2019 09:43:56 -0800 (PST) X-Google-Smtp-Source: AHgI3IaMlqYQZh9G+1I47Atol7WAszcJB7ufuMVSEiwnr+cGVVaaLLDd8kDxx0GGDdoKPQCYWyUc X-Received: by 2002:a62:a1a:: with SMTP id s26mr6166984pfi.31.1549388636691; Tue, 05 Feb 2019 09:43:56 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549388636; cv=none; d=google.com; s=arc-20160816; b=WzGgTLe7HWEd9Ps/H8aU+H8lsEugl3KHDTmVNzvenCN5VQh4iuwkTvyJV8xPa8r52w /V7f0te9CIcul+mge1xIOXPTDuuRZEqTAEk5kxglcZl2wMwnAzi0dRk/gTyYqPtrW9Dj RBEGwU1h42YALS6q/wosNoAsQv0SQ6dw/XwdT7GF5Yaw2wEs7V/DFmdCk5k42YJCOOxh nD/qgpcHIh6N6dJ64bUGOuaVCROVbH7JmvwFIkYfUqk4AjM+imFkye751vaMMQZEMBHA BwFIysp4z86DWCP7RdAp8+wbUCQ/F1XiyMTl9915rvSFnQdJa2T9cLOw19TjlnO7DAGG 215A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=4enINrP4BD78y/Jm1yA3obRtES69JlbFA+Rqq63Qn3A=; b=EPt5riLb0j5tc+x2gnw745b6QZ4HYmTj43WA6+yg9NnKTA5XBa/aX8q1TedLsSkxxf Z8NUf/je7y+iaV9zlhgl4n+UVo95ndCg5ZfrJsWg4rcvPSc4xHCFeq/ye6ToHtfdyXj2 CLdoSqWP9SzVv+0V8SL9KnGaOEp0QdnJhaNISYeYoKcCoESAFTEDjitPNPosgzKhNJVO 0GlU+1FFPiDDUNeafYODuTFNR19aPue5EZLI3ILgb48FihPR4yKMV5CIkOKoHimLJZnp AWnuTvxBIRKLNXdOi6UHXYa9UyMFSDk8OqaNxlZSl0aVT+zi90VcUXZE8t0jxXL2Ck/4 Ovhw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=K4hRj681; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g8si3413699pgb.128.2019.02.05.09.43.56; Tue, 05 Feb 2019 09:43:56 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=K4hRj681; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728688AbfBERn4 (ORCPT + 7 others); Tue, 5 Feb 2019 12:43:56 -0500 Received: from mail-wm1-f66.google.com ([209.85.128.66]:53095 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727752AbfBERnz (ORCPT ); Tue, 5 Feb 2019 12:43:55 -0500 Received: by mail-wm1-f66.google.com with SMTP id m1so4588918wml.2 for ; Tue, 05 Feb 2019 09:43:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=4enINrP4BD78y/Jm1yA3obRtES69JlbFA+Rqq63Qn3A=; b=K4hRj681f1Fw2WbiwgObNQOtlG+iWZXFx9iYExMajT9KyPWkHsgCAtFEth/cmHCxRW 7Zni7jTtTbImfGWIDr+jHj216YRvQbOQVTxXoXA3ojc575r7ElnrCsDMSPY4KpKCZWM/ t0UOjCawEGrsjNCmB9nkXoV98E2EE+CU7eZaYmlEVpZxTRYCIWCBtiqdEom8IprRqz3+ G1ITua2UKDxnDRYumUcHIPXRAVm5G+FRCFTXq61IHbujHQ73UmT23TexiM8nH7dQabSd tP0UUDaS38h+LXyVxzBDY1Vh6Vcx03sXL0FbizGPmK06Z4vnOZsa1PF889WG8pjJDw1Z yJ9g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=4enINrP4BD78y/Jm1yA3obRtES69JlbFA+Rqq63Qn3A=; b=eFE0ipD8i9rpnQyEJooujJLjI4NbOlj6w72mrLOMwWLTu9bMnIPJja/xqa2W4CcpIJ 8+NFrWSPrtfIEfeOv0WVQZbwYJqMHDIQ5LOeZJS64mq+SEk2r8lMajOWcvEt6HnSGvF+ srvEDunfXRMI0gBBNa4i0MxlLgMUOyLZIvMn5DWDsv3ChqOuU3iac/EfC3FCeI6JfZiL tgfhWKgkzmsVIL7wDxpj7B00rSoQpl0YEzTdBwkisoBGiML55m+WbSnCG8o2WTGA8M5u ux5n0FwHXs3vtOuyNRXRfVibXpuS+ubMQ6HDHzgr9nHVj2mT5rV2uEIuzLzYIe5XsoRy Z6CA== X-Gm-Message-State: AHQUAubwNcBMLPpTI1lm+zcMFHdeiwSA7bHVGJjmY6/DJArSE9DOF7T4 jf7wSRnLmE5zgqttPGELVjiz7g== X-Received: by 2002:a7b:cc86:: with SMTP id p6mr4536668wma.19.1549388631716; Tue, 05 Feb 2019 09:43:51 -0800 (PST) Received: from arch-late.local (a109-49-46-234.cpe.netcabo.pt. [109.49.46.234]) by smtp.gmail.com with ESMTPSA id s132sm12225751wmf.28.2019.02.05.09.43.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 05 Feb 2019 09:43:51 -0800 (PST) From: Rui Miguel Silva To: Jonathan Cameron , Hartmut Knaack , Lars-Peter Clausen , Peter Meerwald-Stadler , Shawn Guo , Rob Herring , Fabio Estevam Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, Rui Miguel Silva Subject: [PATCH v2 2/5] iio: gyro: fxas2100x: add core driver for fxas2100x gyroscope Date: Tue, 5 Feb 2019 17:43:30 +0000 Message-Id: <20190205174333.17672-3-rui.silva@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190205174333.17672-1-rui.silva@linaro.org> References: <20190205174333.17672-1-rui.silva@linaro.org> MIME-Version: 1.0 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This adds core support for the NXP fxas2100x Tri-axis gyroscope, using the iio subsystem. It supports PM operations, axis reading, temperature, scale factor of the axis, high pass and low pass filtering, and sampling frequency selection. It will have extras modules to support the communication over i2c and spi. Signed-off-by: Rui Miguel Silva --- drivers/iio/gyro/Kconfig | 11 + drivers/iio/gyro/Makefile | 1 + drivers/iio/gyro/fxas2100x.h | 151 +++++ drivers/iio/gyro/fxas2100x_core.c | 931 ++++++++++++++++++++++++++++++ 4 files changed, 1094 insertions(+) create mode 100644 drivers/iio/gyro/fxas2100x.h create mode 100644 drivers/iio/gyro/fxas2100x_core.c -- 2.20.1 diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig index 3126cf05e6b9..c168aa63de3b 100644 --- a/drivers/iio/gyro/Kconfig +++ b/drivers/iio/gyro/Kconfig @@ -73,6 +73,17 @@ config BMG160_SPI tristate select REGMAP_SPI +config FXAS2100X + tristate "NXP FXAS2100X Gyro Sensor" + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER + help + Say yes here to build support for NXP FXAS2100X family Tri-axis Gyro + Sensor driver connected via I2C or SPI. + + This driver can also be built as a module. If so, the module + will be called fxas2100x_i2c or fxas2100x_spi. + config HID_SENSOR_GYRO_3D depends on HID_SENSOR_HUB select IIO_BUFFER diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile index 295ec780c4eb..9e2395185a6e 100644 --- a/drivers/iio/gyro/Makefile +++ b/drivers/iio/gyro/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_ADXRS450) += adxrs450.o obj-$(CONFIG_BMG160) += bmg160_core.o obj-$(CONFIG_BMG160_I2C) += bmg160_i2c.o obj-$(CONFIG_BMG160_SPI) += bmg160_spi.o +obj-$(CONFIG_FXAS2100X) += fxas2100x_core.o obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o diff --git a/drivers/iio/gyro/fxas2100x.h b/drivers/iio/gyro/fxas2100x.h new file mode 100644 index 000000000000..2b503196337f --- /dev/null +++ b/drivers/iio/gyro/fxas2100x.h @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Driver for NXP FXAS2100x Gyroscope - Header + * + * Copyright (C) 2019 Linaro Ltd. + * + */ + +#ifndef FXAS2100X_H_ +#define FXAS2100X_H_ + +#include + +#define FXAS2100X_REG_STATUS 0x00 +#define FXAS2100X_REG_OUT_X_MSB 0x01 +#define FXAS2100X_REG_OUT_X_LSB 0x02 +#define FXAS2100X_REG_OUT_Y_MSB 0x03 +#define FXAS2100X_REG_OUT_Y_LSB 0x04 +#define FXAS2100X_REG_OUT_Z_MSB 0x05 +#define FXAS2100X_REG_OUT_Z_LSB 0x06 +#define FXAS2100X_REG_DR_STATUS 0x07 +#define FXAS2100X_REG_F_STATUS 0x08 +#define FXAS2100X_REG_F_SETUP 0x09 +#define FXAS2100X_REG_F_EVENT 0x0A +#define FXAS2100X_REG_INT_SRC_FLAG 0x0B +#define FXAS2100X_REG_WHO_AM_I 0x0C +#define FXAS2100X_REG_CTRL0 0x0D +#define FXAS2100X_REG_RT_CFG 0x0E +#define FXAS2100X_REG_RT_SRC 0x0F +#define FXAS2100X_REG_RT_THS 0x10 +#define FXAS2100X_REG_RT_COUNT 0x11 +#define FXAS2100X_REG_TEMP 0x12 +#define FXAS2100X_REG_CTRL1 0x13 +#define FXAS2100X_REG_CTRL2 0x14 +#define FXAS2100X_REG_CTRL3 0x15 + +enum fxas2100x_fields { + F_DR_STATUS, + F_OUT_X_MSB, + F_OUT_X_LSB, + F_OUT_Y_MSB, + F_OUT_Y_LSB, + F_OUT_Z_MSB, + F_OUT_Z_LSB, + /* DR_STATUS */ + F_ZYX_OW, F_Z_OW, F_Y_OW, F_X_OW, F_ZYX_DR, F_Z_DR, F_Y_DR, F_X_DR, + /* F_STATUS */ + F_OVF, F_WMKF, F_CNT, + /* F_SETUP */ + F_MODE, F_WMRK, + /* F_EVENT */ + F_EVENT, FE_TIME, + /* INT_SOURCE_FLAG */ + F_BOOTEND, F_SRC_FIFO, F_SRC_RT, F_SRC_DRDY, + /* WHO_AM_I */ + F_WHO_AM_I, + /* CTRL_REG0 */ + F_BW, F_SPIW, F_SEL, F_HPF_EN, F_FS, + /* RT_CFG */ + F_ELE, F_ZTEFE, F_YTEFE, F_XTEFE, + /* RT_SRC */ + F_EA, F_ZRT, F_ZRT_POL, F_YRT, F_YRT_POL, F_XRT, F_XRT_POL, + /* RT_THS */ + F_DBCNTM, F_THS, + /* RT_COUNT */ + F_RT_COUNT, + /* TEMP */ + F_TEMP, + /* CTRL_REG1 */ + F_RST, F_ST, F_DR, F_ACTIVE, F_READY, + /* CTRL_REG2 */ + F_INT_CFG_FIFO, F_INT_EN_FIFO, F_INT_CFG_RT, F_INT_EN_RT, + F_INT_CFG_DRDY, F_INT_EN_DRDY, F_IPOL, F_PP_OD, + /* CTRL_REG3 */ + F_WRAPTOONE, F_EXTCTRLEN, F_FS_DOUBLE, + /* MAX FIELDS */ + F_MAX_FIELDS, +}; + +static const struct reg_field fxas2100x_reg_fields[] = { + [F_DR_STATUS] = REG_FIELD(FXAS2100X_REG_STATUS, 0, 7), + [F_OUT_X_MSB] = REG_FIELD(FXAS2100X_REG_OUT_X_MSB, 0, 7), + [F_OUT_X_LSB] = REG_FIELD(FXAS2100X_REG_OUT_X_LSB, 0, 7), + [F_OUT_Y_MSB] = REG_FIELD(FXAS2100X_REG_OUT_Y_MSB, 0, 7), + [F_OUT_Y_LSB] = REG_FIELD(FXAS2100X_REG_OUT_Y_LSB, 0, 7), + [F_OUT_Z_MSB] = REG_FIELD(FXAS2100X_REG_OUT_Z_MSB, 0, 7), + [F_OUT_Z_LSB] = REG_FIELD(FXAS2100X_REG_OUT_Z_LSB, 0, 7), + [F_ZYX_OW] = REG_FIELD(FXAS2100X_REG_DR_STATUS, 7, 7), + [F_Z_OW] = REG_FIELD(FXAS2100X_REG_DR_STATUS, 6, 6), + [F_Y_OW] = REG_FIELD(FXAS2100X_REG_DR_STATUS, 5, 5), + [F_X_OW] = REG_FIELD(FXAS2100X_REG_DR_STATUS, 4, 4), + [F_ZYX_DR] = REG_FIELD(FXAS2100X_REG_DR_STATUS, 3, 3), + [F_Z_DR] = REG_FIELD(FXAS2100X_REG_DR_STATUS, 2, 2), + [F_Y_DR] = REG_FIELD(FXAS2100X_REG_DR_STATUS, 1, 1), + [F_X_DR] = REG_FIELD(FXAS2100X_REG_DR_STATUS, 0, 0), + [F_OVF] = REG_FIELD(FXAS2100X_REG_F_STATUS, 7, 7), + [F_WMKF] = REG_FIELD(FXAS2100X_REG_F_STATUS, 6, 6), + [F_CNT] = REG_FIELD(FXAS2100X_REG_F_STATUS, 0, 5), + [F_MODE] = REG_FIELD(FXAS2100X_REG_F_SETUP, 6, 7), + [F_WMRK] = REG_FIELD(FXAS2100X_REG_F_SETUP, 0, 5), + [F_EVENT] = REG_FIELD(FXAS2100X_REG_F_EVENT, 5, 5), + [FE_TIME] = REG_FIELD(FXAS2100X_REG_F_EVENT, 0, 4), + [F_BOOTEND] = REG_FIELD(FXAS2100X_REG_INT_SRC_FLAG, 3, 3), + [F_SRC_FIFO] = REG_FIELD(FXAS2100X_REG_INT_SRC_FLAG, 2, 2), + [F_SRC_RT] = REG_FIELD(FXAS2100X_REG_INT_SRC_FLAG, 1, 1), + [F_SRC_DRDY] = REG_FIELD(FXAS2100X_REG_INT_SRC_FLAG, 0, 0), + [F_WHO_AM_I] = REG_FIELD(FXAS2100X_REG_WHO_AM_I, 0, 7), + [F_BW] = REG_FIELD(FXAS2100X_REG_CTRL0, 6, 7), + [F_SPIW] = REG_FIELD(FXAS2100X_REG_CTRL0, 5, 5), + [F_SEL] = REG_FIELD(FXAS2100X_REG_CTRL0, 3, 4), + [F_HPF_EN] = REG_FIELD(FXAS2100X_REG_CTRL0, 2, 2), + [F_FS] = REG_FIELD(FXAS2100X_REG_CTRL0, 0, 1), + [F_ELE] = REG_FIELD(FXAS2100X_REG_RT_CFG, 3, 3), + [F_ZTEFE] = REG_FIELD(FXAS2100X_REG_RT_CFG, 2, 2), + [F_YTEFE] = REG_FIELD(FXAS2100X_REG_RT_CFG, 1, 1), + [F_XTEFE] = REG_FIELD(FXAS2100X_REG_RT_CFG, 0, 0), + [F_EA] = REG_FIELD(FXAS2100X_REG_RT_SRC, 6, 6), + [F_ZRT] = REG_FIELD(FXAS2100X_REG_RT_SRC, 5, 5), + [F_ZRT_POL] = REG_FIELD(FXAS2100X_REG_RT_SRC, 4, 4), + [F_YRT] = REG_FIELD(FXAS2100X_REG_RT_SRC, 3, 3), + [F_YRT_POL] = REG_FIELD(FXAS2100X_REG_RT_SRC, 2, 2), + [F_XRT] = REG_FIELD(FXAS2100X_REG_RT_SRC, 1, 1), + [F_XRT_POL] = REG_FIELD(FXAS2100X_REG_RT_SRC, 0, 0), + [F_DBCNTM] = REG_FIELD(FXAS2100X_REG_RT_THS, 7, 7), + [F_THS] = REG_FIELD(FXAS2100X_REG_RT_SRC, 0, 6), + [F_RT_COUNT] = REG_FIELD(FXAS2100X_REG_RT_COUNT, 0, 7), + [F_TEMP] = REG_FIELD(FXAS2100X_REG_TEMP, 0, 7), + [F_RST] = REG_FIELD(FXAS2100X_REG_CTRL1, 6, 6), + [F_ST] = REG_FIELD(FXAS2100X_REG_CTRL1, 5, 5), + [F_DR] = REG_FIELD(FXAS2100X_REG_CTRL1, 2, 4), + [F_ACTIVE] = REG_FIELD(FXAS2100X_REG_CTRL1, 1, 1), + [F_READY] = REG_FIELD(FXAS2100X_REG_CTRL1, 0, 0), + [F_INT_CFG_FIFO] = REG_FIELD(FXAS2100X_REG_CTRL2, 7, 7), + [F_INT_EN_FIFO] = REG_FIELD(FXAS2100X_REG_CTRL2, 6, 6), + [F_INT_CFG_RT] = REG_FIELD(FXAS2100X_REG_CTRL2, 5, 5), + [F_INT_EN_RT] = REG_FIELD(FXAS2100X_REG_CTRL2, 4, 4), + [F_INT_CFG_DRDY] = REG_FIELD(FXAS2100X_REG_CTRL2, 3, 3), + [F_INT_EN_DRDY] = REG_FIELD(FXAS2100X_REG_CTRL2, 2, 2), + [F_IPOL] = REG_FIELD(FXAS2100X_REG_CTRL2, 1, 1), + [F_PP_OD] = REG_FIELD(FXAS2100X_REG_CTRL2, 0, 0), + [F_WRAPTOONE] = REG_FIELD(FXAS2100X_REG_CTRL3, 3, 3), + [F_EXTCTRLEN] = REG_FIELD(FXAS2100X_REG_CTRL3, 2, 2), + [F_FS_DOUBLE] = REG_FIELD(FXAS2100X_REG_CTRL3, 0, 0), +}; + +extern const struct dev_pm_ops fxas2100x_pm_ops; + +int fxas2100x_core_probe(struct device *dev, struct regmap *regmap, int irq, + const char *name); +void fxas2100x_core_remove(struct device *dev); +#endif diff --git a/drivers/iio/gyro/fxas2100x_core.c b/drivers/iio/gyro/fxas2100x_core.c new file mode 100644 index 000000000000..9c0ba283fea8 --- /dev/null +++ b/drivers/iio/gyro/fxas2100x_core.c @@ -0,0 +1,931 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for NXP FXAS2100x Gyroscope - Core + * + * Copyright (C) 2019 Linaro Ltd. + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "fxas2100x.h" + +#define FXAS21002_CHIP_ID_1 0xD6 +#define FXAS21002_CHIP_ID_2 0xD7 + +enum fxas2100x_mode_state { + FXAS2100X_MODE_STANDBY, + FXAS2100X_MODE_READY, + FXAS2100X_MODE_ACTIVE, +}; + +#define FXAS2100X_STANDBY_ACTIVE_TIME_MS 62 +#define FXAS2100X_READY_ACTIVE_TIME_MS 7 + +#define FXAS2100X_ODR_LIST_MAX 10 + +#define FXAS2100X_SCALE_FRACTIONAL 32 +#define FXAS2100X_RANGE_LIMIT_DOUBLE 2000 + +#define FXAS2100X_AXIS_TO_REG(axis) (FXAS2100X_REG_OUT_X_MSB + ((axis) * 2)) + +static const int fxas2100x_odr_values[] = { + 800, 400, 200, 100, 50, 25, 12, 12 +}; + +/* + * These values are taken from the low-pass filter cutoff frequency calculated + * ODR * 0.lpf_values. So, for ODR = 800Hz with a lpf value = 0.32 + * => LPF cutoff frequency = 800 * 0.32 = 256 Hz + */ +static const int fxas2100x_lpf_values[] = { + 32, 16, 8 +}; + +/* + * These values are taken from the high-pass filter cutoff frequency calculated + * ODR * 0.0hpf_values. So, for ODR = 800Hz with a hpf value = 0.018750 + * => HPF cutoff frequency = 800 * 0.018750 = 15 Hz + */ +static const int fxas2100x_hpf_values[] = { + 18750, 9625, 4875, 2475 +}; + +static const int fxas2100x_range_values[] = { + 4000, 2000, 1000, 500, 250 +}; + +struct fxas2100x_data { + u8 chip_id; + enum fxas2100x_mode_state mode; + enum fxas2100x_mode_state prev_mode; + + struct mutex lock; /* serialize data access */ + struct regmap *regmap; + struct regmap_field *regmap_fields[F_MAX_FIELDS]; + s16 buffer[8]; + + struct iio_trigger *dready_trig; + int irq; + + struct regulator *vdd; + struct regulator *vddio; +}; + +enum fxas2100x_channel_index { + CHANNEL_SCAN_INDEX_X, + CHANNEL_SCAN_INDEX_Y, + CHANNEL_SCAN_INDEX_Z, + CHANNEL_SCAN_MAX, +}; + +static int fxas2100x_odr_hz_from_value(struct fxas2100x_data *data, u8 value) +{ + int odr_value_max = ARRAY_SIZE(fxas2100x_odr_values) - 1; + + value = min_t(u8, value, odr_value_max); + + return fxas2100x_odr_values[value]; +} + +static int fxas2100x_odr_value_from_hz(struct fxas2100x_data *data, + unsigned int hz) +{ + int odr_table_size = ARRAY_SIZE(fxas2100x_odr_values); + int i; + + for (i = 0; i < odr_table_size; i++) + if (fxas2100x_odr_values[i] == hz) + return i; + + return -EINVAL; +} + +static int fxas2100x_lpf_bw_from_value(struct fxas2100x_data *data, u8 value) +{ + int lpf_value_max = ARRAY_SIZE(fxas2100x_lpf_values) - 1; + + value = min_t(u8, value, lpf_value_max); + + return fxas2100x_lpf_values[value]; +} + +static int fxas2100x_lpf_value_from_bw(struct fxas2100x_data *data, + unsigned int hz) +{ + int lpf_table_size = ARRAY_SIZE(fxas2100x_lpf_values); + int i; + + for (i = 0; i < lpf_table_size; i++) + if (fxas2100x_lpf_values[i] == hz) + return i; + + return -EINVAL; +} + +static int fxas2100x_hpf_sel_from_value(struct fxas2100x_data *data, u8 value) +{ + int hpf_value_max = ARRAY_SIZE(fxas2100x_hpf_values) - 1; + + value = min_t(u8, value, hpf_value_max); + + return fxas2100x_hpf_values[value]; +} + +static int fxas2100x_hpf_value_from_sel(struct fxas2100x_data *data, + unsigned int hz) +{ + int hpf_table_size = ARRAY_SIZE(fxas2100x_hpf_values); + int i; + + for (i = 0; i < hpf_table_size; i++) + if (fxas2100x_hpf_values[i] == hz) + return i; + + return -EINVAL; +} + +static int fxas2100x_range_fs_from_value(struct fxas2100x_data *data, + u8 value) +{ + int range_value_max = ARRAY_SIZE(fxas2100x_range_values) - 1; + unsigned int fs_double; + int ret; + + /* We need to check if FS_DOUBLE is enabled to offset the value */ + ret = regmap_field_read(data->regmap_fields[F_FS_DOUBLE], &fs_double); + if (ret < 0) + return ret; + + if (!fs_double) + value += 1; + + value = min_t(u8, value, range_value_max); + + return fxas2100x_range_values[value]; +} + +static int fxas2100x_range_value_from_fs(struct fxas2100x_data *data, + unsigned int range) +{ + int range_table_size = ARRAY_SIZE(fxas2100x_range_values); + bool found = false; + int ret; + int i; + + for (i = 0; i < range_table_size; i++) + if (fxas2100x_range_values[i] == range) + found = true; + if (!found) + return -EINVAL; + + if (range > FXAS2100X_RANGE_LIMIT_DOUBLE) + ret = regmap_field_write(data->regmap_fields[F_FS_DOUBLE], 1); + else + ret = regmap_field_write(data->regmap_fields[F_FS_DOUBLE], 0); + if (ret < 0) + return ret; + + return i; +} + +static int fxas2100x_mode_get(struct fxas2100x_data *data) +{ + unsigned int active; + unsigned int ready; + int ret; + + ret = regmap_field_read(data->regmap_fields[F_ACTIVE], &active); + if (ret < 0) + return ret; + if (active) + return FXAS2100X_MODE_ACTIVE; + + ret = regmap_field_read(data->regmap_fields[F_READY], &ready); + if (ret < 0) + return ret; + if (ready) + return FXAS2100X_MODE_READY; + + return FXAS2100X_MODE_STANDBY; +} + +static int fxas2100x_mode_set(struct fxas2100x_data *data, + enum fxas2100x_mode_state mode) +{ + int ret; + + if (mode > FXAS2100X_MODE_ACTIVE) + return -EINVAL; + + if (mode == data->mode) + return 0; + + if (mode == FXAS2100X_MODE_READY) + ret = regmap_field_write(data->regmap_fields[F_READY], 1); + else + ret = regmap_field_write(data->regmap_fields[F_READY], 0); + if (ret < 0) + return ret; + + if (mode == FXAS2100X_MODE_ACTIVE) + ret = regmap_field_write(data->regmap_fields[F_ACTIVE], 1); + else + ret = regmap_field_write(data->regmap_fields[F_ACTIVE], 0); + if (ret < 0) + return ret; + + /* if going to active wait the setup times */ + if (mode == FXAS2100X_MODE_ACTIVE) + if (data->mode == FXAS2100X_MODE_STANDBY) + msleep_interruptible(FXAS2100X_STANDBY_ACTIVE_TIME_MS); + if (data->mode == FXAS2100X_MODE_READY) + msleep_interruptible(FXAS2100X_READY_ACTIVE_TIME_MS); + + data->prev_mode = data->mode; + data->mode = mode; + + return ret; +} + +static int fxas2100x_write(struct fxas2100x_data *data, + enum fxas2100x_fields field, int bits) +{ + int actual_mode; + int ret; + + mutex_lock(&data->lock); + + actual_mode = fxas2100x_mode_get(data); + if (actual_mode < 0) { + ret = actual_mode; + goto out_unlock; + } + + ret = fxas2100x_mode_set(data, FXAS2100X_MODE_READY); + if (ret < 0) + goto out_unlock; + + ret = regmap_field_write(data->regmap_fields[field], bits); + if (ret < 0) + goto out_unlock; + + ret = fxas2100x_mode_set(data, data->prev_mode); + +out_unlock: + mutex_unlock(&data->lock); + + return ret; +} + +static int fxas2100x_pm_get(struct fxas2100x_data *data) +{ + struct device *dev = regmap_get_device(data->regmap); + int ret; + + ret = pm_runtime_get_sync(dev); + if (ret < 0) + pm_runtime_put_noidle(dev); + + return ret; +} + +static int fxas2100x_pm_put(struct fxas2100x_data *data) +{ + struct device *dev = regmap_get_device(data->regmap); + + pm_runtime_mark_last_busy(dev); + + return pm_runtime_put_autosuspend(dev); +} + +static int fxas2100x_temp_get(struct fxas2100x_data *data, int *val) +{ + struct device *dev = regmap_get_device(data->regmap); + unsigned int temp; + int ret; + + mutex_lock(&data->lock); + ret = fxas2100x_pm_get(data); + if (ret < 0) + goto data_unlock; + + ret = regmap_field_read(data->regmap_fields[F_TEMP], &temp); + if (ret < 0) { + dev_err(dev, "failed to read temp: %d\n", ret); + goto data_unlock; + } + + *val = sign_extend32(temp, 7); + + ret = fxas2100x_pm_put(data); + if (ret < 0) + goto data_unlock; + + ret = IIO_VAL_INT; + +data_unlock: + mutex_unlock(&data->lock); + + return ret; +} + +static int fxas2100x_axis_get(struct fxas2100x_data *data, int index, int *val) +{ + struct device *dev = regmap_get_device(data->regmap); + __be16 axis_be; + int ret; + + mutex_lock(&data->lock); + ret = fxas2100x_pm_get(data); + if (ret < 0) + goto data_unlock; + + ret = regmap_bulk_read(data->regmap, FXAS2100X_AXIS_TO_REG(index), + &axis_be, sizeof(axis_be)); + if (ret < 0) { + dev_err(dev, "failed to read axis: %d: %d\n", index, ret); + goto data_unlock; + } + + *val = sign_extend32(be16_to_cpu(axis_be), 15); + + ret = fxas2100x_pm_put(data); + if (ret < 0) + goto data_unlock; + + ret = IIO_VAL_INT; + +data_unlock: + mutex_unlock(&data->lock); + + return ret; +} + +static int fxas2100x_odr_get(struct fxas2100x_data *data, int *odr) +{ + unsigned int odr_bits; + int ret; + + mutex_lock(&data->lock); + ret = regmap_field_read(data->regmap_fields[F_DR], &odr_bits); + if (ret < 0) + goto data_unlock; + + *odr = fxas2100x_odr_hz_from_value(data, odr_bits); + + ret = IIO_VAL_INT; + +data_unlock: + mutex_unlock(&data->lock); + + return ret; +} + +static int fxas2100x_odr_set(struct fxas2100x_data *data, int odr) +{ + int odr_bits; + + odr_bits = fxas2100x_odr_value_from_hz(data, odr); + if (odr_bits < 0) + return odr_bits; + + return fxas2100x_write(data, F_DR, odr_bits); +} + +static int fxas2100x_lpf_get(struct fxas2100x_data *data, int *val2) +{ + unsigned int bw_bits; + int ret; + + mutex_lock(&data->lock); + ret = regmap_field_read(data->regmap_fields[F_BW], &bw_bits); + if (ret < 0) + goto data_unlock; + + *val2 = fxas2100x_lpf_bw_from_value(data, bw_bits) * 10000; + + ret = IIO_VAL_INT_PLUS_MICRO; + +data_unlock: + mutex_unlock(&data->lock); + + return ret; +} + +static int fxas2100x_lpf_set(struct fxas2100x_data *data, int bw) +{ + int bw_bits; + int odr; + int ret; + + bw_bits = fxas2100x_lpf_value_from_bw(data, bw); + if (bw_bits < 0) + return bw_bits; + + /* + * From table 33 of the device spec, for ODR = 25Hz and 12.5 value 0.08 + * is not allowed and for ODR = 12.5 value 0.16 is also not allowed + */ + ret = fxas2100x_odr_get(data, &odr); + if (ret < 0) + return -EINVAL; + + if ((odr == 25 && bw_bits > 0x01) || (odr == 12 && bw_bits > 0)) + return -EINVAL; + + return fxas2100x_write(data, F_BW, bw_bits); +} + +static int fxas2100x_hpf_get(struct fxas2100x_data *data, int *val2) +{ + unsigned int sel_bits; + int ret; + + mutex_lock(&data->lock); + ret = regmap_field_read(data->regmap_fields[F_SEL], &sel_bits); + if (ret < 0) + goto data_unlock; + + *val2 = fxas2100x_hpf_sel_from_value(data, sel_bits); + + ret = IIO_VAL_INT_PLUS_MICRO; + +data_unlock: + mutex_unlock(&data->lock); + + return ret; +} + +static int fxas2100x_hpf_set(struct fxas2100x_data *data, int sel) +{ + int sel_bits; + + sel_bits = fxas2100x_hpf_value_from_sel(data, sel); + if (sel_bits < 0) + return sel_bits; + + return fxas2100x_write(data, F_SEL, sel_bits); +} + +static int fxas2100x_scale_get(struct fxas2100x_data *data, int *val) +{ + int fs_bits; + int scale; + int ret; + + mutex_lock(&data->lock); + ret = regmap_field_read(data->regmap_fields[F_FS], &fs_bits); + if (ret < 0) + goto data_unlock; + + scale = fxas2100x_range_fs_from_value(data, fs_bits); + + *val = scale; + + ret = IIO_VAL_FRACTIONAL; + +data_unlock: + mutex_unlock(&data->lock); + + return ret; +} + +static int fxas2100x_scale_set(struct fxas2100x_data *data, int range) +{ + int fs_bits; + + fs_bits = fxas2100x_range_value_from_fs(data, range); + if (fs_bits < 0) + return fs_bits; + + return fxas2100x_write(data, F_FS, fs_bits); +} + +static int fxas2100x_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int *val, + int *val2, long mask) +{ + struct fxas2100x_data *data = iio_priv(indio_dev); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + switch (chan->type) { + case IIO_TEMP: + return fxas2100x_temp_get(data, val); + case IIO_ANGL_VEL: + return fxas2100x_axis_get(data, chan->scan_index, val); + default: + return -EINVAL; + } + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ANGL_VEL: + *val2 = FXAS2100X_SCALE_FRACTIONAL; + return fxas2100x_scale_get(data, val); + default: + return -EINVAL; + } + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + *val = 0; + return fxas2100x_lpf_get(data, val2); + case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: + *val = 0; + return fxas2100x_hpf_get(data, val2); + case IIO_CHAN_INFO_SAMP_FREQ: + *val2 = 0; + return fxas2100x_odr_get(data, val); + default: + return -EINVAL; + } +} + +static int fxas2100x_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, + int val2, long mask) +{ + struct fxas2100x_data *data = iio_priv(indio_dev); + int range; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + if (val2) + return -EINVAL; + + return fxas2100x_odr_set(data, val); + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + if (val) + return -EINVAL; + + val2 = val2 / 10000; + return fxas2100x_lpf_set(data, val2); + case IIO_CHAN_INFO_SCALE: + switch (chan->type) { + case IIO_ANGL_VEL: + range = (((val * 1000 + val2 / 1000) * + FXAS2100X_SCALE_FRACTIONAL) / 1000); + return fxas2100x_scale_set(data, range); + default: + return -EINVAL; + } + case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: + return fxas2100x_hpf_set(data, val2); + default: + return -EINVAL; + } +} + +static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("12.5 25 50 100 200 400 800"); + +static IIO_CONST_ATTR(in_anglvel_filter_low_pass_3db_frequency_available, + "0.32 0.16 0.08"); + +static IIO_CONST_ATTR(in_anglvel_filter_high_pass_3db_frequency_available, + "0.018750 0.009625 0.004875 0.002475"); + +static IIO_CONST_ATTR(in_anglvel_scale_available, + "125.0 62.5 31.25 15.625 7.8125"); + +static struct attribute *fxas2100x_attributes[] = { + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + &iio_const_attr_in_anglvel_filter_low_pass_3db_frequency_available.dev_attr.attr, + &iio_const_attr_in_anglvel_filter_high_pass_3db_frequency_available.dev_attr.attr, + &iio_const_attr_in_anglvel_scale_available.dev_attr.attr, + NULL, +}; + +static const struct attribute_group fxas2100x_attrs_group = { + .attrs = fxas2100x_attributes, +}; + +#define FXAS2100X_CHANNEL(_axis) { \ + .type = IIO_ANGL_VEL, \ + .modified = 1, \ + .channel2 = IIO_MOD_##_axis, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \ + BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY) | \ + BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .scan_index = CHANNEL_SCAN_INDEX_##_axis, \ + .scan_type = { \ + .sign = 's', \ + .realbits = 16, \ + .storagebits = 16, \ + .endianness = IIO_BE, \ + }, \ +} + +static const struct iio_chan_spec fxas2100x_channels[] = { + { + .type = IIO_TEMP, + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), + .scan_index = -1, + }, + FXAS2100X_CHANNEL(X), + FXAS2100X_CHANNEL(Y), + FXAS2100X_CHANNEL(Z), +}; + +static const struct iio_info fxas2100x_info = { + .attrs = &fxas2100x_attrs_group, + .read_raw = &fxas2100x_read_raw, + .write_raw = &fxas2100x_write_raw, +}; + +static irqreturn_t fxas2100x_trigger_handler(int irq, void *p) +{ + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct fxas2100x_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->lock); + ret = regmap_bulk_read(data->regmap, FXAS2100X_REG_OUT_X_MSB, + data->buffer, CHANNEL_SCAN_MAX * sizeof(s16)); + mutex_unlock(&data->lock); + if (ret < 0) + goto notify_done; + + iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + pf->timestamp); + +notify_done: + iio_trigger_notify_done(indio_dev->trig); + + return IRQ_HANDLED; +} + +static int fxas2100x_chip_init(struct fxas2100x_data *data) +{ + struct device *dev = regmap_get_device(data->regmap); + unsigned int chip_id; + int ret; + + ret = regmap_field_read(data->regmap_fields[F_WHO_AM_I], &chip_id); + if (ret < 0) + return ret; + + if (chip_id != FXAS21002_CHIP_ID_1 && chip_id != FXAS21002_CHIP_ID_2) { + dev_err(dev, "chip id 0x%02x is not supported\n", chip_id); + return -EINVAL; + } + + data->chip_id = chip_id; + + ret = fxas2100x_mode_set(data, FXAS2100X_MODE_STANDBY); + if (ret < 0) + return ret; + + /* Set ODR to 200HZ as default */ + ret = fxas2100x_odr_set(data, 200); + if (ret < 0) + dev_err(dev, "failed to set ODR: %d\n", ret); + + return ret; +} + +static int fxas2100x_data_rdy_trigger_set_state(struct iio_trigger *trig, + bool state) +{ + struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); + struct fxas2100x_data *data = iio_priv(indio_dev); + + return regmap_field_write(data->regmap_fields[F_INT_EN_DRDY], state); +} + +static const struct iio_trigger_ops fxas2100x_trigger_ops = { + .set_trigger_state = &fxas2100x_data_rdy_trigger_set_state, +}; + +static irqreturn_t fxas2100x_data_rdy_trig_poll(int irq, void *private) +{ + struct iio_dev *indio_dev = private; + struct fxas2100x_data *data = iio_priv(indio_dev); + + iio_trigger_poll(data->dready_trig); + + return IRQ_HANDLED; +} + +static int fxas2100x_trigger_probe(struct fxas2100x_data *data) +{ + struct device *dev = regmap_get_device(data->regmap); + struct iio_dev *indio_dev = dev_get_drvdata(dev); + int ret; + + if (!data->irq) + return 0; + + data->dready_trig = devm_iio_trigger_alloc(dev, "%s-dev%d", + indio_dev->name, + indio_dev->id); + if (!data->dready_trig) + return -ENOMEM; + + ret = devm_request_irq(dev, data->irq, fxas2100x_data_rdy_trig_poll, + IRQF_TRIGGER_RISING, "fxas2100x_data_ready", + data->dready_trig); + if (ret < 0) + return ret; + + data->dready_trig->dev.parent = dev; + data->dready_trig->ops = &fxas2100x_trigger_ops; + iio_trigger_set_drvdata(data->dready_trig, indio_dev); + + return devm_iio_trigger_register(dev, data->dready_trig); +} + +static int fxas2100x_power_enable(struct fxas2100x_data *data) +{ + struct device *dev = regmap_get_device(data->regmap); + int ret; + + data->vdd = devm_regulator_get(dev->parent, "vdd"); + if (IS_ERR(data->vdd)) { + dev_err(dev, "failed to get Vdd supply\n"); + return PTR_ERR(data->vdd); + } + + ret = regulator_enable(data->vdd); + if (ret < 0) + return ret; + + data->vddio = devm_regulator_get(dev->parent, "vddio"); + if (IS_ERR(data->vddio)) { + dev_err(dev, "failed to get Vdd_IO supply\n"); + regulator_disable(data->vdd); + return PTR_ERR(data->vddio); + } + + ret = regulator_enable(data->vddio); + if (ret < 0) + return ret; + + return 0; +} + +static void fxas2100x_power_disable(struct fxas2100x_data *data) +{ + regulator_disable(data->vdd); + regulator_disable(data->vddio); +} + +int fxas2100x_core_probe(struct device *dev, struct regmap *regmap, int irq, + const char *name) +{ + struct fxas2100x_data *data; + struct iio_dev *indio_dev; + struct regmap_field *f; + int i; + int ret; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + dev_set_drvdata(dev, indio_dev); + data->irq = irq; + data->regmap = regmap; + + for (i = 0; i < F_MAX_FIELDS; i++) { + f = devm_regmap_field_alloc(dev, data->regmap, + fxas2100x_reg_fields[i]); + if (IS_ERR(f)) + return PTR_ERR(f); + + data->regmap_fields[i] = f; + } + + mutex_init(&data->lock); + + ret = fxas2100x_power_enable(data); + if (ret < 0) + return ret; + + ret = fxas2100x_chip_init(data); + if (ret < 0) + goto power_disable; + + indio_dev->dev.parent = dev; + indio_dev->channels = fxas2100x_channels; + indio_dev->num_channels = ARRAY_SIZE(fxas2100x_channels); + indio_dev->name = name; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &fxas2100x_info; + + ret = fxas2100x_trigger_probe(data); + if (ret < 0) + goto power_disable; + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, + iio_pollfunc_store_time, + fxas2100x_trigger_handler, NULL); + if (ret < 0) + goto power_disable; + + ret = pm_runtime_set_active(dev); + if (ret) + goto power_disable; + + pm_runtime_enable(dev); + pm_runtime_set_autosuspend_delay(dev, 2000); + pm_runtime_use_autosuspend(dev); + + ret = devm_iio_device_register(dev, indio_dev); + if (ret < 0) + goto power_disable; + + return 0; + +power_disable: + fxas2100x_power_disable(data); + + return ret; +} +EXPORT_SYMBOL_GPL(fxas2100x_core_probe); + +void fxas2100x_core_remove(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct fxas2100x_data *data = iio_priv(indio_dev); + + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_put_noidle(dev); + + fxas2100x_mode_set(data, FXAS2100X_MODE_STANDBY); + fxas2100x_power_disable(data); +} +EXPORT_SYMBOL_GPL(fxas2100x_core_remove); + +static int __maybe_unused fxas2100x_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct fxas2100x_data *data = iio_priv(indio_dev); + + fxas2100x_mode_set(data, FXAS2100X_MODE_STANDBY); + + return 0; +} + +static int __maybe_unused fxas2100x_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct fxas2100x_data *data = iio_priv(indio_dev); + + fxas2100x_mode_set(data, data->prev_mode); + + return 0; +} + +static int __maybe_unused fxas2100x_runtime_suspend(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct fxas2100x_data *data = iio_priv(indio_dev); + int ret; + + ret = fxas2100x_mode_set(data, FXAS2100X_MODE_READY); + if (ret < 0) + return -EAGAIN; + + return 0; +} + +static int __maybe_unused fxas2100x_runtime_resume(struct device *dev) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct fxas2100x_data *data = iio_priv(indio_dev); + int ret; + + ret = fxas2100x_mode_set(data, FXAS2100X_MODE_ACTIVE); + if (ret < 0) + return -EAGAIN; + + return 0; +} + +const struct dev_pm_ops fxas2100x_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(fxas2100x_suspend, fxas2100x_resume) + SET_RUNTIME_PM_OPS(fxas2100x_runtime_suspend, + fxas2100x_runtime_resume, NULL) +}; +EXPORT_SYMBOL_GPL(fxas2100x_pm_ops); + +MODULE_AUTHOR("Rui Miguel Silva "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("FXAS2100X Gyro driver"); From patchwork Tue Feb 5 17:43:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rui Miguel Silva X-Patchwork-Id: 157507 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp5445252jaa; Tue, 5 Feb 2019 09:43:57 -0800 (PST) X-Google-Smtp-Source: AHgI3IZnPoOreRzr49v1RRVYb9gnDKj2Ibyoah8RK5orHhVnbXlNvlUwuh62IQXOccICbKCWGfjM X-Received: by 2002:a63:5723:: with SMTP id l35mr5407133pgb.228.1549388637358; Tue, 05 Feb 2019 09:43:57 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549388637; cv=none; d=google.com; s=arc-20160816; b=Y6e9ftf5oQ4/08SYGs+QUlybLQ/A6L4+6bvolij0+YIVKhOJrUdS+oTgsjr+HKLLWj 3bldPBuccT9dYcudzLqhJWcpMXEKMWHoUcqpe0g+UwpGtjUHTMaGWQyL4H1OTdEqx1Wv 5a6RNOdrrmb1BqL3+VH0TvE/Kpu9O9ybLmVi9YLZxI05uBLv8nyTKRhFtDAdOWLsnpIk oPSrzUbbLaoKBUum05KD00gQKK2XTuGQqxPXtkD2ts+Rj+KpOyMrQy8IkB85xXk18Mdj Q3tPToSn7t+zOQEyG1SzSD/Z2fvaBwBUWtgfX0FUnBemXvBy9SMLXIfX8hA3CJUr3I/x kQ4Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=2luiUc6gzFLBKKxk29xFnHm2KXg4oKTSaw5uIVColWk=; b=LjIxaw40006M6gRQxSTnPxgLBtDn6EvXIjYkA8hStlsKFSm+aeM5esVyDiuoBLbRtx 4Dt3V8p3pZs9oOylDerj3lNnFbbkrpA+hxPQSsexe8oG8MfxKJlzkt0n1jzkr9+gE2qd SFcOgILmK56AnedhOIGHU9UXuDbx/J6lnpDB5Vz+0XXJahnWbbAZcf+PWHwP/faOa5FX vQgFny90AjU2RKGO6X/YMVbJ6Vs5XCw7/Kq2256hkwRtNUN0hYyK8RlCSI0IDNxDjzX6 woMRxf8pGSYQ6BL4jgIJkUDD8yKVo0gzZE0MxogrZ8qY069ERFDF6jX92vugRlQlLiRM xgDQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=rjVwGa4L; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g8si3413699pgb.128.2019.02.05.09.43.57; Tue, 05 Feb 2019 09:43:57 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=rjVwGa4L; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728740AbfBERn4 (ORCPT + 7 others); Tue, 5 Feb 2019 12:43:56 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:53308 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728614AbfBERn4 (ORCPT ); Tue, 5 Feb 2019 12:43:56 -0500 Received: by mail-wm1-f68.google.com with SMTP id d15so4581097wmb.3 for ; Tue, 05 Feb 2019 09:43:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=2luiUc6gzFLBKKxk29xFnHm2KXg4oKTSaw5uIVColWk=; b=rjVwGa4L999FeZ3SVbbJ4+aGsJWVX8rXVl+QWAqfkR5qA43P+71VQlBAjbrZUMxrQ5 ZUm5cIEOfvR+X+85JftO81d8SCgK1DNvTy9eFvmi+ChncIEyh6DZGEZqmNuj7pDlBdVU IcGnvDmnG7yRtw4Quk/8/Yun87pQOSe0LT1WXe/g+vrcziA4y3cEjwgylvQF45TIW7G1 pbyD0oZRZZlKHT853SdWekLwi3Q6TJaiin5vredXltaYgykbIbQ+LmK6lpYA1oCrufMv QhCTBFh2JiC1swzaE5aVbkEWOy5vQvJgnMaae1btA9BZtf1J26iMuI2OTr+a+G1xWa9L 1NCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=2luiUc6gzFLBKKxk29xFnHm2KXg4oKTSaw5uIVColWk=; b=SvWzSmFRHh2gRF3+Rt6ddeVbKPExqM4KkaMKdZjPKOq8jNDF+hh5/vJLL25XqK9lEd 6Zbq6zrXA1UDBvhm8Nsd8ZJu3mnB9WGPo4jKn0V+jFu0OYR9oyAlt5SvdtRwr2jHDDiZ YsfrZkwwvAMhumzgCVCh2vC3IUIeesf0e4Q9aGS+3f5XRS44qz7z3N7tyyVtLtxGFMeP /blUenNLsrAr4ZgWSTjsNods4wthdMJ4k4zv50ONkDcnT3X4dHwBAD2Dbi3ECfA/kZsp 9nbzRrMhL6OSnHiWl8fdcfjTzO5tOb6WDkAuid+oLo1zV+G//Jvi9kC8UrNG3GtsloJh pkkg== X-Gm-Message-State: AHQUAuZ7kJzExgS6UNghbRRNtFw61caefNkmC6badeKj3PMY2MK6bTWr cvs5AyznPQ+qSQhPgCB0+oW7hA== X-Received: by 2002:a7b:c1d7:: with SMTP id a23mr4475270wmj.48.1549388633646; Tue, 05 Feb 2019 09:43:53 -0800 (PST) Received: from arch-late.local (a109-49-46-234.cpe.netcabo.pt. [109.49.46.234]) by smtp.gmail.com with ESMTPSA id s132sm12225751wmf.28.2019.02.05.09.43.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 05 Feb 2019 09:43:53 -0800 (PST) From: Rui Miguel Silva To: Jonathan Cameron , Hartmut Knaack , Lars-Peter Clausen , Peter Meerwald-Stadler , Shawn Guo , Rob Herring , Fabio Estevam Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, Rui Miguel Silva Subject: [PATCH v2 3/5] iio: gyro: fxas2100x: add i2c driver Date: Tue, 5 Feb 2019 17:43:31 +0000 Message-Id: <20190205174333.17672-4-rui.silva@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190205174333.17672-1-rui.silva@linaro.org> References: <20190205174333.17672-1-rui.silva@linaro.org> MIME-Version: 1.0 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org This add the real driver to talk over i2c and use the fxas2100x core for the main tasks. Signed-off-by: Rui Miguel Silva --- drivers/iio/gyro/Kconfig | 6 +++ drivers/iio/gyro/Makefile | 1 + drivers/iio/gyro/fxas2100x_i2c.c | 73 ++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 drivers/iio/gyro/fxas2100x_i2c.c -- 2.20.1 diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig index c168aa63de3b..1f9bfc51febb 100644 --- a/drivers/iio/gyro/Kconfig +++ b/drivers/iio/gyro/Kconfig @@ -77,6 +77,8 @@ config FXAS2100X tristate "NXP FXAS2100X Gyro Sensor" select IIO_BUFFER select IIO_TRIGGERED_BUFFER + select FXAS2100X_I2C if (I2C) + depends on (I2C || SPI_MASTER) help Say yes here to build support for NXP FXAS2100X family Tri-axis Gyro Sensor driver connected via I2C or SPI. @@ -84,6 +86,10 @@ config FXAS2100X This driver can also be built as a module. If so, the module will be called fxas2100x_i2c or fxas2100x_spi. +config FXAS2100X_I2C + tristate + select REGMAP_I2C + config HID_SENSOR_GYRO_3D depends on HID_SENSOR_HUB select IIO_BUFFER diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile index 9e2395185a6e..8b1540ddbbce 100644 --- a/drivers/iio/gyro/Makefile +++ b/drivers/iio/gyro/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_BMG160) += bmg160_core.o obj-$(CONFIG_BMG160_I2C) += bmg160_i2c.o obj-$(CONFIG_BMG160_SPI) += bmg160_spi.o obj-$(CONFIG_FXAS2100X) += fxas2100x_core.o +obj-$(CONFIG_FXAS2100X_I2C) += fxas2100x_i2c.o obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o diff --git a/drivers/iio/gyro/fxas2100x_i2c.c b/drivers/iio/gyro/fxas2100x_i2c.c new file mode 100644 index 000000000000..b8f6d2b7f6dd --- /dev/null +++ b/drivers/iio/gyro/fxas2100x_i2c.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for NXP FXAS2100x Gyroscope - I2C + * + * Copyright (C) 2018 Linaro Ltd. + * + */ +#include +#include +#include +#include + +#include "fxas2100x.h" + +static const struct regmap_config fxas2100x_regmap_i2c_conf = { + .reg_bits = 8, + .val_bits = 8, + .max_register = FXAS2100X_REG_CTRL3, +}; + +static int fxas2100x_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct regmap *regmap; + const char *name = NULL; + + regmap = devm_regmap_init_i2c(i2c, &fxas2100x_regmap_i2c_conf); + if (IS_ERR(regmap)) { + dev_err(&i2c->dev, "Failed to register i2c regmap: %ld\n", + PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + if (id) + name = id->name; + + return fxas2100x_core_probe(&i2c->dev, regmap, i2c->irq, name); +} + +static int fxas2100x_i2c_remove(struct i2c_client *i2c) +{ + fxas2100x_core_remove(&i2c->dev); + + return 0; +} + +static const struct i2c_device_id fxas2100x_i2c_id[] = { + { "fxas2100x", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, fxas2100x_i2c_id); + +static const struct of_device_id fxas2100x_i2c_of_match[] = { + { .compatible = "nxp,fxas21002", }, + { }, +}; +MODULE_DEVICE_TABLE(of, fxas2100x_i2c_of_match); + +static struct i2c_driver fxas2100x_i2c_driver = { + .driver = { + .name = "fxas2100x_i2c", + .pm = &fxas2100x_pm_ops, + .of_match_table = of_match_ptr(fxas2100x_i2c_of_match), + }, + .probe = fxas2100x_i2c_probe, + .remove = fxas2100x_i2c_remove, + .id_table = fxas2100x_i2c_id, +}; +module_i2c_driver(fxas2100x_i2c_driver); + +MODULE_AUTHOR("Rui Miguel Silva "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("FXAS2100X I2C Gyro driver"); From patchwork Tue Feb 5 17:43:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rui Miguel Silva X-Patchwork-Id: 157508 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp5445275jaa; Tue, 5 Feb 2019 09:43:58 -0800 (PST) X-Google-Smtp-Source: AHgI3IZUhuQjIibSbE9q7WTIGSR9vVUtvuVfudmUjWh3uk6Ud09PBk4eJngfowICEhhwmydaqPyF X-Received: by 2002:a62:5007:: with SMTP id e7mr6189989pfb.92.1549388638898; Tue, 05 Feb 2019 09:43:58 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549388638; cv=none; d=google.com; s=arc-20160816; b=uP/REHhVyZAm30Wi8zrlufjpk9Fhs0UzIeC0xUFuZUpwrYJvKrQKAaxhegNV6QJjJY c3N94uE+RTOyXCDsto4MwkqrrQOkDgSAsUkS66S2qyVi+LmyzKNeFKHMhjVE1uOaS/CK 5w0C41fVl6aQhx3X7QiH+run56cyvbZaCfUCdIC5V8fQBy1Ngjd81jEAX4sHtkQsr47P njmgiuGVtgfL533uX+s17Ujle/gP2Yh2YKi0gDjMgAHOrZFKEA23WxSE8hhwQWFiJ9vE otU0Rmi7MljjL4CbSwloNTqqITkzFq+X87DOJ1xbpW5Tgxp2hoJZNFB1kEQw2rkq2sSI pGfQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=gDgmk73jZxpcUob0JtNtldENUWQY6jE2DXwyzn7tmw8=; b=ikOuMIdGPs9H92pC6HQiEo8oirsJmjx5Sr/Hvwk+Q1yGytkg/pD9PVS/5RFmecfJ4T 3Bd1wGj0O3ls3/7po0kaRizmdJiPvCPu04dPKSJFoLbNbgjV/eRsFuA1JQ9s0fnR1GZD CDUrrnzuqmvLdOIKVjiLTR8d6Za9PjPJurqWG/L6gdgfnQNYOJ21ASoMVpV0SLK6I4Dy gkcX2InvXVfv3L/4GQIcbe0qR9AF4FsSfQUhEMuVihudUmmAI+lro99qFIXxJ+3EsiwT o4dv/N0FbU3QA+LQ7kvADkpGxDVKd0fEKIS7gYURX+mCfzYpIOEwFkG3sRdJdfEBNB0W W2yg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=FFWqg5ck; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g8si3413699pgb.128.2019.02.05.09.43.58; Tue, 05 Feb 2019 09:43:58 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=FFWqg5ck; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727835AbfBERn6 (ORCPT + 7 others); Tue, 5 Feb 2019 12:43:58 -0500 Received: from mail-wm1-f66.google.com ([209.85.128.66]:38757 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727752AbfBERn6 (ORCPT ); Tue, 5 Feb 2019 12:43:58 -0500 Received: by mail-wm1-f66.google.com with SMTP id m22so4655300wml.3 for ; Tue, 05 Feb 2019 09:43:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=gDgmk73jZxpcUob0JtNtldENUWQY6jE2DXwyzn7tmw8=; b=FFWqg5ckf/0PWzXYi1ObveJ1ACjS4K62xIljtH0ecFKVbLdTFeV0ipWd3DZa5X0T/8 71tlAK9js3avffXFWwkiesU0RkMAy84y/J0lUcV05icR6o7naw3H1YJhzNJUJqXwFfWw Ahj2tECW76394VTqCLC8G0HJ+lKlGsm/EulW2scJ5qMF3b8x98dsPF1E3M+Mz5c7y2sH NNWYlUiDPeuRxzKiGzcFMqiEr1Raj55EqmyUOUsjg9FV4WQ9pkZn5TNMc6koB4FpOpim ewkFfr5G86o+H/hmQhUUzVhXHBJ3kLOdc+js8pfKnBc7Wb6S/N3b+Bz1iNcmdTDv3990 wYZg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=gDgmk73jZxpcUob0JtNtldENUWQY6jE2DXwyzn7tmw8=; b=F4o+z3w3kmpD13ovE+ptSII+jzkqV0QuY5JDNvIirT6o8VZIwRGYISPuLEk1YSCvs0 fV3ap2YNc7ntcFiAJ1nhGRwFMXJI+nrLA0222NZR/Q3YyD3kHTgrK1fU7TqOvOpYlDg2 jKyutvcpyJKNRgLbNwjGaKzCA02ancJ1aOLnztQf2DXaycCrlBS70eFQgD0gOWuTa9kH TKH2t6IEhydC0fe1mjYyHtAXuWrngQHZgmwBTnQHrKU4jMAWpb30gPugt7I3Kl3s8BQI CNOXmStrte+TgK8vdFxcMxsDc2Kk9C8+jMLAEItVX4t/MU8l4XzYwCo36Adx0NMQKrAu ft4A== X-Gm-Message-State: AHQUAuYdlhhPaUf83c0URJaV0VCczf4WijxGIYr2b6QzRFvnVRJD1s0s hnZOaN75+gv3MApthMZHWaHiWg== X-Received: by 2002:a1c:5a42:: with SMTP id o63mr4608833wmb.88.1549388635740; Tue, 05 Feb 2019 09:43:55 -0800 (PST) Received: from arch-late.local (a109-49-46-234.cpe.netcabo.pt. [109.49.46.234]) by smtp.gmail.com with ESMTPSA id s132sm12225751wmf.28.2019.02.05.09.43.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 05 Feb 2019 09:43:55 -0800 (PST) From: Rui Miguel Silva To: Jonathan Cameron , Hartmut Knaack , Lars-Peter Clausen , Peter Meerwald-Stadler , Shawn Guo , Rob Herring , Fabio Estevam Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, Rui Miguel Silva Subject: [PATCH v2 4/5] iio: gyro: fxas2100x: add spi driver Date: Tue, 5 Feb 2019 17:43:32 +0000 Message-Id: <20190205174333.17672-5-rui.silva@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190205174333.17672-1-rui.silva@linaro.org> References: <20190205174333.17672-1-rui.silva@linaro.org> MIME-Version: 1.0 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add driver to talk over spi to a fxas21002 gyroscope device and use the core as main controller. Signed-off-by: Rui Miguel Silva --- drivers/iio/gyro/Kconfig | 5 +++ drivers/iio/gyro/Makefile | 1 + drivers/iio/gyro/fxas2100x_spi.c | 70 ++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 drivers/iio/gyro/fxas2100x_spi.c -- 2.20.1 diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig index 1f9bfc51febb..4f6d6b393ad8 100644 --- a/drivers/iio/gyro/Kconfig +++ b/drivers/iio/gyro/Kconfig @@ -78,6 +78,7 @@ config FXAS2100X select IIO_BUFFER select IIO_TRIGGERED_BUFFER select FXAS2100X_I2C if (I2C) + select FXAS2100X_SPI if (SPI) depends on (I2C || SPI_MASTER) help Say yes here to build support for NXP FXAS2100X family Tri-axis Gyro @@ -90,6 +91,10 @@ config FXAS2100X_I2C tristate select REGMAP_I2C +config FXAS2100X_SPI + tristate + select REGMAP_SPI + config HID_SENSOR_GYRO_3D depends on HID_SENSOR_HUB select IIO_BUFFER diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile index 8b1540ddbbce..29915ba124b0 100644 --- a/drivers/iio/gyro/Makefile +++ b/drivers/iio/gyro/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_BMG160_I2C) += bmg160_i2c.o obj-$(CONFIG_BMG160_SPI) += bmg160_spi.o obj-$(CONFIG_FXAS2100X) += fxas2100x_core.o obj-$(CONFIG_FXAS2100X_I2C) += fxas2100x_i2c.o +obj-$(CONFIG_FXAS2100X_SPI) += fxas2100x_spi.o obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o diff --git a/drivers/iio/gyro/fxas2100x_spi.c b/drivers/iio/gyro/fxas2100x_spi.c new file mode 100644 index 000000000000..7bd16a607372 --- /dev/null +++ b/drivers/iio/gyro/fxas2100x_spi.c @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for NXP FXAS2100x Gyroscope - SPI + * + * Copyright (C) 2018 Linaro Ltd. + * + */ + +#include +#include +#include +#include + +#include "fxas2100x.h" + +static const struct regmap_config fxas2100x_regmap_spi_conf = { + .reg_bits = 8, + .val_bits = 8, + .max_register = FXAS2100X_REG_CTRL3, +}; + +static int fxas2100x_spi_probe(struct spi_device *spi) +{ + const struct spi_device_id *id = spi_get_device_id(spi); + struct regmap *regmap; + + regmap = devm_regmap_init_spi(spi, &fxas2100x_regmap_spi_conf); + if (IS_ERR(regmap)) { + dev_err(&spi->dev, "Failed to register spi regmap: %ld\n", + PTR_ERR(regmap)); + return PTR_ERR(regmap); + } + + return fxas2100x_core_probe(&spi->dev, regmap, spi->irq, id->name); +} + +static int fxas2100x_spi_remove(struct spi_device *spi) +{ + fxas2100x_core_remove(&spi->dev); + + return 0; +} + +static const struct spi_device_id fxas2100x_spi_id[] = { + { "fxas2100x", 0 }, + { } +}; +MODULE_DEVICE_TABLE(spi, fxas2100x_spi_id); + +static const struct of_device_id fxas2100x_spi_of_match[] = { + { .compatible = "nxp,fxas21002", }, + { }, +}; +MODULE_DEVICE_TABLE(of, fxas2100x_spi_of_match); + +static struct spi_driver fxas2100x_spi_driver = { + .driver = { + .name = "fxas2100x_spi", + .pm = &fxas2100x_pm_ops, + .of_match_table = of_match_ptr(fxas2100x_spi_of_match), + }, + .probe = fxas2100x_spi_probe, + .remove = fxas2100x_spi_remove, + .id_table = fxas2100x_spi_id, +}; +module_spi_driver(fxas2100x_spi_driver); + +MODULE_AUTHOR("Rui Miguel Silva "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("FXAS2100X SPI Gyro driver"); From patchwork Tue Feb 5 17:43:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rui Miguel Silva X-Patchwork-Id: 157509 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp5445293jaa; Tue, 5 Feb 2019 09:44:00 -0800 (PST) X-Google-Smtp-Source: AHgI3Ibl7W5/k/ySXbnDx/3+97Tq92IHBnC3SX+lieG3LvakJp0gjHn2+MLdj976UUqKXXLyoFtb X-Received: by 2002:a17:902:8d8e:: with SMTP id v14mr6200429plo.133.1549388640453; Tue, 05 Feb 2019 09:44:00 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549388640; cv=none; d=google.com; s=arc-20160816; b=mfNdH24jN7uyBPT8uB3qSXlF4a5bgIphJ/iulkoyIrr3EcTcAxCXWN1ol5gxzRKMXz upTP3B1Hx1o+z319E0k8XrCecZmr6ziEba7EmtYeqNx22aV88pKTJy1J55bPfRv/oClm fk+xyGtKMkVBJihSil9pRFigeSpWLge7FH33isZzxDYeS0h5/ZXEPrSoBxdJxr9Vh/lG 0acm9fB7OWDpM/jba8jmCzVrK31rcmEj08YyrB3yQFDUp+s1kMc5+r/SWyKTl/5CrB/Q qldnSPrpU4sl9+28xabp/iihv0a+aEgmjFvxQZpMaE0CDhZv3EacB8j7cVgtMCx00gfJ PF6w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=1beXyQ7Gf29kAeZEAs9WtF0BKb4rwWHgLwQvrdn6V/Y=; b=F51zF5/0qxL7n68DTt/RbKFAdvdx/RvbPdCmcvBr1Ll0uITxJx+lBv/AQz8EPcUi6X +unkDo6oOinQ41xsKENf9LSOxRCZGASe9O3tks2aEGwSgqEe2oODFmDgFdJyqgOVbzCK LhHQVpNAs8+q1nqYgsmCtyAbM0JJt3atdRTubdzhVCaAckkac0wc7guF0vcgv5SajVqN FheKNjAE6KcrS8Bwmx9wMALvDEua/89do6IDL6tWzwEsh+55WfSFmksLnPakUsaTxbAm crWCpQfMksJXXTkDiFhBPHYrJ4ThwtezoCVaUtjONoRrRfNv++Fx47+hNXYWKFxyk03o q8Dw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="bHzekH/b"; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g8si3413699pgb.128.2019.02.05.09.44.00; Tue, 05 Feb 2019 09:44:00 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="bHzekH/b"; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728749AbfBERn7 (ORCPT + 7 others); Tue, 5 Feb 2019 12:43:59 -0500 Received: from mail-wm1-f66.google.com ([209.85.128.66]:38759 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727752AbfBERn7 (ORCPT ); Tue, 5 Feb 2019 12:43:59 -0500 Received: by mail-wm1-f66.google.com with SMTP id m22so4655439wml.3 for ; Tue, 05 Feb 2019 09:43:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=1beXyQ7Gf29kAeZEAs9WtF0BKb4rwWHgLwQvrdn6V/Y=; b=bHzekH/bWSHQl3zTXv2YVD9MjXSFYUPbsiuMgER2iccqk0ib4nip+rpB3WWWvODWDi 9evwdQqULxH+ix0hKCpAS98nNNqiAsIYhVJOU52peR5lVT7N/QFMfoQZ8oZJrQylalu/ J6FxXl/oe6LCvr9r3JWUNj9NPbxV4xRljdGrMEM+r5VKEirxq5f8paXw+npuPUrDEHZj vvoDX3NFF1tgK0dQFvasDZKdD96/FzVLYMDb1LtW7t+bBasNkTyvaaMEzLydWmhfiBg6 twc8kU21S7bPqP8EeLiOy43PbXAtonr9nScoS6Efk5ur4CUzZ7LxF4JVwGFJk2A0QS5c nSTA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=1beXyQ7Gf29kAeZEAs9WtF0BKb4rwWHgLwQvrdn6V/Y=; b=JLew8YneAyvm7e0M32JA9v9z3KMNgEDRxe61mAwFkXiRNMjr+MVUN+ypxYu8lK59JI KHzpa38z7D9qdKs+Lwr4Xut+LlPmuisvW4wYAxpFhW+39SLzBrJlY+Er++HqW6V4OLaW y1ydXYDY274yKfDCMEmP1I541u1nVe1rejl9ub74QYOPFNyr38HyHUoGPxrSps+CoZhQ /L3fJG7n1Ag2igb3n2ZiZgRMWfnSBkOCNS3vQ9epKgWo7bYOad6fQVzUTbnF3lsFHHkG WYY98i9Ez3R73C1SO9BCdb8QF6y9xBn8+FVU/lgQ+TiI8yU26PXtSst4QYQFGrUpaWhO ITfg== X-Gm-Message-State: AHQUAuZE/JpqsG5lm4gLXziE5DLWRVcJNc+B6qxrscm7dcOYNhc/nm/r RcXRMXd4hT4faHN1fI/A9I1w/w== X-Received: by 2002:a1c:bc82:: with SMTP id m124mr4554500wmf.77.1549388637813; Tue, 05 Feb 2019 09:43:57 -0800 (PST) Received: from arch-late.local (a109-49-46-234.cpe.netcabo.pt. [109.49.46.234]) by smtp.gmail.com with ESMTPSA id s132sm12225751wmf.28.2019.02.05.09.43.56 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 05 Feb 2019 09:43:57 -0800 (PST) From: Rui Miguel Silva To: Jonathan Cameron , Hartmut Knaack , Lars-Peter Clausen , Peter Meerwald-Stadler , Shawn Guo , Rob Herring , Fabio Estevam Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, Rui Miguel Silva Subject: [PATCH v2 5/5] ARM: dts: imx7s-warp: add fxas21002 gyroscope Date: Tue, 5 Feb 2019 17:43:33 +0000 Message-Id: <20190205174333.17672-6-rui.silva@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190205174333.17672-1-rui.silva@linaro.org> References: <20190205174333.17672-1-rui.silva@linaro.org> MIME-Version: 1.0 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Add entry to enable the fxas21002 in the warp7 board Signed-off-by: Rui Miguel Silva --- arch/arm/boot/dts/imx7s-warp.dts | 7 +++++++ 1 file changed, 7 insertions(+) -- 2.20.1 diff --git a/arch/arm/boot/dts/imx7s-warp.dts b/arch/arm/boot/dts/imx7s-warp.dts index 58d1a89ee3e3..233ff2b68488 100644 --- a/arch/arm/boot/dts/imx7s-warp.dts +++ b/arch/arm/boot/dts/imx7s-warp.dts @@ -238,6 +238,13 @@ compatible = "fsl,mpl3115"; reg = <0x60>; }; + + fxas21002@20 { + compatible = "nxp,fxas21002"; + reg = <0x20>; + vdd-supply = <®_peri_3p15v>; + vddio-supply = <®_peri_3p15v>; + }; }; &sai1 {