[PATCH v11 0/2] iio: health: add MAX86150 ECG and PPG biosensor driver

From: Md Shofiqul Islam

Date: Sun Sep 13 2026 - 06:48:51 EST


Add IIO support for the Analog Devices MAX86150 combined ECG and PPG
biosensor: a devicetree binding and a driver that registers a kfifo
buffer directly off the device's hardware FIFO (matching max30102.c
in this directory), draining it from a threaded IRQ handler.

Tested against i2c-stub with the expected PART_ID and FIFO bytes
pre-seeded, covering probe (both a matching and a mismatched part
ID), the chip_init() register programming, raw-channel decode of a
simulated FIFO burst, and buffer enable/disable. Not yet tested
against real MAX86150 hardware.

A kernel test robot build error reported against an intermediate,
unsent tree state (incompatible .validate_trigger pointer type on
iio_trigger_validate_own_device()) does not apply here: the trigger
framework that error was in is gone in this version, replaced by the
kfifo buffer described below.

Full history of this series (v1-v10): https://lore.kernel.org/linux-iio/?q=MAX86150

Changes since v10 (2026-07-17):
- Redesigned onto a kfifo buffer instead of the hardware-trigger +
triggered-buffer framework, matching max30102.c in this directory
(Jonathan Cameron -- this was the big one: a trigger + triggered
buffer doesn't fit a device that just has one hardware FIFO and no
concept of a triggered "scan").
- get_unaligned_be24() for the three 24-bit FIFO fields instead of
manual shift/or (Andy Shevchenko).
- regmap cache added (volatile_reg() + REGCACHE_RBTREE); FIFO_DATA,
FIFO_WR_PTR, FIFO_RD_PTR, OVF_COUNTER and INT_STATUS1/2 stay
volatile (Andy Shevchenko).
- devm_regulator_bulk_get_enable() for the four supplies instead of
four separate calls (Jonathan Cameron).
- sample_period_ns expressed as NSEC_PER_SEC / 100 instead of a bare
10000000 (Jonathan Cameron).
- Added a comment explaining why a part-ID mismatch is fatal here
instead of a warn-and-continue (Jonathan Cameron).
- _nA / _Hz suffixes on the ADC-range and sample-rate defines; moved
the LED pulse amplitude comment next to the define it documents;
dropped two comments that just repeated what the diff/code already
showed (Andy Shevchenko).
- FIELD_PREP_CONST() in place of FIELD_PREP() everywhere the operands
are compile-time constants (Andy Shevchenko).
- USEC_PER_MSEC-based constants in the PPG_RDY poll timeout instead of
raw 1000/25000 (Andy Shevchenko).
- max86150_do_read_raw() split into two functions (the shutdown-wrap
outer function and a max86150_read_raw_locked() inner one) instead
of a label + goto (Andy Shevchenko).
- All three switch cases in read_raw() now `return IIO_VAL_INT;`
directly instead of `break;` + one shared return (Andy Shevchenko).
- C99 initialiser for the i2c_device_id table entry (Andy Shevchenko).
- devm_regmap_init_i2c() now runs before the regulators are enabled,
so the pure-software setup happens before any HW interaction (Andy
Shevchenko).
- Kconfig now selects IIO_KFIFO_BUF instead of the now-unused
IIO_TRIGGERED_BUFFER, matching the buffer redesign above.
- Shortened this commit message -- the implementation-detail bullet
list duplicated what's now in this cover letter and in the code
comments themselves (Andy Shevchenko).

Changes since v9 (2026-07-07):
- Rewrote the buffer implementation around devm_iio_trigger_alloc() +
devm_iio_triggered_buffer_setup() instead of the kfifo buffer and
manual postenable/predisable pair. The hard-irq handler only read
and cleared INT_STATUS1 before calling iio_trigger_poll(); the
threaded trigger handler did the FIFO drain. This relied on the
trigger core's own attach/detach synchronization instead of an
explicit iio_buffer_enabled() guard or synchronize_irq(), which the
old design needed to avoid a NULL active_scan_mask race on teardown
(Sashiko, both HIGH severity findings).
[NOTE: v11 above reverts this back onto a kfifo buffer per Jonathan
Cameron's v10 review -- a triggered buffer was the wrong tool here.]

Earlier versions (v1-v8) are in the full history link above. The
notable structural changes along the way:
- v1->v2: split the original single combined patch into three (dt-
bindings, driver, MAINTAINERS entry).
- v4->v5: renamed the devicetree compatible string from
"maxim,max86150" to "adi,max86150", matching the vendor prefix
Analog Devices actually uses upstream (Maxim was acquired by ADI).
- v8->v9: folded the standalone MAINTAINERS patch back into the
driver patch, dropping the series from three patches to two.

Md Shofiqul Islam (2):
dt-bindings: iio: health: add adi,max86150
iio: health: add MAX86150 ECG and PPG biosensor driver

.../bindings/iio/health/adi,max86150.yaml | 77 ++
MAINTAINERS | 7 +
drivers/iio/health/Kconfig | 13 +
drivers/iio/health/Makefile | 1 +
drivers/iio/health/max86150.c | 658 ++++++++++++++++++
5 files changed, 756 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iio/health/adi,max86150.yaml
create mode 100644 drivers/iio/health/max86150.c

--
2.55.0