From patchwork Mon Feb 4 17:00:08 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: 157441 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp4137422jaa; Mon, 4 Feb 2019 09:00:28 -0800 (PST) X-Google-Smtp-Source: AHgI3IaluVOGSaqb9spqxSa4iGNOVOOH2qrxPwdnnHgtVLymF/0jTWZvHOYelnMlH/12ux6H26KB X-Received: by 2002:a65:64c8:: with SMTP id t8mr297163pgv.31.1549299628174; Mon, 04 Feb 2019 09:00:28 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549299628; cv=none; d=google.com; s=arc-20160816; b=IQFyB/piBxXdM/MIXD6iYG4nKPOqhUBf7tJGkl1++9s4ZtJR2U6Z73uZGStrWShKLX Rq6RUTW3EWoXQHlBs0q5sHxmZBDiX9CP/8vwDI3CkhX80MyQmy0Lhyp67aIhgiPAw7N2 xc8nDEIsEf5jkzrdc+VeMfjLz18WOuKhNXrhN704bkWPOG2fASaiQQaqqRaBuys4A/a9 sEdvw9WOFdk029oA6s7yfRG90udbAaqm8hVP/X0yfX5bAQ6MBP+Ys+bZQAre1fZEBbLw Ij/65428BlbwP4rfPLmw8RazOoum70kplJWYTxfnKiFQBq+Njk/TdTzbZhqgki2llGt3 2OXg== 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=o9qCpqJP82RdcTtRba0fR7RcEAMMQ60ffSXBQwSUjWE=; b=AvhoA79p7L8N4akHOD/7+xNtb+Cul5q4RQ4Rxr3XyeLT5/w8Jcw7OIx+HnweQ4dYEK NIS8sVddMnMzn3HcTArdZ7jQjg0yEGvSu8zdZRL7l9MVdxN5IH/rS7dCOESZe1QkA5Ss JevKE5L03cKltLcgogtWUBcmxRiE6C94hPz39NPsFEuOf9vgm4W5tQxdCEH84Ft/Lpss ieuoKJsSRtTCI1xt90FKEJmOnhhRqha76Sc2bU+cHNhmalXYmT9zVSIrrXN3I4i67OoC Ka2RcvN4POcIW2T6XajUzhecc4j5YTv1XCDW3FJFB05EPpGMDwAkWk3QUWVV80s4RaT9 6A/A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=h9KyE6ZX; 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 m64si502677pfb.224.2019.02.04.09.00.27; Mon, 04 Feb 2019 09:00:28 -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=h9KyE6ZX; 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 S1728082AbfBDRA1 (ORCPT + 7 others); Mon, 4 Feb 2019 12:00:27 -0500 Received: from mail-wm1-f68.google.com ([209.85.128.68]:52510 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725937AbfBDRA1 (ORCPT ); Mon, 4 Feb 2019 12:00:27 -0500 Received: by mail-wm1-f68.google.com with SMTP id m1so639427wml.2 for ; Mon, 04 Feb 2019 09:00:25 -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=o9qCpqJP82RdcTtRba0fR7RcEAMMQ60ffSXBQwSUjWE=; b=h9KyE6ZXlM2YU2lnlH+ueRSS5mlmESCUPuqJtlaF16l0w3MNC886AYlvXPdqfcII5m guuBv5u4uduqWZd0jh6ppg0pZ0GZvsI8VS8zu2uq/pZZ7e2lgmPyHotxIk7c1RpZbMJZ YdQqSHBhIKPP545R5HSdvtOzaP+X63h3TgMsY= 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=o9qCpqJP82RdcTtRba0fR7RcEAMMQ60ffSXBQwSUjWE=; b=Sfv9TtRpQLJdDdzGiSLJiOyPHpbLvb1aB9Odwxg+UmgzJfSn3iFt6LHpy4g/SMh/yA OqBGVE5UZl8fE702fc79TeEy4hnkjxL6jh37lIJOBJmVE8hD5XB5bamYHORT0J4WoWKP vnuviE41EZf87ymQHKPh/nt8iz5oWHeq5/KeAyO6CGHZesZKGpckIHY7bQvGYw2rOOTO 4bRFseiIcepUqXJwFNznouURcwia5WwcaG4bV+Sb7iA64Ac8GqcSsTYyt4z03i41gFjN H5Z9qSjnKMrKh5FEQ4OAWKUW6FSmBEVVqKMV14ds2KAT3G/KWc4c9NHhmbroGfK2qEbQ PPRg== X-Gm-Message-State: AHQUAuaAjzZKXgntT4WLLbibk3R/HGetOIWKPpX9C3PjQnMTQoWw38FF 32ZitKvwnKHJFXeM5S895cnUZg== X-Received: by 2002:a1c:7706:: with SMTP id t6mr240787wmi.57.1549299625223; Mon, 04 Feb 2019 09:00:25 -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 i186sm19352297wmd.19.2019.02.04.09.00.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 04 Feb 2019 09:00:24 -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 1/5] iio: gyro: add DT bindings to fxas2100x Date: Mon, 4 Feb 2019 17:00:08 +0000 Message-Id: <20190204170012.13617-2-rui.silva@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190204170012.13617-1-rui.silva@linaro.org> References: <20190204170012.13617-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 FXAS2100x gyroscope. Signed-off-by: Rui Miguel Silva --- .../bindings/iio/gyroscope/fxas2100x.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/gyroscope/fxas2100x.txt -- 2.20.1 diff --git a/Documentation/devicetree/bindings/iio/gyroscope/fxas2100x.txt b/Documentation/devicetree/bindings/iio/gyroscope/fxas2100x.txt new file mode 100644 index 000000000000..2aeef9aafec4 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/gyroscope/fxas2100x.txt @@ -0,0 +1,14 @@ +* NXP FXAS2100X Gyroscope device tree bindings + +http://www.nxp.com/products/sensors/gyroscopes/3-axis-digital-gyroscope:FXAS21002C + +Required properties: + - compatible : should be "nxp,fxas2100x" + - reg : the I2C address of the sensor + +Example: + +fxas2100x@20 { + compatible = "nxp,fxas2100x" + reg = <0x20>; +}; From patchwork Mon Feb 4 17:00:09 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: 157443 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp4137550jaa; Mon, 4 Feb 2019 09:00:34 -0800 (PST) X-Google-Smtp-Source: AHgI3IbEpX2oythoxJQuw0gFB0yvgvx+v2Mw5lbKcNChai0cJCesmEEFAmf4DAY0gtsNwp6eimM/ X-Received: by 2002:a62:2b8b:: with SMTP id r133mr336492pfr.246.1549299634763; Mon, 04 Feb 2019 09:00:34 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549299634; cv=none; d=google.com; s=arc-20160816; b=vxM5gUv7m6G5Las/SUFrJy7TR4lm14k36Z0h92qAYKzWkrrrRXZm7Mrbg7rECE6mGu jBdI+84SmWSUi5Si7NSb0P5WF4Wwt+qJC/ddHYwZtFhFAV7ujCsA1Rs1JxqtwvXeTlYz d56RFGLQxUFHdUAZPcG5x5ZefVWivl0SWvXu6CHuUdmNUkHS7NMk9ZTBLoOQigQwYnaz lHZAExYqiyjo0jS5+1ChShPJiQxvSZGgT9G1/t2e/T+QRq/oDnnfZte97NJqfRgQreAv yhrP9StQul+pMuKdBahx+7xPKbnwTnxpEL5O1Er3300rQg2CJL8sh+DkmpHD4Bygl0J9 6hMQ== 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=VT5Z56rBjx0ZN1adOZFVAKK7wHM5fKHADzibei+3Grk=; b=F8sPraVeC0fmIF6RbYk9D31tpckjwrYDgOc/lhaNbX+92NBThwo0lKA4cpNvNSrKJT jpGOJlQ+/J9i6pXKEmgNtVupdbmI7OPbALOZXwmpzz9qZi2Sql9vAwUzFraMryK6Ktf7 y8LXDk3UfTS6pzLxoAfKJPyutznO3GT6DM7r3aQzCGWmA9FmGF0of7I4M7mI2f8d4PZA 1TLWHgd2/xH4CMn0cuyMidfZNk2HlXFylZNn1TLHGXPs8ynYaXc72ZAs6N1PsErnVzC0 HR57I1Fc5uOfxB6smQmrPq8Iv12pqhW9Fdm3/AuqNZVMH7CFPL60Qeq5mNnqF0UVsQ8y MwXQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=AhAfK24w; 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 m64si502677pfb.224.2019.02.04.09.00.34; Mon, 04 Feb 2019 09:00:34 -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=AhAfK24w; 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 S1729275AbfBDRAd (ORCPT + 7 others); Mon, 4 Feb 2019 12:00:33 -0500 Received: from mail-wm1-f67.google.com ([209.85.128.67]:54287 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725937AbfBDRAd (ORCPT ); Mon, 4 Feb 2019 12:00:33 -0500 Received: by mail-wm1-f67.google.com with SMTP id a62so626911wmh.4 for ; Mon, 04 Feb 2019 09:00:28 -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=VT5Z56rBjx0ZN1adOZFVAKK7wHM5fKHADzibei+3Grk=; b=AhAfK24wO5e2aJpOKg1KxAEGCtT5BLlA6t4gCNDjPBNn+awfGC+6sUs/QTAYXmlrRO hVpS2KyDXUl3MW0VvWOx7xWdB+zj4T5YxoOXM4Cf9jnhbxbQwH5fl33k0NvrKSd//vkS 814Au9AyVenkvalDnWrSqqWqJ5pL7Ro9n6ovE= 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=VT5Z56rBjx0ZN1adOZFVAKK7wHM5fKHADzibei+3Grk=; b=po0Z9UnZRyZLb9HCBdMdVBc5e33A6TOQ1jMX5N2Lllo6wTmUGiviB8oeCPdDj99l/I g3eW+iSrIDvePUVmfhDinHdzd8dmeeWhpeAC960d9NaR7cRB6O/yNzNG6K/IDU/81/rS gEQrkE6V0RqSxh4OvmXPfs82LkdG+riXuUTB4sW4KaTUTElcq50pNKPIDyPXLess3h5u W8CSAKhEX1g4W1MHefUESibsfhjyxYcZRoXv0ySVCticSd/6cnDTb/tpTpRA6Xhk96if t7hrO1v+wiH5Yayk1Hcn8vqz4IVuHWSGNyuaqikoYhmSSHpXzUYC/mGynwnUoJvoaaUF kaHQ== X-Gm-Message-State: AHQUAuYyVeHtCWgACGl3ZG16WRh02BZN6Nj59FCAo0TfsU9ABsqAWHfp eDsr8nKKjZWIVftscHilj+ZcWg== X-Received: by 2002:a7b:c5d1:: with SMTP id n17mr267881wmk.152.1549299627615; Mon, 04 Feb 2019 09:00:27 -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 i186sm19352297wmd.19.2019.02.04.09.00.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 04 Feb 2019 09:00:27 -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 2/5] iio: gyro: fxas2100x: add core driver for fxas2100x gyroscope Date: Mon, 4 Feb 2019 17:00:09 +0000 Message-Id: <20190204170012.13617-3-rui.silva@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190204170012.13617-1-rui.silva@linaro.org> References: <20190204170012.13617-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 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 | 149 +++++ drivers/iio/gyro/fxas2100x_core.c | 930 ++++++++++++++++++++++++++++++ 4 files changed, 1091 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..417445d2bcda --- /dev/null +++ b/drivers/iio/gyro/fxas2100x.h @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Driver for NXP FXAS2100x Gyroscope - Header + * + * Copyright (C) 2018 Linaro Ltd. + * + */ + +#ifndef FXAS2100X_H_ +#define FXAS2100X_H_ + +#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..1f88760563dd --- /dev/null +++ b/drivers/iio/gyro/fxas2100x_core.c @@ -0,0 +1,930 @@ +// 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 "fxas2100x.h" + +#define FXAS21002_CHIP_ID_1 0xD6 +#define FXAS21002_CHIP_ID_2 0xD7 + +#define FXAS2100X_MODE_STANDBY 0x00 +#define FXAS2100X_MODE_READY 0x01 +#define FXAS2100X_MODE_ACTIVE 0x02 + +#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 +}; + +/* + * This values are taken from the low-pass filter cuttoff frequency calculated + * ODR * 0.lpf_values. So, for ODR = 800Hz with a lpf value = 0.32 + * => LPF cuttof frequency = 800 * 0.32 = 256 Hz + */ +static const int fxas2100x_lpf_values[] = { + 32, 16, 8 +}; + +/* + * This values are taken from the high-pass filter cuttoff frequency calculated + * ODR * 0.0hpf_values. So, for ODR = 800Hz with a hpf value = 0.018750 + * => HPF cuttof 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; + u8 mode; + u8 prev_mode; + struct regmap *regmap; + struct regmap_field *regmap_fields[F_MAX_FIELDS]; + struct iio_trigger *dready_trig; + struct mutex lock; /* protect access */ + s16 buffer[3]; + int irq; +}; + +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; + + value = min_t(u8, value, range_value_max); + + if (!fs_double) + value += 1; + + 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); + + 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, u8 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_pre_write(struct fxas2100x_data *data) +{ + int actual_mode; + + actual_mode = fxas2100x_mode_get(data); + + if (actual_mode < 0) + return actual_mode; + + return fxas2100x_mode_set(data, FXAS2100X_MODE_READY); +} + +static int fxas2100x_post_write(struct fxas2100x_data *data) +{ + return fxas2100x_mode_set(data, data->prev_mode); +} + +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; + int ret; + + odr_bits = fxas2100x_odr_value_from_hz(data, odr); + + if (odr_bits < 0) + return odr_bits; + + mutex_lock(&data->lock); + ret = fxas2100x_pre_write(data); + if (ret < 0) + goto post_write; + + ret = regmap_field_write(data->regmap_fields[F_DR], odr_bits); + if (ret < 0) + goto post_write; + +post_write: + ret = fxas2100x_post_write(data); + + mutex_unlock(&data->lock); + + return ret; +} + +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; + + mutex_lock(&data->lock); + ret = fxas2100x_pre_write(data); + if (ret < 0) + goto post_write; + + ret = regmap_field_write(data->regmap_fields[F_BW], bw_bits); + if (ret < 0) + goto post_write; + +post_write: + ret = fxas2100x_post_write(data); + + mutex_unlock(&data->lock); + + return ret; +} + +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; + int ret; + + sel_bits = fxas2100x_hpf_value_from_sel(data, sel); + + if (sel_bits < 0) + return sel_bits; + + mutex_lock(&data->lock); + ret = fxas2100x_pre_write(data); + if (ret < 0) + goto post_write; + + ret = regmap_field_write(data->regmap_fields[F_SEL], sel_bits); + if (ret < 0) + goto post_write; + +post_write: + ret = fxas2100x_post_write(data); + + mutex_unlock(&data->lock); + + return ret; +} + +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; + int ret; + + fs_bits = fxas2100x_range_value_from_fs(data, range); + + if (fs_bits < 0) + return fs_bits; + + mutex_lock(&data->lock); + ret = fxas2100x_pre_write(data); + if (ret < 0) + goto post_write; + + ret = regmap_field_write(data->regmap_fields[F_FS], fs_bits); + if (ret < 0) + goto post_write; + +post_write: + ret = fxas2100x_post_write(data); + + mutex_unlock(&data->lock); + + return ret; +} + +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: + return fxas2100x_odr_set(data, val); + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: + 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.8130"); + +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 * 2); + 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 %d 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); + + ret = devm_iio_trigger_register(dev, data->dready_trig); + if (ret) + return ret; + + return 0; +} + +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)) { + dev_err(dev, "failed to alloc regmap field %d: %ld\n", + i, PTR_ERR(f)); + return PTR_ERR(f); + } + data->regmap_fields[i] = f; + } + + mutex_init(&data->lock); + + ret = fxas2100x_chip_init(data); + if (ret < 0) + return ret; + + 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) + return ret; + + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, + iio_pollfunc_store_time, + fxas2100x_trigger_handler, NULL); + if (ret < 0) + return ret; + + ret = pm_runtime_set_active(dev); + if (ret) + return ret; + + 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) { + dev_err(dev, "unable to register iio device: %d\n", ret); + return ret; + } + + return 0; +} +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); +} +EXPORT_SYMBOL_GPL(fxas2100x_core_remove); + +#ifdef CONFIG_PM_SLEEP +static int 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 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; +} +#endif + +#ifdef CONFIG_PM +static int 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 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; +} +#endif + +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 Mon Feb 4 17:00:10 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: 157442 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp4137517jaa; Mon, 4 Feb 2019 09:00:33 -0800 (PST) X-Google-Smtp-Source: AHgI3IZYZCHIQhRuraEEDdEmzu7fo5vP6nkBhsEm3nIgmNpsICXWPGMILM2F0NFKZJJaPz3t09iL X-Received: by 2002:a63:193:: with SMTP id 141mr333051pgb.136.1549299633403; Mon, 04 Feb 2019 09:00:33 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549299633; cv=none; d=google.com; s=arc-20160816; b=FLveRe5QmjtuC+dhyNEwu/SdGlPrmZkByBm4a0ezMkfsHfBrrH9Bb4RZEs8i0YK33E jmz3yQKd98kY8kqUpLkoB1Bi3EJXx5LuSvYXwlkcmGw8REZWCqfIOJqVlYC2zNk3NGKp NpND3Gq1HcZH/M7YvgWfGQT1zFg5ebdlJHwe5Z+vzzKjqQjmkMXODXRKTtFclpIFHImZ LP8G1PxJg5eHwGhoMfSjxwy7AdTrsFjRL7UFYS8OgXIcs6lFCGgzYEXVB4hBMOBmN7FS Zd7IRHufDc9Z1hkiWeYHb6KmMRral0UGejRvORKas3wo3hAPIxzOck0mnvJXIB2LljrW VGhw== 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=5f8oMTPzqMVYaxal2igosMLVQNNuQ7nNTfzq//5p9Iw=; b=1D3Gf3mYD7Yxmv10vmzpBb/5ZStACVaWWhfdwyHITEe0qRsLqMqDW7Ejd+68gafcth eOb7HHOsxrT/U3qpnhDPO6o0KIDBeGfRSpPWh7QC0GTd5335rckAhb4JxahpnEm78ufk YUYrrrm0FoCOVq+T8tmSFnf1J7w3IvQMH8CJRSn2L2bOYD+acxArnZZ+/hbqWH/zS1UL CFu5/ciD1dAjNykbUO/eAGwB2tnjjysYi0899ubK5WuPHHthCPw3q9h+tc9Ctf7R7l6W h+mixjahHC7jiHu7NnJyvTOmSD5zRBpPp3VcDB0B0Er0xiKxQYNybjGFJ+g60x1YZKRk NNgw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=aYObJGOh; 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 m64si502677pfb.224.2019.02.04.09.00.33; Mon, 04 Feb 2019 09:00:33 -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=aYObJGOh; 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 S1728937AbfBDRAc (ORCPT + 7 others); Mon, 4 Feb 2019 12:00:32 -0500 Received: from mail-wm1-f67.google.com ([209.85.128.67]:38493 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728861AbfBDRAc (ORCPT ); Mon, 4 Feb 2019 12:00:32 -0500 Received: by mail-wm1-f67.google.com with SMTP id m22so677280wml.3 for ; Mon, 04 Feb 2019 09:00:30 -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=5f8oMTPzqMVYaxal2igosMLVQNNuQ7nNTfzq//5p9Iw=; b=aYObJGOhZohn7H47dJU7KBgYnT5NmbtMXBE1lpevT+oKYzTmH21o4e7NqzOlpzyoON iOdadJpCNyDfZQfj+bYpZVkYLjcKtk9wMWzAweYO75oYp++ktnu7pEMtsMUkcy4I66Aq uYC2p1rHW3+UK21ps119uCA5d0EAdHNTuanzI= 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=5f8oMTPzqMVYaxal2igosMLVQNNuQ7nNTfzq//5p9Iw=; b=PniO9lo94lvoTIu0ZuxhUxPeN6kROlK5wLbDYbhBcJILVUQ5MKEkRH6Sr6TP54knL4 QMxJ0dS4UT4dlIfGzF31rTU6KtGXYXb8T1rwymOYEZXJqiQS5ZhSHKGtyQEMMc1A43zU c0hYo8122IrstfG7gh32g9aJ4hhhSUIVuCZRMGo56WsAKYUfZJmfKwnn9fOPJMkZyb+h wT3CsR3p9Cp6RqVUy7oahxEIs4d65r9vUeHEfqwrbfM046XbMSGjkFQ2sKsugqEyTWrb bzVTG8LB5XHHcgtXfKlOBYZb5mLuDSH+xEB1ihdN4W4AGcHoRoLAeakkBmXRudMKaQAF AdrA== X-Gm-Message-State: AHQUAuaOXoaW/CbxmCgVS0qW6DktCYz48T7rYr7NioO2o2bv0+vSh+1Q BUmVFo0hcrFldNtyoeqwhRdGAQ== X-Received: by 2002:a7b:cb86:: with SMTP id m6mr249233wmi.61.1549299629980; Mon, 04 Feb 2019 09:00:29 -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 i186sm19352297wmd.19.2019.02.04.09.00.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 04 Feb 2019 09:00:29 -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 3/5] iio: gyro: fxas2100x: add i2c driver Date: Mon, 4 Feb 2019 17:00:10 +0000 Message-Id: <20190204170012.13617-4-rui.silva@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190204170012.13617-1-rui.silva@linaro.org> References: <20190204170012.13617-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..af4e8af6d301 --- /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,fxas2100x", }, + { }, +}; +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 Mon Feb 4 17:00:11 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: 157444 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp4137562jaa; Mon, 4 Feb 2019 09:00:35 -0800 (PST) X-Google-Smtp-Source: AHgI3IbYAykm4bOXJZfIapifKKHZ9fgWKiIxMyJ7RU5WWrdNLbd6rRgVsYda9JxmfVnqNTeUurkG X-Received: by 2002:a63:5761:: with SMTP id h33mr278695pgm.283.1549299635477; Mon, 04 Feb 2019 09:00:35 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549299635; cv=none; d=google.com; s=arc-20160816; b=AKvb/LkLLjbh5zUoWNGIZR5KEpvN/r8S0COA4pUKsFyoAqGdJ4vvnWgi9xYWt24W3g bbiANQUeCXT/xlyRaf9U8y3uUS6ZEOfKJ7m7CS8rawMRFOrpGkTbdBMntjZ0s0ACkjn8 3vxpSStpSQhCYPhLZsXwhhp4W1r+XevWS51Lzh3IE23KEE/449tXfumLom9kvccVYlQu PzIpHnkyESff9sp7GmUQPpQpWp8gPzYDxWs+GTAleZWMCdaHwflcB1g8Rj73b9BG6TZ9 c0Ga1pED3HsTwCq1ETSV4AyOId262EZcG6gyY+eztx0epiiwhWNbugziWPg90l8Ltx+C B+oA== 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=Zk+k4NwCj9C6idQWY81wkY90chc1s21YlDxiBhAehLk=; b=d935/Wczuww+ILpz7vNoYNRdIV3QHaXFLRu/4rUq9s29u1GuGx3yw8KjZbQBFsnjvZ TYrfLfBI4B7bbZWX01bLpLeuY8IrHUqvsBNQSIIIfH/cWRiuOQxay8bpFFvavJFTNE8B BRoszahbKwNgcLcFtVY2NYGyq9eeijr67NjXI+nlT1hwhcImuYxJAY+3y0KWrKn5Oeub pASJUa6kmVpHTbKxpBopt1EIWKXtfqTrWS9vJq8LaQ2D+6lCxz1A4Z2w+OiLPPm1PI7y 55Gyw3jAeFnIZ/sZQY9AmDm0bsdht1hO4KyWZnG62/TW34ifmbAppzxLMas5O9afCPoo MudA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=K8iwgojr; 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 m64si502677pfb.224.2019.02.04.09.00.35; Mon, 04 Feb 2019 09:00:35 -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=K8iwgojr; 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 S1729141AbfBDRAe (ORCPT + 7 others); Mon, 4 Feb 2019 12:00:34 -0500 Received: from mail-wm1-f66.google.com ([209.85.128.66]:50699 "EHLO mail-wm1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728861AbfBDRAe (ORCPT ); Mon, 4 Feb 2019 12:00:34 -0500 Received: by mail-wm1-f66.google.com with SMTP id z5so648636wmf.0 for ; Mon, 04 Feb 2019 09:00:33 -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=Zk+k4NwCj9C6idQWY81wkY90chc1s21YlDxiBhAehLk=; b=K8iwgojrh9sLhig662Rf0RGySpXes4IsZVpH8QW5WZFCW/wcOUGt4RxT0KZY7oTaKu lujVEgDAfzsn3gCDyCinek7w0B+6eOmlweR1L59cVI471EhvqiHo/NBW8GXKDK+aQLpZ tAvLs0w9yhNSwVkwLeAqWJoJfQdG1/1WFfbq4= 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=Zk+k4NwCj9C6idQWY81wkY90chc1s21YlDxiBhAehLk=; b=fLtzc1x7cgkWeok6Utll2IgcnOXQLn5fwq2IDi8BmpCEef7p4PlbP6sen3NZWHC6lT H/auqT+3RXpaXGDAWSHDGmHlr4tc5MMY8UpyykRRcgtDeiK1fwEmsn/G/SGlJrqtz/4b bxBTnAZRTxWe87czIcgtpWc7IFTT9uE+ees/QoWp1LRSV5XIT/wyMVvL0tB38U17ZrJO 34Bx6B6XwV3jmZvDLSIMeDfy9Y2H9mp43c4/qZE8De7f6GF/IppmwUrwelH/pXXQ4m4N Kgjf3FkiIvznb9ONys7003Ak3s8EkBrJhRRemP0WgFAwj5a/sADHU9YU0gIDCizx/IVK So7g== X-Gm-Message-State: AHQUAuYZ9+SKa3bqBt2+JdjRbsEoNI2RPUnXXI0Asg36efFJCP6dEmJF ezTEiHaMDupCJKIkKHYkGMl9fA== X-Received: by 2002:a1c:650a:: with SMTP id z10mr268685wmb.148.1549299632091; Mon, 04 Feb 2019 09:00:32 -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 i186sm19352297wmd.19.2019.02.04.09.00.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 04 Feb 2019 09:00:31 -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 4/5] iio: gyro: fxas2100x: add spi driver Date: Mon, 4 Feb 2019 17:00:11 +0000 Message-Id: <20190204170012.13617-5-rui.silva@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190204170012.13617-1-rui.silva@linaro.org> References: <20190204170012.13617-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 fxas2100x 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..10f856ba6f47 --- /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,fxas2100x", }, + { }, +}; +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 Mon Feb 4 17:00:12 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: 157445 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp4137585jaa; Mon, 4 Feb 2019 09:00:37 -0800 (PST) X-Google-Smtp-Source: AHgI3IZJA35/S9zYQub9TcPlfefyV2uNV9AbOiVTO4ubr5p2HRWAmriMMN6NW9wpAJZziMtl98OZ X-Received: by 2002:a65:624c:: with SMTP id q12mr274368pgv.379.1549299637354; Mon, 04 Feb 2019 09:00:37 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549299637; cv=none; d=google.com; s=arc-20160816; b=mEIv1e+1AyODYCM0wCUuIXXXYkXFC6Y3tLEnxqHV0qxGeZLVDfoOFUKgOcYNdboryX f6suToulXyY/ozzgEf6GQelG5xsXDJn2V8Ebc5qJtaF6gkmREAXQyV1Xor7ghqCnW9Op E7hgJdOk15YCa+gX1qJisYlJI/u0BXI2biEVkGpQmGoYI2QwkqyOjibtcaehElx8n6YX rz91J5syX/3FFfjVNhlAIYkCPnDZsBqtGP4zkJS+8+T2nW9wGAR1fnEa5WBprOD87kFF TMWk/UPafzdwaXwBqC6tCDTmmRXUV3MO6SC1NJMAL6n7EmbQF3JFRceeiWtwLYrYZmFe UlBQ== 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=du8lrySGcO2WJA5/+uAnRzTcnQRKVBAHdlz4DPUA1Dc=; b=CbDE3X8OKlcl+F1vKgn2Bwb+VqsqIEaE06qfWj4RIbK4talGcc2sLL+CU/MMR6+gO4 l/KDMHeU/+MIWcwysAX836pXc98GtDdXsG17LbSMr43b5FhVeSkowpaIDpQ/aLp7j3NQ ecb+qUbHFfz9vDY6UuEC4zWaaPJq54Tc7BB6mzWdhvnjERjB9yoVA1DWEVVESU5vwn/X rGGJ3wv7KOgZGvz1g2YItHCCD4jOCUCi2T/PvSgneU5Kj1EpSYV3PgNyW6Fg+0wGPuVd Hn2gGpH2tX8bEVBLPNvxpuRxOf+KKoDmXGQX/3S/hoS03KPbAUcDiinw1IgX9Zojgpie /MUw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=dBGz09Ep; 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 m64si502677pfb.224.2019.02.04.09.00.37; Mon, 04 Feb 2019 09:00:37 -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=dBGz09Ep; 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 S1729343AbfBDRAg (ORCPT + 7 others); Mon, 4 Feb 2019 12:00:36 -0500 Received: from mail-wr1-f65.google.com ([209.85.221.65]:42107 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729295AbfBDRAg (ORCPT ); Mon, 4 Feb 2019 12:00:36 -0500 Received: by mail-wr1-f65.google.com with SMTP id q18so589239wrx.9 for ; Mon, 04 Feb 2019 09:00:35 -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=du8lrySGcO2WJA5/+uAnRzTcnQRKVBAHdlz4DPUA1Dc=; b=dBGz09EpaU24J4UaI/0Ml+Zcm6sz/+Azur8bZf5QpYaxdrXvBdjYiLOgBbFYLcI66u hXvD+X4DgCH6azFILLZx66/Y8uvM6DN9Lxl2Va9+jPm2NYHJpvb5Jq7JVaUBvjFO7Xy4 IYyh+O3yBF1p6YuDBB+0M07+cxdFpOwyqP7GE= 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=du8lrySGcO2WJA5/+uAnRzTcnQRKVBAHdlz4DPUA1Dc=; b=hVUcZQ01jASShuga19AiRXoyEzkLr1+p9JDof1u2dz88aif+iT39VxQCjR+QHDWuTx 0IlllW0g1bDmhTTX40FAJo9YQpwp9GZxDSk2vbY5GH/Br5gRqvwrfvXncRj0k9GSf95y 2l62inkcnXPXyt2B2HoYeLDS+OFab6mbRksdHwj9VzkLk2atct8eNytj+ATyydcKRbiT lsc9f3sfMvSTDny51wP9KpKLqhBrL4HAVy/jLyF/pTKqhXfRJ+nIi2xLQGmW6OI5BPSY j2hSBdzX5SoScO94Xdar75kXJMxxMqeaZKsvyOqkfI+Cc42Q8Uabh36SRGCxpISjsM3N tMXA== X-Gm-Message-State: AHQUAuZftpYDvDTwebKJxC13rfvxS5/vqBtXr8VZFAaBF2wx74O++JJw IVPumMspmuti4flYnXsurrrpWQ== X-Received: by 2002:a5d:6b8b:: with SMTP id n11mr274269wrx.216.1549299634451; Mon, 04 Feb 2019 09:00:34 -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 i186sm19352297wmd.19.2019.02.04.09.00.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 04 Feb 2019 09:00:33 -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 5/5] ARM: dts: imx7s-warp: add fxas2100x gyroscope Date: Mon, 4 Feb 2019 17:00:12 +0000 Message-Id: <20190204170012.13617-6-rui.silva@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190204170012.13617-1-rui.silva@linaro.org> References: <20190204170012.13617-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 fxas2100x in the warp7 board Signed-off-by: Rui Miguel Silva --- arch/arm/boot/dts/imx7s-warp.dts | 5 +++++ 1 file changed, 5 insertions(+) -- 2.20.1 diff --git a/arch/arm/boot/dts/imx7s-warp.dts b/arch/arm/boot/dts/imx7s-warp.dts index 58d1a89ee3e3..47ff43cd229e 100644 --- a/arch/arm/boot/dts/imx7s-warp.dts +++ b/arch/arm/boot/dts/imx7s-warp.dts @@ -238,6 +238,11 @@ compatible = "fsl,mpl3115"; reg = <0x60>; }; + + fxas2100x@20 { + compatible = "nxp,fxas2100x"; + reg = <0x20>; + }; }; &sai1 {