brintos

brintos / linux-shallow public Read only

0
0
Text · 15.6 KiB · 13e1dd4 Raw
595 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * AFE4403 Heart Rate Monitors and Low-Cost Pulse Oximeters4 *5 * Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/6 *	Andrew F. Davis <afd@ti.com>7 */8 9#include <linux/device.h>10#include <linux/err.h>11#include <linux/interrupt.h>12#include <linux/kernel.h>13#include <linux/module.h>14#include <linux/regmap.h>15#include <linux/spi/spi.h>16#include <linux/sysfs.h>17#include <linux/regulator/consumer.h>18 19#include <linux/iio/iio.h>20#include <linux/iio/sysfs.h>21#include <linux/iio/buffer.h>22#include <linux/iio/trigger.h>23#include <linux/iio/triggered_buffer.h>24#include <linux/iio/trigger_consumer.h>25 26#include <linux/unaligned.h>27 28#include "afe440x.h"29 30#define AFE4403_DRIVER_NAME		"afe4403"31 32/* AFE4403 Registers */33#define AFE4403_TIAGAIN			0x2034#define AFE4403_TIA_AMB_GAIN		0x2135 36enum afe4403_fields {37	/* Gains */38	F_RF_LED1, F_CF_LED1,39	F_RF_LED, F_CF_LED,40 41	/* LED Current */42	F_ILED1, F_ILED2,43 44	/* sentinel */45	F_MAX_FIELDS46};47 48static const struct reg_field afe4403_reg_fields[] = {49	/* Gains */50	[F_RF_LED1]	= REG_FIELD(AFE4403_TIAGAIN, 0, 2),51	[F_CF_LED1]	= REG_FIELD(AFE4403_TIAGAIN, 3, 7),52	[F_RF_LED]	= REG_FIELD(AFE4403_TIA_AMB_GAIN, 0, 2),53	[F_CF_LED]	= REG_FIELD(AFE4403_TIA_AMB_GAIN, 3, 7),54	/* LED Current */55	[F_ILED1]	= REG_FIELD(AFE440X_LEDCNTRL, 0, 7),56	[F_ILED2]	= REG_FIELD(AFE440X_LEDCNTRL, 8, 15),57};58 59/**60 * struct afe4403_data - AFE4403 device instance data61 * @dev: Device structure62 * @spi: SPI device handle63 * @regmap: Register map of the device64 * @fields: Register fields of the device65 * @regulator: Pointer to the regulator for the IC66 * @trig: IIO trigger for this device67 * @irq: ADC_RDY line interrupt number68 * @buffer: Used to construct data layout to push into IIO buffer.69 */70struct afe4403_data {71	struct device *dev;72	struct spi_device *spi;73	struct regmap *regmap;74	struct regmap_field *fields[F_MAX_FIELDS];75	struct regulator *regulator;76	struct iio_trigger *trig;77	int irq;78	/* Ensure suitable alignment for timestamp */79	s32 buffer[8] __aligned(8);80};81 82enum afe4403_chan_id {83	LED2 = 1,84	ALED2,85	LED1,86	ALED1,87	LED2_ALED2,88	LED1_ALED1,89};90 91static const unsigned int afe4403_channel_values[] = {92	[LED2] = AFE440X_LED2VAL,93	[ALED2] = AFE440X_ALED2VAL,94	[LED1] = AFE440X_LED1VAL,95	[ALED1] = AFE440X_ALED1VAL,96	[LED2_ALED2] = AFE440X_LED2_ALED2VAL,97	[LED1_ALED1] = AFE440X_LED1_ALED1VAL,98};99 100static const unsigned int afe4403_channel_leds[] = {101	[LED2] = F_ILED2,102	[LED1] = F_ILED1,103};104 105static const struct iio_chan_spec afe4403_channels[] = {106	/* ADC values */107	AFE440X_INTENSITY_CHAN(LED2, 0),108	AFE440X_INTENSITY_CHAN(ALED2, 0),109	AFE440X_INTENSITY_CHAN(LED1, 0),110	AFE440X_INTENSITY_CHAN(ALED1, 0),111	AFE440X_INTENSITY_CHAN(LED2_ALED2, 0),112	AFE440X_INTENSITY_CHAN(LED1_ALED1, 0),113	/* LED current */114	AFE440X_CURRENT_CHAN(LED2),115	AFE440X_CURRENT_CHAN(LED1),116};117 118static const struct afe440x_val_table afe4403_res_table[] = {119	{ 500000 }, { 250000 }, { 100000 }, { 50000 },120	{ 25000 }, { 10000 }, { 1000000 }, { 0 },121};122AFE440X_TABLE_ATTR(in_intensity_resistance_available, afe4403_res_table);123 124static const struct afe440x_val_table afe4403_cap_table[] = {125	{ 0, 5000 }, { 0, 10000 }, { 0, 20000 }, { 0, 25000 },126	{ 0, 30000 }, { 0, 35000 }, { 0, 45000 }, { 0, 50000 },127	{ 0, 55000 }, { 0, 60000 }, { 0, 70000 }, { 0, 75000 },128	{ 0, 80000 }, { 0, 85000 }, { 0, 95000 }, { 0, 100000 },129	{ 0, 155000 }, { 0, 160000 }, { 0, 170000 }, { 0, 175000 },130	{ 0, 180000 }, { 0, 185000 }, { 0, 195000 }, { 0, 200000 },131	{ 0, 205000 }, { 0, 210000 }, { 0, 220000 }, { 0, 225000 },132	{ 0, 230000 }, { 0, 235000 }, { 0, 245000 }, { 0, 250000 },133};134AFE440X_TABLE_ATTR(in_intensity_capacitance_available, afe4403_cap_table);135 136static ssize_t afe440x_show_register(struct device *dev,137				     struct device_attribute *attr,138				     char *buf)139{140	struct iio_dev *indio_dev = dev_to_iio_dev(dev);141	struct afe4403_data *afe = iio_priv(indio_dev);142	struct afe440x_attr *afe440x_attr = to_afe440x_attr(attr);143	unsigned int reg_val;144	int vals[2];145	int ret;146 147	ret = regmap_field_read(afe->fields[afe440x_attr->field], &reg_val);148	if (ret)149		return ret;150 151	if (reg_val >= afe440x_attr->table_size)152		return -EINVAL;153 154	vals[0] = afe440x_attr->val_table[reg_val].integer;155	vals[1] = afe440x_attr->val_table[reg_val].fract;156 157	return iio_format_value(buf, IIO_VAL_INT_PLUS_MICRO, 2, vals);158}159 160static ssize_t afe440x_store_register(struct device *dev,161				      struct device_attribute *attr,162				      const char *buf, size_t count)163{164	struct iio_dev *indio_dev = dev_to_iio_dev(dev);165	struct afe4403_data *afe = iio_priv(indio_dev);166	struct afe440x_attr *afe440x_attr = to_afe440x_attr(attr);167	int val, integer, fract, ret;168 169	ret = iio_str_to_fixpoint(buf, 100000, &integer, &fract);170	if (ret)171		return ret;172 173	for (val = 0; val < afe440x_attr->table_size; val++)174		if (afe440x_attr->val_table[val].integer == integer &&175		    afe440x_attr->val_table[val].fract == fract)176			break;177	if (val == afe440x_attr->table_size)178		return -EINVAL;179 180	ret = regmap_field_write(afe->fields[afe440x_attr->field], val);181	if (ret)182		return ret;183 184	return count;185}186 187static AFE440X_ATTR(in_intensity1_resistance, F_RF_LED, afe4403_res_table);188static AFE440X_ATTR(in_intensity1_capacitance, F_CF_LED, afe4403_cap_table);189 190static AFE440X_ATTR(in_intensity2_resistance, F_RF_LED, afe4403_res_table);191static AFE440X_ATTR(in_intensity2_capacitance, F_CF_LED, afe4403_cap_table);192 193static AFE440X_ATTR(in_intensity3_resistance, F_RF_LED1, afe4403_res_table);194static AFE440X_ATTR(in_intensity3_capacitance, F_CF_LED1, afe4403_cap_table);195 196static AFE440X_ATTR(in_intensity4_resistance, F_RF_LED1, afe4403_res_table);197static AFE440X_ATTR(in_intensity4_capacitance, F_CF_LED1, afe4403_cap_table);198 199static struct attribute *afe440x_attributes[] = {200	&dev_attr_in_intensity_resistance_available.attr,201	&dev_attr_in_intensity_capacitance_available.attr,202	&afe440x_attr_in_intensity1_resistance.dev_attr.attr,203	&afe440x_attr_in_intensity1_capacitance.dev_attr.attr,204	&afe440x_attr_in_intensity2_resistance.dev_attr.attr,205	&afe440x_attr_in_intensity2_capacitance.dev_attr.attr,206	&afe440x_attr_in_intensity3_resistance.dev_attr.attr,207	&afe440x_attr_in_intensity3_capacitance.dev_attr.attr,208	&afe440x_attr_in_intensity4_resistance.dev_attr.attr,209	&afe440x_attr_in_intensity4_capacitance.dev_attr.attr,210	NULL211};212 213static const struct attribute_group afe440x_attribute_group = {214	.attrs = afe440x_attributes215};216 217static int afe4403_read(struct afe4403_data *afe, unsigned int reg, u32 *val)218{219	u8 tx[4] = {AFE440X_CONTROL0, 0x0, 0x0, AFE440X_CONTROL0_READ};220	u8 rx[3];221	int ret;222 223	/* Enable reading from the device */224	ret = spi_write_then_read(afe->spi, tx, 4, NULL, 0);225	if (ret)226		return ret;227 228	ret = spi_write_then_read(afe->spi, &reg, 1, rx, sizeof(rx));229	if (ret)230		return ret;231 232	*val = get_unaligned_be24(&rx[0]);233 234	/* Disable reading from the device */235	tx[3] = AFE440X_CONTROL0_WRITE;236	ret = spi_write_then_read(afe->spi, tx, 4, NULL, 0);237	if (ret)238		return ret;239 240	return 0;241}242 243static int afe4403_read_raw(struct iio_dev *indio_dev,244			    struct iio_chan_spec const *chan,245			    int *val, int *val2, long mask)246{247	struct afe4403_data *afe = iio_priv(indio_dev);248	unsigned int reg, field;249	int ret;250 251	switch (chan->type) {252	case IIO_INTENSITY:253		switch (mask) {254		case IIO_CHAN_INFO_RAW:255			reg = afe4403_channel_values[chan->address];256			ret = afe4403_read(afe, reg, val);257			if (ret)258				return ret;259			return IIO_VAL_INT;260		}261		break;262	case IIO_CURRENT:263		switch (mask) {264		case IIO_CHAN_INFO_RAW:265			field = afe4403_channel_leds[chan->address];266			ret = regmap_field_read(afe->fields[field], val);267			if (ret)268				return ret;269			return IIO_VAL_INT;270		case IIO_CHAN_INFO_SCALE:271			*val = 0;272			*val2 = 800000;273			return IIO_VAL_INT_PLUS_MICRO;274		}275		break;276	default:277		break;278	}279 280	return -EINVAL;281}282 283static int afe4403_write_raw(struct iio_dev *indio_dev,284			     struct iio_chan_spec const *chan,285			     int val, int val2, long mask)286{287	struct afe4403_data *afe = iio_priv(indio_dev);288	unsigned int field = afe4403_channel_leds[chan->address];289 290	switch (chan->type) {291	case IIO_CURRENT:292		switch (mask) {293		case IIO_CHAN_INFO_RAW:294			return regmap_field_write(afe->fields[field], val);295		}296		break;297	default:298		break;299	}300 301	return -EINVAL;302}303 304static const struct iio_info afe4403_iio_info = {305	.attrs = &afe440x_attribute_group,306	.read_raw = afe4403_read_raw,307	.write_raw = afe4403_write_raw,308};309 310static irqreturn_t afe4403_trigger_handler(int irq, void *private)311{312	struct iio_poll_func *pf = private;313	struct iio_dev *indio_dev = pf->indio_dev;314	struct afe4403_data *afe = iio_priv(indio_dev);315	int ret, bit, i = 0;316	u8 tx[4] = {AFE440X_CONTROL0, 0x0, 0x0, AFE440X_CONTROL0_READ};317	u8 rx[3];318 319	/* Enable reading from the device */320	ret = spi_write_then_read(afe->spi, tx, 4, NULL, 0);321	if (ret)322		goto err;323 324	iio_for_each_active_channel(indio_dev, bit) {325		ret = spi_write_then_read(afe->spi,326					  &afe4403_channel_values[bit], 1,327					  rx, sizeof(rx));328		if (ret)329			goto err;330 331		afe->buffer[i++] = get_unaligned_be24(&rx[0]);332	}333 334	/* Disable reading from the device */335	tx[3] = AFE440X_CONTROL0_WRITE;336	ret = spi_write_then_read(afe->spi, tx, 4, NULL, 0);337	if (ret)338		goto err;339 340	iio_push_to_buffers_with_timestamp(indio_dev, afe->buffer,341					   pf->timestamp);342err:343	iio_trigger_notify_done(indio_dev->trig);344 345	return IRQ_HANDLED;346}347 348static void afe4403_regulator_disable(void *data)349{350	struct regulator *regulator = data;351 352	regulator_disable(regulator);353}354 355#define AFE4403_TIMING_PAIRS			\356	{ AFE440X_LED2STC,	0x000050 },	\357	{ AFE440X_LED2ENDC,	0x0003e7 },	\358	{ AFE440X_LED1LEDSTC,	0x0007d0 },	\359	{ AFE440X_LED1LEDENDC,	0x000bb7 },	\360	{ AFE440X_ALED2STC,	0x000438 },	\361	{ AFE440X_ALED2ENDC,	0x0007cf },	\362	{ AFE440X_LED1STC,	0x000820 },	\363	{ AFE440X_LED1ENDC,	0x000bb7 },	\364	{ AFE440X_LED2LEDSTC,	0x000000 },	\365	{ AFE440X_LED2LEDENDC,	0x0003e7 },	\366	{ AFE440X_ALED1STC,	0x000c08 },	\367	{ AFE440X_ALED1ENDC,	0x000f9f },	\368	{ AFE440X_LED2CONVST,	0x0003ef },	\369	{ AFE440X_LED2CONVEND,	0x0007cf },	\370	{ AFE440X_ALED2CONVST,	0x0007d7 },	\371	{ AFE440X_ALED2CONVEND,	0x000bb7 },	\372	{ AFE440X_LED1CONVST,	0x000bbf },	\373	{ AFE440X_LED1CONVEND,	0x009c3f },	\374	{ AFE440X_ALED1CONVST,	0x000fa7 },	\375	{ AFE440X_ALED1CONVEND,	0x001387 },	\376	{ AFE440X_ADCRSTSTCT0,	0x0003e8 },	\377	{ AFE440X_ADCRSTENDCT0,	0x0003eb },	\378	{ AFE440X_ADCRSTSTCT1,	0x0007d0 },	\379	{ AFE440X_ADCRSTENDCT1,	0x0007d3 },	\380	{ AFE440X_ADCRSTSTCT2,	0x000bb8 },	\381	{ AFE440X_ADCRSTENDCT2,	0x000bbb },	\382	{ AFE440X_ADCRSTSTCT3,	0x000fa0 },	\383	{ AFE440X_ADCRSTENDCT3,	0x000fa3 },	\384	{ AFE440X_PRPCOUNT,	0x009c3f },	\385	{ AFE440X_PDNCYCLESTC,	0x001518 },	\386	{ AFE440X_PDNCYCLEENDC,	0x00991f }387 388static const struct reg_sequence afe4403_reg_sequences[] = {389	AFE4403_TIMING_PAIRS,390	{ AFE440X_CONTROL1, AFE440X_CONTROL1_TIMEREN },391	{ AFE4403_TIAGAIN, AFE440X_TIAGAIN_ENSEPGAIN },392};393 394static const struct regmap_range afe4403_yes_ranges[] = {395	regmap_reg_range(AFE440X_LED2VAL, AFE440X_LED1_ALED1VAL),396};397 398static const struct regmap_access_table afe4403_volatile_table = {399	.yes_ranges = afe4403_yes_ranges,400	.n_yes_ranges = ARRAY_SIZE(afe4403_yes_ranges),401};402 403static const struct regmap_config afe4403_regmap_config = {404	.reg_bits = 8,405	.val_bits = 24,406 407	.max_register = AFE440X_PDNCYCLEENDC,408	.cache_type = REGCACHE_RBTREE,409	.volatile_table = &afe4403_volatile_table,410};411 412static const struct of_device_id afe4403_of_match[] = {413	{ .compatible = "ti,afe4403", },414	{ /* sentinel */ }415};416MODULE_DEVICE_TABLE(of, afe4403_of_match);417 418static int afe4403_suspend(struct device *dev)419{420	struct iio_dev *indio_dev = spi_get_drvdata(to_spi_device(dev));421	struct afe4403_data *afe = iio_priv(indio_dev);422	int ret;423 424	ret = regmap_set_bits(afe->regmap, AFE440X_CONTROL2,425			      AFE440X_CONTROL2_PDN_AFE);426	if (ret)427		return ret;428 429	ret = regulator_disable(afe->regulator);430	if (ret) {431		dev_err(dev, "Unable to disable regulator\n");432		return ret;433	}434 435	return 0;436}437 438static int afe4403_resume(struct device *dev)439{440	struct iio_dev *indio_dev = spi_get_drvdata(to_spi_device(dev));441	struct afe4403_data *afe = iio_priv(indio_dev);442	int ret;443 444	ret = regulator_enable(afe->regulator);445	if (ret) {446		dev_err(dev, "Unable to enable regulator\n");447		return ret;448	}449 450	ret = regmap_clear_bits(afe->regmap, AFE440X_CONTROL2,451				AFE440X_CONTROL2_PDN_AFE);452	if (ret)453		return ret;454 455	return 0;456}457 458static DEFINE_SIMPLE_DEV_PM_OPS(afe4403_pm_ops, afe4403_suspend,459				afe4403_resume);460 461static int afe4403_probe(struct spi_device *spi)462{463	struct iio_dev *indio_dev;464	struct afe4403_data *afe;465	int i, ret;466 467	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*afe));468	if (!indio_dev)469		return -ENOMEM;470 471	afe = iio_priv(indio_dev);472	spi_set_drvdata(spi, indio_dev);473 474	afe->dev = &spi->dev;475	afe->spi = spi;476	afe->irq = spi->irq;477 478	afe->regmap = devm_regmap_init_spi(spi, &afe4403_regmap_config);479	if (IS_ERR(afe->regmap)) {480		dev_err(afe->dev, "Unable to allocate register map\n");481		return PTR_ERR(afe->regmap);482	}483 484	for (i = 0; i < F_MAX_FIELDS; i++) {485		afe->fields[i] = devm_regmap_field_alloc(afe->dev, afe->regmap,486							 afe4403_reg_fields[i]);487		if (IS_ERR(afe->fields[i])) {488			dev_err(afe->dev, "Unable to allocate regmap fields\n");489			return PTR_ERR(afe->fields[i]);490		}491	}492 493	afe->regulator = devm_regulator_get(afe->dev, "tx_sup");494	if (IS_ERR(afe->regulator))495		return dev_err_probe(afe->dev, PTR_ERR(afe->regulator),496				     "Unable to get regulator\n");497 498	ret = regulator_enable(afe->regulator);499	if (ret) {500		dev_err(afe->dev, "Unable to enable regulator\n");501		return ret;502	}503	ret = devm_add_action_or_reset(afe->dev, afe4403_regulator_disable, afe->regulator);504	if (ret) {505		dev_err(afe->dev, "Unable to add regulator disable action\n");506		return ret;507	}508 509	ret = regmap_write(afe->regmap, AFE440X_CONTROL0,510			   AFE440X_CONTROL0_SW_RESET);511	if (ret) {512		dev_err(afe->dev, "Unable to reset device\n");513		return ret;514	}515 516	ret = regmap_multi_reg_write(afe->regmap, afe4403_reg_sequences,517				     ARRAY_SIZE(afe4403_reg_sequences));518	if (ret) {519		dev_err(afe->dev, "Unable to set register defaults\n");520		return ret;521	}522 523	indio_dev->modes = INDIO_DIRECT_MODE;524	indio_dev->channels = afe4403_channels;525	indio_dev->num_channels = ARRAY_SIZE(afe4403_channels);526	indio_dev->name = AFE4403_DRIVER_NAME;527	indio_dev->info = &afe4403_iio_info;528 529	if (afe->irq > 0) {530		afe->trig = devm_iio_trigger_alloc(afe->dev,531						   "%s-dev%d",532						   indio_dev->name,533						   iio_device_id(indio_dev));534		if (!afe->trig) {535			dev_err(afe->dev, "Unable to allocate IIO trigger\n");536			return -ENOMEM;537		}538 539		iio_trigger_set_drvdata(afe->trig, indio_dev);540 541		ret = devm_iio_trigger_register(afe->dev, afe->trig);542		if (ret) {543			dev_err(afe->dev, "Unable to register IIO trigger\n");544			return ret;545		}546 547		ret = devm_request_threaded_irq(afe->dev, afe->irq,548						iio_trigger_generic_data_rdy_poll,549						NULL, IRQF_ONESHOT,550						AFE4403_DRIVER_NAME,551						afe->trig);552		if (ret) {553			dev_err(afe->dev, "Unable to request IRQ\n");554			return ret;555		}556	}557 558	ret = devm_iio_triggered_buffer_setup(afe->dev, indio_dev,559					      &iio_pollfunc_store_time,560					      afe4403_trigger_handler, NULL);561	if (ret) {562		dev_err(afe->dev, "Unable to setup buffer\n");563		return ret;564	}565 566	ret = devm_iio_device_register(afe->dev, indio_dev);567	if (ret) {568		dev_err(afe->dev, "Unable to register IIO device\n");569		return ret;570	}571 572	return 0;573}574 575static const struct spi_device_id afe4403_ids[] = {576	{ "afe4403", 0 },577	{ /* sentinel */ }578};579MODULE_DEVICE_TABLE(spi, afe4403_ids);580 581static struct spi_driver afe4403_spi_driver = {582	.driver = {583		.name = AFE4403_DRIVER_NAME,584		.of_match_table = afe4403_of_match,585		.pm = pm_sleep_ptr(&afe4403_pm_ops),586	},587	.probe = afe4403_probe,588	.id_table = afe4403_ids,589};590module_spi_driver(afe4403_spi_driver);591 592MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>");593MODULE_DESCRIPTION("TI AFE4403 Heart Rate Monitor and Pulse Oximeter AFE");594MODULE_LICENSE("GPL v2");595