FILE
max30100.c
File preview with syntax highlighting.
linux-6.19.14/drivers/iio/health/max30100.c
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * max30100.c - Support for MAX30100 heart rate and pulse oximeter sensor 4 * 5 * Copyright (C) 2015, 2018 6 * Author: Matt Ranostay <matt.ranostay@konsulko.com> 7 * 8 */ 9 10#include <linux/module.h> 11#include <linux/init.h> 12#include <linux/interrupt.h> 13#include <linux/delay.h> 14#include <linux/err.h> 15#include <linux/irq.h> 16#include <linux/i2c.h> 17#include <linux/mutex.h> 18#include <linux/property.h> 19#include <linux/regmap.h> 20#include <linux/bitfield.h> 21#include <linux/iio/iio.h> 22#include <linux/iio/buffer.h> 23#include <linux/iio/kfifo_buf.h> 24 25#define MAX30100_DRV_NAME "max30100" 26 27#define MAX30100_REG_INT_STATUS 0x00 28#define MAX30100_REG_INT_STATUS_PWR_RDY BIT(0) 29#define MAX30100_REG_INT_STATUS_SPO2_RDY BIT(4) 30#define MAX30100_REG_INT_STATUS_HR_RDY BIT(5) 31#define MAX30100_REG_INT_STATUS_FIFO_RDY BIT(7) 32 33#define MAX30100_REG_INT_ENABLE 0x01 34#define MAX30100_REG_INT_ENABLE_SPO2_EN BIT(0) 35#define MAX30100_REG_INT_ENABLE_HR_EN BIT(1) 36#define MAX30100_REG_INT_ENABLE_FIFO_EN BIT(3) 37#define MAX30100_REG_INT_ENABLE_MASK 0xf0 38#define MAX30100_REG_INT_ENABLE_MASK_SHIFT 4 39 40#define MAX30100_REG_FIFO_WR_PTR 0x02 41#define MAX30100_REG_FIFO_OVR_CTR 0x03 42#define MAX30100_REG_FIFO_RD_PTR 0x04 43#define MAX30100_REG_FIFO_DATA 0x05 44#define MAX30100_REG_FIFO_DATA_ENTRY_COUNT 16 45#define MAX30100_REG_FIFO_DATA_ENTRY_LEN 4 46 47#define MAX30100_REG_MODE_CONFIG 0x06 48#define MAX30100_REG_MODE_CONFIG_MODE_SPO2_EN BIT(0) 49#define MAX30100_REG_MODE_CONFIG_MODE_HR_EN BIT(1) 50#define MAX30100_REG_MODE_CONFIG_MODE_MASK 0x03 51#define MAX30100_REG_MODE_CONFIG_TEMP_EN BIT(3) 52#define MAX30100_REG_MODE_CONFIG_PWR BIT(7) 53 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 60#define MAX30100_REG_SPO2_CONFIG_100HZ BIT(2) 61#define MAX30100_REG_SPO2_CONFIG_HI_RES_EN BIT(6) 62 63#define MAX30100_REG_LED_CONFIG 0x09 64#define MAX30100_REG_LED_CONFIG_LED_MASK 0x0f 65#define MAX30100_REG_LED_CONFIG_RED_LED_SHIFT 4 66 67#define MAX30100_REG_LED_CONFIG_24MA 0x07 68#define MAX30100_REG_LED_CONFIG_50MA 0x0f 69 70#define MAX30100_REG_TEMP_INTEGER 0x16 71#define MAX30100_REG_TEMP_FRACTION 0x17 72 73struct max30100_data { 74 struct i2c_client *client; 75 struct iio_dev *indio_dev; 76 struct mutex lock; 77 struct regmap *regmap; 78 79 __be16 buffer[2]; /* 2 16-bit channels */ 80}; 81 82static bool max30100_is_volatile_reg(struct device *dev, unsigned int reg) 83{ 84 switch (reg) { 85 case MAX30100_REG_INT_STATUS: 86 case MAX30100_REG_MODE_CONFIG: 87 case MAX30100_REG_FIFO_WR_PTR: 88 case MAX30100_REG_FIFO_OVR_CTR: 89 case MAX30100_REG_FIFO_RD_PTR: 90 case MAX30100_REG_FIFO_DATA: 91 case MAX30100_REG_TEMP_INTEGER: 92 case MAX30100_REG_TEMP_FRACTION: 93 return true; 94 default: 95 return false; 96 } 97} 98 99static const struct regmap_config max30100_regmap_config = { 100 .name = "max30100_regmap", 101 102 .reg_bits = 8, 103 .val_bits = 8, 104 105 .max_register = MAX30100_REG_TEMP_FRACTION, 106 .cache_type = REGCACHE_FLAT, 107 108 .volatile_reg = max30100_is_volatile_reg, 109}; 110 111static const unsigned int max30100_led_current_mapping[] = { 112 4400, 7600, 11000, 14200, 17400, 113 20800, 24000, 27100, 30600, 33800, 114 37000, 40200, 43600, 46800, 50000 115}; 116 117static const unsigned long max30100_scan_masks[] = {0x3, 0}; 118 119static const struct iio_chan_spec max30100_channels[] = { 120 { 121 .type = IIO_INTENSITY, 122 .channel2 = IIO_MOD_LIGHT_IR, 123 .modified = 1, 124 125 .scan_index = 0, 126 .scan_type = { 127 .sign = 'u', 128 .realbits = 16, 129 .storagebits = 16, 130 .endianness = IIO_BE, 131 }, 132 }, 133 { 134 .type = IIO_INTENSITY, 135 .channel2 = IIO_MOD_LIGHT_RED, 136 .modified = 1, 137 138 .scan_index = 1, 139 .scan_type = { 140 .sign = 'u', 141 .realbits = 16, 142 .storagebits = 16, 143 .endianness = IIO_BE, 144 }, 145 }, 146 { 147 .type = IIO_TEMP, 148 .info_mask_separate = 149 BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), 150 .scan_index = -1, 151 }, 152}; 153 154static int max30100_set_powermode(struct max30100_data *data, bool state) 155{ 156 return regmap_update_bits(data->regmap, MAX30100_REG_MODE_CONFIG, 157 MAX30100_REG_MODE_CONFIG_PWR, 158 state ? 0 : MAX30100_REG_MODE_CONFIG_PWR); 159} 160 161static int max30100_clear_fifo(struct max30100_data *data) 162{ 163 int ret; 164 165 ret = regmap_write(data->regmap, MAX30100_REG_FIFO_WR_PTR, 0); 166 if (ret) 167 return ret; 168 169 ret = regmap_write(data->regmap, MAX30100_REG_FIFO_OVR_CTR, 0); 170 if (ret) 171 return ret; 172 173 return regmap_write(data->regmap, MAX30100_REG_FIFO_RD_PTR, 0); 174} 175 176static int max30100_buffer_postenable(struct iio_dev *indio_dev) 177{ 178 struct max30100_data *data = iio_priv(indio_dev); 179 int ret; 180 181 ret = max30100_set_powermode(data, true); 182 if (ret) 183 return ret; 184 185 return max30100_clear_fifo(data); 186} 187 188static int max30100_buffer_predisable(struct iio_dev *indio_dev) 189{ 190 struct max30100_data *data = iio_priv(indio_dev); 191 192 return max30100_set_powermode(data, false); 193} 194 195static const struct iio_buffer_setup_ops max30100_buffer_setup_ops = { 196 .postenable = max30100_buffer_postenable, 197 .predisable = max30100_buffer_predisable, 198}; 199 200static inline int max30100_fifo_count(struct max30100_data *data) 201{ 202 unsigned int val; 203 int ret; 204 205 ret = regmap_read(data->regmap, MAX30100_REG_INT_STATUS, &val); 206 if (ret) 207 return ret; 208 209 /* FIFO is almost full */ 210 if (val & MAX30100_REG_INT_STATUS_FIFO_RDY) 211 return MAX30100_REG_FIFO_DATA_ENTRY_COUNT - 1; 212 213 return 0; 214} 215 216static int max30100_read_measurement(struct max30100_data *data) 217{ 218 int ret; 219 220 ret = i2c_smbus_read_i2c_block_data(data->client, 221 MAX30100_REG_FIFO_DATA, 222 MAX30100_REG_FIFO_DATA_ENTRY_LEN, 223 (u8 *) &data->buffer); 224 225 return (ret == MAX30100_REG_FIFO_DATA_ENTRY_LEN) ? 0 : ret; 226} 227 228static irqreturn_t max30100_interrupt_handler(int irq, void *private) 229{ 230 struct iio_dev *indio_dev = private; 231 struct max30100_data *data = iio_priv(indio_dev); 232 int ret, cnt = 0; 233 234 mutex_lock(&data->lock); 235 236 while (cnt || (cnt = max30100_fifo_count(data)) > 0) { 237 ret = max30100_read_measurement(data); 238 if (ret) 239 break; 240 241 iio_push_to_buffers(data->indio_dev, data->buffer); 242 cnt--; 243 } 244 245 mutex_unlock(&data->lock); 246 247 return IRQ_HANDLED; 248} 249 250static int max30100_get_current_idx(unsigned int val, int *reg) 251{ 252 int idx; 253 254 /* LED turned off */ 255 if (val == 0) { 256 *reg = 0; 257 return 0; 258 } 259 260 for (idx = 0; idx < ARRAY_SIZE(max30100_led_current_mapping); idx++) { 261 if (max30100_led_current_mapping[idx] == val) { 262 *reg = idx + 1; 263 return 0; 264 } 265 } 266 267 return -EINVAL; 268} 269 270static int max30100_led_init(struct max30100_data *data) 271{ 272 struct device *dev = &data->client->dev; 273 unsigned int val[2]; 274 int reg, ret; 275 276 ret = device_property_read_u32_array(dev, "maxim,led-current-microamp", 277 (unsigned int *) &val, 2); 278 if (ret) { 279 /* Default to 24 mA RED LED, 50 mA IR LED */ 280 reg = (MAX30100_REG_LED_CONFIG_24MA << 281 MAX30100_REG_LED_CONFIG_RED_LED_SHIFT) | 282 MAX30100_REG_LED_CONFIG_50MA; 283 dev_warn(dev, "no led-current-microamp set"); 284 285 return regmap_write(data->regmap, MAX30100_REG_LED_CONFIG, reg); 286 } 287 288 /* RED LED current */ 289 ret = max30100_get_current_idx(val[0], ®); 290 if (ret) { 291 dev_err(dev, "invalid RED current setting %d", val[0]); 292 return ret; 293 } 294 295 ret = regmap_update_bits(data->regmap, MAX30100_REG_LED_CONFIG, 296 MAX30100_REG_LED_CONFIG_LED_MASK << 297 MAX30100_REG_LED_CONFIG_RED_LED_SHIFT, 298 reg << MAX30100_REG_LED_CONFIG_RED_LED_SHIFT); 299 if (ret) 300 return ret; 301 302 /* IR LED current */ 303 ret = max30100_get_current_idx(val[1], ®); 304 if (ret) { 305 dev_err(dev, "invalid IR current setting %d", val[1]); 306 return ret; 307 } 308 309 return regmap_update_bits(data->regmap, MAX30100_REG_LED_CONFIG, 310 MAX30100_REG_LED_CONFIG_LED_MASK, reg); 311} 312 313static int max30100_get_pulse_width(unsigned int pwidth_us) 314{ 315 switch (pwidth_us) { 316 case 200: 317 return MAX30100_REG_SPO2_CONFIG_200US; 318 case 400: 319 return MAX30100_REG_SPO2_CONFIG_400US; 320 case 800: 321 return MAX30100_REG_SPO2_CONFIG_800US; 322 case 1600: 323 return MAX30100_REG_SPO2_CONFIG_1600US; 324 default: 325 return -EINVAL; 326 } 327} 328 329static int max30100_chip_init(struct max30100_data *data) 330{ 331 int ret; 332 int pulse_width; 333 /* set default LED pulse-width to 1600 us */ 334 unsigned int pulse_us = 1600; 335 struct device *dev = &data->client->dev; 336 337 /* setup LED current settings */ 338 ret = max30100_led_init(data); 339 if (ret) 340 return ret; 341 342 /* Read LED pulse-width-us from DT */ 343 device_property_read_u32(dev, "maxim,pulse-width-us", &pulse_us); 344 345 pulse_width = max30100_get_pulse_width(pulse_us); 346 if (pulse_width < 0) 347 return dev_err_probe(dev, pulse_width, "invalid LED pulse-width %uus\n", pulse_us); 348 349 /* enable hi-res SPO2 readings at 100Hz */ 350 ret = regmap_write(data->regmap, MAX30100_REG_SPO2_CONFIG, 351 MAX30100_REG_SPO2_CONFIG_HI_RES_EN | 352 MAX30100_REG_SPO2_CONFIG_100HZ | 353 FIELD_PREP(MAX30100_REG_SPO2_CONFIG_PW_MASK, pulse_width)); 354 if (ret) 355 return ret; 356 357 /* enable SPO2 mode */ 358 ret = regmap_update_bits(data->regmap, MAX30100_REG_MODE_CONFIG, 359 MAX30100_REG_MODE_CONFIG_MODE_MASK, 360 MAX30100_REG_MODE_CONFIG_MODE_HR_EN | 361 MAX30100_REG_MODE_CONFIG_MODE_SPO2_EN); 362 if (ret) 363 return ret; 364 365 /* enable FIFO interrupt */ 366 return regmap_update_bits(data->regmap, MAX30100_REG_INT_ENABLE, 367 MAX30100_REG_INT_ENABLE_MASK, 368 MAX30100_REG_INT_ENABLE_FIFO_EN 369 << MAX30100_REG_INT_ENABLE_MASK_SHIFT); 370} 371 372static int max30100_read_temp(struct max30100_data *data, int *val) 373{ 374 int ret; 375 unsigned int reg; 376 377 ret = regmap_read(data->regmap, MAX30100_REG_TEMP_INTEGER, ®); 378 if (ret < 0) 379 return ret; 380 *val = reg << 4; 381 382 ret = regmap_read(data->regmap, MAX30100_REG_TEMP_FRACTION, ®); 383 if (ret < 0) 384 return ret; 385 386 *val |= reg & 0xf; 387 *val = sign_extend32(*val, 11); 388 389 return 0; 390} 391 392static int max30100_get_temp(struct max30100_data *data, int *val) 393{ 394 int ret; 395 396 /* start acquisition */ 397 ret = regmap_set_bits(data->regmap, MAX30100_REG_MODE_CONFIG, 398 MAX30100_REG_MODE_CONFIG_TEMP_EN); 399 if (ret) 400 return ret; 401 402 msleep(35); 403 404 return max30100_read_temp(data, val); 405} 406 407static int max30100_read_raw(struct iio_dev *indio_dev, 408 struct iio_chan_spec const *chan, 409 int *val, int *val2, long mask) 410{ 411 struct max30100_data *data = iio_priv(indio_dev); 412 int ret = -EINVAL; 413 414 switch (mask) { 415 case IIO_CHAN_INFO_RAW: 416 /* 417 * Temperature reading can only be acquired while engine 418 * is running 419 */ 420 if (iio_device_claim_buffer_mode(indio_dev)) { 421 /* 422 * Replacing -EBUSY or other error code 423 * returned by iio_device_claim_buffer_mode() 424 * because user space may rely on the current 425 * one. 426 */ 427 ret = -EAGAIN; 428 } else { 429 ret = max30100_get_temp(data, val); 430 if (!ret) 431 ret = IIO_VAL_INT; 432 433 iio_device_release_buffer_mode(indio_dev); 434 } 435 break; 436 case IIO_CHAN_INFO_SCALE: 437 *val = 1; /* 0.0625 */ 438 *val2 = 16; 439 ret = IIO_VAL_FRACTIONAL; 440 break; 441 } 442 443 return ret; 444} 445 446static const struct iio_info max30100_info = { 447 .read_raw = max30100_read_raw, 448}; 449 450static int max30100_probe(struct i2c_client *client) 451{ 452 struct max30100_data *data; 453 struct iio_dev *indio_dev; 454 int ret; 455 456 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 457 if (!indio_dev) 458 return -ENOMEM; 459 460 indio_dev->name = MAX30100_DRV_NAME; 461 indio_dev->channels = max30100_channels; 462 indio_dev->info = &max30100_info; 463 indio_dev->num_channels = ARRAY_SIZE(max30100_channels); 464 indio_dev->available_scan_masks = max30100_scan_masks; 465 indio_dev->modes = INDIO_DIRECT_MODE; 466 467 ret = devm_iio_kfifo_buffer_setup(&client->dev, indio_dev, 468 &max30100_buffer_setup_ops); 469 if (ret) 470 return ret; 471 472 data = iio_priv(indio_dev); 473 data->indio_dev = indio_dev; 474 data->client = client; 475 476 mutex_init(&data->lock); 477 i2c_set_clientdata(client, indio_dev); 478 479 data->regmap = devm_regmap_init_i2c(client, &max30100_regmap_config); 480 if (IS_ERR(data->regmap)) { 481 dev_err(&client->dev, "regmap initialization failed.\n"); 482 return PTR_ERR(data->regmap); 483 } 484 max30100_set_powermode(data, false); 485 486 ret = max30100_chip_init(data); 487 if (ret) 488 return ret; 489 490 if (client->irq <= 0) { 491 dev_err(&client->dev, "no valid irq defined\n"); 492 return -EINVAL; 493 } 494 ret = devm_request_threaded_irq(&client->dev, client->irq, 495 NULL, max30100_interrupt_handler, 496 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 497 "max30100_irq", indio_dev); 498 if (ret) { 499 dev_err(&client->dev, "request irq (%d) failed\n", client->irq); 500 return ret; 501 } 502 503 return iio_device_register(indio_dev); 504} 505 506static void max30100_remove(struct i2c_client *client) 507{ 508 struct iio_dev *indio_dev = i2c_get_clientdata(client); 509 struct max30100_data *data = iio_priv(indio_dev); 510 511 iio_device_unregister(indio_dev); 512 max30100_set_powermode(data, false); 513} 514 515static const struct i2c_device_id max30100_id[] = { 516 { "max30100" }, 517 { } 518}; 519MODULE_DEVICE_TABLE(i2c, max30100_id); 520 521static const struct of_device_id max30100_dt_ids[] = { 522 { .compatible = "maxim,max30100" }, 523 { } 524}; 525MODULE_DEVICE_TABLE(of, max30100_dt_ids); 526 527static struct i2c_driver max30100_driver = { 528 .driver = { 529 .name = MAX30100_DRV_NAME, 530 .of_match_table = max30100_dt_ids, 531 }, 532 .probe = max30100_probe, 533 .remove = max30100_remove, 534 .id_table = max30100_id, 535}; 536module_i2c_driver(max30100_driver); 537 538MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>"); 539MODULE_DESCRIPTION("MAX30100 heart rate and pulse oximeter sensor"); 540MODULE_LICENSE("GPL");
~/
Read-only file preview.