From nobody Mon Jun 15 10:48:18 2026 Received: from mail-10629.protonmail.ch (mail-10629.protonmail.ch [79.135.106.29]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 857B63DFC78; Thu, 9 Apr 2026 16:24:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.135.106.29 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775751844; cv=none; b=J1FQHJyQmIWVM2RYM7F199dX+0AKZ0TrOJSAILLaVERX/mOlXipgfUAZIZpUcQqBxCO0uA+lsTHoNyUBDPh7p3IqfgclyCNW6oDm7QXCUHQArnD8hnQXmDeArVWSC+RFWlPNMfoXfs2NlMo3F0sRt+75V0R6XUJc7EM+Q9GEdUs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775751844; c=relaxed/simple; bh=rt69GKfvtm6r7L6ZdS0LmDtC2CKxY+kKDxYTToslLME=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=tJ7N9lNSIoZ4ffvCXk3kqbfzC+0f/0uHw/T4Rwqmk2XRMgA23tRf2jPYjO/+xpCDw+bspCJsgIfCjWC9Y5CciGGlP55+0ucPL40ZRlL1gZQZL2oSatJRLH96SuNRwidnGyFMnsug0GqjcWKfRXnHBnai6ruDvusfLcWhxfm0UXs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me; spf=pass smtp.mailfrom=pm.me; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b=TLvXAfcG; arc=none smtp.client-ip=79.135.106.29 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pm.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b="TLvXAfcG" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pm.me; s=protonmail3; t=1775751839; x=1776011039; bh=W/g6MIBZ3+LHjZsDhg8NMVRAvD8105CPrmbxQAoiqUo=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=TLvXAfcGlUIzXKBLeb9f6W58aVdB+B5MkHrgh9D0LEucpZQNAedg4X/04HPssC1LA f4NwweZkCfwEC7Rwu2wdnJHr53D1OaiA+3pTLfepcoNFje6YFtlfn2eoDeAopocMPD pf37+m/O8mktsO5fnEs1OBg8Ld51Qq7UX6Tkobf2DM85xEEnzsYlbPmeUyJRj37qK1 Z02wrzBNZ8oOxo27+rgHcPtp+nxFlPXwiI+GHlw6sOytfzNTIHhA+HyQm/2h1kxFXX ksZnV8DPWqUKrott8saTU9oPXWc4UdC7tO+ZDYFOGRmxYUY6hdmOsMz5j5/JKhFivl aoM4ShiSx0Ctw== Date: Thu, 09 Apr 2026 16:23:53 +0000 To: Greg Kroah-Hartman From: Hardik Phalet Cc: Jonathan Cameron , David Lechner , =?utf-8?Q?Nuno_S=C3=A1?= , Andy Shevchenko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Brigham Campbell , Shuah Khan , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-staging@lists.linux.dev, Hardik Phalet Subject: [PATCH 1/4] dt-bindings: vendor-prefixes: Add QST Corporation Message-ID: <20260409162308.2590385-2-hardik.phalet@pm.me> In-Reply-To: <20260409162308.2590385-1-hardik.phalet@pm.me> References: <20260409162308.2590385-1-hardik.phalet@pm.me> Feedback-ID: 166659585:user:proton X-Pm-Message-ID: af7bf9a7adb12b7898c0e4fbd07ebd168d8a52a8 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add the vendor prefix 'qst' for QST Corporation, a manufacturer of MEMS sensors. Signed-off-by: Hardik Phalet --- Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Docum= entation/devicetree/bindings/vendor-prefixes.yaml index 5d2a7a8d3ac6..71a1b9087c5e 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -1244,6 +1244,8 @@ patternProperties: description: Shenzhen QiShenglong Industrialist Co., Ltd. "^qnap,.*": description: QNAP Systems, Inc. + "^qst,.*": + description: QST Corporation "^quanta,.*": description: Quanta Computer Inc. "^radxa,.*": --=20 2.53.0 From nobody Mon Jun 15 10:48:18 2026 Received: from mail-4316.protonmail.ch (mail-4316.protonmail.ch [185.70.43.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D2A723B9D99; Thu, 9 Apr 2026 16:24:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.43.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775751860; cv=none; b=KCoJu6t19WlsLwIOCgJBCLdna5NHs3rg2Gbbv4rwpR8inWtBX756vuAyvzJu+exKdsPMHfBt2hb4QN2Hlc4rxau/uSADK/9QlsCEmhuVDzULklN+ZtDg+FdTW+iqbxp2BGD5vtam3vUNmu6Ime717wo9LoyMl1UF5vV4di4/O+k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775751860; c=relaxed/simple; bh=FHqavf4x2LMnpKhwYIAJLhWWLpu5loE7rr7KuHjSJBs=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Q7YjRv+Bwo0NjrfpzwlfMjidheRrUBnDWwVuMItTp/rkt6BYx5k0R29fcttAt1WYtCZVL2JXgAqRDWyeQz38z+dGANZzbT9tf4kEukoXQCTyaTuC1uq2KjIbL6JilyVotGZvKvaXf1lnoblitCqCuAu87StbNrBMfR6VKneIZoU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me; spf=pass smtp.mailfrom=pm.me; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b=W3WtiRWC; arc=none smtp.client-ip=185.70.43.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pm.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b="W3WtiRWC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pm.me; s=protonmail3; t=1775751851; x=1776011051; bh=MyqNqpuNtgV8td1byNhhPh0LwJSSFfPtn7H4KgGMCEY=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=W3WtiRWCUQMsjfJgajIHTMq2Qmaa8uqUIuw6M7Jj0STqXFJ2Apgtyc34+FDHpGXtQ xgvfJLGuU3w19OUVS1mhYbFBUqA5vSNKqPCYWX0TJKXeGgCDylACcNSe3O09ulN7qs t38hAQmHa44z42R5al+v5JN4JPhW0mjCeUf2LnBFd0m51k/wT4+r3DjyHGeKJZbr3e 8ctDfUsxtNsPLsuY/kosLUv2AqbDovsdAFg7vguG1WWlazftTsze5CFTJbsgvFuCNf emKn/vxs6eQqFAcDIqqON6Z1iVa4k0RMeUKWCNOF1eMyoVs5xznCaK/cIuYPjCR1FW Y3ZnfYhiR92rA== Date: Thu, 09 Apr 2026 16:24:05 +0000 To: Greg Kroah-Hartman From: Hardik Phalet Cc: Jonathan Cameron , David Lechner , =?utf-8?Q?Nuno_S=C3=A1?= , Andy Shevchenko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Brigham Campbell , Shuah Khan , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-staging@lists.linux.dev, Hardik Phalet Subject: [PATCH 2/4] dt-bindings: iio: magnetometer: Add binding for QST QMC5883P Message-ID: <20260409162308.2590385-3-hardik.phalet@pm.me> In-Reply-To: <20260409162308.2590385-1-hardik.phalet@pm.me> References: <20260409162308.2590385-1-hardik.phalet@pm.me> Feedback-ID: 166659585:user:proton X-Pm-Message-ID: 56cf74d2e6e82df571b58112540e55c2da1541cd Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add the device tree binding document for the QST QMC5883P, a 3-axis anisotropic magneto-resistive (AMR) sensor with a 16-bit ADC that communicates over I2C. The binding exposes the required 'compatible' and 'reg' properties along with an optional 'vdd-supply' for the 2.5 V=E2=80=933.6 V VDD rail. Signed-off-by: Hardik Phalet --- .../iio/magnetometer/qst,qmc5883p.yaml | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/magnetometer/qst,= qmc5883p.yaml diff --git a/Documentation/devicetree/bindings/iio/magnetometer/qst,qmc5883= p.yaml b/Documentation/devicetree/bindings/iio/magnetometer/qst,qmc5883p.ya= ml new file mode 100644 index 000000000000..84fec10d8b9a --- /dev/null +++ b/Documentation/devicetree/bindings/iio/magnetometer/qst,qmc5883p.yaml @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/magnetometer/qst,qmc5883p.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: QST QMC5883P 3-axis magnetometer + +maintainers: + - Hardik Phalet + +description: + The QMC5883P is a 3-axis anisotropic magneto-resistive (AMR) sensor with= a + 16-bit ADC. It communicates over I2C (standard and fast modes) and is + targeted at compass, navigation, and industrial applications. + +properties: + compatible: + const: qst,qmc5883p + + reg: + maxItems: 1 + description: I2C address of the device; the default address is 0x2c. + + vdd-supply: + description: + VDD power supply (2.5 V to 3.6 V). Powers all internal analog and + digital functional blocks. + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells =3D <1>; + #size-cells =3D <0>; + + magnetometer@2c { + compatible =3D "qst,qmc5883p"; + reg =3D <0x2c>; + vdd-supply =3D <&vdd_3v3>; + }; + }; +... --=20 2.53.0 From nobody Mon Jun 15 10:48:18 2026 Received: from mail-244122.protonmail.ch (mail-244122.protonmail.ch [109.224.244.122]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0B4A13E0C6D for ; Thu, 9 Apr 2026 16:24:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=109.224.244.122 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775751868; cv=none; b=fEZdVw3nybrhiu9BwnXKLIyfOaWWOESycYiaGkrovFtgCnRwIpaakRDTH6NeuxbXhNbRCr56qpmKVPWAJZN6N7rdWVl3D4tpTyNSNeenZw4P8sKoBAbhQWNGv3rry4MiMURC8ZccLYXI4zeeff1VUOzFRoVkBr1gK6IlANpjCLg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775751868; c=relaxed/simple; bh=ofaoZ3GwpVGeJ3+m9GvD3udQNMOTWqfUz/k2VYDH73o=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=cZLA8BW25ibCjn9s1QLEGrNSLXVRgEanDX4hWbEtGZmE36e5UtEbadIilzvqkr31fyKeQmoN6q63wnH8VZJxaXr8BaC0S9lAw5viD4Q13BVsvi7gXwTIvvpTpv8a2OVHlVDFp0Sl+S1YjlcZrp8QrpihOfvnqTxkc6DwDXdqkTE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me; spf=pass smtp.mailfrom=pm.me; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b=XNUSL4rc; arc=none smtp.client-ip=109.224.244.122 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pm.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b="XNUSL4rc" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pm.me; s=protonmail3; t=1775751862; x=1776011062; bh=3G5wMUA8Y/1GpMxnYDFBKiEoksHmdkGe6qqFMVlJNww=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=XNUSL4rcWProRZZZGBHk8yTcn7TsYO5DFl7dRHdm65TNGFSJSbM0Uz8s7qSWoadI2 D7CcML8K0haMy2hQsAbSlcMC19fbZ5T5cGdQU7ne/Y38H5N2/1RQ01QyHcQuq0aB0N /AT9Ya9EHcKQmjsRNAbCYWSL8dWHkTBEZmvBY05BXFKtbxcISvUurdhpfIefcDOmJf a3xuotJvuXrrjCOqpXqYGIozYG+ThRYyu7+ulU+lMbCkAadP+aU9XB/tdGLAF0Zpco xatWo4Z9QeQP04HwTLvcdE0Zj24WiOJVR5eDAqCd9aAslMirZNmFo7gSGlReGOpQzh 0gUGRgaTL11Og== Date: Thu, 09 Apr 2026 16:24:17 +0000 To: Greg Kroah-Hartman From: Hardik Phalet Cc: Jonathan Cameron , David Lechner , =?utf-8?Q?Nuno_S=C3=A1?= , Andy Shevchenko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Brigham Campbell , Shuah Khan , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-staging@lists.linux.dev, Hardik Phalet Subject: [PATCH 3/4] staging: iio: magnetometer: Add QST QMC5883P driver Message-ID: <20260409162308.2590385-4-hardik.phalet@pm.me> In-Reply-To: <20260409162308.2590385-1-hardik.phalet@pm.me> References: <20260409162308.2590385-1-hardik.phalet@pm.me> Feedback-ID: 166659585:user:proton X-Pm-Message-ID: dcac24137a995ea1ba17e170cc1c80436327ce72 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add an IIO driver for the QST QMC5883P 3-axis magnetometer. The device communicates over I2C and is managed via regmap with an rbtree cache. Regmap fields are used to access the individual bit fields in CTRL_1 and CTRL_2 registers. The driver supports: - Raw magnetic field readings on X, Y and Z axes - Four full-scale ranges (=C2=B12 G, =C2=B18 G, =C2=B112 G, =C2=B130 G) - Configurable output data rate (10, 50, 100, 200 Hz) - Configurable oversampling ratio (1, 2, 4, 8) - Configurable downsampling ratio (1, 2, 4, 8) via a custom sysfs attr - Runtime PM with a 2 s autosuspend delay Known limitations tracked in TODO: - No triggered buffer support - No DRDY interrupt support - Self-test register field is unused Signed-off-by: Hardik Phalet --- drivers/staging/iio/Kconfig | 1 + drivers/staging/iio/Makefile | 1 + drivers/staging/iio/magnetometer/Kconfig | 20 + drivers/staging/iio/magnetometer/Makefile | 7 + drivers/staging/iio/magnetometer/TODO | 5 + drivers/staging/iio/magnetometer/qmc5883p.c | 819 ++++++++++++++++++++ 6 files changed, 853 insertions(+) create mode 100644 drivers/staging/iio/magnetometer/Kconfig create mode 100644 drivers/staging/iio/magnetometer/Makefile create mode 100644 drivers/staging/iio/magnetometer/TODO create mode 100644 drivers/staging/iio/magnetometer/qmc5883p.c diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig index a60631c1f449..d363e163d248 100644 --- a/drivers/staging/iio/Kconfig +++ b/drivers/staging/iio/Kconfig @@ -10,5 +10,6 @@ source "drivers/staging/iio/adc/Kconfig" source "drivers/staging/iio/addac/Kconfig" source "drivers/staging/iio/frequency/Kconfig" source "drivers/staging/iio/impedance-analyzer/Kconfig" +source "drivers/staging/iio/magnetometer/Kconfig" =20 endmenu diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile index 628583535393..7dcbb75d43f0 100644 --- a/drivers/staging/iio/Makefile +++ b/drivers/staging/iio/Makefile @@ -8,3 +8,4 @@ obj-y +=3D adc/ obj-y +=3D addac/ obj-y +=3D frequency/ obj-y +=3D impedance-analyzer/ +obj-y +=3D magnetometer/ diff --git a/drivers/staging/iio/magnetometer/Kconfig b/drivers/staging/iio= /magnetometer/Kconfig new file mode 100644 index 000000000000..d631da9578a1 --- /dev/null +++ b/drivers/staging/iio/magnetometer/Kconfig @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Magnetometer sensors +# +# When adding new entries keep the list in alphabetical order + +menu "Magnetometer sensors" + +config QMC5883P + tristate "QMC5883P 3-Axis Magnetometer" + depends on I2C + select REGMAP_I2C + help + Say yes here to build support for QMC5883P I2C-based + 3-axis magnetometer chip. + + To compile this driver as a module, choose M here: the + module will be called qmc5883p. + +endmenu diff --git a/drivers/staging/iio/magnetometer/Makefile b/drivers/staging/ii= o/magnetometer/Makefile new file mode 100644 index 000000000000..8e650f2e3b02 --- /dev/null +++ b/drivers/staging/iio/magnetometer/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Makefile for staging industrial I/O Magnetometer sensor devices +# +# When adding new entries keep the list in alphabetical order + +obj-$(CONFIG_QMC5883P) +=3D qmc5883p.o diff --git a/drivers/staging/iio/magnetometer/TODO b/drivers/staging/iio/ma= gnetometer/TODO new file mode 100644 index 000000000000..6a8084c0dded --- /dev/null +++ b/drivers/staging/iio/magnetometer/TODO @@ -0,0 +1,5 @@ +TODO +=3D=3D=3D=3D +- Implement triggered buffer support (iio_triggered_buffer_setup) +- Add interrupt (DRDY) support +- Implement self-test (selftest regmap field is unused) diff --git a/drivers/staging/iio/magnetometer/qmc5883p.c b/drivers/staging/= iio/magnetometer/qmc5883p.c new file mode 100644 index 000000000000..6a71dc47efb9 --- /dev/null +++ b/drivers/staging/iio/magnetometer/qmc5883p.c @@ -0,0 +1,819 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * qmc5883p.c - QMC5883P magnetometer driver + * + * Copyright 2026 Hardik Phalet + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Register definition */ +#define QMC5883P_REG_CHIP_ID 0x00 +#define QMC5883P_REG_X_LSB 0x01 +#define QMC5883P_REG_X_MSB 0x02 +#define QMC5883P_REG_Y_LSB 0x03 +#define QMC5883P_REG_Y_MSB 0x04 +#define QMC5883P_REG_Z_LSB 0x05 +#define QMC5883P_REG_Z_MSB 0x06 +#define QMC5883P_REG_STATUS 0x09 +#define QMC5883P_REG_CTRL_1 0x0A +#define QMC5883P_REG_CTRL_2 0x0B + +/* Value definition */ +#define QMC5883P_MODE_SUSPEND 0x00 +#define QMC5883P_MODE_NORMAL 0x01 +#define QMC5883P_MODE_SINGLE 0x02 +#define QMC5883P_MODE_CONTINUOUS 0x03 + +/* Output data rate */ +#define QMC5883P_ODR_10 0x00 +#define QMC5883P_ODR_50 0x01 +#define QMC5883P_ODR_100 0x02 +#define QMC5883P_ODR_200 0x03 + +/* Oversampling rate */ +#define QMC5883P_OSR_8 0x00 +#define QMC5883P_OSR_4 0x01 +#define QMC5883P_OSR_2 0x02 +#define QMC5883P_OSR_1 0x03 + +/* Downsampling rate */ +#define QMC5883P_DSR_1 0x00 +#define QMC5883P_DSR_2 0x01 +#define QMC5883P_DSR_4 0x02 +#define QMC5883P_DSR_8 0x03 + +#define QMC5883P_RSTCTRL_SET_RESET \ + 0x00 /* Set and reset on, i.e. the offset of device is renewed */ +#define QMC5883P_RSTCTRL_SET_ONLY 0x01 /* Set only on */ +#define QMC5883P_RSTCTRL_OFF 0x02 /* Set and reset off */ + +#define QMC5883P_RNG_30G 0x00 +#define QMC5883P_RNG_12G 0x01 +#define QMC5883P_RNG_08G 0x02 +#define QMC5883P_RNG_02G 0x03 + +#define QMC5883P_DEFAULT_ODR QMC5883P_ODR_100 +#define QMC5883P_DEFAULT_OSR QMC5883P_OSR_4 +#define QMC5883P_DEFAULT_DSR QMC5883P_DSR_4 +#define QMC5883P_DEFAULT_RNG QMC5883P_RNG_08G + +#define QMC5883P_DRDY_POLL_US 1000 + +#define QMC5883P_CHIP_ID 0x80 + +#define QMC5883P_STATUS_DRDY BIT(0) +#define QMC5883P_STATUS_OVFL BIT(1) + +/* + * Scale factors in T/LSB for IIO_VAL_FRACTIONAL (val/val2), derived from + * datasheet Table 2 sensitivities (LSB/G) converted to LSB/T (1 G =3D 1e-= 4 T): + * sensitivity_T =3D sensitivity_G * 10000 + * scale =3D 1 / sensitivity_T + * + * Index matches register value: RNG<1:0> =3D 0b00..0b11 + */ +static const int qmc5883p_scale[][2] =3D { + [QMC5883P_RNG_30G] =3D { 1, 10000000 }, + [QMC5883P_RNG_12G] =3D { 1, 25000000 }, + [QMC5883P_RNG_08G] =3D { 1, 37500000 }, + [QMC5883P_RNG_02G] =3D { 1, 150000000 }, +}; + +static const int qmc5883p_odr[] =3D { + [QMC5883P_ODR_10] =3D 10, + [QMC5883P_ODR_50] =3D 50, + [QMC5883P_ODR_100] =3D 100, + [QMC5883P_ODR_200] =3D 200, +}; + +static const int qmc5883p_osr[] =3D { + [QMC5883P_OSR_1] =3D 1, + [QMC5883P_OSR_2] =3D 2, + [QMC5883P_OSR_4] =3D 4, + [QMC5883P_OSR_8] =3D 8, +}; + +static const unsigned int qmc5883p_dsr[] =3D { + [QMC5883P_DSR_1] =3D 1, + [QMC5883P_DSR_2] =3D 2, + [QMC5883P_DSR_4] =3D 4, + [QMC5883P_DSR_8] =3D 8, +}; + +struct qmc5883p_rf { + struct regmap_field *osr; + struct regmap_field *dsr; + struct regmap_field *odr; + struct regmap_field *mode; + struct regmap_field *rng; + struct regmap_field *rstctrl; + struct regmap_field *sftrst; + struct regmap_field *selftest; + struct regmap_field *chip_id; +}; + +static const struct regmap_range qmc5883p_readable_ranges[] =3D { + regmap_reg_range(QMC5883P_REG_CHIP_ID, QMC5883P_REG_STATUS), + regmap_reg_range(QMC5883P_REG_CTRL_1, QMC5883P_REG_CTRL_2), +}; + +static const struct regmap_range qmc5883p_writable_ranges[] =3D { + regmap_reg_range(QMC5883P_REG_CTRL_1, QMC5883P_REG_CTRL_2), +}; + +/* + * Volatile registers: hardware updates these independently of the driver. + * regmap will never serve these from cache. + */ +static const struct regmap_range qmc5883p_volatile_ranges[] =3D { + regmap_reg_range(QMC5883P_REG_X_LSB, QMC5883P_REG_Z_MSB), + regmap_reg_range(QMC5883P_REG_STATUS, QMC5883P_REG_STATUS), +}; + +/* + * Precious registers: reading has a side effect (clears DRDY/OVFL bits). + * regmap will never read these speculatively. + */ +static const struct regmap_range qmc5883p_precious_ranges[] =3D { + regmap_reg_range(QMC5883P_REG_STATUS, QMC5883P_REG_STATUS), +}; + +static const struct regmap_access_table qmc5883p_readable_table =3D { + .yes_ranges =3D qmc5883p_readable_ranges, + .n_yes_ranges =3D ARRAY_SIZE(qmc5883p_readable_ranges), +}; + +static const struct regmap_access_table qmc5883p_writable_table =3D { + .yes_ranges =3D qmc5883p_writable_ranges, + .n_yes_ranges =3D ARRAY_SIZE(qmc5883p_writable_ranges), +}; + +static const struct regmap_access_table qmc5883p_volatile_table =3D { + .yes_ranges =3D qmc5883p_volatile_ranges, + .n_yes_ranges =3D ARRAY_SIZE(qmc5883p_volatile_ranges), +}; + +static const struct regmap_access_table qmc5883p_precious_table =3D { + .yes_ranges =3D qmc5883p_precious_ranges, + .n_yes_ranges =3D ARRAY_SIZE(qmc5883p_precious_ranges), +}; + +static const struct regmap_config qmc5883p_regmap_config =3D { + .reg_bits =3D 8, + .val_bits =3D 8, + .max_register =3D 0x0B, + .cache_type =3D REGCACHE_RBTREE, + .rd_table =3D &qmc5883p_readable_table, + .wr_table =3D &qmc5883p_writable_table, + .volatile_table =3D &qmc5883p_volatile_table, + .precious_table =3D &qmc5883p_precious_table, +}; + +struct qmc5883p_data { + struct device *dev; + struct regmap *regmap; + struct mutex mutex; /* protects regmap and rf field accesses */ + struct qmc5883p_rf rf; +}; + +enum qmc5883p_channels { + AXIS_X =3D 0, + AXIS_Y, + AXIS_Z, +}; + +static const struct reg_field qmc5883p_rf_osr =3D + REG_FIELD(QMC5883P_REG_CTRL_1, 4, 5); +static const struct reg_field qmc5883p_rf_dsr =3D + REG_FIELD(QMC5883P_REG_CTRL_1, 6, 7); +static const struct reg_field qmc5883p_rf_odr =3D + REG_FIELD(QMC5883P_REG_CTRL_1, 2, 3); +static const struct reg_field qmc5883p_rf_mode =3D + REG_FIELD(QMC5883P_REG_CTRL_1, 0, 1); +static const struct reg_field qmc5883p_rf_rng =3D + REG_FIELD(QMC5883P_REG_CTRL_2, 2, 3); +static const struct reg_field qmc5883p_rf_rstctrl =3D + REG_FIELD(QMC5883P_REG_CTRL_2, 0, 1); +static const struct reg_field qmc5883p_rf_sftrst =3D + REG_FIELD(QMC5883P_REG_CTRL_2, 7, 7); +static const struct reg_field qmc5883p_rf_selftest =3D + REG_FIELD(QMC5883P_REG_CTRL_2, 6, 6); +static const struct reg_field qmc5883p_rf_chip_id =3D + REG_FIELD(QMC5883P_REG_CHIP_ID, 0, 7); + +static int qmc5883p_rf_init(struct qmc5883p_data *data) +{ + struct regmap *regmap =3D data->regmap; + struct device *dev =3D data->dev; + struct qmc5883p_rf *rf =3D &data->rf; + + rf->osr =3D devm_regmap_field_alloc(dev, regmap, qmc5883p_rf_osr); + if (IS_ERR(rf->osr)) + return PTR_ERR(rf->osr); + + rf->dsr =3D devm_regmap_field_alloc(dev, regmap, qmc5883p_rf_dsr); + if (IS_ERR(rf->dsr)) + return PTR_ERR(rf->dsr); + + rf->odr =3D devm_regmap_field_alloc(dev, regmap, qmc5883p_rf_odr); + if (IS_ERR(rf->odr)) + return PTR_ERR(rf->odr); + + rf->mode =3D devm_regmap_field_alloc(dev, regmap, qmc5883p_rf_mode); + if (IS_ERR(rf->mode)) + return PTR_ERR(rf->mode); + + rf->rng =3D devm_regmap_field_alloc(dev, regmap, qmc5883p_rf_rng); + if (IS_ERR(rf->rng)) + return PTR_ERR(rf->rng); + + rf->rstctrl =3D devm_regmap_field_alloc(dev, regmap, qmc5883p_rf_rstctrl); + if (IS_ERR(rf->rstctrl)) + return PTR_ERR(rf->rstctrl); + + rf->sftrst =3D devm_regmap_field_alloc(dev, regmap, qmc5883p_rf_sftrst); + if (IS_ERR(rf->sftrst)) + return PTR_ERR(rf->sftrst); + + rf->selftest =3D + devm_regmap_field_alloc(dev, regmap, qmc5883p_rf_selftest); + if (IS_ERR(rf->selftest)) + return PTR_ERR(rf->selftest); + + rf->chip_id =3D devm_regmap_field_alloc(dev, regmap, qmc5883p_rf_chip_id); + if (IS_ERR(rf->chip_id)) + return PTR_ERR(rf->chip_id); + + return 0; +} + +static int qmc5883p_verify_chip_id(struct qmc5883p_data *data) +{ + int ret, regval; + + ret =3D regmap_field_read(data->rf.chip_id, ®val); + if (ret) + return dev_err_probe(data->dev, ret, + "failed to read chip ID\n"); + + if (regval !=3D QMC5883P_CHIP_ID) + return dev_err_probe(data->dev, -ENODEV, + "unexpected chip ID 0x%02x, expected 0x%02x\n", + regval, QMC5883P_CHIP_ID); + return ret; +} + +static int qmc5883p_chip_init(struct qmc5883p_data *data) +{ + int ret; + + ret =3D regmap_field_write(data->rf.sftrst, 1); + if (ret) + return ret; + + usleep_range(1000, 2000); + + ret =3D regmap_field_write(data->rf.sftrst, 0); + if (ret) + return ret; + + ret =3D regmap_field_write(data->rf.rstctrl, QMC5883P_RSTCTRL_SET_RESET); + if (ret) + return ret; + + ret =3D regmap_field_write(data->rf.rng, QMC5883P_DEFAULT_RNG); + if (ret) + return ret; + + ret =3D regmap_field_write(data->rf.osr, QMC5883P_DEFAULT_OSR); + if (ret) + return ret; + + ret =3D regmap_field_write(data->rf.dsr, QMC5883P_DEFAULT_DSR); + if (ret) + return ret; + + ret =3D regmap_field_write(data->rf.odr, QMC5883P_DEFAULT_ODR); + if (ret) + return ret; + + return regmap_field_write(data->rf.mode, QMC5883P_MODE_NORMAL); +} + +/* + * qmc5883p_get_measure - read all three axes. + * Must be called with data->mutex held. + * Handles PM internally: resumes device, reads data, schedules autosuspen= d. + */ +static int qmc5883p_get_measure(struct qmc5883p_data *data, s16 *x, s16 *y, + s16 *z) +{ + int ret; + u8 reg_data[6]; + unsigned int status; + + ret =3D pm_runtime_resume_and_get(data->dev); + if (ret < 0) + return ret; + + /* + * Poll the status register until DRDY is set or timeout. + * Read the whole register in one shot so that OVFL is captured from + * the same read: reading 0x09 clears both DRDY and OVFL, so a second + * read would always see OVFL=3D0. + * At ODR=3D10Hz one period is 100ms; use 150ms as a safe upper bound. + */ + ret =3D regmap_read_poll_timeout(data->regmap, QMC5883P_REG_STATUS, + status, status & QMC5883P_STATUS_DRDY, + QMC5883P_DRDY_POLL_US, 150000); + if (ret) + goto out; + + if (status & QMC5883P_STATUS_OVFL) { + dev_warn_ratelimited(data->dev, + "data overflow, consider reducing field range\n"); + ret =3D -ERANGE; + goto out; + } + + ret =3D regmap_bulk_read(data->regmap, QMC5883P_REG_X_LSB, reg_data, + ARRAY_SIZE(reg_data)); + if (ret) + goto out; + + *x =3D (s16)((reg_data[1] << 8) | reg_data[0]); + *y =3D (s16)((reg_data[3] << 8) | reg_data[2]); + *z =3D (s16)((reg_data[5] << 8) | reg_data[4]); + +out: + pm_runtime_mark_last_busy(data->dev); + pm_runtime_put_autosuspend(data->dev); + return ret; +} + +static int qmc5883p_write_scale(struct qmc5883p_data *data, int val, int v= al2) +{ + int i; + + for (i =3D 0; i < ARRAY_SIZE(qmc5883p_scale); i++) { + if (qmc5883p_scale[i][0] =3D=3D val && qmc5883p_scale[i][1] =3D=3D val2) + return regmap_field_write(data->rf.rng, i); + } + + return -EINVAL; +} + +static int qmc5883p_write_odr(struct qmc5883p_data *data, int val) +{ + int i; + + for (i =3D 0; i < ARRAY_SIZE(qmc5883p_odr); i++) { + if (qmc5883p_odr[i] =3D=3D val) + return regmap_field_write(data->rf.odr, i); + } + + return -EINVAL; +} + +static int qmc5883p_write_osr(struct qmc5883p_data *data, int val) +{ + int i; + + for (i =3D 0; i < ARRAY_SIZE(qmc5883p_osr); i++) { + if (qmc5883p_osr[i] =3D=3D val) + return regmap_field_write(data->rf.osr, i); + } + + return -EINVAL; +} + +static ssize_t downsampling_ratio_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev =3D dev_get_drvdata(dev); + struct qmc5883p_data *data =3D iio_priv(indio_dev); + unsigned int regval; + int ret; + + guard(mutex)(&data->mutex); + + ret =3D regmap_field_read(data->rf.dsr, ®val); + if (ret) + return ret; + + return sysfs_emit(buf, "%u\n", qmc5883p_dsr[regval]); +} + +static ssize_t downsampling_ratio_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + struct iio_dev *indio_dev =3D dev_get_drvdata(dev); + struct qmc5883p_data *data =3D iio_priv(indio_dev); + unsigned int val; + int i, ret, restore; + + ret =3D kstrtouint(buf, 10, &val); + if (ret) + return ret; + + guard(mutex)(&data->mutex); + + ret =3D pm_runtime_resume_and_get(dev); + if (ret) + return ret; + + ret =3D regmap_field_write(data->rf.mode, QMC5883P_MODE_SUSPEND); + if (ret) + goto out; + + ret =3D -EINVAL; + for (i =3D 0; i < ARRAY_SIZE(qmc5883p_dsr); i++) { + if (qmc5883p_dsr[i] =3D=3D val) { + ret =3D regmap_field_write(data->rf.dsr, i); + break; + } + } + + restore =3D regmap_field_write(data->rf.mode, QMC5883P_MODE_NORMAL); + if (restore && !ret) + ret =3D restore; + +out: + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + return ret ? ret : (ssize_t)len; +} + +static int qmc5883p_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, int *val, + int *val2, long mask) +{ + s16 x, y, z; + struct qmc5883p_data *data =3D iio_priv(indio_dev); + int ret; + unsigned int regval; + + guard(mutex)(&data->mutex); + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret =3D qmc5883p_get_measure(data, &x, &y, &z); + if (ret < 0) + return ret; + switch (chan->address) { + case AXIS_X: + *val =3D x; + break; + case AXIS_Y: + *val =3D y; + break; + case AXIS_Z: + *val =3D z; + break; + } + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + ret =3D regmap_field_read(data->rf.rng, ®val); + if (ret < 0) + return ret; + *val =3D qmc5883p_scale[regval][0]; + *val2 =3D qmc5883p_scale[regval][1]; + return IIO_VAL_FRACTIONAL; + + case IIO_CHAN_INFO_SAMP_FREQ: + ret =3D regmap_field_read(data->rf.odr, ®val); + if (ret < 0) + return ret; + *val =3D qmc5883p_odr[regval]; + return IIO_VAL_INT; + + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + ret =3D regmap_field_read(data->rf.osr, ®val); + if (ret < 0) + return ret; + *val =3D qmc5883p_osr[regval]; + return IIO_VAL_INT; + } + + return -EINVAL; +} + +static int qmc5883p_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, + int val2, long mask) +{ + struct qmc5883p_data *data =3D iio_priv(indio_dev); + int ret, restore; + + guard(mutex)(&data->mutex); + + ret =3D pm_runtime_resume_and_get(data->dev); + if (ret) + return ret; + + ret =3D regmap_field_write(data->rf.mode, QMC5883P_MODE_SUSPEND); + if (ret) + goto out; + + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + ret =3D qmc5883p_write_odr(data, val); + break; + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + ret =3D qmc5883p_write_osr(data, val); + break; + case IIO_CHAN_INFO_SCALE: + ret =3D qmc5883p_write_scale(data, val, val2); + break; + default: + ret =3D -EINVAL; + break; + } + + restore =3D regmap_field_write(data->rf.mode, QMC5883P_MODE_NORMAL); + if (restore && !ret) + ret =3D restore; + +out: + pm_runtime_mark_last_busy(data->dev); + pm_runtime_put_autosuspend(data->dev); + return ret; +} + +/* + * qmc5883p_read_avail - expose available values to userspace. + * + * Creates the _available sysfs attributes automatically: + * in_magn_sampling_frequency_available + * in_magn_oversampling_ratio_available + * in_magn_scale_available + */ +static int qmc5883p_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, + long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + *vals =3D qmc5883p_odr; + *type =3D IIO_VAL_INT; + *length =3D ARRAY_SIZE(qmc5883p_odr); + return IIO_AVAIL_LIST; + + case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + *vals =3D qmc5883p_osr; + *type =3D IIO_VAL_INT; + *length =3D ARRAY_SIZE(qmc5883p_osr); + return IIO_AVAIL_LIST; + + case IIO_CHAN_INFO_SCALE: + *vals =3D (const int *)qmc5883p_scale; + *type =3D IIO_VAL_FRACTIONAL; + *length =3D ARRAY_SIZE(qmc5883p_scale) * 2; + return IIO_AVAIL_LIST; + + default: + return -EINVAL; + } +} + +static IIO_DEVICE_ATTR(downsampling_ratio, 0644, downsampling_ratio_show, + downsampling_ratio_store, 0); +static IIO_CONST_ATTR(downsampling_ratio_available, "1 2 4 8"); + +static struct attribute *qmc5883p_attributes[] =3D { + &iio_dev_attr_downsampling_ratio.dev_attr.attr, + &iio_const_attr_downsampling_ratio_available.dev_attr.attr, NULL +}; + +static const struct attribute_group qmc5883p_attribute_group =3D { + .attrs =3D qmc5883p_attributes, +}; + +static const struct iio_info qmc5883p_info =3D { + .attrs =3D &qmc5883p_attribute_group, + .read_raw =3D qmc5883p_read_raw, + .write_raw =3D qmc5883p_write_raw, + .read_avail =3D qmc5883p_read_avail, +}; + +static const struct iio_chan_spec qmc5883p_channels[] =3D { + { + .type =3D IIO_MAGN, + .channel2 =3D IIO_MOD_X, + .modified =3D 1, + .address =3D AXIS_X, + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .info_mask_separate_available =3D BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_type =3D + BIT(IIO_CHAN_INFO_SAMP_FREQ) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_shared_by_type_available =3D + BIT(IIO_CHAN_INFO_SAMP_FREQ) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + }, + { + .type =3D IIO_MAGN, + .channel2 =3D IIO_MOD_Y, + .modified =3D 1, + .address =3D AXIS_Y, + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .info_mask_separate_available =3D BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_type =3D + BIT(IIO_CHAN_INFO_SAMP_FREQ) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_shared_by_type_available =3D + BIT(IIO_CHAN_INFO_SAMP_FREQ) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + }, + { + .type =3D IIO_MAGN, + .channel2 =3D IIO_MOD_Z, + .modified =3D 1, + .address =3D AXIS_Z, + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW) | + BIT(IIO_CHAN_INFO_SCALE), + .info_mask_separate_available =3D BIT(IIO_CHAN_INFO_SCALE), + .info_mask_shared_by_type =3D + BIT(IIO_CHAN_INFO_SAMP_FREQ) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + .info_mask_shared_by_type_available =3D + BIT(IIO_CHAN_INFO_SAMP_FREQ) | + BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), + }, +}; + +static void qmc5883p_runtime_pm_disable(void *dev) +{ + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); +} + +static int qmc5883p_probe(struct i2c_client *client) +{ + struct device *dev =3D &client->dev; + struct qmc5883p_data *data; + struct iio_dev *indio_dev; + struct regmap *regmap; + int ret; + + indio_dev =3D devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + regmap =3D devm_regmap_init_i2c(client, &qmc5883p_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), + "regmap initialization failed\n"); + + data =3D iio_priv(indio_dev); + data->dev =3D dev; + data->regmap =3D regmap; + mutex_init(&data->mutex); + + i2c_set_clientdata(client, indio_dev); + + ret =3D qmc5883p_rf_init(data); + if (ret) + return dev_err_probe(dev, ret, + "failed to initialize regmap fields\n"); + + ret =3D qmc5883p_verify_chip_id(data); + if (ret) + return ret; + + ret =3D qmc5883p_chip_init(data); + if (ret) + return dev_err_probe(dev, ret, "failed to initialize chip\n"); + + indio_dev->name =3D "qmc5883p"; + indio_dev->info =3D &qmc5883p_info; + indio_dev->modes =3D INDIO_DIRECT_MODE; + indio_dev->channels =3D qmc5883p_channels; + indio_dev->num_channels =3D ARRAY_SIZE(qmc5883p_channels); + + pm_runtime_set_autosuspend_delay(dev, 2000); + pm_runtime_use_autosuspend(dev); + + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + ret =3D devm_add_action_or_reset(dev, + (void (*)(void *))qmc5883p_runtime_pm_disable, + dev); + if (ret) + return ret; + + pm_runtime_mark_last_busy(dev); + + ret =3D devm_iio_device_register(dev, indio_dev); + if (ret) + return dev_err_probe(dev, ret, + "failed to register IIO device\n"); + return 0; +} + +static int qmc5883p_runtime_suspend(struct device *dev) +{ + struct iio_dev *indio_dev =3D dev_get_drvdata(dev); + struct qmc5883p_data *data =3D iio_priv(indio_dev); + + return regmap_field_write(data->rf.mode, QMC5883P_MODE_SUSPEND); +} + +static int qmc5883p_runtime_resume(struct device *dev) +{ + struct iio_dev *indio_dev =3D dev_get_drvdata(dev); + struct qmc5883p_data *data =3D iio_priv(indio_dev); + int ret; + + ret =3D regmap_field_write(data->rf.mode, QMC5883P_MODE_NORMAL); + if (ret) + return ret; + + usleep_range(10000, 11000); + return 0; +} + +static int qmc5883p_runtime_idle(struct device *dev) +{ + return 0; +} + +static int qmc5883p_system_suspend(struct device *dev) +{ + return pm_runtime_force_suspend(dev); +} + +static int qmc5883p_system_resume(struct device *dev) +{ + return pm_runtime_force_resume(dev); +} + +static void qmc5883p_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev =3D i2c_get_clientdata(client); + struct qmc5883p_data *data =3D iio_priv(indio_dev); + + /* + * Best effort: put device to sleep on removal. + * Ignore error since we cannot do anything useful with it here. + * Runtime PM disable is handled by the devm cleanup action registered + * in probe. + */ + regmap_field_write(data->rf.mode, QMC5883P_MODE_SUSPEND); +} + +static const struct dev_pm_ops qmc5883p_dev_pm_ops =3D { + SYSTEM_SLEEP_PM_OPS(qmc5883p_system_suspend, qmc5883p_system_resume) + RUNTIME_PM_OPS(qmc5883p_runtime_suspend, qmc5883p_runtime_resume, NULL) +}; + +static const struct of_device_id qmc5883p_of_match[] =3D { + { .compatible =3D "qst,qmc5883p" }, + {} +}; +MODULE_DEVICE_TABLE(of, qmc5883p_of_match); + +static const struct i2c_device_id qmc5883p_id[] =3D { + { "qmc5883p", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(i2c, qmc5883p_id); + +static struct i2c_driver qmc5883p_driver =3D { + .driver =3D { + .name =3D "qmc5883p", + .of_match_table =3D qmc5883p_of_match, + .pm =3D pm_ptr(&qmc5883p_dev_pm_ops), + }, + .probe =3D qmc5883p_probe, + .remove =3D qmc5883p_remove, + .id_table =3D qmc5883p_id, +}; +module_i2c_driver(qmc5883p_driver); + +MODULE_AUTHOR("Hardik Phalet "); +MODULE_DESCRIPTION("QMC5883P magnetic sensor driver"); +MODULE_LICENSE("GPL"); --=20 2.53.0 From nobody Mon Jun 15 10:48:18 2026 Received: from mail-106118.protonmail.ch (mail-106118.protonmail.ch [79.135.106.118]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5CBE93E0C6D for ; Thu, 9 Apr 2026 16:24:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=79.135.106.118 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775751878; cv=none; b=UZ/k4tNWi08ALFODnH8eo0feI6pZ0PuGgrY3E5gobhljN241AXwMnVrULebBAEZGSNVTwKZVu5dLPmLYfql9ClYwZpcKUG5lWuhTY7lC8fZtmXaL+coKHzD93EtBHij59EItCin+1TH5W4sVVIU6ozHWHrDQmjVp7yoHkZyumrI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775751878; c=relaxed/simple; bh=1pxZBrLmy2pMWIo0LdsENmdYtsvl8jy8EOqABhANfgE=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=rYueetRbiyNh1dKfCxRDZfuktYoY4DFiYrxPhoT1Zv0rg6uuO6UO0dWc1UQluIUS3/BbWGmoWeteFMgHjqPF+5KSnP5i9g5AQMIKS4GC0khG2/kpapeqkgs4RldIKqhXTqgcxLmXtt6BvaYyrLav2cPQsHNMdOuXy/RdEEoWk64= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me; spf=pass smtp.mailfrom=pm.me; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b=iRToTGEC; arc=none smtp.client-ip=79.135.106.118 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=pm.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pm.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=pm.me header.i=@pm.me header.b="iRToTGEC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pm.me; s=protonmail3; t=1775751875; x=1776011075; bh=1pxZBrLmy2pMWIo0LdsENmdYtsvl8jy8EOqABhANfgE=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=iRToTGECnVE+8mvp2PylT9VBlBWBKMJjXAgcYtlTlbO5Mm5I+/1nHDD2S9Oh8e4ac rbHnmucn39RU3PveCgaHiRTWygCvfh43J2km94FCqkFSreqdtphlB/TQAksSr26aej p6g9QToDUQxQKm2yTMW/z314tUqJ7sRqtZKG01mShW1BW7bdbiOVbM6PBjVJCOB6wu WL1dyxVbgVkEXLVb5yqYjhgcjPWa/02x2ouKqvfMfrnxf9EG8GIQUKuJZVIjV0hlyd 1ac/8SQ9oNTWirsIufvtt6ps6LmlG8f9z1+kqbOADDhl+uBR4n+2S6u6ybL2iI1xsX JGwceMQsaKv2Q== Date: Thu, 09 Apr 2026 16:24:28 +0000 To: Greg Kroah-Hartman From: Hardik Phalet Cc: Jonathan Cameron , David Lechner , =?utf-8?Q?Nuno_S=C3=A1?= , Andy Shevchenko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Brigham Campbell , Shuah Khan , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-staging@lists.linux.dev, Hardik Phalet Subject: [PATCH 4/4] MAINTAINERS: Add entry for QST QMC5883P magnetometer driver Message-ID: <20260409162308.2590385-5-hardik.phalet@pm.me> In-Reply-To: <20260409162308.2590385-1-hardik.phalet@pm.me> References: <20260409162308.2590385-1-hardik.phalet@pm.me> Feedback-ID: 166659585:user:proton X-Pm-Message-ID: 2b7baa0548efb5feb749682b4d124577346ff50a Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a MAINTAINERS entry for the QST QMC5883P staging IIO driver, covering the driver source and its device tree binding. Signed-off-by: Hardik Phalet --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index a92290fffa16..d0b9bfceb283 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20274,6 +20274,13 @@ F: Documentation/networking/device_drivers/etherne= t/freescale/dpaa2/overview.rst F: drivers/bus/fsl-mc/ F: include/uapi/linux/fsl_mc.h =20 +QST QMC5883P MAGNETOMETER DRIVER +M: Hardik Phalet +L: linux-iio@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/iio/magnetometer/qst,qmc5883p.yaml +F: drivers/staging/iio/magnetometer/ + QT1010 MEDIA DRIVER L: linux-media@vger.kernel.org S: Orphan --=20 2.53.0