Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Shrikant Raskar and committed by
Jonathan Cameron
6365d2b9 e7966a49

+35 -3
+35 -3
drivers/iio/health/max30100.c
··· 5 5 * Copyright (C) 2015, 2018 6 6 * Author: Matt Ranostay <matt.ranostay@konsulko.com> 7 7 * 8 - * TODO: enable pulse length controls via device tree properties 9 8 */ 10 9 11 10 #include <linux/module.h> ··· 17 18 #include <linux/mutex.h> 18 19 #include <linux/property.h> 19 20 #include <linux/regmap.h> 21 + #include <linux/bitfield.h> 20 22 #include <linux/iio/iio.h> 21 23 #include <linux/iio/buffer.h> 22 24 #include <linux/iio/kfifo_buf.h> ··· 52 52 #define MAX30100_REG_MODE_CONFIG_PWR BIT(7) 53 53 54 54 #define MAX30100_REG_SPO2_CONFIG 0x07 55 + #define MAX30100_REG_SPO2_CONFIG_PW_MASK GENMASK(1, 0) 56 + #define MAX30100_REG_SPO2_CONFIG_200US 0x0 57 + #define MAX30100_REG_SPO2_CONFIG_400US 0x1 58 + #define MAX30100_REG_SPO2_CONFIG_800US 0x2 59 + #define MAX30100_REG_SPO2_CONFIG_1600US 0x3 55 60 #define MAX30100_REG_SPO2_CONFIG_100HZ BIT(2) 56 61 #define MAX30100_REG_SPO2_CONFIG_HI_RES_EN BIT(6) 57 - #define MAX30100_REG_SPO2_CONFIG_1600US 0x3 58 62 59 63 #define MAX30100_REG_LED_CONFIG 0x09 60 64 #define MAX30100_REG_LED_CONFIG_LED_MASK 0x0f ··· 310 306 MAX30100_REG_LED_CONFIG_LED_MASK, reg); 311 307 } 312 308 309 + static int max30100_get_pulse_width(unsigned int pwidth_us) 310 + { 311 + switch (pwidth_us) { 312 + case 200: 313 + return MAX30100_REG_SPO2_CONFIG_200US; 314 + case 400: 315 + return MAX30100_REG_SPO2_CONFIG_400US; 316 + case 800: 317 + return MAX30100_REG_SPO2_CONFIG_800US; 318 + case 1600: 319 + return MAX30100_REG_SPO2_CONFIG_1600US; 320 + default: 321 + return -EINVAL; 322 + } 323 + } 324 + 313 325 static int max30100_chip_init(struct max30100_data *data) 314 326 { 315 327 int ret; 328 + int pulse_width; 329 + /* set default LED pulse-width to 1600 us */ 330 + unsigned int pulse_us = 1600; 331 + struct device *dev = &data->client->dev; 316 332 317 333 /* setup LED current settings */ 318 334 ret = max30100_led_init(data); 319 335 if (ret) 320 336 return ret; 321 337 338 + /* Read LED pulse-width-us from DT */ 339 + device_property_read_u32(dev, "maxim,pulse-width-us", &pulse_us); 340 + 341 + pulse_width = max30100_get_pulse_width(pulse_us); 342 + if (pulse_width < 0) 343 + return dev_err_probe(dev, pulse_width, "invalid LED pulse-width %uus\n", pulse_us); 344 + 322 345 /* enable hi-res SPO2 readings at 100Hz */ 323 346 ret = regmap_write(data->regmap, MAX30100_REG_SPO2_CONFIG, 324 347 MAX30100_REG_SPO2_CONFIG_HI_RES_EN | 325 - MAX30100_REG_SPO2_CONFIG_100HZ); 348 + MAX30100_REG_SPO2_CONFIG_100HZ | 349 + FIELD_PREP(MAX30100_REG_SPO2_CONFIG_PW_MASK, pulse_width)); 326 350 if (ret) 327 351 return ret; 328 352