brintos

brintos / linux-shallow public Read only

0
0
Text · 16.1 KiB · 1d074eb Raw
644 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * max30102.c - Support for MAX30102 heart rate and pulse oximeter sensor4 *5 * Copyright (C) 2017 Matt Ranostay <matt.ranostay@konsulko.com>6 *7 * Support for MAX30105 optical particle sensor8 * Copyright (C) 2017 Peter Meerwald-Stadler <pmeerw@pmeerw.net>9 *10 * 7-bit I2C chip address: 0x5711 * TODO: proximity power saving feature12 */13 14#include <linux/module.h>15#include <linux/init.h>16#include <linux/interrupt.h>17#include <linux/delay.h>18#include <linux/err.h>19#include <linux/irq.h>20#include <linux/i2c.h>21#include <linux/mutex.h>22#include <linux/mod_devicetable.h>23#include <linux/regmap.h>24#include <linux/iio/iio.h>25#include <linux/iio/buffer.h>26#include <linux/iio/kfifo_buf.h>27 28#define MAX30102_REGMAP_NAME	"max30102_regmap"29#define MAX30102_DRV_NAME	"max30102"30#define MAX30102_PART_NUMBER	0x1531 32enum max30102_chip_id {33	max30102,34	max30105,35};36 37enum max3012_led_idx {38	MAX30102_LED_RED,39	MAX30102_LED_IR,40	MAX30105_LED_GREEN,41};42 43#define MAX30102_REG_INT_STATUS			0x0044#define MAX30102_REG_INT_STATUS_PWR_RDY		BIT(0)45#define MAX30102_REG_INT_STATUS_PROX_INT	BIT(4)46#define MAX30102_REG_INT_STATUS_ALC_OVF		BIT(5)47#define MAX30102_REG_INT_STATUS_PPG_RDY		BIT(6)48#define MAX30102_REG_INT_STATUS_FIFO_RDY	BIT(7)49 50#define MAX30102_REG_INT_ENABLE			0x0251#define MAX30102_REG_INT_ENABLE_PROX_INT_EN	BIT(4)52#define MAX30102_REG_INT_ENABLE_ALC_OVF_EN	BIT(5)53#define MAX30102_REG_INT_ENABLE_PPG_EN		BIT(6)54#define MAX30102_REG_INT_ENABLE_FIFO_EN		BIT(7)55#define MAX30102_REG_INT_ENABLE_MASK		0xf056#define MAX30102_REG_INT_ENABLE_MASK_SHIFT	457 58#define MAX30102_REG_FIFO_WR_PTR		0x0459#define MAX30102_REG_FIFO_OVR_CTR		0x0560#define MAX30102_REG_FIFO_RD_PTR		0x0661#define MAX30102_REG_FIFO_DATA			0x0762#define MAX30102_REG_FIFO_DATA_BYTES		363 64#define MAX30102_REG_FIFO_CONFIG		0x0865#define MAX30102_REG_FIFO_CONFIG_AVG_4SAMPLES	BIT(1)66#define MAX30102_REG_FIFO_CONFIG_AVG_SHIFT	567#define MAX30102_REG_FIFO_CONFIG_AFULL		BIT(0)68 69#define MAX30102_REG_MODE_CONFIG		0x0970#define MAX30102_REG_MODE_CONFIG_MODE_NONE	0x0071#define MAX30102_REG_MODE_CONFIG_MODE_HR	0x02 /* red LED */72#define MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2	0x03 /* red + IR LED */73#define MAX30102_REG_MODE_CONFIG_MODE_MULTI	0x07 /* multi-LED mode */74#define MAX30102_REG_MODE_CONFIG_MODE_MASK	GENMASK(2, 0)75#define MAX30102_REG_MODE_CONFIG_PWR		BIT(7)76 77#define MAX30102_REG_MODE_CONTROL_SLOT21	0x11 /* multi-LED control */78#define MAX30102_REG_MODE_CONTROL_SLOT43	0x1279#define MAX30102_REG_MODE_CONTROL_SLOT_MASK	(GENMASK(6, 4) | GENMASK(2, 0))80#define MAX30102_REG_MODE_CONTROL_SLOT_SHIFT	481 82#define MAX30102_REG_SPO2_CONFIG		0x0a83#define MAX30102_REG_SPO2_CONFIG_PULSE_411_US	0x0384#define MAX30102_REG_SPO2_CONFIG_SR_400HZ	0x0385#define MAX30102_REG_SPO2_CONFIG_SR_MASK	0x0786#define MAX30102_REG_SPO2_CONFIG_SR_MASK_SHIFT	287#define MAX30102_REG_SPO2_CONFIG_ADC_4096_STEPS	BIT(0)88#define MAX30102_REG_SPO2_CONFIG_ADC_MASK_SHIFT	589 90#define MAX30102_REG_RED_LED_CONFIG		0x0c91#define MAX30102_REG_IR_LED_CONFIG		0x0d92#define MAX30105_REG_GREEN_LED_CONFIG		0x0e93 94#define MAX30102_REG_TEMP_CONFIG		0x2195#define MAX30102_REG_TEMP_CONFIG_TEMP_EN	BIT(0)96 97#define MAX30102_REG_TEMP_INTEGER		0x1f98#define MAX30102_REG_TEMP_FRACTION		0x2099 100#define MAX30102_REG_REV_ID			0xfe101#define MAX30102_REG_PART_ID			0xff102 103struct max30102_data {104	struct i2c_client *client;105	struct iio_dev *indio_dev;106	struct mutex lock;107	struct regmap *regmap;108	enum max30102_chip_id chip_id;109 110	u8 buffer[12];111	__be32 processed_buffer[3]; /* 3 x 18-bit (padded to 32-bits) */112};113 114static const struct regmap_config max30102_regmap_config = {115	.name = MAX30102_REGMAP_NAME,116 117	.reg_bits = 8,118	.val_bits = 8,119};120 121static const unsigned long max30102_scan_masks[] = {122	BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR),123	0124};125 126static const unsigned long max30105_scan_masks[] = {127	BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR),128	BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR) |129		BIT(MAX30105_LED_GREEN),130	0131};132 133#define MAX30102_INTENSITY_CHANNEL(_si, _mod) { \134		.type = IIO_INTENSITY, \135		.channel2 = _mod, \136		.modified = 1, \137		.scan_index = _si, \138		.scan_type = { \139			.sign = 'u', \140			.shift = 8, \141			.realbits = 18, \142			.storagebits = 32, \143			.endianness = IIO_BE, \144		}, \145	}146 147static const struct iio_chan_spec max30102_channels[] = {148	MAX30102_INTENSITY_CHANNEL(MAX30102_LED_RED, IIO_MOD_LIGHT_RED),149	MAX30102_INTENSITY_CHANNEL(MAX30102_LED_IR, IIO_MOD_LIGHT_IR),150	{151		.type = IIO_TEMP,152		.info_mask_separate =153			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),154		.scan_index = -1,155	},156};157 158static const struct iio_chan_spec max30105_channels[] = {159	MAX30102_INTENSITY_CHANNEL(MAX30102_LED_RED, IIO_MOD_LIGHT_RED),160	MAX30102_INTENSITY_CHANNEL(MAX30102_LED_IR, IIO_MOD_LIGHT_IR),161	MAX30102_INTENSITY_CHANNEL(MAX30105_LED_GREEN, IIO_MOD_LIGHT_GREEN),162	{163		.type = IIO_TEMP,164		.info_mask_separate =165			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),166		.scan_index = -1,167	},168};169 170static int max30102_set_power(struct max30102_data *data, bool en)171{172	return regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,173				  MAX30102_REG_MODE_CONFIG_PWR,174				  en ? 0 : MAX30102_REG_MODE_CONFIG_PWR);175}176 177static int max30102_set_powermode(struct max30102_data *data, u8 mode, bool en)178{179	u8 reg = mode;180 181	if (!en)182		reg |= MAX30102_REG_MODE_CONFIG_PWR;183 184	return regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,185				  MAX30102_REG_MODE_CONFIG_PWR |186				  MAX30102_REG_MODE_CONFIG_MODE_MASK, reg);187}188 189#define MAX30102_MODE_CONTROL_LED_SLOTS(slot2, slot1) \190	((slot2 << MAX30102_REG_MODE_CONTROL_SLOT_SHIFT) | slot1)191 192static int max30102_buffer_postenable(struct iio_dev *indio_dev)193{194	struct max30102_data *data = iio_priv(indio_dev);195	int ret;196	u8 reg;197 198	switch (*indio_dev->active_scan_mask) {199	case BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR):200		reg = MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2;201		break;202	case BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR) |203	     BIT(MAX30105_LED_GREEN):204		ret = regmap_update_bits(data->regmap,205					 MAX30102_REG_MODE_CONTROL_SLOT21,206					 MAX30102_REG_MODE_CONTROL_SLOT_MASK,207					 MAX30102_MODE_CONTROL_LED_SLOTS(2, 1));208		if (ret)209			return ret;210 211		ret = regmap_update_bits(data->regmap,212					 MAX30102_REG_MODE_CONTROL_SLOT43,213					 MAX30102_REG_MODE_CONTROL_SLOT_MASK,214					 MAX30102_MODE_CONTROL_LED_SLOTS(0, 3));215		if (ret)216			return ret;217 218		reg = MAX30102_REG_MODE_CONFIG_MODE_MULTI;219		break;220	default:221		return -EINVAL;222	}223 224	return max30102_set_powermode(data, reg, true);225}226 227static int max30102_buffer_predisable(struct iio_dev *indio_dev)228{229	struct max30102_data *data = iio_priv(indio_dev);230 231	return max30102_set_powermode(data, MAX30102_REG_MODE_CONFIG_MODE_NONE,232				      false);233}234 235static const struct iio_buffer_setup_ops max30102_buffer_setup_ops = {236	.postenable = max30102_buffer_postenable,237	.predisable = max30102_buffer_predisable,238};239 240static inline int max30102_fifo_count(struct max30102_data *data)241{242	unsigned int val;243	int ret;244 245	ret = regmap_read(data->regmap, MAX30102_REG_INT_STATUS, &val);246	if (ret)247		return ret;248 249	/* FIFO has one sample slot left */250	if (val & MAX30102_REG_INT_STATUS_FIFO_RDY)251		return 1;252 253	return 0;254}255 256#define MAX30102_COPY_DATA(i) \257	memcpy(&data->processed_buffer[(i)], \258	       &buffer[(i) * MAX30102_REG_FIFO_DATA_BYTES], \259	       MAX30102_REG_FIFO_DATA_BYTES)260 261static int max30102_read_measurement(struct max30102_data *data,262				     unsigned int measurements)263{264	int ret;265	u8 *buffer = (u8 *) &data->buffer;266 267	ret = i2c_smbus_read_i2c_block_data(data->client,268					    MAX30102_REG_FIFO_DATA,269					    measurements *270					    MAX30102_REG_FIFO_DATA_BYTES,271					    buffer);272 273	switch (measurements) {274	case 3:275		MAX30102_COPY_DATA(2);276		fallthrough;277	case 2:278		MAX30102_COPY_DATA(1);279		fallthrough;280	case 1:281		MAX30102_COPY_DATA(0);282		break;283	default:284		return -EINVAL;285	}286 287	return (ret == measurements * MAX30102_REG_FIFO_DATA_BYTES) ?288	       0 : -EINVAL;289}290 291static irqreturn_t max30102_interrupt_handler(int irq, void *private)292{293	struct iio_dev *indio_dev = private;294	struct max30102_data *data = iio_priv(indio_dev);295	unsigned int measurements = bitmap_weight(indio_dev->active_scan_mask,296						  iio_get_masklength(indio_dev));297	int ret, cnt = 0;298 299	mutex_lock(&data->lock);300 301	while (cnt || (cnt = max30102_fifo_count(data)) > 0) {302		ret = max30102_read_measurement(data, measurements);303		if (ret)304			break;305 306		iio_push_to_buffers(data->indio_dev, data->processed_buffer);307		cnt--;308	}309 310	mutex_unlock(&data->lock);311 312	return IRQ_HANDLED;313}314 315static int max30102_get_current_idx(unsigned int val, int *reg)316{317	/* each step is 0.200 mA */318	*reg = val / 200;319 320	return *reg > 0xff ? -EINVAL : 0;321}322 323static int max30102_led_init(struct max30102_data *data)324{325	struct device *dev = &data->client->dev;326	unsigned int val;327	int reg, ret;328 329	ret = device_property_read_u32(dev, "maxim,red-led-current-microamp", &val);330	if (ret) {331		dev_info(dev, "no red-led-current-microamp set\n");332 333		/* Default to 7 mA RED LED */334		val = 7000;335	}336 337	ret = max30102_get_current_idx(val, &reg);338	if (ret) {339		dev_err(dev, "invalid RED LED current setting %d\n", val);340		return ret;341	}342 343	ret = regmap_write(data->regmap, MAX30102_REG_RED_LED_CONFIG, reg);344	if (ret)345		return ret;346 347	if (data->chip_id == max30105) {348		ret = device_property_read_u32(dev,349			"maxim,green-led-current-microamp", &val);350		if (ret) {351			dev_info(dev, "no green-led-current-microamp set\n");352 353			/* Default to 7 mA green LED */354			val = 7000;355		}356 357		ret = max30102_get_current_idx(val, &reg);358		if (ret) {359			dev_err(dev, "invalid green LED current setting %d\n",360				val);361			return ret;362		}363 364		ret = regmap_write(data->regmap, MAX30105_REG_GREEN_LED_CONFIG,365				   reg);366		if (ret)367			return ret;368	}369 370	ret = device_property_read_u32(dev, "maxim,ir-led-current-microamp", &val);371	if (ret) {372		dev_info(dev, "no ir-led-current-microamp set\n");373 374		/* Default to 7 mA IR LED */375		val = 7000;376	}377 378	ret = max30102_get_current_idx(val, &reg);379	if (ret) {380		dev_err(dev, "invalid IR LED current setting %d\n", val);381		return ret;382	}383 384	return regmap_write(data->regmap, MAX30102_REG_IR_LED_CONFIG, reg);385}386 387static int max30102_chip_init(struct max30102_data *data)388{389	int ret;390 391	/* setup LED current settings */392	ret = max30102_led_init(data);393	if (ret)394		return ret;395 396	/* configure 18-bit HR + SpO2 readings at 400Hz */397	ret = regmap_write(data->regmap, MAX30102_REG_SPO2_CONFIG,398				(MAX30102_REG_SPO2_CONFIG_ADC_4096_STEPS399				 << MAX30102_REG_SPO2_CONFIG_ADC_MASK_SHIFT) |400				(MAX30102_REG_SPO2_CONFIG_SR_400HZ401				 << MAX30102_REG_SPO2_CONFIG_SR_MASK_SHIFT) |402				 MAX30102_REG_SPO2_CONFIG_PULSE_411_US);403	if (ret)404		return ret;405 406	/* average 4 samples + generate FIFO interrupt */407	ret = regmap_write(data->regmap, MAX30102_REG_FIFO_CONFIG,408				(MAX30102_REG_FIFO_CONFIG_AVG_4SAMPLES409				 << MAX30102_REG_FIFO_CONFIG_AVG_SHIFT) |410				 MAX30102_REG_FIFO_CONFIG_AFULL);411	if (ret)412		return ret;413 414	/* enable FIFO interrupt */415	return regmap_update_bits(data->regmap, MAX30102_REG_INT_ENABLE,416				 MAX30102_REG_INT_ENABLE_MASK,417				 MAX30102_REG_INT_ENABLE_FIFO_EN);418}419 420static int max30102_read_temp(struct max30102_data *data, int *val)421{422	int ret;423	unsigned int reg;424 425	ret = regmap_read(data->regmap, MAX30102_REG_TEMP_INTEGER, &reg);426	if (ret < 0)427		return ret;428	*val = reg << 4;429 430	ret = regmap_read(data->regmap, MAX30102_REG_TEMP_FRACTION, &reg);431	if (ret < 0)432		return ret;433 434	*val |= reg & 0xf;435	*val = sign_extend32(*val, 11);436 437	return 0;438}439 440static int max30102_get_temp(struct max30102_data *data, int *val, bool en)441{442	int ret;443 444	if (en) {445		ret = max30102_set_power(data, true);446		if (ret)447			return ret;448	}449 450	/* start acquisition */451	ret = regmap_set_bits(data->regmap, MAX30102_REG_TEMP_CONFIG,452			      MAX30102_REG_TEMP_CONFIG_TEMP_EN);453	if (ret)454		goto out;455 456	msleep(35);457	ret = max30102_read_temp(data, val);458 459out:460	if (en)461		max30102_set_power(data, false);462 463	return ret;464}465 466static int max30102_read_raw(struct iio_dev *indio_dev,467			     struct iio_chan_spec const *chan,468			     int *val, int *val2, long mask)469{470	struct max30102_data *data = iio_priv(indio_dev);471	int ret = -EINVAL;472 473	switch (mask) {474	case IIO_CHAN_INFO_RAW:475		/*476		 * Temperature reading can only be acquired when not in477		 * shutdown; leave shutdown briefly when buffer not running478		 */479any_mode_retry:480		if (iio_device_claim_buffer_mode(indio_dev)) {481			/*482			 * This one is a *bit* hacky. If we cannot claim buffer483			 * mode, then try direct mode so that we make sure484			 * things cannot concurrently change. And we just keep485			 * trying until we get one of the modes...486			 */487			if (iio_device_claim_direct_mode(indio_dev))488				goto any_mode_retry;489 490			ret = max30102_get_temp(data, val, true);491			iio_device_release_direct_mode(indio_dev);492		} else {493			ret = max30102_get_temp(data, val, false);494			iio_device_release_buffer_mode(indio_dev);495		}496		if (ret)497			return ret;498 499		ret = IIO_VAL_INT;500		break;501	case IIO_CHAN_INFO_SCALE:502		*val = 1000;  /* 62.5 */503		*val2 = 16;504		ret = IIO_VAL_FRACTIONAL;505		break;506	}507 508	return ret;509}510 511static const struct iio_info max30102_info = {512	.read_raw = max30102_read_raw,513};514 515static int max30102_probe(struct i2c_client *client)516{517	const struct i2c_device_id *id = i2c_client_get_device_id(client);518	struct max30102_data *data;519	struct iio_dev *indio_dev;520	int ret;521	unsigned int reg;522 523	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));524	if (!indio_dev)525		return -ENOMEM;526 527	indio_dev->name = MAX30102_DRV_NAME;528	indio_dev->info = &max30102_info;529	indio_dev->modes = INDIO_DIRECT_MODE;530 531	data = iio_priv(indio_dev);532	data->indio_dev = indio_dev;533	data->client = client;534	data->chip_id = id->driver_data;535 536	mutex_init(&data->lock);537	i2c_set_clientdata(client, indio_dev);538 539	switch (data->chip_id) {540	case max30105:541		indio_dev->channels = max30105_channels;542		indio_dev->num_channels = ARRAY_SIZE(max30105_channels);543		indio_dev->available_scan_masks = max30105_scan_masks;544		break;545	case max30102:546		indio_dev->channels = max30102_channels;547		indio_dev->num_channels = ARRAY_SIZE(max30102_channels);548		indio_dev->available_scan_masks = max30102_scan_masks;549		break;550	default:551		return -ENODEV;552	}553 554	ret = devm_iio_kfifo_buffer_setup(&client->dev, indio_dev,555					  &max30102_buffer_setup_ops);556	if (ret)557		return ret;558 559	data->regmap = devm_regmap_init_i2c(client, &max30102_regmap_config);560	if (IS_ERR(data->regmap)) {561		dev_err(&client->dev, "regmap initialization failed\n");562		return PTR_ERR(data->regmap);563	}564 565	/* check part ID */566	ret = regmap_read(data->regmap, MAX30102_REG_PART_ID, &reg);567	if (ret)568		return ret;569	if (reg != MAX30102_PART_NUMBER)570		return -ENODEV;571 572	/* show revision ID */573	ret = regmap_read(data->regmap, MAX30102_REG_REV_ID, &reg);574	if (ret)575		return ret;576	dev_dbg(&client->dev, "max3010x revision %02x\n", reg);577 578	/* clear mode setting, chip shutdown */579	ret = max30102_set_powermode(data, MAX30102_REG_MODE_CONFIG_MODE_NONE,580				     false);581	if (ret)582		return ret;583 584	ret = max30102_chip_init(data);585	if (ret)586		return ret;587 588	if (client->irq <= 0) {589		dev_err(&client->dev, "no valid irq defined\n");590		return -EINVAL;591	}592 593	ret = devm_request_threaded_irq(&client->dev, client->irq,594					NULL, max30102_interrupt_handler,595					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,596					"max30102_irq", indio_dev);597	if (ret) {598		dev_err(&client->dev, "request irq (%d) failed\n", client->irq);599		return ret;600	}601 602	return iio_device_register(indio_dev);603}604 605static void max30102_remove(struct i2c_client *client)606{607	struct iio_dev *indio_dev = i2c_get_clientdata(client);608	struct max30102_data *data = iio_priv(indio_dev);609 610	iio_device_unregister(indio_dev);611	max30102_set_power(data, false);612}613 614static const struct i2c_device_id max30102_id[] = {615	{ "max30101", max30105 },616	{ "max30102", max30102 },617	{ "max30105", max30105 },618	{}619};620MODULE_DEVICE_TABLE(i2c, max30102_id);621 622static const struct of_device_id max30102_dt_ids[] = {623	{ .compatible = "maxim,max30101" },624	{ .compatible = "maxim,max30102" },625	{ .compatible = "maxim,max30105" },626	{ }627};628MODULE_DEVICE_TABLE(of, max30102_dt_ids);629 630static struct i2c_driver max30102_driver = {631	.driver = {632		.name	= MAX30102_DRV_NAME,633		.of_match_table	= max30102_dt_ids,634	},635	.probe		= max30102_probe,636	.remove		= max30102_remove,637	.id_table	= max30102_id,638};639module_i2c_driver(max30102_driver);640 641MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");642MODULE_DESCRIPTION("MAX30102 heart rate/pulse oximeter and MAX30105 particle sensor driver");643MODULE_LICENSE("GPL");644