cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

max30100.c (12294B)


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