diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-06-09 09:15:58 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-06-09 09:15:58 -0700 |
commit | aabb406008fc722ff2c992867d755ec2176e55b5 (patch) | |
tree | cfac80cb56a9a32ff73c62609b57c05b691ccf4c /drivers/iio/health | |
parent | 73e81350ad7a45117c17fb3ec433a266b3fa7d78 (diff) | |
parent | bc2e1126eccb47517b9d1c685020c38600f99a3d (diff) | |
download | linux-aabb406008fc722ff2c992867d755ec2176e55b5.tar.bz2 |
Merge tag 'iio-for-4.8a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next
Jonathan writes:
First round of IIO new device support, features and cleanups for the 4.8 cycle.
New device support
* ads1015
- add ads1115 support
* bma220 accelerometer
- new driver
- triggered buffer support.
* bmc150
- add bmm150 support.
* bmp280
- bme280 support with addition of humidity channel.
* max5487 potentiometer
- new driver
* MMA7660FC accelerometer.
- New driver
* st-pressure
- support for the lps22hb
* loop trigger.
- This one is *nasty* but we have real applications (parrot drones) where
it is useful. The trigger basically spins as hard as it can firing off
a new trigger each time all triggered devices come back to say they are
done. It doesn't hang a machine even when doing it on a dummy driver.
A lot nicer than having this implemented within lots of device drivers
anyway.
Core stuff
* Add support to create IIO devices via configfs (similar to we did for
triggers a while back) + docs.
* New channel types
- IIO_ELECTRICAL_CONDUCTIVITY
* Couple of MAINTAINERS patches to list the device tree bindings.
* Make trigger ops structure non optional (comment fix). It hasn't been for
an awful long time, but that's not what the description said.
New features
* ak8975
- support adapters that are limited to byte data only by allowing the
emulated block read i2c function that was recently introduced.
* atlas-ph
- support atlas-ec (electrical conductivity sensor)
* bmi160
- add available frequency and scale attributes to make the driver
more user friendly (and avoid having to read the datasheet to know
what will work).
* dummy
- move creation to configfs interface. It's not real hardware so we
are not that worried about the ABI breakage ;)
* mma8452
- oversampling ration support
* nau7802
- expose available gains to make life easier for userspace.
* st-sensors
- allow use of emulation for SMBus block reads as all the st parts support
it.
* ti-ads1015
- list datasheet names to allow their use by inkernel consumers.
* Various module alias additions to help auto probing. Drop one redundant one
as well.
Cleanups
* ad7266, ad7476, ad7887, ad7923, ad799x
- use direct mode claim function rather than open coding it during sensor
read (prevents switching on buffers mid read).
* ad7793, ad7791
- use direct mode claim to prevent frequency changes when buffers running.
* afe440x - These are ABI breaking but the driver requires custom userspace
code to do anything useful anyway and that is still being written and under
control of TI. Ultimately we may have other libraries to do pulse
oximetry with these devices but we aren't aware of any yet.
- kernel-doc format fixes
- drop ifdef fun around of_match_ptr - it's not worth the mess to save
a tiny amount of space.
- drop some unnecessary register initializations.
- drop the weird locked gain modes as they gain us nothing (can just set
all gains separately).
- remove handling of offset attributes seeing as no channels actually have
them (oops)
- Drop the LED3 input channel as it's an alias for ALED2.
- *big one* remove channel names - an experiment that turned out to not
make sense - see patch for details.
- use regmap fields to clean up code.
- tie the tia gain stages to appropriate channels in the ABI as that is
what they really effect. Same with the LED currents.
- cleanout some unused defines and fix a missnamed one.
* atlas-ph
- reorganise to allow support of other similar parts.
* bmc150
- document supported chips in kconfig help.
* jsa1212
- drop an unneeded i2c functionality check for functionality the driver
doesn't use.
* mxs-lradc
- simply touch screen registration code.
- remove the touch screen unregister as all devm based now.
- disable only those channels that are masked in hardware stop (others
are already dealt with elsewhere)
* st-sensors
- unexport st_sensors_get_buffer_element as nothing outside the st-sensors
core driver uses it.
- fix handling of failure to start up regulators.
* tpl0102
- drop an i2c functionality test for features that aren't needed.
* ti-am335x
- use variable name rather than type in sizeof for clarity.
- use SIMPLE_DEV_PM_OPS helper macro to tidy up a bit.
Tools
* Add install / uninstall to makefile. Someone cares, so presumably
some people will find it useful!
* generic_buffer
- rename to iio_generic_buffer to line up with other tools.
- handle cleanup when receiving signals
- Add a --device-num option and a --trigger-num option rather than
relying on naming which doesn't work if you have two of the same part.
Diffstat (limited to 'drivers/iio/health')
-rw-r--r-- | drivers/iio/health/afe4403.c | 299 | ||||
-rw-r--r-- | drivers/iio/health/afe4404.c | 308 | ||||
-rw-r--r-- | drivers/iio/health/afe440x.h | 48 |
3 files changed, 254 insertions, 401 deletions
diff --git a/drivers/iio/health/afe4403.c b/drivers/iio/health/afe4403.c index 88e43f87b926..9a081465c42f 100644 --- a/drivers/iio/health/afe4403.c +++ b/drivers/iio/health/afe4403.c @@ -1,7 +1,7 @@ /* * AFE4403 Heart Rate Monitors and Low-Cost Pulse Oximeters * - * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/ * Andrew F. Davis <afd@ti.com> * * This program is free software; you can redistribute it and/or modify @@ -39,127 +39,90 @@ #define AFE4403_TIAGAIN 0x20 #define AFE4403_TIA_AMB_GAIN 0x21 -/* AFE4403 GAIN register fields */ -#define AFE4403_TIAGAIN_RES_MASK GENMASK(2, 0) -#define AFE4403_TIAGAIN_RES_SHIFT 0 -#define AFE4403_TIAGAIN_CAP_MASK GENMASK(7, 3) -#define AFE4403_TIAGAIN_CAP_SHIFT 3 - -/* AFE4403 LEDCNTRL register fields */ -#define AFE440X_LEDCNTRL_LED1_MASK GENMASK(15, 8) -#define AFE440X_LEDCNTRL_LED1_SHIFT 8 -#define AFE440X_LEDCNTRL_LED2_MASK GENMASK(7, 0) -#define AFE440X_LEDCNTRL_LED2_SHIFT 0 -#define AFE440X_LEDCNTRL_LED_RANGE_MASK GENMASK(17, 16) -#define AFE440X_LEDCNTRL_LED_RANGE_SHIFT 16 - -/* AFE4403 CONTROL2 register fields */ -#define AFE440X_CONTROL2_PWR_DWN_TX BIT(2) -#define AFE440X_CONTROL2_EN_SLOW_DIAG BIT(8) -#define AFE440X_CONTROL2_DIAG_OUT_TRI BIT(10) -#define AFE440X_CONTROL2_TX_BRDG_MOD BIT(11) -#define AFE440X_CONTROL2_TX_REF_MASK GENMASK(18, 17) -#define AFE440X_CONTROL2_TX_REF_SHIFT 17 - -/* AFE4404 NULL fields */ -#define NULL_MASK 0 -#define NULL_SHIFT 0 - -/* AFE4403 LEDCNTRL values */ -#define AFE440X_LEDCNTRL_RANGE_TX_HALF 0x1 -#define AFE440X_LEDCNTRL_RANGE_TX_FULL 0x2 -#define AFE440X_LEDCNTRL_RANGE_TX_OFF 0x3 - -/* AFE4403 CONTROL2 values */ -#define AFE440X_CONTROL2_TX_REF_025 0x0 -#define AFE440X_CONTROL2_TX_REF_050 0x1 -#define AFE440X_CONTROL2_TX_REF_100 0x2 -#define AFE440X_CONTROL2_TX_REF_075 0x3 - -/* AFE4403 CONTROL3 values */ -#define AFE440X_CONTROL3_CLK_DIV_2 0x0 -#define AFE440X_CONTROL3_CLK_DIV_4 0x2 -#define AFE440X_CONTROL3_CLK_DIV_6 0x3 -#define AFE440X_CONTROL3_CLK_DIV_8 0x4 -#define AFE440X_CONTROL3_CLK_DIV_12 0x5 -#define AFE440X_CONTROL3_CLK_DIV_1 0x7 - -/* AFE4403 TIAGAIN_CAP values */ -#define AFE4403_TIAGAIN_CAP_5_P 0x0 -#define AFE4403_TIAGAIN_CAP_10_P 0x1 -#define AFE4403_TIAGAIN_CAP_20_P 0x2 -#define AFE4403_TIAGAIN_CAP_30_P 0x3 -#define AFE4403_TIAGAIN_CAP_55_P 0x8 -#define AFE4403_TIAGAIN_CAP_155_P 0x10 - -/* AFE4403 TIAGAIN_RES values */ -#define AFE4403_TIAGAIN_RES_500_K 0x0 -#define AFE4403_TIAGAIN_RES_250_K 0x1 -#define AFE4403_TIAGAIN_RES_100_K 0x2 -#define AFE4403_TIAGAIN_RES_50_K 0x3 -#define AFE4403_TIAGAIN_RES_25_K 0x4 -#define AFE4403_TIAGAIN_RES_10_K 0x5 -#define AFE4403_TIAGAIN_RES_1_M 0x6 -#define AFE4403_TIAGAIN_RES_NONE 0x7 +enum afe4403_fields { + /* Gains */ + F_RF_LED1, F_CF_LED1, + F_RF_LED, F_CF_LED, + + /* LED Current */ + F_ILED1, F_ILED2, + + /* sentinel */ + F_MAX_FIELDS +}; + +static const struct reg_field afe4403_reg_fields[] = { + /* Gains */ + [F_RF_LED1] = REG_FIELD(AFE4403_TIAGAIN, 0, 2), + [F_CF_LED1] = REG_FIELD(AFE4403_TIAGAIN, 3, 7), + [F_RF_LED] = REG_FIELD(AFE4403_TIA_AMB_GAIN, 0, 2), + [F_CF_LED] = REG_FIELD(AFE4403_TIA_AMB_GAIN, 3, 7), + /* LED Current */ + [F_ILED1] = REG_FIELD(AFE440X_LEDCNTRL, 0, 7), + [F_ILED2] = REG_FIELD(AFE440X_LEDCNTRL, 8, 15), +}; /** - * struct afe4403_data - * @dev - Device structure - * @spi - SPI device handle - * @regmap - Register map of the device - * @regulator - Pointer to the regulator for the IC - * @trig - IIO trigger for this device - * @irq - ADC_RDY line interrupt number + * struct afe4403_data - AFE4403 device instance data + * @dev: Device structure + * @spi: SPI device handle + * @regmap: Register map of the device + * @fields: Register fields of the device + * @regulator: Pointer to the regulator for the IC + * @trig: IIO trigger for this device + * @irq: ADC_RDY line interrupt number */ struct afe4403_data { struct device *dev; struct spi_device *spi; struct regmap *regmap; + struct regmap_field *fields[F_MAX_FIELDS]; struct regulator *regulator; struct iio_trigger *trig; int irq; }; enum afe4403_chan_id { + LED2 = 1, + ALED2, LED1, ALED1, - LED2, - ALED2, - LED1_ALED1, LED2_ALED2, - ILED1, - ILED2, + LED1_ALED1, }; -static const struct afe440x_reg_info afe4403_reg_info[] = { - [LED1] = AFE440X_REG_INFO(AFE440X_LED1VAL, 0, NULL), - [ALED1] = AFE440X_REG_INFO(AFE440X_ALED1VAL, 0, NULL), - [LED2] = AFE440X_REG_INFO(AFE440X_LED2VAL, 0, NULL), - [ALED2] = AFE440X_REG_INFO(AFE440X_ALED2VAL, 0, NULL), - [LED1_ALED1] = AFE440X_REG_INFO(AFE440X_LED1_ALED1VAL, 0, NULL), - [LED2_ALED2] = AFE440X_REG_INFO(AFE440X_LED2_ALED2VAL, 0, NULL), - [ILED1] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE440X_LEDCNTRL_LED1), - [ILED2] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE440X_LEDCNTRL_LED2), +static const unsigned int afe4403_channel_values[] = { + [LED2] = AFE440X_LED2VAL, + [ALED2] = AFE440X_ALED2VAL, + [LED1] = AFE440X_LED1VAL, + [ALED1] = AFE440X_ALED1VAL, + [LED2_ALED2] = AFE440X_LED2_ALED2VAL, + [LED1_ALED1] = AFE440X_LED1_ALED1VAL, +}; + +static const unsigned int afe4403_channel_leds[] = { + [LED2] = F_ILED2, + [LED1] = F_ILED1, }; static const struct iio_chan_spec afe4403_channels[] = { /* ADC values */ - AFE440X_INTENSITY_CHAN(LED1, "led1", 0), - AFE440X_INTENSITY_CHAN(ALED1, "led1_ambient", 0), - AFE440X_INTENSITY_CHAN(LED2, "led2", 0), - AFE440X_INTENSITY_CHAN(ALED2, "led2_ambient", 0), - AFE440X_INTENSITY_CHAN(LED1_ALED1, "led1-led1_ambient", 0), - AFE440X_INTENSITY_CHAN(LED2_ALED2, "led2-led2_ambient", 0), + AFE440X_INTENSITY_CHAN(LED2, 0), + AFE440X_INTENSITY_CHAN(ALED2, 0), + AFE440X_INTENSITY_CHAN(LED1, 0), + AFE440X_INTENSITY_CHAN(ALED1, 0), + AFE440X_INTENSITY_CHAN(LED2_ALED2, 0), + AFE440X_INTENSITY_CHAN(LED1_ALED1, 0), /* LED current */ - AFE440X_CURRENT_CHAN(ILED1, "led1"), - AFE440X_CURRENT_CHAN(ILED2, "led2"), + AFE440X_CURRENT_CHAN(LED2), + AFE440X_CURRENT_CHAN(LED1), }; static const struct afe440x_val_table afe4403_res_table[] = { { 500000 }, { 250000 }, { 100000 }, { 50000 }, { 25000 }, { 10000 }, { 1000000 }, { 0 }, }; -AFE440X_TABLE_ATTR(tia_resistance_available, afe4403_res_table); +AFE440X_TABLE_ATTR(in_intensity_resistance_available, afe4403_res_table); static const struct afe440x_val_table afe4403_cap_table[] = { { 0, 5000 }, { 0, 10000 }, { 0, 20000 }, { 0, 25000 }, @@ -171,7 +134,7 @@ static const struct afe440x_val_table afe4403_cap_table[] = { { 0, 205000 }, { 0, 210000 }, { 0, 220000 }, { 0, 225000 }, { 0, 230000 }, { 0, 235000 }, { 0, 245000 }, { 0, 250000 }, }; -AFE440X_TABLE_ATTR(tia_capacitance_available, afe4403_cap_table); +AFE440X_TABLE_ATTR(in_intensity_capacitance_available, afe4403_cap_table); static ssize_t afe440x_show_register(struct device *dev, struct device_attribute *attr, @@ -180,38 +143,21 @@ static ssize_t afe440x_show_register(struct device *dev, struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct afe4403_data *afe = iio_priv(indio_dev); struct afe440x_attr *afe440x_attr = to_afe440x_attr(attr); - unsigned int reg_val, type; + unsigned int reg_val; int vals[2]; - int ret, val_len; + int ret; - ret = regmap_read(afe->regmap, afe440x_attr->reg, ®_val); + ret = regmap_field_read(afe->fields[afe440x_attr->field], ®_val); if (ret) return ret; - reg_val &= afe440x_attr->mask; - reg_val >>= afe440x_attr->shift; - - switch (afe440x_attr->type) { - case SIMPLE: - type = IIO_VAL_INT; - val_len = 1; - vals[0] = reg_val; - break; - case RESISTANCE: - case CAPACITANCE: - type = IIO_VAL_INT_PLUS_MICRO; - val_len = 2; - if (reg_val < afe440x_attr->table_size) { - vals[0] = afe440x_attr->val_table[reg_val].integer; - vals[1] = afe440x_attr->val_table[reg_val].fract; - break; - } - return -EINVAL; - default: + if (reg_val >= afe440x_attr->table_size) return -EINVAL; - } - return iio_format_value(buf, type, val_len, vals); + vals[0] = afe440x_attr->val_table[reg_val].integer; + vals[1] = afe440x_attr->val_table[reg_val].fract; + + return iio_format_value(buf, IIO_VAL_INT_PLUS_MICRO, 2, vals); } static ssize_t afe440x_store_register(struct device *dev, @@ -227,48 +173,43 @@ static ssize_t afe440x_store_register(struct device *dev, if (ret) return ret; - switch (afe440x_attr->type) { - case SIMPLE: - val = integer; - break; - case RESISTANCE: - case CAPACITANCE: - for (val = 0; val < afe440x_attr->table_size; val++) - if (afe440x_attr->val_table[val].integer == integer && - afe440x_attr->val_table[val].fract == fract) - break; - if (val == afe440x_attr->table_size) - return -EINVAL; - break; - default: + for (val = 0; val < afe440x_attr->table_size; val++) + if (afe440x_attr->val_table[val].integer == integer && + afe440x_attr->val_table[val].fract == fract) + break; + if (val == afe440x_attr->table_size) return -EINVAL; - } - ret = regmap_update_bits(afe->regmap, afe440x_attr->reg, - afe440x_attr->mask, - (val << afe440x_attr->shift)); + ret = regmap_field_write(afe->fields[afe440x_attr->field], val); if (ret) return ret; return count; } -static AFE440X_ATTR(tia_separate_en, AFE4403_TIAGAIN, AFE440X_TIAGAIN_ENSEPGAIN, SIMPLE, NULL, 0); +static AFE440X_ATTR(in_intensity1_resistance, F_RF_LED, afe4403_res_table); +static AFE440X_ATTR(in_intensity1_capacitance, F_CF_LED, afe4403_cap_table); + +static AFE440X_ATTR(in_intensity2_resistance, F_RF_LED, afe4403_res_table); +static AFE440X_ATTR(in_intensity2_capacitance, F_CF_LED, afe4403_cap_table); -static AFE440X_ATTR(tia_resistance1, AFE4403_TIAGAIN, AFE4403_TIAGAIN_RES, RESISTANCE, afe4403_res_table, ARRAY_SIZE(afe4403_res_table)); -static AFE440X_ATTR(tia_capacitance1, AFE4403_TIAGAIN, AFE4403_TIAGAIN_CAP, CAPACITANCE, afe4403_cap_table, ARRAY_SIZE(afe4403_cap_table)); +static AFE440X_ATTR(in_intensity3_resistance, F_RF_LED1, afe4403_res_table); +static AFE440X_ATTR(in_intensity3_capacitance, F_CF_LED1, afe4403_cap_table); -static AFE440X_ATTR(tia_resistance2, AFE4403_TIA_AMB_GAIN, AFE4403_TIAGAIN_RES, RESISTANCE, afe4403_res_table, ARRAY_SIZE(afe4403_res_table)); -static AFE440X_ATTR(tia_capacitance2, AFE4403_TIA_AMB_GAIN, AFE4403_TIAGAIN_RES, CAPACITANCE, afe4403_cap_table, ARRAY_SIZE(afe4403_cap_table)); +static AFE440X_ATTR(in_intensity4_resistance, F_RF_LED1, afe4403_res_table); +static AFE440X_ATTR(in_intensity4_capacitance, F_CF_LED1, afe4403_cap_table); static struct attribute *afe440x_attributes[] = { - &afe440x_attr_tia_separate_en.dev_attr.attr, - &afe440x_attr_tia_resistance1.dev_attr.attr, - &afe440x_attr_tia_capacitance1.dev_attr.attr, - &afe440x_attr_tia_resistance2.dev_attr.attr, - &afe440x_attr_tia_capacitance2.dev_attr.attr, - &dev_attr_tia_resistance_available.attr, - &dev_attr_tia_capacitance_available.attr, + &dev_attr_in_intensity_resistance_available.attr, + &dev_attr_in_intensity_capacitance_available.attr, + &afe440x_attr_in_intensity1_resistance.dev_attr.attr, + &afe440x_attr_in_intensity1_capacitance.dev_attr.attr, + &afe440x_attr_in_intensity2_resistance.dev_attr.attr, + &afe440x_attr_in_intensity2_capacitance.dev_attr.attr, + &afe440x_attr_in_intensity3_resistance.dev_attr.attr, + &afe440x_attr_in_intensity3_capacitance.dev_attr.attr, + &afe440x_attr_in_intensity4_resistance.dev_attr.attr, + &afe440x_attr_in_intensity4_capacitance.dev_attr.attr, NULL }; @@ -309,35 +250,26 @@ static int afe4403_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { struct afe4403_data *afe = iio_priv(indio_dev); - const struct afe440x_reg_info reg_info = afe4403_reg_info[chan->address]; + unsigned int reg = afe4403_channel_values[chan->address]; + unsigned int field = afe4403_channel_leds[chan->address]; int ret; switch (chan->type) { case IIO_INTENSITY: switch (mask) { case IIO_CHAN_INFO_RAW: - ret = afe4403_read(afe, reg_info.reg, val); - if (ret) - return ret; - return IIO_VAL_INT; - case IIO_CHAN_INFO_OFFSET: - ret = regmap_read(afe->regmap, reg_info.offreg, - val); + ret = afe4403_read(afe, reg, val); if (ret) return ret; - *val &= reg_info.mask; - *val >>= reg_info.shift; return IIO_VAL_INT; } break; case IIO_CURRENT: switch (mask) { case IIO_CHAN_INFO_RAW: - ret = regmap_read(afe->regmap, reg_info.reg, val); + ret = regmap_field_read(afe->fields[field], val); if (ret) return ret; - *val &= reg_info.mask; - *val >>= reg_info.shift; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: *val = 0; @@ -357,25 +289,13 @@ static int afe4403_write_raw(struct iio_dev *indio_dev, int val, int val2, long mask) { struct afe4403_data *afe = iio_priv(indio_dev); - const struct afe440x_reg_info reg_info = afe4403_reg_info[chan->address]; + unsigned int field = afe4403_channel_leds[chan->address]; switch (chan->type) { - case IIO_INTENSITY: - switch (mask) { - case IIO_CHAN_INFO_OFFSET: - return regmap_update_bits(afe->regmap, - reg_info.offreg, - reg_info.mask, - (val << reg_info.shift)); - } - break; case IIO_CURRENT: switch (mask) { case IIO_CHAN_INFO_RAW: - return regmap_update_bits(afe->regmap, - reg_info.reg, - reg_info.mask, - (val << reg_info.shift)); + return regmap_field_write(afe->fields[field], val); } break; default: @@ -410,7 +330,7 @@ static irqreturn_t afe4403_trigger_handler(int irq, void *private) for_each_set_bit(bit, indio_dev->active_scan_mask, indio_dev->masklength) { ret = spi_write_then_read(afe->spi, - &afe4403_reg_info[bit].reg, 1, + &afe4403_channel_values[bit], 1, rx, 3); if (ret) goto err; @@ -472,12 +392,8 @@ static const struct iio_trigger_ops afe4403_trigger_ops = { static const struct reg_sequence afe4403_reg_sequences[] = { AFE4403_TIMING_PAIRS, - { AFE440X_CONTROL1, AFE440X_CONTROL1_TIMEREN | 0x000007}, - { AFE4403_TIA_AMB_GAIN, AFE4403_TIAGAIN_RES_1_M }, - { AFE440X_LEDCNTRL, (0x14 << AFE440X_LEDCNTRL_LED1_SHIFT) | - (0x14 << AFE440X_LEDCNTRL_LED2_SHIFT) }, - { AFE440X_CONTROL2, AFE440X_CONTROL2_TX_REF_050 << - AFE440X_CONTROL2_TX_REF_SHIFT }, + { AFE440X_CONTROL1, AFE440X_CONTROL1_TIMEREN }, + { AFE4403_TIAGAIN, AFE440X_TIAGAIN_ENSEPGAIN }, }; static const struct regmap_range afe4403_yes_ranges[] = { @@ -498,13 +414,11 @@ static const struct regmap_config afe4403_regmap_config = { .volatile_table = &afe4403_volatile_table, }; -#ifdef CONFIG_OF static const struct of_device_id afe4403_of_match[] = { { .compatible = "ti,afe4403", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, afe4403_of_match); -#endif static int __maybe_unused afe4403_suspend(struct device *dev) { @@ -553,7 +467,7 @@ static int afe4403_probe(struct spi_device *spi) { struct iio_dev *indio_dev; struct afe4403_data *afe; - int ret; + int i, ret; indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*afe)); if (!indio_dev) @@ -572,6 +486,15 @@ static int afe4403_probe(struct spi_device *spi) return PTR_ERR(afe->regmap); } + for (i = 0; i < F_MAX_FIELDS; i++) { + afe->fields[i] = devm_regmap_field_alloc(afe->dev, afe->regmap, + afe4403_reg_fields[i]); + if (IS_ERR(afe->fields[i])) { + dev_err(afe->dev, "Unable to allocate regmap fields\n"); + return PTR_ERR(afe->fields[i]); + } + } + afe->regulator = devm_regulator_get(afe->dev, "tx_sup"); if (IS_ERR(afe->regulator)) { dev_err(afe->dev, "Unable to get regulator\n"); @@ -694,7 +617,7 @@ MODULE_DEVICE_TABLE(spi, afe4403_ids); static struct spi_driver afe4403_spi_driver = { .driver = { .name = AFE4403_DRIVER_NAME, - .of_match_table = of_match_ptr(afe4403_of_match), + .of_match_table = afe4403_of_match, .pm = &afe4403_pm_ops, }, .probe = afe4403_probe, @@ -704,5 +627,5 @@ static struct spi_driver afe4403_spi_driver = { module_spi_driver(afe4403_spi_driver); MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); -MODULE_DESCRIPTION("TI AFE4403 Heart Rate and Pulse Oximeter"); +MODULE_DESCRIPTION("TI AFE4403 Heart Rate Monitor and Pulse Oximeter AFE"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/health/afe4404.c b/drivers/iio/health/afe4404.c index 5096a4643784..45266404f7e3 100644 --- a/drivers/iio/health/afe4404.c +++ b/drivers/iio/health/afe4404.c @@ -1,7 +1,7 @@ /* * AFE4404 Heart Rate Monitors and Low-Cost Pulse Oximeters * - * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/ * Andrew F. Davis <afd@ti.com> * * This program is free software; you can redistribute it and/or modify @@ -48,118 +48,102 @@ #define AFE4404_AVG_LED2_ALED2VAL 0x3f #define AFE4404_AVG_LED1_ALED1VAL 0x40 -/* AFE4404 GAIN register fields */ -#define AFE4404_TIA_GAIN_RES_MASK GENMASK(2, 0) -#define AFE4404_TIA_GAIN_RES_SHIFT 0 -#define AFE4404_TIA_GAIN_CAP_MASK GENMASK(5, 3) -#define AFE4404_TIA_GAIN_CAP_SHIFT 3 +/* AFE4404 CONTROL2 register fields */ +#define AFE440X_CONTROL2_OSC_ENABLE BIT(9) -/* AFE4404 LEDCNTRL register fields */ -#define AFE4404_LEDCNTRL_ILED1_MASK GENMASK(5, 0) -#define AFE4404_LEDCNTRL_ILED1_SHIFT 0 -#define AFE4404_LEDCNTRL_ILED2_MASK GENMASK(11, 6) -#define AFE4404_LEDCNTRL_ILED2_SHIFT 6 -#define AFE4404_LEDCNTRL_ILED3_MASK GENMASK(17, 12) -#define AFE4404_LEDCNTRL_ILED3_SHIFT 12 +enum afe4404_fields { + /* Gains */ + F_TIA_GAIN_SEP, F_TIA_CF_SEP, + F_TIA_GAIN, TIA_CF, -/* AFE4404 CONTROL2 register fields */ -#define AFE440X_CONTROL2_ILED_2X_MASK BIT(17) -#define AFE440X_CONTROL2_ILED_2X_SHIFT 17 - -/* AFE4404 CONTROL3 register fields */ -#define AFE440X_CONTROL3_OSC_ENABLE BIT(9) - -/* AFE4404 OFFDAC register current fields */ -#define AFE4404_OFFDAC_CURR_LED1_MASK GENMASK(9, 5) -#define AFE4404_OFFDAC_CURR_LED1_SHIFT 5 -#define AFE4404_OFFDAC_CURR_LED2_MASK GENMASK(19, 15) -#define AFE4404_OFFDAC_CURR_LED2_SHIFT 15 -#define AFE4404_OFFDAC_CURR_LED3_MASK GENMASK(4, 0) -#define AFE4404_OFFDAC_CURR_LED3_SHIFT 0 -#define AFE4404_OFFDAC_CURR_ALED1_MASK GENMASK(14, 10) -#define AFE4404_OFFDAC_CURR_ALED1_SHIFT 10 -#define AFE4404_OFFDAC_CURR_ALED2_MASK GENMASK(4, 0) -#define AFE4404_OFFDAC_CURR_ALED2_SHIFT 0 - -/* AFE4404 NULL fields */ -#define NULL_MASK 0 -#define NULL_SHIFT 0 - -/* AFE4404 TIA_GAIN_CAP values */ -#define AFE4404_TIA_GAIN_CAP_5_P 0x0 -#define AFE4404_TIA_GAIN_CAP_2_5_P 0x1 -#define AFE4404_TIA_GAIN_CAP_10_P 0x2 -#define AFE4404_TIA_GAIN_CAP_7_5_P 0x3 -#define AFE4404_TIA_GAIN_CAP_20_P 0x4 -#define AFE4404_TIA_GAIN_CAP_17_5_P 0x5 -#define AFE4404_TIA_GAIN_CAP_25_P 0x6 -#define AFE4404_TIA_GAIN_CAP_22_5_P 0x7 - -/* AFE4404 TIA_GAIN_RES values */ -#define AFE4404_TIA_GAIN_RES_500_K 0x0 -#define AFE4404_TIA_GAIN_RES_250_K 0x1 -#define AFE4404_TIA_GAIN_RES_100_K 0x2 -#define AFE4404_TIA_GAIN_RES_50_K 0x3 -#define AFE4404_TIA_GAIN_RES_25_K 0x4 -#define AFE4404_TIA_GAIN_RES_10_K 0x5 -#define AFE4404_TIA_GAIN_RES_1_M 0x6 -#define AFE4404_TIA_GAIN_RES_2_M 0x7 + /* LED Current */ + F_ILED1, F_ILED2, F_ILED3, + + /* Offset DAC */ + F_OFFDAC_AMB2, F_OFFDAC_LED1, F_OFFDAC_AMB1, F_OFFDAC_LED2, + + /* sentinel */ + F_MAX_FIELDS +}; + +static const struct reg_field afe4404_reg_fields[] = { + /* Gains */ + [F_TIA_GAIN_SEP] = REG_FIELD(AFE4404_TIA_GAIN_SEP, 0, 2), + [F_TIA_CF_SEP] = REG_FIELD(AFE4404_TIA_GAIN_SEP, 3, 5), + [F_TIA_GAIN] = REG_FIELD(AFE4404_TIA_GAIN, 0, 2), + [TIA_CF] = REG_FIELD(AFE4404_TIA_GAIN, 3, 5), + /* LED Current */ + [F_ILED1] = REG_FIELD(AFE440X_LEDCNTRL, 0, 5), + [F_ILED2] = REG_FIELD(AFE440X_LEDCNTRL, 6, 11), + [F_ILED3] = REG_FIELD(AFE440X_LEDCNTRL, 12, 17), + /* Offset DAC */ + [F_OFFDAC_AMB2] = REG_FIELD(AFE4404_OFFDAC, 0, 4), + [F_OFFDAC_LED1] = REG_FIELD(AFE4404_OFFDAC, 5, 9), + [F_OFFDAC_AMB1] = REG_FIELD(AFE4404_OFFDAC, 10, 14), + [F_OFFDAC_LED2] = REG_FIELD(AFE4404_OFFDAC, 15, 19), +}; /** - * struct afe4404_data - * @dev - Device structure - * @regmap - Register map of the device - * @regulator - Pointer to the regulator for the IC - * @trig - IIO trigger for this device - * @irq - ADC_RDY line interrupt number + * struct afe4404_data - AFE4404 device instance data + * @dev: Device structure + * @regmap: Register map of the device + * @fields: Register fields of the device + * @regulator: Pointer to the regulator for the IC + * @trig: IIO trigger for this device + * @irq: ADC_RDY line interrupt number */ struct afe4404_data { struct device *dev; struct regmap *regmap; + struct regmap_field *fields[F_MAX_FIELDS]; struct regulator *regulator; struct iio_trigger *trig; int irq; }; enum afe4404_chan_id { + LED2 = 1, + ALED2, LED1, ALED1, - LED2, - ALED2, - LED3, - LED1_ALED1, LED2_ALED2, - ILED1, - ILED2, - ILED3, + LED1_ALED1, +}; + +static const unsigned int afe4404_channel_values[] = { + [LED2] = AFE440X_LED2VAL, + [ALED2] = AFE440X_ALED2VAL, + [LED1] = AFE440X_LED1VAL, + [ALED1] = AFE440X_ALED1VAL, + [LED2_ALED2] = AFE440X_LED2_ALED2VAL, + [LED1_ALED1] = AFE440X_LED1_ALED1VAL, }; -static const struct afe440x_reg_info afe4404_reg_info[] = { - [LED1] = AFE440X_REG_INFO(AFE440X_LED1VAL, AFE4404_OFFDAC, AFE4404_OFFDAC_CURR_LED1), - [ALED1] = AFE440X_REG_INFO(AFE440X_ALED1VAL, AFE4404_OFFDAC, AFE4404_OFFDAC_CURR_ALED1), - [LED2] = AFE440X_REG_INFO(AFE440X_LED2VAL, AFE4404_OFFDAC, AFE4404_OFFDAC_CURR_LED2), - [ALED2] = AFE440X_REG_INFO(AFE440X_ALED2VAL, AFE4404_OFFDAC, AFE4404_OFFDAC_CURR_ALED2), - [LED3] = AFE440X_REG_INFO(AFE440X_ALED2VAL, 0, NULL), - [LED1_ALED1] = AFE440X_REG_INFO(AFE440X_LED1_ALED1VAL, 0, NULL), - [LED2_ALED2] = AFE440X_REG_INFO(AFE440X_LED2_ALED2VAL, 0, NULL), - [ILED1] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE4404_LEDCNTRL_ILED1), - [ILED2] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE4404_LEDCNTRL_ILED2), - [ILED3] = AFE440X_REG_INFO(AFE440X_LEDCNTRL, 0, AFE4404_LEDCNTRL_ILED3), +static const unsigned int afe4404_channel_leds[] = { + [LED2] = F_ILED2, + [ALED2] = F_ILED3, + [LED1] = F_ILED1, +}; + +static const unsigned int afe4404_channel_offdacs[] = { + [LED2] = F_OFFDAC_LED2, + [ALED2] = F_OFFDAC_AMB2, + [LED1] = F_OFFDAC_LED1, + [ALED1] = F_OFFDAC_AMB1, }; static const struct iio_chan_spec afe4404_channels[] = { /* ADC values */ - AFE440X_INTENSITY_CHAN(LED1, "led1", BIT(IIO_CHAN_INFO_OFFSET)), - AFE440X_INTENSITY_CHAN(ALED1, "led1_ambient", BIT(IIO_CHAN_INFO_OFFSET)), - AFE440X_INTENSITY_CHAN(LED2, "led2", BIT(IIO_CHAN_INFO_OFFSET)), - AFE440X_INTENSITY_CHAN(ALED2, "led2_ambient", BIT(IIO_CHAN_INFO_OFFSET)), - AFE440X_INTENSITY_CHAN(LED3, "led3", BIT(IIO_CHAN_INFO_OFFSET)), - AFE440X_INTENSITY_CHAN(LED1_ALED1, "led1-led1_ambient", 0), - AFE440X_INTENSITY_CHAN(LED2_ALED2, "led2-led2_ambient", 0), + AFE440X_INTENSITY_CHAN(LED2, BIT(IIO_CHAN_INFO_OFFSET)), + AFE440X_INTENSITY_CHAN(ALED2, BIT(IIO_CHAN_INFO_OFFSET)), + AFE440X_INTENSITY_CHAN(LED1, BIT(IIO_CHAN_INFO_OFFSET)), + AFE440X_INTENSITY_CHAN(ALED1, BIT(IIO_CHAN_INFO_OFFSET)), + AFE440X_INTENSITY_CHAN(LED2_ALED2, 0), + AFE440X_INTENSITY_CHAN(LED1_ALED1, 0), /* LED current */ - AFE440X_CURRENT_CHAN(ILED1, "led1"), - AFE440X_CURRENT_CHAN(ILED2, "led2"), - AFE440X_CURRENT_CHAN(ILED3, "led3"), + AFE440X_CURRENT_CHAN(LED2), + AFE440X_CURRENT_CHAN(ALED2), + AFE440X_CURRENT_CHAN(LED1), }; static const struct afe440x_val_table afe4404_res_table[] = { @@ -172,7 +156,7 @@ static const struct afe440x_val_table afe4404_res_table[] = { { .integer = 1000000, .fract = 0 }, { .integer = 2000000, .fract = 0 }, }; -AFE440X_TABLE_ATTR(tia_resistance_available, afe4404_res_table); +AFE440X_TABLE_ATTR(in_intensity_resistance_available, afe4404_res_table); static const struct afe440x_val_table afe4404_cap_table[] = { { .integer = 0, .fract = 5000 }, @@ -184,7 +168,7 @@ static const struct afe440x_val_table afe4404_cap_table[] = { { .integer = 0, .fract = 25000 }, { .integer = 0, .fract = 22500 }, }; -AFE440X_TABLE_ATTR(tia_capacitance_available, afe4404_cap_table); +AFE440X_TABLE_ATTR(in_intensity_capacitance_available, afe4404_cap_table); static ssize_t afe440x_show_register(struct device *dev, struct device_attribute *attr, @@ -193,38 +177,21 @@ static ssize_t afe440x_show_register(struct device *dev, struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct afe4404_data *afe = iio_priv(indio_dev); struct afe440x_attr *afe440x_attr = to_afe440x_attr(attr); - unsigned int reg_val, type; + unsigned int reg_val; int vals[2]; - int ret, val_len; + int ret; - ret = regmap_read(afe->regmap, afe440x_attr->reg, ®_val); + ret = regmap_field_read(afe->fields[afe440x_attr->field], ®_val); if (ret) return ret; - reg_val &= afe440x_attr->mask; - reg_val >>= afe440x_attr->shift; - - switch (afe440x_attr->type) { - case SIMPLE: - type = IIO_VAL_INT; - val_len = 1; - vals[0] = reg_val; - break; - case RESISTANCE: - case CAPACITANCE: - type = IIO_VAL_INT_PLUS_MICRO; - val_len = 2; - if (reg_val < afe440x_attr->table_size) { - vals[0] = afe440x_attr->val_table[reg_val].integer; - vals[1] = afe440x_attr->val_table[reg_val].fract; - break; - } - return -EINVAL; - default: + if (reg_val >= afe440x_attr->table_size) return -EINVAL; - } - return iio_format_value(buf, type, val_len, vals); + vals[0] = afe440x_attr->val_table[reg_val].integer; + vals[1] = afe440x_attr->val_table[reg_val].fract; + + return iio_format_value(buf, IIO_VAL_INT_PLUS_MICRO, 2, vals); } static ssize_t afe440x_store_register(struct device *dev, @@ -240,48 +207,43 @@ static ssize_t afe440x_store_register(struct device *dev, if (ret) return ret; - switch (afe440x_attr->type) { - case SIMPLE: - val = integer; - break; - case RESISTANCE: - case CAPACITANCE: - for (val = 0; val < afe440x_attr->table_size; val++) - if (afe440x_attr->val_table[val].integer == integer && - afe440x_attr->val_table[val].fract == fract) - break; - if (val == afe440x_attr->table_size) - return -EINVAL; - break; - default: + for (val = 0; val < afe440x_attr->table_size; val++) + if (afe440x_attr->val_table[val].integer == integer && + afe440x_attr->val_table[val].fract == fract) + break; + if (val == afe440x_attr->table_size) return -EINVAL; - } - ret = regmap_update_bits(afe->regmap, afe440x_attr->reg, - afe440x_attr->mask, - (val << afe440x_attr->shift)); + ret = regmap_field_write(afe->fields[afe440x_attr->field], val); if (ret) return ret; return count; } -static AFE440X_ATTR(tia_separate_en, AFE4404_TIA_GAIN_SEP, AFE440X_TIAGAIN_ENSEPGAIN, SIMPLE, NULL, 0); +static AFE440X_ATTR(in_intensity1_resistance, F_TIA_GAIN_SEP, afe4404_res_table); +static AFE440X_ATTR(in_intensity1_capacitance, F_TIA_CF_SEP, afe4404_cap_table); + +static AFE440X_ATTR(in_intensity2_resistance, F_TIA_GAIN_SEP, afe4404_res_table); +static AFE440X_ATTR(in_intensity2_capacitance, F_TIA_CF_SEP, afe4404_cap_table); -static AFE440X_ATTR(tia_resistance1, AFE4404_TIA_GAIN, AFE4404_TIA_GAIN_RES, RESISTANCE, afe4404_res_table, ARRAY_SIZE(afe4404_res_table)); -static AFE440X_ATTR(tia_capacitance1, AFE4404_TIA_GAIN, AFE4404_TIA_GAIN_CAP, CAPACITANCE, afe4404_cap_table, ARRAY_SIZE(afe4404_cap_table)); +static AFE440X_ATTR(in_intensity3_resistance, F_TIA_GAIN, afe4404_res_table); +static AFE440X_ATTR(in_intensity3_capacitance, TIA_CF, afe4404_cap_table); -static AFE440X_ATTR(tia_resistance2, AFE4404_TIA_GAIN_SEP, AFE4404_TIA_GAIN_RES, RESISTANCE, afe4404_res_table, ARRAY_SIZE(afe4404_res_table)); -static AFE440X_ATTR(tia_capacitance2, AFE4404_TIA_GAIN_SEP, AFE4404_TIA_GAIN_CAP, CAPACITANCE, afe4404_cap_table, ARRAY_SIZE(afe4404_cap_table)); +static AFE440X_ATTR(in_intensity4_resistance, F_TIA_GAIN, afe4404_res_table); +static AFE440X_ATTR(in_intensity4_capacitance, TIA_CF, afe4404_cap_table); static struct attribute *afe440x_attributes[] = { - &afe440x_attr_tia_separate_en.dev_attr.attr, - &afe440x_attr_tia_resistance1.dev_attr.attr, - &afe440x_attr_tia_capacitance1.dev_attr.attr, - &afe440x_attr_tia_resistance2.dev_attr.attr, - &afe440x_attr_tia_capacitance2.dev_attr.attr, - &dev_attr_tia_resistance_available.attr, - &dev_attr_tia_capacitance_available.attr, + &dev_attr_in_intensity_resistance_available.attr, + &dev_attr_in_intensity_capacitance_available.attr, + &afe440x_attr_in_intensity1_resistance.dev_attr.attr, + &afe440x_attr_in_intensity1_capacitance.dev_attr.attr, + &afe440x_attr_in_intensity2_resistance.dev_attr.attr, + &afe440x_attr_in_intensity2_capacitance.dev_attr.attr, + &afe440x_attr_in_intensity3_resistance.dev_attr.attr, + &afe440x_attr_in_intensity3_capacitance.dev_attr.attr, + &afe440x_attr_in_intensity4_resistance.dev_attr.attr, + &afe440x_attr_in_intensity4_capacitance.dev_attr.attr, NULL }; @@ -294,35 +256,32 @@ static int afe4404_read_raw(struct iio_dev *indio_dev, int *val, int *val2, long mask) { struct afe4404_data *afe = iio_priv(indio_dev); - const struct afe440x_reg_info reg_info = afe4404_reg_info[chan->address]; + unsigned int value_reg = afe4404_channel_values[chan->address]; + unsigned int led_field = afe4404_channel_leds[chan->address]; + unsigned int offdac_field = afe4404_channel_offdacs[chan->address]; int ret; switch (chan->type) { case IIO_INTENSITY: switch (mask) { case IIO_CHAN_INFO_RAW: - ret = regmap_read(afe->regmap, reg_info.reg, val); + ret = regmap_read(afe->regmap, value_reg, val); if (ret) return ret; return IIO_VAL_INT; case IIO_CHAN_INFO_OFFSET: - ret = regmap_read(afe->regmap, reg_info.offreg, - val); + ret = regmap_field_read(afe->fields[offdac_field], val); if (ret) return ret; - *val &= reg_info.mask; - *val >>= reg_info.shift; return IIO_VAL_INT; } break; case IIO_CURRENT: switch (mask) { case IIO_CHAN_INFO_RAW: - ret = regmap_read(afe->regmap, reg_info.reg, val); + ret = regmap_field_read(afe->fields[led_field], val); if (ret) return ret; - *val &= reg_info.mask; - *val >>= reg_info.shift; return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: *val = 0; @@ -342,25 +301,20 @@ static int afe4404_write_raw(struct iio_dev *indio_dev, int val, int val2, long mask) { struct afe4404_data *afe = iio_priv(indio_dev); - const struct afe440x_reg_info reg_info = afe4404_reg_info[chan->address]; + unsigned int led_field = afe4404_channel_leds[chan->address]; + unsigned int offdac_field = afe4404_channel_offdacs[chan->address]; switch (chan->type) { case IIO_INTENSITY: switch (mask) { case IIO_CHAN_INFO_OFFSET: - return regmap_update_bits(afe->regmap, - reg_info.offreg, - reg_info.mask, - (val << reg_info.shift)); + return regmap_field_write(afe->fields[offdac_field], val); } break; case IIO_CURRENT: switch (mask) { case IIO_CHAN_INFO_RAW: - return regmap_update_bits(afe->regmap, - reg_info.reg, - reg_info.mask, - (val << reg_info.shift)); + return regmap_field_write(afe->fields[led_field], val); } break; default: @@ -387,7 +341,7 @@ static irqreturn_t afe4404_trigger_handler(int irq, void *private) for_each_set_bit(bit, indio_dev->active_scan_mask, indio_dev->masklength) { - ret = regmap_read(afe->regmap, afe4404_reg_info[bit].reg, + ret = regmap_read(afe->regmap, afe4404_channel_values[bit], &buffer[i++]); if (ret) goto err; @@ -443,11 +397,8 @@ static const struct iio_trigger_ops afe4404_trigger_ops = { static const struct reg_sequence afe4404_reg_sequences[] = { AFE4404_TIMING_PAIRS, { AFE440X_CONTROL1, AFE440X_CONTROL1_TIMEREN }, - { AFE4404_TIA_GAIN, AFE4404_TIA_GAIN_RES_50_K }, - { AFE440X_LEDCNTRL, (0xf << AFE4404_LEDCNTRL_ILED1_SHIFT) | - (0x3 << AFE4404_LEDCNTRL_ILED2_SHIFT) | - (0x3 << AFE4404_LEDCNTRL_ILED3_SHIFT) }, - { AFE440X_CONTROL2, AFE440X_CONTROL3_OSC_ENABLE }, + { AFE4404_TIA_GAIN_SEP, AFE440X_TIAGAIN_ENSEPGAIN }, + { AFE440X_CONTROL2, AFE440X_CONTROL2_OSC_ENABLE }, }; static const struct regmap_range afe4404_yes_ranges[] = { @@ -469,13 +420,11 @@ static const struct regmap_config afe4404_regmap_config = { .volatile_table = &afe4404_volatile_table, }; -#ifdef CONFIG_OF static const struct of_device_id afe4404_of_match[] = { { .compatible = "ti,afe4404", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, afe4404_of_match); -#endif static int __maybe_unused afe4404_suspend(struct device *dev) { @@ -525,7 +474,7 @@ static int afe4404_probe(struct i2c_client *client, { struct iio_dev *indio_dev; struct afe4404_data *afe; - int ret; + int i, ret; indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*afe)); if (!indio_dev) @@ -543,6 +492,15 @@ static int afe4404_probe(struct i2c_client *client, return PTR_ERR(afe->regmap); } + for (i = 0; i < F_MAX_FIELDS; i++) { + afe->fields[i] = devm_regmap_field_alloc(afe->dev, afe->regmap, + afe4404_reg_fields[i]); + if (IS_ERR(afe->fields[i])) { + dev_err(afe->dev, "Unable to allocate regmap fields\n"); + return PTR_ERR(afe->fields[i]); + } + } + afe->regulator = devm_regulator_get(afe->dev, "tx_sup"); if (IS_ERR(afe->regulator)) { dev_err(afe->dev, "Unable to get regulator\n"); @@ -665,7 +623,7 @@ MODULE_DEVICE_TABLE(i2c, afe4404_ids); static struct i2c_driver afe4404_i2c_driver = { .driver = { .name = AFE4404_DRIVER_NAME, - .of_match_table = of_match_ptr(afe4404_of_match), + .of_match_table = afe4404_of_match, .pm = &afe4404_pm_ops, }, .probe = afe4404_probe, @@ -675,5 +633,5 @@ static struct i2c_driver afe4404_i2c_driver = { module_i2c_driver(afe4404_i2c_driver); MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); -MODULE_DESCRIPTION("TI AFE4404 Heart Rate and Pulse Oximeter"); +MODULE_DESCRIPTION("TI AFE4404 Heart Rate Monitor and Pulse Oximeter AFE"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/health/afe440x.h b/drivers/iio/health/afe440x.h index c671ab78a23a..1a0f247043ca 100644 --- a/drivers/iio/health/afe440x.h +++ b/drivers/iio/health/afe440x.h @@ -71,8 +71,7 @@ #define AFE440X_CONTROL1_TIMEREN BIT(8) /* TIAGAIN register fields */ -#define AFE440X_TIAGAIN_ENSEPGAIN_MASK BIT(15) -#define AFE440X_TIAGAIN_ENSEPGAIN_SHIFT 15 +#define AFE440X_TIAGAIN_ENSEPGAIN BIT(15) /* CONTROL2 register fields */ #define AFE440X_CONTROL2_PDN_AFE BIT(0) @@ -89,22 +88,7 @@ #define AFE440X_CONTROL0_WRITE 0x0 #define AFE440X_CONTROL0_READ 0x1 -struct afe440x_reg_info { - unsigned int reg; - unsigned int offreg; - unsigned int shift; - unsigned int mask; -}; - -#define AFE440X_REG_INFO(_reg, _offreg, _sm) \ - { \ - .reg = _reg, \ - .offreg = _offreg, \ - .shift = _sm ## _SHIFT, \ - .mask = _sm ## _MASK, \ - } - -#define AFE440X_INTENSITY_CHAN(_index, _name, _mask) \ +#define AFE440X_INTENSITY_CHAN(_index, _mask) \ { \ .type = IIO_INTENSITY, \ .channel = _index, \ @@ -116,29 +100,23 @@ struct afe440x_reg_info { .storagebits = 32, \ .endianness = IIO_CPU, \ }, \ - .extend_name = _name, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ _mask, \ + .indexed = true, \ } -#define AFE440X_CURRENT_CHAN(_index, _name) \ +#define AFE440X_CURRENT_CHAN(_index) \ { \ .type = IIO_CURRENT, \ .channel = _index, \ .address = _index, \ - .scan_index = _index, \ - .extend_name = _name, \ + .scan_index = -1, \ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ BIT(IIO_CHAN_INFO_SCALE), \ + .indexed = true, \ .output = true, \ } -enum afe440x_reg_type { - SIMPLE, - RESISTANCE, - CAPACITANCE, -}; - struct afe440x_val_table { int integer; int fract; @@ -164,10 +142,7 @@ static DEVICE_ATTR_RO(_name) struct afe440x_attr { struct device_attribute dev_attr; - unsigned int reg; - unsigned int shift; - unsigned int mask; - enum afe440x_reg_type type; + unsigned int field; const struct afe440x_val_table *val_table; unsigned int table_size; }; @@ -175,17 +150,14 @@ struct afe440x_attr { #define to_afe440x_attr(_dev_attr) \ container_of(_dev_attr, struct afe440x_attr, dev_attr) -#define AFE440X_ATTR(_name, _reg, _field, _type, _table, _size) \ +#define AFE440X_ATTR(_name, _field, _table) \ struct afe440x_attr afe440x_attr_##_name = { \ .dev_attr = __ATTR(_name, (S_IRUGO | S_IWUSR), \ afe440x_show_register, \ afe440x_store_register), \ - .reg = _reg, \ - .shift = _field ## _SHIFT, \ - .mask = _field ## _MASK, \ - .type = _type, \ + .field = _field, \ .val_table = _table, \ - .table_size = _size, \ + .table_size = ARRAY_SIZE(_table), \ } #endif /* _AFE440X_H */ |