public inbox for linux-staging@lists.linux.dev
 help / color / mirror / Atom feed
* [PATCH v3 0/5] iio: magnetometer: add driver for QST QMC5883P
@ 2026-04-19 22:32 Hardik Phalet
  2026-04-19 22:32 ` [PATCH v3 1/5] dt-bindings: vendor-prefixes: Add QST Corporation Hardik Phalet
                   ` (6 more replies)
  0 siblings, 7 replies; 16+ messages in thread
From: Hardik Phalet @ 2026-04-19 22:32 UTC (permalink / raw)
  To: gregkh, jic23
  Cc: andy, conor+dt, devicetree, dlechner, krzk+dt, linux-iio,
	linux-kernel, linux-staging, me, nuno.sa, robh, skhan,
	Hardik Phalet, Hardik Phalet

This series adds an IIO driver for the QST QMC5883P, a 3-axis
anisotropic magneto-resistive (AMR) magnetometer with a 16-bit ADC,
communicating over I2C. To my knowledge there is no existing
upstream driver for this device (see "Prior-art register-map check"
below).

The driver supports:
  - Raw magnetic field readings on X, Y and Z axes
  - Four full-scale ranges (+/-2 G, +/-8 G, +/-12 G, +/-30 G),
    selectable via IIO_CHAN_INFO_SCALE
  - Four output data rates (10, 50, 100, 200 Hz), selectable via
    IIO_CHAN_INFO_SAMP_FREQ
  - Four oversampling ratios (1, 2, 4, 8), selectable via
    IIO_CHAN_INFO_OVERSAMPLING_RATIO
  - Runtime PM with a 2 s autosuspend delay
  - System suspend/resume delegated to the runtime callbacks

Regmap with an rbtree cache is used throughout. CTRL_1 and CTRL_2
bit fields are accessed via regmap_field to avoid read-modify-write
races. The STATUS register is marked precious so regmap never reads
it speculatively and clears the DRDY/OVFL bits unexpectedly.

The probe-time init sequence is: soft reset, wait 300 us for POR
to complete, deassert reset, drop the register cache so subsequent
RMW writes read fresh values, then enter normal mode. 300 us
comfortably covers the 250 us POR time given in the datasheet.

Patches:
  1/5 - dt-bindings: vendor-prefixes: Add QST Corporation
  2/5 - dt-bindings: iio: magnetometer: QSTCORP QMC5883P
  3/5 - iio: magnetometer: add driver for QST QMC5883P
  4/5 - iio: magnetometer: qmc5883p: add oversampling ratio support
  5/5 - iio: magnetometer: qmc5883p: add PM support

Patches 4 and 5 are split out from the main driver so that the core
(1-3) can be reviewed and picked independently, per review feedback
on v2. 4/5 exposes the CTRL_1 OSR field via
IIO_CHAN_INFO_OVERSAMPLING_RATIO. 5/5 adds runtime PM that puts the
chip into MODE_SUSPEND when idle and wakes it to MODE_NORMAL on
demand.

Changes in v3
=============
Addressing review feedback on v2:

  - Moved the driver out of staging and into drivers/iio/magnetometer/
    (Greg Kroah-Hartman).

  - Changed the vendor prefix from "qst" to "qstcorp" to match the
    manufacturer's domain (qstcorp.com) (Krzysztof Kozlowski).

  - Subject of the binding patch no longer says "Add binding for";
    "dt-bindings:" already conveys that (Krzysztof Kozlowski).

  - Dropped the redundant last sentence of the binding commit message
    (Krzysztof Kozlowski).

  - VDD supply is now made required (Krzysztof Kozlowski).

  - Split runtime PM + system sleep handling out of the core driver
    patch into its own patch (5/5), so the core driver can be reviewed
    independently (David Lechner).

  - Split oversampling-ratio support out into its own patch (4/5)
    (David Lechner).

  - Dropped the custom downsampling_ratio sysfs attribute entirely.
    The datasheet describes OSR2 only as "another filter ... depth can
    be adjusted through OSR2", with no further characterisation, and
    no application note clarifying it. Without a precise definition
    of what the filter actually does it is not possible to map OSR2
    to any existing IIO ABI, so support for it is dropped from this
    series (David Lechner).

  - qmc5883p_verify_chip_id() -> qmc5883p_read_chip_id() no longer
    treats an ID mismatch as a probe failure; the chip-ID check is
    informational only (David Lechner).

  - qmc5883p_chip_init() no longer programs driver-chosen defaults
    for RNG/OSR/DSR/ODR. The hardware defaults are sufficient and the
    explicit writes were a development artifact (David Lechner).

  - Post-reset delay in qmc5883p_chip_init() uses fsleep() with a
    comment citing the 250 us POR time from the datasheet
    (David Lechner).

  - Timeout in regmap_read_poll_timeout() written as
    150 * (MICRO / MILLI) instead of 150000 (David Lechner).

  - Channel spec duplication collapsed behind a QMC5883P_CHAN(ch)
    macro (David Lechner).

  - qmc5883p_rf_init() moved up in probe, before the regulator and
    chip-ID reads, so the regmap fields are available by the time
    they are needed (David Lechner).

  - Trailing comma and extra whitespace in the of_device_id and
    i2c_device_id sentinel entries cleaned up (David Lechner).

  - Verified that there is no existing driver in drivers/iio/,
    drivers/hwmon/, drivers/input/, drivers/staging/iio/ or
    drivers/misc/ that matches the QMC5883P register map. Summary
    of candidates inspected is included in the "Testing" section
    below (Andy Shevchenko).

  - Waited ~10 days before sending v3 to allow time for review
    (Andy Shevchenko).

Additional v3 changes not directly from review:

  - Scale encoding changed from IIO_VAL_FRACTIONAL to
    IIO_VAL_INT_PLUS_NANO with a matching write_raw_get_fmt(),
    because the IIO core defaults sysfs writes to
    IIO_VAL_INT_PLUS_MICRO and was silently truncating nano-precision
    writes. The truncation on the 8 G and 2 G entries is documented
    in a comment above the scale table.

  - STATUS register marked precious (in addition to volatile) so
    regmap never reads it speculatively and clears DRDY/OVFL.

  - Added regcache_drop_region() after the soft-reset deassert, so
    subsequent RMW writes read fresh values rather than cached
    pre-reset values.

Changes in v2
=============
  - Use get_unaligned_le16() from <linux/unaligned.h> instead of
    manual byte-shifting for deserialising axis data (review feedback).
  - Fix pm_runtime_* calls in downsampling_ratio_store() to use
    data->dev (the i2c parent device) instead of dev (the iio
    device), avoiding PM refcount imbalances (review feedback).
  - Replace manual pm_runtime_disable() devm action with
    devm_pm_runtime_enable(), which avoids a kcfi-violating function
    pointer cast (review feedback).
  - Move chip suspend into a devm action (qmc5883p_suspend_action)
    registered before devm_iio_device_register() so that devres LIFO
    ordering guarantees the IIO interface is fully unregistered
    before the hardware is put to sleep, closing a race window on
    removal (review feedback).
  - Drop qmc5883p_remove() and the .remove hook entirely, as the
    above devm action subsumes it (review feedback).
  - Remove the empty qmc5883p_runtime_idle() stub; passing NULL in
    RUNTIME_PM_OPS already provides the correct default behaviour.
  - Add regulator support: use devm_regulator_get_enable_optional()
    for the vdd-supply documented in the dt-binding, with a 50 ms
    post-enable delay per datasheet section 5.3 (PSUP ramp + POR
    time) (review feedback).
  - Reinitialise the chip in qmc5883p_system_resume() via
    qmc5883p_chip_init() followed by regcache_mark_dirty() +
    regcache_sync(), so that the driver recovers correctly if the
    regulator was physically cut during system suspend and POR
    reset all registers (review feedback).

Links
=====
  v1: https://lore.kernel.org/all/20260409162308.2590385-1-hardik.phalet@pm.me/
  v2: https://lore.kernel.org/all/20260409210639.3197576-1-hardik.phalet@pm.me/

Testing
=======
Hardware
  A GY-271 HM-246 breakout (this board is a QMC5883P, not a QMC5883L,
  despite what some vendors put on the silkscreen), connected over
  I2C bus 1 to a Raspberry Pi 4B running a mainline aarch64 kernel.
  The chip enumerates at address 0x2C via i2cdetect, and CHIP_ID
  (register 0x00) reads back 0x80 as expected.

Prior-art register-map check (for Andy)
  I grepped drivers/iio/magnetometer/, drivers/hwmon/,
  drivers/input/misc/, drivers/staging/iio/ and drivers/misc/ for
  the distinctive offsets 0x09 (STATUS) and 0x0A (CTRL_1), narrowed
  to files containing both, and manually compared each candidate's
  register layout and control-bit encoding against the QMC5883P.

  Closest candidates:
    ak8975.c    - four register offsets coincide (0x00, 0x09, 0x0A,
                  0x0B) but the data registers sit at 0x03-0x08
                  (shifted +2 vs QMC5883P's 0x01-0x06), DRDY is in
                  ST1 at 0x02 rather than STATUS at 0x09, and CNTL
                  encodes a 4-bit mode only - no packed ODR/OSR/range
                  fields.
    hmc5843.c   - STATUS matches at 0x09, but 0x0A is a read-only ID
                  register, configuration spans 0x00-0x02 rather than
                  a single CTRL_1 byte, and data is MSB-first at 0x03
                  in X/Z/Y order.
    af8133j.c   - 0x0A and 0x0B carry mode and range, but STATUS is
                  at 0x02, data starts at 0x03, and the mode field is
                  2-valued (standby/work) rather than 4-valued.
    mmc35240.c  - data at 0x00-0x05 overlaps, but STATUS and control
                  land at 0x06-0x08.

  No overlap worth discussing: mmc5633, mag3110, tlv493d, tmag5273,
  bmc150_magn, rm3100, yamaha-yas530, st_magn, si7210, als31300. No
  magnetometer driver under drivers/hwmon/, drivers/input/misc/ or
  drivers/staging/.

  Conclusion: no existing driver can be extended to cover the
  QMC5883P without restructuring its register addressing and
  control-bit model. A new driver is warranted.

Functional testing on v3
  - Chip ID read: 0x80 (matches datasheet).
  - Raw axis reads: in_magn_{x,y,z}_raw return stable s16 values
    and track manual reorientation of the board.
  - Scale: all four ranges (+/-2/8/12/30 G) selectable via
    in_magn_scale; in_magn_scale_available lists all four; sysfs
    write-back round-trips cleanly at nano precision.
  - Sampling frequency: 10/50/100/200 Hz all selectable via
    in_magn_sampling_frequency; _available lists all four.
  - Oversampling ratio (patch 4): 1/2/4/8 selectable via
    in_magn_oversampling_ratio; _available lists all four.
  - DRDY polling: verified STATUS.DRDY asserts and clears on read,
    and that OVFL is captured in the same read as DRDY.
  - Soft reset: register state after qmc5883p_chip_init() matches
    the datasheet defaults; regcache_drop_region() confirmed by
    observing fresh values being read on the first post-reset RMW.
  - Runtime PM (patch 5): power/runtime_status transitions to
    "suspended" after the 2 s autosuspend delay (MODE_SUSPEND on
    the wire, verified by i2cdump); next sysfs read resumes the
    device and returns valid data.
  - System sleep: echo mem > /sys/power/state (s2idle on the Pi)
    followed by wake; readings are valid after resume.
  - Unbind: echo <dev> > /sys/bus/i2c/drivers/qmc5883p/unbind
    leaves the chip in MODE_SUSPEND, confirming the devm LIFO
    teardown order.
  - Build: CONFIG_QMC5883P=y and =m both clean; W=1 clean on
    aarch64; sparse clean; checkpatch --strict clean.
  - dt_binding_check: passes for patch 2/5.

Signed-off-by: Hardik Phalet <hardik.phalet@pm.me>
---
Hardik Phalet (5):
      dt-bindings: vendor-prefixes: Add QST Corporation
      dt-bindings: iio: magnetometer: QSTCORP QMC5883P
      iio: magnetometer: add driver for QST QMC5883P
      iio: magnetometer: qmc5883p: add oversampling ratio support
      iio: magnetometer: qmc5883p: add PM support

 .../iio/magnetometer/qstcorp,qmc5883p.yaml         |  48 ++
 .../devicetree/bindings/vendor-prefixes.yaml       |   2 +
 MAINTAINERS                                        |   7 +
 drivers/iio/magnetometer/Kconfig                   |  11 +
 drivers/iio/magnetometer/Makefile                  |   2 +
 drivers/iio/magnetometer/qmc5883p.c                | 673 +++++++++++++++++++++
 6 files changed, 743 insertions(+)
---
base-commit: d2a4ec19d2a2e54c23b5180e939994d3da4a6b91
change-id: 20260418-qmc5883p-driver-dcc74bd4a789

Best regards,
--  
Hardik Phalet <hardik.phalet@pm.me>


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2026-04-20 14:25 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-19 22:32 [PATCH v3 0/5] iio: magnetometer: add driver for QST QMC5883P Hardik Phalet
2026-04-19 22:32 ` [PATCH v3 1/5] dt-bindings: vendor-prefixes: Add QST Corporation Hardik Phalet
2026-04-20 14:08   ` Krzysztof Kozlowski
2026-04-19 22:32 ` [PATCH v3 2/5] dt-bindings: iio: magnetometer: QSTCORP QMC5883P Hardik Phalet
2026-04-20 13:37   ` Jonathan Cameron
2026-04-20 14:10   ` Krzysztof Kozlowski
2026-04-19 22:32 ` [PATCH v3 3/5] iio: magnetometer: add driver for QST QMC5883P Hardik Phalet
2026-04-20  9:43   ` Andy Shevchenko
2026-04-20 14:22   ` Jonathan Cameron
2026-04-19 22:32 ` [PATCH v3 4/5] iio: magnetometer: qmc5883p: add oversampling ratio support Hardik Phalet
2026-04-20  9:45   ` Andy Shevchenko
2026-04-20 14:25   ` Jonathan Cameron
2026-04-19 22:33 ` [PATCH v3 5/5] iio: magnetometer: qmc5883p: add PM support Hardik Phalet
2026-04-20  9:52   ` Andy Shevchenko
2026-04-20  9:18 ` [PATCH v3 0/5] iio: magnetometer: add driver for QST QMC5883P Andy Shevchenko
2026-04-20 13:45 ` Jonathan Cameron

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox