iio: health: max30100: Make LED pulse-width configurable via DT

The required LED pulse width depends on board-specific optical and
mechanical design, which affects measurement accuracy and power use.
Making it configurable via Device Tree allows each platform to define
an appropriate value instead of relying on a hardcoded default.

If unspecified, the driver defaults to 1600 us for backward compatibility.

Tested on: Raspberry Pi 3B + MAX30100 breakout board.

Reviewed-by: Nuno Sa <nuno.sa@analog.com>
Signed-off-by: Shrikant Raskar <raskar.shree97@gmail.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
pull/1354/merge
Shrikant Raskar 2025-10-12 23:00:35 +05:30 committed by Jonathan Cameron
parent e7966a4953
commit 6365d2b988
1 changed files with 35 additions and 3 deletions

View File

@ -5,7 +5,6 @@
* Copyright (C) 2015, 2018
* Author: Matt Ranostay <matt.ranostay@konsulko.com>
*
* TODO: enable pulse length controls via device tree properties
*/
#include <linux/module.h>
@ -18,6 +17,7 @@
#include <linux/mutex.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/bitfield.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/kfifo_buf.h>
@ -52,9 +52,13 @@
#define MAX30100_REG_MODE_CONFIG_PWR BIT(7)
#define MAX30100_REG_SPO2_CONFIG 0x07
#define MAX30100_REG_SPO2_CONFIG_PW_MASK GENMASK(1, 0)
#define MAX30100_REG_SPO2_CONFIG_200US 0x0
#define MAX30100_REG_SPO2_CONFIG_400US 0x1
#define MAX30100_REG_SPO2_CONFIG_800US 0x2
#define MAX30100_REG_SPO2_CONFIG_1600US 0x3
#define MAX30100_REG_SPO2_CONFIG_100HZ BIT(2)
#define MAX30100_REG_SPO2_CONFIG_HI_RES_EN BIT(6)
#define MAX30100_REG_SPO2_CONFIG_1600US 0x3
#define MAX30100_REG_LED_CONFIG 0x09
#define MAX30100_REG_LED_CONFIG_LED_MASK 0x0f
@ -306,19 +310,47 @@ static int max30100_led_init(struct max30100_data *data)
MAX30100_REG_LED_CONFIG_LED_MASK, reg);
}
static int max30100_get_pulse_width(unsigned int pwidth_us)
{
switch (pwidth_us) {
case 200:
return MAX30100_REG_SPO2_CONFIG_200US;
case 400:
return MAX30100_REG_SPO2_CONFIG_400US;
case 800:
return MAX30100_REG_SPO2_CONFIG_800US;
case 1600:
return MAX30100_REG_SPO2_CONFIG_1600US;
default:
return -EINVAL;
}
}
static int max30100_chip_init(struct max30100_data *data)
{
int ret;
int pulse_width;
/* set default LED pulse-width to 1600 us */
unsigned int pulse_us = 1600;
struct device *dev = &data->client->dev;
/* setup LED current settings */
ret = max30100_led_init(data);
if (ret)
return ret;
/* Read LED pulse-width-us from DT */
device_property_read_u32(dev, "maxim,pulse-width-us", &pulse_us);
pulse_width = max30100_get_pulse_width(pulse_us);
if (pulse_width < 0)
return dev_err_probe(dev, pulse_width, "invalid LED pulse-width %uus\n", pulse_us);
/* enable hi-res SPO2 readings at 100Hz */
ret = regmap_write(data->regmap, MAX30100_REG_SPO2_CONFIG,
MAX30100_REG_SPO2_CONFIG_HI_RES_EN |
MAX30100_REG_SPO2_CONFIG_100HZ);
MAX30100_REG_SPO2_CONFIG_100HZ |
FIELD_PREP(MAX30100_REG_SPO2_CONFIG_PW_MASK, pulse_width));
if (ret)
return ret;