* [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver
@ 2017-10-27 19:45 Peter Meerwald-Stadler
2017-10-27 19:45 ` [PATCH v2 01/13] iio: health: max30102: Temperature should be in milli Celsius Peter Meerwald-Stadler
` (13 more replies)
0 siblings, 14 replies; 41+ messages in thread
From: Peter Meerwald-Stadler @ 2017-10-27 19:45 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio
This patch series reworks the max30102 driver to add support for the MAX30105
part (which add a third LED)
v2:
* send correct patches, sorry for the mess
* fix Matt Ranostay's email address
patches 1 to 3 are bugfix
patches 4 to 6 add minor features and cleanup
patch 8 allows to read the temperature without currently measuring other channels
patches 9 to 11 prepare for adding another LED, more flexibility
patch 12 adds support for the MAX30105 part
patch 13 updates devicetree documentation for the MAX30105 part
Peter Meerwald-Stadler (13):
iio: health: max30102: Temperature should be in milli Celsius
iio: health: max30102: Fix missing newline in dev_err
iio: health: max30102: Remove inconsistent full stop in error message
iio: health: max30102: Fix mode config values
iio: health: max30102: Check retval of powermode function
iio: health: max30102: Add check for part ID
iio: health: max30102: Introduce intensity channel macro
iio: health: max30102: Add power enable parameter to get_temp function
iio: health: max30102: Introduce indices for LED channels
iio: health: max30102: Move mode setting to buffer_postenable
iio: health: max30102: Prepare for copying varying number of
measurements
iio: health: max30102: Add MAX30105 support
dt-bindings: iio: health: Add MAX30105 support to max30102.txt
.../devicetree/bindings/iio/health/max30102.txt | 8 +-
drivers/iio/health/max30102.c | 310 ++++++++++++++++-----
2 files changed, 241 insertions(+), 77 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 41+ messages in thread
* [PATCH v2 01/13] iio: health: max30102: Temperature should be in milli Celsius
2017-10-27 19:45 [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver Peter Meerwald-Stadler
@ 2017-10-27 19:45 ` Peter Meerwald-Stadler
2017-11-19 21:09 ` Matt Ranostay
2017-10-27 19:45 ` [PATCH v2 02/13] iio: health: max30102: Fix missing newline in dev_err Peter Meerwald-Stadler
` (12 subsequent siblings)
13 siblings, 1 reply; 41+ messages in thread
From: Peter Meerwald-Stadler @ 2017-10-27 19:45 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, Peter Meerwald-Stadler, Matt Ranostay
As per ABI temperature should be in milli Celsius after scaling,
not Celsius
Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
Cc: Matt Ranostay <matt.ranostay@konsulko.com>
---
drivers/iio/health/max30102.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
index 203ffb9..147a8c1 100644
--- a/drivers/iio/health/max30102.c
+++ b/drivers/iio/health/max30102.c
@@ -371,7 +371,7 @@ static int max30102_read_raw(struct iio_dev *indio_dev,
mutex_unlock(&indio_dev->mlock);
break;
case IIO_CHAN_INFO_SCALE:
- *val = 1; /* 0.0625 */
+ *val = 1000; /* 62.5 */
*val2 = 16;
ret = IIO_VAL_FRACTIONAL;
break;
--
2.7.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v2 02/13] iio: health: max30102: Fix missing newline in dev_err
2017-10-27 19:45 [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver Peter Meerwald-Stadler
2017-10-27 19:45 ` [PATCH v2 01/13] iio: health: max30102: Temperature should be in milli Celsius Peter Meerwald-Stadler
@ 2017-10-27 19:45 ` Peter Meerwald-Stadler
2017-11-19 20:28 ` Matt Ranostay
2017-10-27 19:45 ` [PATCH v2 03/13] iio: health: max30102: Remove inconsistent full stop in error message Peter Meerwald-Stadler
` (11 subsequent siblings)
13 siblings, 1 reply; 41+ messages in thread
From: Peter Meerwald-Stadler @ 2017-10-27 19:45 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, Peter Meerwald-Stadler, Matt Ranostay
Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
Cc: Matt Ranostay <matt.ranostay@konsulko.com>
---
drivers/iio/health/max30102.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
index 147a8c1..62b1b35 100644
--- a/drivers/iio/health/max30102.c
+++ b/drivers/iio/health/max30102.c
@@ -261,7 +261,7 @@ static int max30102_led_init(struct max30102_data *data)
ret = max30102_get_current_idx(val, ®);
if (ret) {
- dev_err(dev, "invalid IR LED current setting %d", val);
+ dev_err(dev, "invalid IR LED current setting %d\n", val);
return ret;
}
--
2.7.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v2 03/13] iio: health: max30102: Remove inconsistent full stop in error message
2017-10-27 19:45 [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver Peter Meerwald-Stadler
2017-10-27 19:45 ` [PATCH v2 01/13] iio: health: max30102: Temperature should be in milli Celsius Peter Meerwald-Stadler
2017-10-27 19:45 ` [PATCH v2 02/13] iio: health: max30102: Fix missing newline in dev_err Peter Meerwald-Stadler
@ 2017-10-27 19:45 ` Peter Meerwald-Stadler
2017-11-19 20:28 ` Matt Ranostay
2017-10-27 19:45 ` [PATCH v2 04/13] iio: health: max30102: Fix mode config values Peter Meerwald-Stadler
` (10 subsequent siblings)
13 siblings, 1 reply; 41+ messages in thread
From: Peter Meerwald-Stadler @ 2017-10-27 19:45 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, Peter Meerwald-Stadler, Matt Ranostay
Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
Cc: Matt Ranostay <matt.ranostay@konsulko.com>
---
drivers/iio/health/max30102.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
index 62b1b35..6ca6182 100644
--- a/drivers/iio/health/max30102.c
+++ b/drivers/iio/health/max30102.c
@@ -420,7 +420,7 @@ static int max30102_probe(struct i2c_client *client,
data->regmap = devm_regmap_init_i2c(client, &max30102_regmap_config);
if (IS_ERR(data->regmap)) {
- dev_err(&client->dev, "regmap initialization failed.\n");
+ dev_err(&client->dev, "regmap initialization failed\n");
return PTR_ERR(data->regmap);
}
max30102_set_powermode(data, false);
--
2.7.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v2 04/13] iio: health: max30102: Fix mode config values
2017-10-27 19:45 [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver Peter Meerwald-Stadler
` (2 preceding siblings ...)
2017-10-27 19:45 ` [PATCH v2 03/13] iio: health: max30102: Remove inconsistent full stop in error message Peter Meerwald-Stadler
@ 2017-10-27 19:45 ` Peter Meerwald-Stadler
2017-11-19 20:46 ` Matt Ranostay
2017-10-27 19:45 ` [PATCH v2 05/13] iio: health: max30102: Check retval of powermode function Peter Meerwald-Stadler
` (9 subsequent siblings)
13 siblings, 1 reply; 41+ messages in thread
From: Peter Meerwald-Stadler @ 2017-10-27 19:45 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, Peter Meerwald-Stadler, Matt Ranostay
Table 4 of the datasheet specifies the mode control, these are not
individual bits; add multi LED mode
Add multi-LED mode and fix MODE_MASK (3 bits wide, not 2)
Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
Cc: Matt Ranostay <matt.ranostay@konsulko.com>
---
drivers/iio/health/max30102.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
index 6ca6182..13d5312 100644
--- a/drivers/iio/health/max30102.c
+++ b/drivers/iio/health/max30102.c
@@ -60,9 +60,10 @@
#define MAX30102_REG_FIFO_CONFIG_AFULL BIT(0)
#define MAX30102_REG_MODE_CONFIG 0x09
-#define MAX30102_REG_MODE_CONFIG_MODE_SPO2_EN BIT(0)
-#define MAX30102_REG_MODE_CONFIG_MODE_HR_EN BIT(1)
-#define MAX30102_REG_MODE_CONFIG_MODE_MASK 0x03
+#define MAX30102_REG_MODE_CONFIG_MODE_HR 0x02 /* red LED */
+#define MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2 0x03 /* red + IR LED */
+#define MAX30102_REG_MODE_CONFIG_MODE_MULTI 0x07 /* multi-LED mode */
+#define MAX30102_REG_MODE_CONFIG_MODE_MASK GENMASK(2, 0)
#define MAX30102_REG_MODE_CONFIG_PWR BIT(7)
#define MAX30102_REG_SPO2_CONFIG 0x0a
@@ -287,11 +288,10 @@ static int max30102_chip_init(struct max30102_data *data)
if (ret)
return ret;
- /* enable SPO2 mode */
+ /* enable HR + SPO2 mode */
ret = regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
MAX30102_REG_MODE_CONFIG_MODE_MASK,
- MAX30102_REG_MODE_CONFIG_MODE_HR_EN |
- MAX30102_REG_MODE_CONFIG_MODE_SPO2_EN);
+ MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2);
if (ret)
return ret;
--
2.7.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v2 05/13] iio: health: max30102: Check retval of powermode function
2017-10-27 19:45 [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver Peter Meerwald-Stadler
` (3 preceding siblings ...)
2017-10-27 19:45 ` [PATCH v2 04/13] iio: health: max30102: Fix mode config values Peter Meerwald-Stadler
@ 2017-10-27 19:45 ` Peter Meerwald-Stadler
2017-11-19 20:43 ` Matt Ranostay
2017-10-27 19:45 ` [PATCH v2 06/13] iio: health: max30102: Add check for part ID Peter Meerwald-Stadler
` (8 subsequent siblings)
13 siblings, 1 reply; 41+ messages in thread
From: Peter Meerwald-Stadler @ 2017-10-27 19:45 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, Peter Meerwald-Stadler, Matt Ranostay
Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
Cc: Matt Ranostay <matt.ranostay@konsulko.com>
---
drivers/iio/health/max30102.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
index 13d5312..389a483 100644
--- a/drivers/iio/health/max30102.c
+++ b/drivers/iio/health/max30102.c
@@ -423,7 +423,10 @@ static int max30102_probe(struct i2c_client *client,
dev_err(&client->dev, "regmap initialization failed\n");
return PTR_ERR(data->regmap);
}
- max30102_set_powermode(data, false);
+
+ ret = max30102_set_powermode(data, false);
+ if (ret)
+ return ret;
ret = max30102_chip_init(data);
if (ret)
--
2.7.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v2 06/13] iio: health: max30102: Add check for part ID
2017-10-27 19:45 [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver Peter Meerwald-Stadler
` (4 preceding siblings ...)
2017-10-27 19:45 ` [PATCH v2 05/13] iio: health: max30102: Check retval of powermode function Peter Meerwald-Stadler
@ 2017-10-27 19:45 ` Peter Meerwald-Stadler
2017-11-19 20:38 ` Matt Ranostay
2017-10-27 19:45 ` [PATCH v2 07/13] iio: health: max30102: Introduce intensity channel macro Peter Meerwald-Stadler
` (7 subsequent siblings)
13 siblings, 1 reply; 41+ messages in thread
From: Peter Meerwald-Stadler @ 2017-10-27 19:45 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, Peter Meerwald-Stadler, Matt Ranostay
Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
Cc: Matt Ranostay <matt.ranostay@konsulko.com>
---
drivers/iio/health/max30102.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
index 389a483..c43957e 100644
--- a/drivers/iio/health/max30102.c
+++ b/drivers/iio/health/max30102.c
@@ -32,6 +32,7 @@
#define MAX30102_REGMAP_NAME "max30102_regmap"
#define MAX30102_DRV_NAME "max30102"
+#define MAX30102_PART_NUMBER 0x15
#define MAX30102_REG_INT_STATUS 0x00
#define MAX30102_REG_INT_STATUS_PWR_RDY BIT(0)
@@ -83,6 +84,9 @@
#define MAX30102_REG_TEMP_INTEGER 0x1f
#define MAX30102_REG_TEMP_FRACTION 0x20
+#define MAX30102_REG_REV_ID 0xfe
+#define MAX30102_REG_PART_ID 0xff
+
struct max30102_data {
struct i2c_client *client;
struct iio_dev *indio_dev;
@@ -391,6 +395,7 @@ static int max30102_probe(struct i2c_client *client,
struct iio_buffer *buffer;
struct iio_dev *indio_dev;
int ret;
+ unsigned int reg;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
@@ -424,6 +429,19 @@ static int max30102_probe(struct i2c_client *client,
return PTR_ERR(data->regmap);
}
+ /* check part ID */
+ ret = regmap_read(data->regmap, MAX30102_REG_PART_ID, ®);
+ if (ret)
+ return ret;
+ if (reg != MAX30102_PART_NUMBER)
+ return -ENODEV;
+
+ /* show revision ID */
+ ret = regmap_read(data->regmap, MAX30102_REG_REV_ID, ®);
+ if (ret)
+ return ret;
+ dev_dbg(&client->dev, "max3010x revision %02x\n", reg);
+
ret = max30102_set_powermode(data, false);
if (ret)
return ret;
--
2.7.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v2 07/13] iio: health: max30102: Introduce intensity channel macro
2017-10-27 19:45 [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver Peter Meerwald-Stadler
` (5 preceding siblings ...)
2017-10-27 19:45 ` [PATCH v2 06/13] iio: health: max30102: Add check for part ID Peter Meerwald-Stadler
@ 2017-10-27 19:45 ` Peter Meerwald-Stadler
2017-11-19 20:37 ` Matt Ranostay
2017-10-27 19:45 ` [PATCH v2 08/13] iio: health: max30102: Add power enable parameter to get_temp function Peter Meerwald-Stadler
` (6 subsequent siblings)
13 siblings, 1 reply; 41+ messages in thread
From: Peter Meerwald-Stadler @ 2017-10-27 19:45 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, Peter Meerwald-Stalder, Matt Ranostay
Signed-off-by: Peter Meerwald-Stalder <pmeerw@pmeerw.net>
Cc: Matt Ranostay <matt.ranostay@konsulko.com>
---
drivers/iio/health/max30102.c | 44 ++++++++++++++++---------------------------
1 file changed, 16 insertions(+), 28 deletions(-)
diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
index c43957e..968b54b 100644
--- a/drivers/iio/health/max30102.c
+++ b/drivers/iio/health/max30102.c
@@ -106,35 +106,23 @@ static const struct regmap_config max30102_regmap_config = {
static const unsigned long max30102_scan_masks[] = {0x3, 0};
+#define MAX30102_INTENSITY_CHANNEL(_si, _mod) { \
+ .type = IIO_INTENSITY, \
+ .channel2 = _mod, \
+ .modified = 1, \
+ .scan_index = _si, \
+ .scan_type = { \
+ .sign = 'u', \
+ .shift = 8, \
+ .realbits = 18, \
+ .storagebits = 32, \
+ .endianness = IIO_BE, \
+ }, \
+ }
+
static const struct iio_chan_spec max30102_channels[] = {
- {
- .type = IIO_INTENSITY,
- .channel2 = IIO_MOD_LIGHT_RED,
- .modified = 1,
-
- .scan_index = 0,
- .scan_type = {
- .sign = 'u',
- .shift = 8,
- .realbits = 18,
- .storagebits = 32,
- .endianness = IIO_BE,
- },
- },
- {
- .type = IIO_INTENSITY,
- .channel2 = IIO_MOD_LIGHT_IR,
- .modified = 1,
-
- .scan_index = 1,
- .scan_type = {
- .sign = 'u',
- .shift = 8,
- .realbits = 18,
- .storagebits = 32,
- .endianness = IIO_BE,
- },
- },
+ MAX30102_INTENSITY_CHANNEL(0, IIO_MOD_LIGHT_RED),
+ MAX30102_INTENSITY_CHANNEL(1, IIO_MOD_LIGHT_IR),
{
.type = IIO_TEMP,
.info_mask_separate =
--
2.7.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v2 08/13] iio: health: max30102: Add power enable parameter to get_temp function
2017-10-27 19:45 [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver Peter Meerwald-Stadler
` (6 preceding siblings ...)
2017-10-27 19:45 ` [PATCH v2 07/13] iio: health: max30102: Introduce intensity channel macro Peter Meerwald-Stadler
@ 2017-10-27 19:45 ` Peter Meerwald-Stadler
2017-11-19 20:41 ` Matt Ranostay
2017-10-27 19:45 ` [PATCH v2 09/13] iio: health: max30102: Introduce indices for LED channels Peter Meerwald-Stadler
` (5 subsequent siblings)
13 siblings, 1 reply; 41+ messages in thread
From: Peter Meerwald-Stadler @ 2017-10-27 19:45 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, Peter Meerwald-Stadler, Matt Ranostay
Chip must not be in shutdown for reading temperature, so briefly leave
shutdown if buffer is not already running
Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
Cc: Matt Ranostay <matt.ranostay@konsulko.com>
---
drivers/iio/health/max30102.c | 36 +++++++++++++++++++++++-------------
1 file changed, 23 insertions(+), 13 deletions(-)
diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
index 968b54b..520d905 100644
--- a/drivers/iio/health/max30102.c
+++ b/drivers/iio/health/max30102.c
@@ -321,20 +321,31 @@ static int max30102_read_temp(struct max30102_data *data, int *val)
return 0;
}
-static int max30102_get_temp(struct max30102_data *data, int *val)
+static int max30102_get_temp(struct max30102_data *data, int *val, bool en)
{
int ret;
+ if (en) {
+ ret = max30102_set_powermode(data, true);
+ if (ret)
+ return ret;
+ }
+
/* start acquisition */
ret = regmap_update_bits(data->regmap, MAX30102_REG_TEMP_CONFIG,
MAX30102_REG_TEMP_CONFIG_TEMP_EN,
MAX30102_REG_TEMP_CONFIG_TEMP_EN);
if (ret)
- return ret;
+ goto out;
msleep(35);
+ ret = max30102_read_temp(data, val);
+
+out:
+ if (en)
+ max30102_set_powermode(data, false);
- return max30102_read_temp(data, val);
+ return ret;
}
static int max30102_read_raw(struct iio_dev *indio_dev,
@@ -347,20 +358,19 @@ static int max30102_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_RAW:
/*
- * Temperature reading can only be acquired while engine
- * is running
+ * Temperature reading can only be acquired when not in
+ * shutdown; leave shutdown briefly when buffer not running
*/
mutex_lock(&indio_dev->mlock);
-
if (!iio_buffer_enabled(indio_dev))
- ret = -EBUSY;
- else {
- ret = max30102_get_temp(data, val);
- if (!ret)
- ret = IIO_VAL_INT;
- }
-
+ ret = max30102_get_temp(data, val, true);
+ else
+ ret = max30102_get_temp(data, val, false);
mutex_unlock(&indio_dev->mlock);
+ if (ret)
+ return ret;
+
+ ret = IIO_VAL_INT;
break;
case IIO_CHAN_INFO_SCALE:
*val = 1000; /* 62.5 */
--
2.7.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v2 09/13] iio: health: max30102: Introduce indices for LED channels
2017-10-27 19:45 [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver Peter Meerwald-Stadler
` (7 preceding siblings ...)
2017-10-27 19:45 ` [PATCH v2 08/13] iio: health: max30102: Add power enable parameter to get_temp function Peter Meerwald-Stadler
@ 2017-10-27 19:45 ` Peter Meerwald-Stadler
2017-11-19 20:42 ` Matt Ranostay
2017-10-27 19:45 ` [PATCH v2 10/13] iio: health: max30102: Move mode setting to buffer_postenable Peter Meerwald-Stadler
` (4 subsequent siblings)
13 siblings, 1 reply; 41+ messages in thread
From: Peter Meerwald-Stadler @ 2017-10-27 19:45 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, Peter Meerwald-Stadler, Matt Ranostay
Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
Cc: Matt Ranostay <matt.ranostay@konsulko.com>
---
drivers/iio/health/max30102.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
index 520d905..37176c2 100644
--- a/drivers/iio/health/max30102.c
+++ b/drivers/iio/health/max30102.c
@@ -34,6 +34,11 @@
#define MAX30102_DRV_NAME "max30102"
#define MAX30102_PART_NUMBER 0x15
+enum max3012_led_idx {
+ MAX30102_LED_RED,
+ MAX30102_LED_IR,
+};
+
#define MAX30102_REG_INT_STATUS 0x00
#define MAX30102_REG_INT_STATUS_PWR_RDY BIT(0)
#define MAX30102_REG_INT_STATUS_PROX_INT BIT(4)
@@ -104,7 +109,10 @@ static const struct regmap_config max30102_regmap_config = {
.val_bits = 8,
};
-static const unsigned long max30102_scan_masks[] = {0x3, 0};
+static const unsigned long max30102_scan_masks[] = {
+ BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR),
+ 0
+};
#define MAX30102_INTENSITY_CHANNEL(_si, _mod) { \
.type = IIO_INTENSITY, \
@@ -121,8 +129,8 @@ static const unsigned long max30102_scan_masks[] = {0x3, 0};
}
static const struct iio_chan_spec max30102_channels[] = {
- MAX30102_INTENSITY_CHANNEL(0, IIO_MOD_LIGHT_RED),
- MAX30102_INTENSITY_CHANNEL(1, IIO_MOD_LIGHT_IR),
+ MAX30102_INTENSITY_CHANNEL(MAX30102_LED_RED, IIO_MOD_LIGHT_RED),
+ MAX30102_INTENSITY_CHANNEL(MAX30102_LED_IR, IIO_MOD_LIGHT_IR),
{
.type = IIO_TEMP,
.info_mask_separate =
--
2.7.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v2 10/13] iio: health: max30102: Move mode setting to buffer_postenable
2017-10-27 19:45 [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver Peter Meerwald-Stadler
` (8 preceding siblings ...)
2017-10-27 19:45 ` [PATCH v2 09/13] iio: health: max30102: Introduce indices for LED channels Peter Meerwald-Stadler
@ 2017-10-27 19:45 ` Peter Meerwald-Stadler
2017-11-19 20:56 ` Matt Ranostay
2017-10-27 19:45 ` [PATCH v2 11/13] iio: health: max30102: Prepare for copying varying number of measurements Peter Meerwald-Stadler
` (3 subsequent siblings)
13 siblings, 1 reply; 41+ messages in thread
From: Peter Meerwald-Stadler @ 2017-10-27 19:45 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, Peter Meerwald-Stadler, Matt Ranostay
Move the programming of the mode setting from init() to
buffer_postenable()
Split out a separate function to
only update the power/shutdown bit
This changes permits to more easily implement different
modes of measurements in further patches
Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
Cc: Matt Ranostay <matt.ranostay@konsulko.com>
---
drivers/iio/health/max30102.c | 44 +++++++++++++++++++++++++++----------------
1 file changed, 28 insertions(+), 16 deletions(-)
diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
index 37176c2..1c7fe63 100644
--- a/drivers/iio/health/max30102.c
+++ b/drivers/iio/health/max30102.c
@@ -66,6 +66,7 @@ enum max3012_led_idx {
#define MAX30102_REG_FIFO_CONFIG_AFULL BIT(0)
#define MAX30102_REG_MODE_CONFIG 0x09
+#define MAX30102_REG_MODE_CONFIG_MODE_NONE 0x00
#define MAX30102_REG_MODE_CONFIG_MODE_HR 0x02 /* red LED */
#define MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2 0x03 /* red + IR LED */
#define MAX30102_REG_MODE_CONFIG_MODE_MULTI 0x07 /* multi-LED mode */
@@ -139,25 +140,41 @@ static const struct iio_chan_spec max30102_channels[] = {
},
};
-static int max30102_set_powermode(struct max30102_data *data, bool state)
+static int max30102_set_power(struct max30102_data *data, bool en)
{
return regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
MAX30102_REG_MODE_CONFIG_PWR,
- state ? 0 : MAX30102_REG_MODE_CONFIG_PWR);
+ en ? 0 : MAX30102_REG_MODE_CONFIG_PWR);
+}
+
+static int max30102_set_powermode(struct max30102_data *data, u8 mode, bool en)
+{
+ u8 reg = mode;
+
+ if (!en)
+ reg |= MAX30102_REG_MODE_CONFIG_PWR;
+
+ return regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
+ MAX30102_REG_MODE_CONFIG_PWR |
+ MAX30102_REG_MODE_CONFIG_MODE_MASK, reg);
}
static int max30102_buffer_postenable(struct iio_dev *indio_dev)
{
struct max30102_data *data = iio_priv(indio_dev);
+ u8 reg;
+
+ reg = MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2;
- return max30102_set_powermode(data, true);
+ return max30102_set_powermode(data, reg, true);
}
static int max30102_buffer_predisable(struct iio_dev *indio_dev)
{
struct max30102_data *data = iio_priv(indio_dev);
- return max30102_set_powermode(data, false);
+ return max30102_set_powermode(data, MAX30102_REG_MODE_CONFIG_MODE_NONE,
+ false);
}
static const struct iio_buffer_setup_ops max30102_buffer_setup_ops = {
@@ -278,7 +295,7 @@ static int max30102_chip_init(struct max30102_data *data)
if (ret)
return ret;
- /* enable 18-bit HR + SPO2 readings at 400Hz */
+ /* configure 18-bit HR + SpO2 readings at 400Hz */
ret = regmap_write(data->regmap, MAX30102_REG_SPO2_CONFIG,
(MAX30102_REG_SPO2_CONFIG_ADC_4096_STEPS
<< MAX30102_REG_SPO2_CONFIG_ADC_MASK_SHIFT) |
@@ -288,13 +305,6 @@ static int max30102_chip_init(struct max30102_data *data)
if (ret)
return ret;
- /* enable HR + SPO2 mode */
- ret = regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
- MAX30102_REG_MODE_CONFIG_MODE_MASK,
- MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2);
- if (ret)
- return ret;
-
/* average 4 samples + generate FIFO interrupt */
ret = regmap_write(data->regmap, MAX30102_REG_FIFO_CONFIG,
(MAX30102_REG_FIFO_CONFIG_AVG_4SAMPLES
@@ -334,7 +344,7 @@ static int max30102_get_temp(struct max30102_data *data, int *val, bool en)
int ret;
if (en) {
- ret = max30102_set_powermode(data, true);
+ ret = max30102_set_power(data, true);
if (ret)
return ret;
}
@@ -351,7 +361,7 @@ static int max30102_get_temp(struct max30102_data *data, int *val, bool en)
out:
if (en)
- max30102_set_powermode(data, false);
+ max30102_set_power(data, false);
return ret;
}
@@ -448,7 +458,9 @@ static int max30102_probe(struct i2c_client *client,
return ret;
dev_dbg(&client->dev, "max3010x revision %02x\n", reg);
- ret = max30102_set_powermode(data, false);
+ /* clear mode setting, chip shutdown */
+ ret = max30102_set_powermode(data, MAX30102_REG_MODE_CONFIG_MODE_NONE,
+ false);
if (ret)
return ret;
@@ -479,7 +491,7 @@ static int max30102_remove(struct i2c_client *client)
struct max30102_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
- max30102_set_powermode(data, false);
+ max30102_set_power(data, false);
return 0;
}
--
2.7.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v2 11/13] iio: health: max30102: Prepare for copying varying number of measurements
2017-10-27 19:45 [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver Peter Meerwald-Stadler
` (9 preceding siblings ...)
2017-10-27 19:45 ` [PATCH v2 10/13] iio: health: max30102: Move mode setting to buffer_postenable Peter Meerwald-Stadler
@ 2017-10-27 19:45 ` Peter Meerwald-Stadler
2017-11-19 20:52 ` Matt Ranostay
2017-10-27 19:45 ` [PATCH v2 12/13] iio: health: max30102: Add MAX30105 support Peter Meerwald-Stadler
` (2 subsequent siblings)
13 siblings, 1 reply; 41+ messages in thread
From: Peter Meerwald-Stadler @ 2017-10-27 19:45 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, Peter Meerwald-Stadler, Matt Ranostay
Current code assumes always 2 measurements (6 bytes) have to be copied,
prepare for more flexibility
Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
Cc: Matt Ranostay <matt.ranostay@konsulko.com>
---
drivers/iio/health/max30102.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
index 1c7fe63..86058f0 100644
--- a/drivers/iio/health/max30102.c
+++ b/drivers/iio/health/max30102.c
@@ -58,7 +58,7 @@ enum max3012_led_idx {
#define MAX30102_REG_FIFO_OVR_CTR 0x05
#define MAX30102_REG_FIFO_RD_PTR 0x06
#define MAX30102_REG_FIFO_DATA 0x07
-#define MAX30102_REG_FIFO_DATA_ENTRY_LEN 6
+#define MAX30102_REG_FIFO_DATA_BYTES 3
#define MAX30102_REG_FIFO_CONFIG 0x08
#define MAX30102_REG_FIFO_CONFIG_AVG_4SAMPLES BIT(1)
@@ -198,6 +198,11 @@ static inline int max30102_fifo_count(struct max30102_data *data)
return 0;
}
+#define MAX30102_COPY_DATA(i) \
+ memcpy(&data->processed_buffer[(i)], \
+ &buffer[(i) * MAX30102_REG_FIFO_DATA_BYTES], \
+ MAX30102_REG_FIFO_DATA_BYTES)
+
static int max30102_read_measurement(struct max30102_data *data)
{
int ret;
@@ -205,13 +210,13 @@ static int max30102_read_measurement(struct max30102_data *data)
ret = i2c_smbus_read_i2c_block_data(data->client,
MAX30102_REG_FIFO_DATA,
- MAX30102_REG_FIFO_DATA_ENTRY_LEN,
+ 2 * MAX30102_REG_FIFO_DATA_BYTES,
buffer);
- memcpy(&data->processed_buffer[0], &buffer[0], 3);
- memcpy(&data->processed_buffer[1], &buffer[3], 3);
+ MAX30102_COPY_DATA(0);
+ MAX30102_COPY_DATA(1);
- return (ret == MAX30102_REG_FIFO_DATA_ENTRY_LEN) ? 0 : -EINVAL;
+ return (ret == 2 * MAX30102_REG_FIFO_DATA_BYTES) ? 0 : -EINVAL;
}
static irqreturn_t max30102_interrupt_handler(int irq, void *private)
--
2.7.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v2 12/13] iio: health: max30102: Add MAX30105 support
2017-10-27 19:45 [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver Peter Meerwald-Stadler
` (10 preceding siblings ...)
2017-10-27 19:45 ` [PATCH v2 11/13] iio: health: max30102: Prepare for copying varying number of measurements Peter Meerwald-Stadler
@ 2017-10-27 19:45 ` Peter Meerwald-Stadler
2017-11-19 21:00 ` Matt Ranostay
2017-10-27 19:45 ` [PATCH v2 13/13] dt-bindings: iio: health: Add MAX30105 support to max30102.txt Peter Meerwald-Stadler
2017-11-02 14:44 ` [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver Jonathan Cameron
13 siblings, 1 reply; 41+ messages in thread
From: Peter Meerwald-Stadler @ 2017-10-27 19:45 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, Peter Meerwald-Stadler, Matt Ranostay
The Maxim MAX30105 part adds a third LED (green) and uses a multi-LED
measuring mode producing three measurements
Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
Cc: Matt Ranostay <matt.ranostay@konsulko.com>
---
drivers/iio/health/max30102.c | 144 ++++++++++++++++++++++++++++++++++++++----
1 file changed, 130 insertions(+), 14 deletions(-)
diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
index 86058f0..15ccadc 100644
--- a/drivers/iio/health/max30102.c
+++ b/drivers/iio/health/max30102.c
@@ -3,6 +3,9 @@
*
* Copyright (C) 2017 Matt Ranostay <matt@ranostay.consulting>
*
+ * Support for MAX30105 optical particle sensor
+ * Copyright (C) 2017 Peter Meerwald-Stadler <pmeerw@pmeerw.net>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -13,6 +16,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
+ * 7-bit I2C chip address: 0x57
* TODO: proximity power saving feature
*/
@@ -34,9 +38,15 @@
#define MAX30102_DRV_NAME "max30102"
#define MAX30102_PART_NUMBER 0x15
+enum max30102_chip_id {
+ max30102,
+ max30105,
+};
+
enum max3012_led_idx {
MAX30102_LED_RED,
MAX30102_LED_IR,
+ MAX30105_LED_GREEN,
};
#define MAX30102_REG_INT_STATUS 0x00
@@ -73,6 +83,11 @@ enum max3012_led_idx {
#define MAX30102_REG_MODE_CONFIG_MODE_MASK GENMASK(2, 0)
#define MAX30102_REG_MODE_CONFIG_PWR BIT(7)
+#define MAX30102_REG_MODE_CONTROL_SLOT21 0x11 /* multi-LED control */
+#define MAX30102_REG_MODE_CONTROL_SLOT43 0x12
+#define MAX30102_REG_MODE_CONTROL_SLOT_MASK (GENMASK(6, 4) | GENMASK(2, 0))
+#define MAX30102_REG_MODE_CONTROL_SLOT_SHIFT 4
+
#define MAX30102_REG_SPO2_CONFIG 0x0a
#define MAX30102_REG_SPO2_CONFIG_PULSE_411_US 0x03
#define MAX30102_REG_SPO2_CONFIG_SR_400HZ 0x03
@@ -83,6 +98,7 @@ enum max3012_led_idx {
#define MAX30102_REG_RED_LED_CONFIG 0x0c
#define MAX30102_REG_IR_LED_CONFIG 0x0d
+#define MAX30105_REG_GREEN_LED_CONFIG 0x0e
#define MAX30102_REG_TEMP_CONFIG 0x21
#define MAX30102_REG_TEMP_CONFIG_TEMP_EN BIT(0)
@@ -98,9 +114,10 @@ struct max30102_data {
struct iio_dev *indio_dev;
struct mutex lock;
struct regmap *regmap;
+ enum max30102_chip_id chip_id;
- u8 buffer[8];
- __be32 processed_buffer[2]; /* 2 x 18-bit (padded to 32-bits) */
+ u8 buffer[12];
+ __be32 processed_buffer[3]; /* 3 x 18-bit (padded to 32-bits) */
};
static const struct regmap_config max30102_regmap_config = {
@@ -115,6 +132,13 @@ static const unsigned long max30102_scan_masks[] = {
0
};
+static const unsigned long max30105_scan_masks[] = {
+ BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR),
+ BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR) |
+ BIT(MAX30105_LED_GREEN),
+ 0
+};
+
#define MAX30102_INTENSITY_CHANNEL(_si, _mod) { \
.type = IIO_INTENSITY, \
.channel2 = _mod, \
@@ -140,6 +164,18 @@ static const struct iio_chan_spec max30102_channels[] = {
},
};
+static const struct iio_chan_spec max30105_channels[] = {
+ MAX30102_INTENSITY_CHANNEL(MAX30102_LED_RED, IIO_MOD_LIGHT_RED),
+ MAX30102_INTENSITY_CHANNEL(MAX30102_LED_IR, IIO_MOD_LIGHT_IR),
+ MAX30102_INTENSITY_CHANNEL(MAX30105_LED_GREEN, IIO_MOD_LIGHT_GREEN),
+ {
+ .type = IIO_TEMP,
+ .info_mask_separate =
+ BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+ .scan_index = -1,
+ },
+};
+
static int max30102_set_power(struct max30102_data *data, bool en)
{
return regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
@@ -159,12 +195,40 @@ static int max30102_set_powermode(struct max30102_data *data, u8 mode, bool en)
MAX30102_REG_MODE_CONFIG_MODE_MASK, reg);
}
+#define MAX30102_MODE_CONTROL_LED_SLOTS(slot2, slot1) \
+ ((slot2 << MAX30102_REG_MODE_CONTROL_SLOT_SHIFT) | slot1)
+
static int max30102_buffer_postenable(struct iio_dev *indio_dev)
{
struct max30102_data *data = iio_priv(indio_dev);
+ int ret;
u8 reg;
- reg = MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2;
+ switch (*indio_dev->active_scan_mask) {
+ case BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR):
+ reg = MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2;
+ break;
+ case BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR) |
+ BIT(MAX30105_LED_GREEN):
+ ret = regmap_update_bits(data->regmap,
+ MAX30102_REG_MODE_CONTROL_SLOT21,
+ MAX30102_REG_MODE_CONTROL_SLOT_MASK,
+ MAX30102_MODE_CONTROL_LED_SLOTS(2, 1));
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(data->regmap,
+ MAX30102_REG_MODE_CONTROL_SLOT43,
+ MAX30102_REG_MODE_CONTROL_SLOT_MASK,
+ MAX30102_MODE_CONTROL_LED_SLOTS(0, 3));
+ if (ret)
+ return ret;
+
+ reg = MAX30102_REG_MODE_CONFIG_MODE_MULTI;
+ break;
+ default:
+ return -EINVAL;
+ }
return max30102_set_powermode(data, reg, true);
}
@@ -203,32 +267,46 @@ static inline int max30102_fifo_count(struct max30102_data *data)
&buffer[(i) * MAX30102_REG_FIFO_DATA_BYTES], \
MAX30102_REG_FIFO_DATA_BYTES)
-static int max30102_read_measurement(struct max30102_data *data)
+static int max30102_read_measurement(struct max30102_data *data,
+ unsigned int measurements)
{
int ret;
u8 *buffer = (u8 *) &data->buffer;
ret = i2c_smbus_read_i2c_block_data(data->client,
MAX30102_REG_FIFO_DATA,
- 2 * MAX30102_REG_FIFO_DATA_BYTES,
+ measurements *
+ MAX30102_REG_FIFO_DATA_BYTES,
buffer);
- MAX30102_COPY_DATA(0);
- MAX30102_COPY_DATA(1);
+ switch (measurements) {
+ case 3:
+ MAX30102_COPY_DATA(2);
+ case 2: /* fall-through */
+ MAX30102_COPY_DATA(1);
+ case 1: /* fall-through */
+ MAX30102_COPY_DATA(0);
+ break;
+ default:
+ return -EINVAL;
+ }
- return (ret == 2 * MAX30102_REG_FIFO_DATA_BYTES) ? 0 : -EINVAL;
+ return (ret == measurements * MAX30102_REG_FIFO_DATA_BYTES) ?
+ 0 : -EINVAL;
}
static irqreturn_t max30102_interrupt_handler(int irq, void *private)
{
struct iio_dev *indio_dev = private;
struct max30102_data *data = iio_priv(indio_dev);
+ unsigned int measurements = bitmap_weight(indio_dev->active_scan_mask,
+ indio_dev->masklength);
int ret, cnt = 0;
mutex_lock(&data->lock);
while (cnt || (cnt = max30102_fifo_count(data)) > 0) {
- ret = max30102_read_measurement(data);
+ ret = max30102_read_measurement(data, measurements);
if (ret)
break;
@@ -274,6 +352,29 @@ static int max30102_led_init(struct max30102_data *data)
if (ret)
return ret;
+ if (data->chip_id == max30105) {
+ ret = of_property_read_u32(np,
+ "maxim,green-led-current-microamp", &val);
+ if (ret) {
+ dev_info(dev, "no green-led-current-microamp set\n");
+
+ /* Default to 7 mA green LED */
+ val = 7000;
+ }
+
+ ret = max30102_get_current_idx(val, ®);
+ if (ret) {
+ dev_err(dev, "invalid green LED current setting %d\n",
+ val);
+ return ret;
+ }
+
+ ret = regmap_write(data->regmap, MAX30105_REG_GREEN_LED_CONFIG,
+ reg);
+ if (ret)
+ return ret;
+ }
+
ret = of_property_read_u32(np, "maxim,ir-led-current-microamp", &val);
if (ret) {
dev_info(dev, "no ir-led-current-microamp set\n");
@@ -429,10 +530,7 @@ static int max30102_probe(struct i2c_client *client,
iio_device_attach_buffer(indio_dev, buffer);
indio_dev->name = MAX30102_DRV_NAME;
- indio_dev->channels = max30102_channels;
indio_dev->info = &max30102_info;
- indio_dev->num_channels = ARRAY_SIZE(max30102_channels);
- indio_dev->available_scan_masks = max30102_scan_masks;
indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
indio_dev->setup_ops = &max30102_buffer_setup_ops;
indio_dev->dev.parent = &client->dev;
@@ -440,10 +538,26 @@ static int max30102_probe(struct i2c_client *client,
data = iio_priv(indio_dev);
data->indio_dev = indio_dev;
data->client = client;
+ data->chip_id = id->driver_data;
mutex_init(&data->lock);
i2c_set_clientdata(client, indio_dev);
+ switch (data->chip_id) {
+ case max30105:
+ indio_dev->channels = max30105_channels;
+ indio_dev->num_channels = ARRAY_SIZE(max30105_channels);
+ indio_dev->available_scan_masks = max30105_scan_masks;
+ break;
+ case max30102:
+ indio_dev->channels = max30102_channels;
+ indio_dev->num_channels = ARRAY_SIZE(max30102_channels);
+ indio_dev->available_scan_masks = max30102_scan_masks;
+ break;
+ default:
+ return -ENODEV;
+ }
+
data->regmap = devm_regmap_init_i2c(client, &max30102_regmap_config);
if (IS_ERR(data->regmap)) {
dev_err(&client->dev, "regmap initialization failed\n");
@@ -502,13 +616,15 @@ static int max30102_remove(struct i2c_client *client)
}
static const struct i2c_device_id max30102_id[] = {
- { "max30102", 0 },
+ { "max30102", max30102 },
+ { "max30105", max30105 },
{}
};
MODULE_DEVICE_TABLE(i2c, max30102_id);
static const struct of_device_id max30102_dt_ids[] = {
{ .compatible = "maxim,max30102" },
+ { .compatible = "maxim,max30105" },
{ }
};
MODULE_DEVICE_TABLE(of, max30102_dt_ids);
@@ -525,5 +641,5 @@ static struct i2c_driver max30102_driver = {
module_i2c_driver(max30102_driver);
MODULE_AUTHOR("Matt Ranostay <matt@ranostay.consulting>");
-MODULE_DESCRIPTION("MAX30102 heart rate and pulse oximeter sensor");
+MODULE_DESCRIPTION("MAX30102 heart rate/pulse oximeter and MAX30105 particle sensor driver");
MODULE_LICENSE("GPL");
--
2.7.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* [PATCH v2 13/13] dt-bindings: iio: health: Add MAX30105 support to max30102.txt
2017-10-27 19:45 [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver Peter Meerwald-Stadler
` (11 preceding siblings ...)
2017-10-27 19:45 ` [PATCH v2 12/13] iio: health: max30102: Add MAX30105 support Peter Meerwald-Stadler
@ 2017-10-27 19:45 ` Peter Meerwald-Stadler
2017-11-19 20:35 ` Matt Ranostay
2017-11-02 14:44 ` [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver Jonathan Cameron
13 siblings, 1 reply; 41+ messages in thread
From: Peter Meerwald-Stadler @ 2017-10-27 19:45 UTC (permalink / raw)
To: Jonathan Cameron
Cc: linux-iio, Peter Meerwald-Stadler, Matt Ranostay, Rob Herring
Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
Cc: Matt Ranostay <matt.ranostay@konsulko.com>
Cc: Rob Herring <robh+dt@kernel.org>
---
Documentation/devicetree/bindings/iio/health/max30102.txt | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/iio/health/max30102.txt b/Documentation/devicetree/bindings/iio/health/max30102.txt
index 8629c18..ef2ca0a 100644
--- a/Documentation/devicetree/bindings/iio/health/max30102.txt
+++ b/Documentation/devicetree/bindings/iio/health/max30102.txt
@@ -1,9 +1,11 @@
Maxim MAX30102 heart rate and pulse oximeter sensor
+Maxim MAX30105 optical particle-sensing module
* https://datasheets.maximintegrated.com/en/ds/MAX30102.pdf
+* https://datasheets.maximintegrated.com/en/ds/MAX30105.pdf
Required properties:
- - compatible: must be "maxim,max30102"
+ - compatible: must be "maxim,max30102" or "maxim,max30105"
- reg: the I2C address of the sensor
- interrupt-parent: should be the phandle for the interrupt controller
- interrupts: the sole interrupt generated by the device
@@ -12,8 +14,10 @@ Required properties:
interrupt client node bindings.
Optional properties:
- - maxim,red-led-current-microamp: configuration for RED LED current
+ - maxim,red-led-current-microamp: configuration for red LED current
- maxim,ir-led-current-microamp: configuration for IR LED current
+ - maxim,green-led-current-microamp: configuration for green LED current
+ (max30105 only)
Note that each step is approximately 200 microamps, ranging from 0 uA to
50800 uA.
--
2.7.4
^ permalink raw reply related [flat|nested] 41+ messages in thread
* Re: [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver
2017-10-27 19:45 [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver Peter Meerwald-Stadler
` (12 preceding siblings ...)
2017-10-27 19:45 ` [PATCH v2 13/13] dt-bindings: iio: health: Add MAX30105 support to max30102.txt Peter Meerwald-Stadler
@ 2017-11-02 14:44 ` Jonathan Cameron
13 siblings, 0 replies; 41+ messages in thread
From: Jonathan Cameron @ 2017-11-02 14:44 UTC (permalink / raw)
To: Peter Meerwald-Stadler; +Cc: Jonathan Cameron, linux-iio, Matt Ranostay
On Fri, 27 Oct 2017 21:45:30 +0200
Peter Meerwald-Stadler <pmeerw@pmeerw.net> wrote:
> This patch series reworks the max30102 driver to add support for the
> MAX30105 part (which add a third LED)
>
> v2:
> * send correct patches, sorry for the mess
> * fix Matt Ranostay's email address
>
Series looks good to me.
Ideally I'd like Matt to have a look and given where we are in the cycle
(i.e. this one is over for IIO) we have plenty of time.
Thanks,
Jonathan
>
> patches 1 to 3 are bugfix
>
> patches 4 to 6 add minor features and cleanup
>
> patch 8 allows to read the temperature without currently measuring
> other channels
>
> patches 9 to 11 prepare for adding another LED, more flexibility
>
> patch 12 adds support for the MAX30105 part
>
> patch 13 updates devicetree documentation for the MAX30105 part
>
> Peter Meerwald-Stadler (13):
> iio: health: max30102: Temperature should be in milli Celsius
> iio: health: max30102: Fix missing newline in dev_err
> iio: health: max30102: Remove inconsistent full stop in error
> message iio: health: max30102: Fix mode config values
> iio: health: max30102: Check retval of powermode function
> iio: health: max30102: Add check for part ID
> iio: health: max30102: Introduce intensity channel macro
> iio: health: max30102: Add power enable parameter to get_temp
> function iio: health: max30102: Introduce indices for LED channels
> iio: health: max30102: Move mode setting to buffer_postenable
> iio: health: max30102: Prepare for copying varying number of
> measurements
> iio: health: max30102: Add MAX30105 support
> dt-bindings: iio: health: Add MAX30105 support to max30102.txt
>
> .../devicetree/bindings/iio/health/max30102.txt | 8 +-
> drivers/iio/health/max30102.c | 310
> ++++++++++++++++----- 2 files changed, 241 insertions(+), 77
> deletions(-)
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 02/13] iio: health: max30102: Fix missing newline in dev_err
2017-10-27 19:45 ` [PATCH v2 02/13] iio: health: max30102: Fix missing newline in dev_err Peter Meerwald-Stadler
@ 2017-11-19 20:28 ` Matt Ranostay
2017-11-25 14:05 ` Jonathan Cameron
0 siblings, 1 reply; 41+ messages in thread
From: Matt Ranostay @ 2017-11-19 20:28 UTC (permalink / raw)
To: Peter Meerwald-Stadler; +Cc: Jonathan Cameron, linux-iio
On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
<pmeerw@pmeerw.net> wrote:
> Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> Cc: Matt Ranostay <matt.ranostay@konsulko.com>
Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
> ---
> drivers/iio/health/max30102.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> index 147a8c1..62b1b35 100644
> --- a/drivers/iio/health/max30102.c
> +++ b/drivers/iio/health/max30102.c
> @@ -261,7 +261,7 @@ static int max30102_led_init(struct max30102_data *data)
>
> ret = max30102_get_current_idx(val, ®);
> if (ret) {
> - dev_err(dev, "invalid IR LED current setting %d", val);
> + dev_err(dev, "invalid IR LED current setting %d\n", val);
> return ret;
> }
>
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 03/13] iio: health: max30102: Remove inconsistent full stop in error message
2017-10-27 19:45 ` [PATCH v2 03/13] iio: health: max30102: Remove inconsistent full stop in error message Peter Meerwald-Stadler
@ 2017-11-19 20:28 ` Matt Ranostay
2017-11-25 14:06 ` Jonathan Cameron
0 siblings, 1 reply; 41+ messages in thread
From: Matt Ranostay @ 2017-11-19 20:28 UTC (permalink / raw)
To: Peter Meerwald-Stadler; +Cc: Jonathan Cameron, linux-iio
On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
<pmeerw@pmeerw.net> wrote:
> Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> Cc: Matt Ranostay <matt.ranostay@konsulko.com>
Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
> ---
> drivers/iio/health/max30102.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> index 62b1b35..6ca6182 100644
> --- a/drivers/iio/health/max30102.c
> +++ b/drivers/iio/health/max30102.c
> @@ -420,7 +420,7 @@ static int max30102_probe(struct i2c_client *client,
>
> data->regmap = devm_regmap_init_i2c(client, &max30102_regmap_config);
> if (IS_ERR(data->regmap)) {
> - dev_err(&client->dev, "regmap initialization failed.\n");
> + dev_err(&client->dev, "regmap initialization failed\n");
> return PTR_ERR(data->regmap);
> }
> max30102_set_powermode(data, false);
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 13/13] dt-bindings: iio: health: Add MAX30105 support to max30102.txt
2017-10-27 19:45 ` [PATCH v2 13/13] dt-bindings: iio: health: Add MAX30105 support to max30102.txt Peter Meerwald-Stadler
@ 2017-11-19 20:35 ` Matt Ranostay
2017-11-25 14:20 ` Jonathan Cameron
0 siblings, 1 reply; 41+ messages in thread
From: Matt Ranostay @ 2017-11-19 20:35 UTC (permalink / raw)
To: Peter Meerwald-Stadler; +Cc: Jonathan Cameron, linux-iio, Rob Herring
On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
<pmeerw@pmeerw.net> wrote:
> Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> Cc: Matt Ranostay <matt.ranostay@konsulko.com>
> Cc: Rob Herring <robh+dt@kernel.org>
Reviewed-by: Matt Ranostay <matt.ranostay@konsulko.com>
> ---
> Documentation/devicetree/bindings/iio/health/max30102.txt | 8 ++++++--
> 1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/iio/health/max30102.txt b/Documentation/devicetree/bindings/iio/health/max30102.txt
> index 8629c18..ef2ca0a 100644
> --- a/Documentation/devicetree/bindings/iio/health/max30102.txt
> +++ b/Documentation/devicetree/bindings/iio/health/max30102.txt
> @@ -1,9 +1,11 @@
> Maxim MAX30102 heart rate and pulse oximeter sensor
> +Maxim MAX30105 optical particle-sensing module
>
> * https://datasheets.maximintegrated.com/en/ds/MAX30102.pdf
> +* https://datasheets.maximintegrated.com/en/ds/MAX30105.pdf
>
> Required properties:
> - - compatible: must be "maxim,max30102"
> + - compatible: must be "maxim,max30102" or "maxim,max30105"
> - reg: the I2C address of the sensor
> - interrupt-parent: should be the phandle for the interrupt controller
> - interrupts: the sole interrupt generated by the device
> @@ -12,8 +14,10 @@ Required properties:
> interrupt client node bindings.
>
> Optional properties:
> - - maxim,red-led-current-microamp: configuration for RED LED current
> + - maxim,red-led-current-microamp: configuration for red LED current
> - maxim,ir-led-current-microamp: configuration for IR LED current
> + - maxim,green-led-current-microamp: configuration for green LED current
> + (max30105 only)
>
> Note that each step is approximately 200 microamps, ranging from 0 uA to
> 50800 uA.
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 07/13] iio: health: max30102: Introduce intensity channel macro
2017-10-27 19:45 ` [PATCH v2 07/13] iio: health: max30102: Introduce intensity channel macro Peter Meerwald-Stadler
@ 2017-11-19 20:37 ` Matt Ranostay
2017-11-25 14:12 ` Jonathan Cameron
0 siblings, 1 reply; 41+ messages in thread
From: Matt Ranostay @ 2017-11-19 20:37 UTC (permalink / raw)
To: Peter Meerwald-Stadler; +Cc: Jonathan Cameron, linux-iio
On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
<pmeerw@pmeerw.net> wrote:
> Signed-off-by: Peter Meerwald-Stalder <pmeerw@pmeerw.net>
> Cc: Matt Ranostay <matt.ranostay@konsulko.com>
Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
> ---
> drivers/iio/health/max30102.c | 44 ++++++++++++++++---------------------------
> 1 file changed, 16 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> index c43957e..968b54b 100644
> --- a/drivers/iio/health/max30102.c
> +++ b/drivers/iio/health/max30102.c
> @@ -106,35 +106,23 @@ static const struct regmap_config max30102_regmap_config = {
>
> static const unsigned long max30102_scan_masks[] = {0x3, 0};
>
> +#define MAX30102_INTENSITY_CHANNEL(_si, _mod) { \
> + .type = IIO_INTENSITY, \
> + .channel2 = _mod, \
> + .modified = 1, \
> + .scan_index = _si, \
> + .scan_type = { \
> + .sign = 'u', \
> + .shift = 8, \
> + .realbits = 18, \
> + .storagebits = 32, \
> + .endianness = IIO_BE, \
> + }, \
> + }
> +
> static const struct iio_chan_spec max30102_channels[] = {
> - {
> - .type = IIO_INTENSITY,
> - .channel2 = IIO_MOD_LIGHT_RED,
> - .modified = 1,
> -
> - .scan_index = 0,
> - .scan_type = {
> - .sign = 'u',
> - .shift = 8,
> - .realbits = 18,
> - .storagebits = 32,
> - .endianness = IIO_BE,
> - },
> - },
> - {
> - .type = IIO_INTENSITY,
> - .channel2 = IIO_MOD_LIGHT_IR,
> - .modified = 1,
> -
> - .scan_index = 1,
> - .scan_type = {
> - .sign = 'u',
> - .shift = 8,
> - .realbits = 18,
> - .storagebits = 32,
> - .endianness = IIO_BE,
> - },
> - },
> + MAX30102_INTENSITY_CHANNEL(0, IIO_MOD_LIGHT_RED),
> + MAX30102_INTENSITY_CHANNEL(1, IIO_MOD_LIGHT_IR),
> {
> .type = IIO_TEMP,
> .info_mask_separate =
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 06/13] iio: health: max30102: Add check for part ID
2017-10-27 19:45 ` [PATCH v2 06/13] iio: health: max30102: Add check for part ID Peter Meerwald-Stadler
@ 2017-11-19 20:38 ` Matt Ranostay
2017-11-25 14:11 ` Jonathan Cameron
0 siblings, 1 reply; 41+ messages in thread
From: Matt Ranostay @ 2017-11-19 20:38 UTC (permalink / raw)
To: Peter Meerwald-Stadler; +Cc: Jonathan Cameron, linux-iio
On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
<pmeerw@pmeerw.net> wrote:
> Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> Cc: Matt Ranostay <matt.ranostay@konsulko.com>
Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
> ---
> drivers/iio/health/max30102.c | 18 ++++++++++++++++++
> 1 file changed, 18 insertions(+)
>
> diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> index 389a483..c43957e 100644
> --- a/drivers/iio/health/max30102.c
> +++ b/drivers/iio/health/max30102.c
> @@ -32,6 +32,7 @@
>
> #define MAX30102_REGMAP_NAME "max30102_regmap"
> #define MAX30102_DRV_NAME "max30102"
> +#define MAX30102_PART_NUMBER 0x15
>
> #define MAX30102_REG_INT_STATUS 0x00
> #define MAX30102_REG_INT_STATUS_PWR_RDY BIT(0)
> @@ -83,6 +84,9 @@
> #define MAX30102_REG_TEMP_INTEGER 0x1f
> #define MAX30102_REG_TEMP_FRACTION 0x20
>
> +#define MAX30102_REG_REV_ID 0xfe
> +#define MAX30102_REG_PART_ID 0xff
> +
> struct max30102_data {
> struct i2c_client *client;
> struct iio_dev *indio_dev;
> @@ -391,6 +395,7 @@ static int max30102_probe(struct i2c_client *client,
> struct iio_buffer *buffer;
> struct iio_dev *indio_dev;
> int ret;
> + unsigned int reg;
>
> indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> if (!indio_dev)
> @@ -424,6 +429,19 @@ static int max30102_probe(struct i2c_client *client,
> return PTR_ERR(data->regmap);
> }
>
> + /* check part ID */
> + ret = regmap_read(data->regmap, MAX30102_REG_PART_ID, ®);
> + if (ret)
> + return ret;
> + if (reg != MAX30102_PART_NUMBER)
> + return -ENODEV;
> +
> + /* show revision ID */
> + ret = regmap_read(data->regmap, MAX30102_REG_REV_ID, ®);
> + if (ret)
> + return ret;
> + dev_dbg(&client->dev, "max3010x revision %02x\n", reg);
> +
> ret = max30102_set_powermode(data, false);
> if (ret)
> return ret;
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 08/13] iio: health: max30102: Add power enable parameter to get_temp function
2017-10-27 19:45 ` [PATCH v2 08/13] iio: health: max30102: Add power enable parameter to get_temp function Peter Meerwald-Stadler
@ 2017-11-19 20:41 ` Matt Ranostay
2017-11-25 14:15 ` Jonathan Cameron
0 siblings, 1 reply; 41+ messages in thread
From: Matt Ranostay @ 2017-11-19 20:41 UTC (permalink / raw)
To: Peter Meerwald-Stadler; +Cc: Jonathan Cameron, linux-iio
On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
<pmeerw@pmeerw.net> wrote:
> Chip must not be in shutdown for reading temperature, so briefly leave
> shutdown if buffer is not already running
>
Looks good to me. I assume there is no setup delay required for power on though?
Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
> Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> Cc: Matt Ranostay <matt.ranostay@konsulko.com>
> ---
> drivers/iio/health/max30102.c | 36 +++++++++++++++++++++++-------------
> 1 file changed, 23 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> index 968b54b..520d905 100644
> --- a/drivers/iio/health/max30102.c
> +++ b/drivers/iio/health/max30102.c
> @@ -321,20 +321,31 @@ static int max30102_read_temp(struct max30102_data *data, int *val)
> return 0;
> }
>
> -static int max30102_get_temp(struct max30102_data *data, int *val)
> +static int max30102_get_temp(struct max30102_data *data, int *val, bool en)
> {
> int ret;
>
> + if (en) {
> + ret = max30102_set_powermode(data, true);
> + if (ret)
> + return ret;
> + }
> +
> /* start acquisition */
> ret = regmap_update_bits(data->regmap, MAX30102_REG_TEMP_CONFIG,
> MAX30102_REG_TEMP_CONFIG_TEMP_EN,
> MAX30102_REG_TEMP_CONFIG_TEMP_EN);
> if (ret)
> - return ret;
> + goto out;
>
> msleep(35);
> + ret = max30102_read_temp(data, val);
> +
> +out:
> + if (en)
> + max30102_set_powermode(data, false);
>
> - return max30102_read_temp(data, val);
> + return ret;
> }
>
> static int max30102_read_raw(struct iio_dev *indio_dev,
> @@ -347,20 +358,19 @@ static int max30102_read_raw(struct iio_dev *indio_dev,
> switch (mask) {
> case IIO_CHAN_INFO_RAW:
> /*
> - * Temperature reading can only be acquired while engine
> - * is running
> + * Temperature reading can only be acquired when not in
> + * shutdown; leave shutdown briefly when buffer not running
> */
> mutex_lock(&indio_dev->mlock);
> -
> if (!iio_buffer_enabled(indio_dev))
> - ret = -EBUSY;
> - else {
> - ret = max30102_get_temp(data, val);
> - if (!ret)
> - ret = IIO_VAL_INT;
> - }
> -
> + ret = max30102_get_temp(data, val, true);
> + else
> + ret = max30102_get_temp(data, val, false);
> mutex_unlock(&indio_dev->mlock);
> + if (ret)
> + return ret;
> +
> + ret = IIO_VAL_INT;
> break;
> case IIO_CHAN_INFO_SCALE:
> *val = 1000; /* 62.5 */
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 09/13] iio: health: max30102: Introduce indices for LED channels
2017-10-27 19:45 ` [PATCH v2 09/13] iio: health: max30102: Introduce indices for LED channels Peter Meerwald-Stadler
@ 2017-11-19 20:42 ` Matt Ranostay
2017-11-25 14:16 ` Jonathan Cameron
0 siblings, 1 reply; 41+ messages in thread
From: Matt Ranostay @ 2017-11-19 20:42 UTC (permalink / raw)
To: Peter Meerwald-Stadler; +Cc: Jonathan Cameron, linux-iio
On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
<pmeerw@pmeerw.net> wrote:
> Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> Cc: Matt Ranostay <matt.ranostay@konsulko.com>
Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
> ---
> drivers/iio/health/max30102.c | 14 +++++++++++---
> 1 file changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> index 520d905..37176c2 100644
> --- a/drivers/iio/health/max30102.c
> +++ b/drivers/iio/health/max30102.c
> @@ -34,6 +34,11 @@
> #define MAX30102_DRV_NAME "max30102"
> #define MAX30102_PART_NUMBER 0x15
>
> +enum max3012_led_idx {
> + MAX30102_LED_RED,
> + MAX30102_LED_IR,
> +};
> +
> #define MAX30102_REG_INT_STATUS 0x00
> #define MAX30102_REG_INT_STATUS_PWR_RDY BIT(0)
> #define MAX30102_REG_INT_STATUS_PROX_INT BIT(4)
> @@ -104,7 +109,10 @@ static const struct regmap_config max30102_regmap_config = {
> .val_bits = 8,
> };
>
> -static const unsigned long max30102_scan_masks[] = {0x3, 0};
> +static const unsigned long max30102_scan_masks[] = {
> + BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR),
> + 0
> +};
>
> #define MAX30102_INTENSITY_CHANNEL(_si, _mod) { \
> .type = IIO_INTENSITY, \
> @@ -121,8 +129,8 @@ static const unsigned long max30102_scan_masks[] = {0x3, 0};
> }
>
> static const struct iio_chan_spec max30102_channels[] = {
> - MAX30102_INTENSITY_CHANNEL(0, IIO_MOD_LIGHT_RED),
> - MAX30102_INTENSITY_CHANNEL(1, IIO_MOD_LIGHT_IR),
> + MAX30102_INTENSITY_CHANNEL(MAX30102_LED_RED, IIO_MOD_LIGHT_RED),
> + MAX30102_INTENSITY_CHANNEL(MAX30102_LED_IR, IIO_MOD_LIGHT_IR),
> {
> .type = IIO_TEMP,
> .info_mask_separate =
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 05/13] iio: health: max30102: Check retval of powermode function
2017-10-27 19:45 ` [PATCH v2 05/13] iio: health: max30102: Check retval of powermode function Peter Meerwald-Stadler
@ 2017-11-19 20:43 ` Matt Ranostay
2017-11-25 14:08 ` Jonathan Cameron
0 siblings, 1 reply; 41+ messages in thread
From: Matt Ranostay @ 2017-11-19 20:43 UTC (permalink / raw)
To: Peter Meerwald-Stadler; +Cc: Jonathan Cameron, linux-iio
On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
<pmeerw@pmeerw.net> wrote:
> Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> Cc: Matt Ranostay <matt.ranostay@konsulko.com>
Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
> ---
> drivers/iio/health/max30102.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> index 13d5312..389a483 100644
> --- a/drivers/iio/health/max30102.c
> +++ b/drivers/iio/health/max30102.c
> @@ -423,7 +423,10 @@ static int max30102_probe(struct i2c_client *client,
> dev_err(&client->dev, "regmap initialization failed\n");
> return PTR_ERR(data->regmap);
> }
> - max30102_set_powermode(data, false);
> +
> + ret = max30102_set_powermode(data, false);
> + if (ret)
> + return ret;
>
> ret = max30102_chip_init(data);
> if (ret)
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 04/13] iio: health: max30102: Fix mode config values
2017-10-27 19:45 ` [PATCH v2 04/13] iio: health: max30102: Fix mode config values Peter Meerwald-Stadler
@ 2017-11-19 20:46 ` Matt Ranostay
2017-11-25 14:07 ` Jonathan Cameron
0 siblings, 1 reply; 41+ messages in thread
From: Matt Ranostay @ 2017-11-19 20:46 UTC (permalink / raw)
To: Peter Meerwald-Stadler; +Cc: Jonathan Cameron, linux-iio
On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
<pmeerw@pmeerw.net> wrote:
> Table 4 of the datasheet specifies the mode control, these are not
> individual bits; add multi LED mode
>
> Add multi-LED mode and fix MODE_MASK (3 bits wide, not 2)
Yeah this much cleaner than the macros I had defined
Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
>
> Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> Cc: Matt Ranostay <matt.ranostay@konsulko.com>
> ---
> drivers/iio/health/max30102.c | 12 ++++++------
> 1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> index 6ca6182..13d5312 100644
> --- a/drivers/iio/health/max30102.c
> +++ b/drivers/iio/health/max30102.c
> @@ -60,9 +60,10 @@
> #define MAX30102_REG_FIFO_CONFIG_AFULL BIT(0)
>
> #define MAX30102_REG_MODE_CONFIG 0x09
> -#define MAX30102_REG_MODE_CONFIG_MODE_SPO2_EN BIT(0)
> -#define MAX30102_REG_MODE_CONFIG_MODE_HR_EN BIT(1)
> -#define MAX30102_REG_MODE_CONFIG_MODE_MASK 0x03
> +#define MAX30102_REG_MODE_CONFIG_MODE_HR 0x02 /* red LED */
> +#define MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2 0x03 /* red + IR LED */
> +#define MAX30102_REG_MODE_CONFIG_MODE_MULTI 0x07 /* multi-LED mode */
> +#define MAX30102_REG_MODE_CONFIG_MODE_MASK GENMASK(2, 0)
> #define MAX30102_REG_MODE_CONFIG_PWR BIT(7)
>
> #define MAX30102_REG_SPO2_CONFIG 0x0a
> @@ -287,11 +288,10 @@ static int max30102_chip_init(struct max30102_data *data)
> if (ret)
> return ret;
>
> - /* enable SPO2 mode */
> + /* enable HR + SPO2 mode */
> ret = regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
> MAX30102_REG_MODE_CONFIG_MODE_MASK,
> - MAX30102_REG_MODE_CONFIG_MODE_HR_EN |
> - MAX30102_REG_MODE_CONFIG_MODE_SPO2_EN);
> + MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2);
> if (ret)
> return ret;
>
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 11/13] iio: health: max30102: Prepare for copying varying number of measurements
2017-10-27 19:45 ` [PATCH v2 11/13] iio: health: max30102: Prepare for copying varying number of measurements Peter Meerwald-Stadler
@ 2017-11-19 20:52 ` Matt Ranostay
2017-11-25 14:18 ` Jonathan Cameron
0 siblings, 1 reply; 41+ messages in thread
From: Matt Ranostay @ 2017-11-19 20:52 UTC (permalink / raw)
To: Peter Meerwald-Stadler; +Cc: Jonathan Cameron, linux-iio
On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
<pmeerw@pmeerw.net> wrote:
> Current code assumes always 2 measurements (6 bytes) have to be copied,
> prepare for more flexibility
Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
>
> Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> Cc: Matt Ranostay <matt.ranostay@konsulko.com>
> ---
> drivers/iio/health/max30102.c | 15 ++++++++++-----
> 1 file changed, 10 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> index 1c7fe63..86058f0 100644
> --- a/drivers/iio/health/max30102.c
> +++ b/drivers/iio/health/max30102.c
> @@ -58,7 +58,7 @@ enum max3012_led_idx {
> #define MAX30102_REG_FIFO_OVR_CTR 0x05
> #define MAX30102_REG_FIFO_RD_PTR 0x06
> #define MAX30102_REG_FIFO_DATA 0x07
> -#define MAX30102_REG_FIFO_DATA_ENTRY_LEN 6
> +#define MAX30102_REG_FIFO_DATA_BYTES 3
>
> #define MAX30102_REG_FIFO_CONFIG 0x08
> #define MAX30102_REG_FIFO_CONFIG_AVG_4SAMPLES BIT(1)
> @@ -198,6 +198,11 @@ static inline int max30102_fifo_count(struct max30102_data *data)
> return 0;
> }
>
> +#define MAX30102_COPY_DATA(i) \
> + memcpy(&data->processed_buffer[(i)], \
> + &buffer[(i) * MAX30102_REG_FIFO_DATA_BYTES], \
> + MAX30102_REG_FIFO_DATA_BYTES)
> +
> static int max30102_read_measurement(struct max30102_data *data)
> {
> int ret;
> @@ -205,13 +210,13 @@ static int max30102_read_measurement(struct max30102_data *data)
>
> ret = i2c_smbus_read_i2c_block_data(data->client,
> MAX30102_REG_FIFO_DATA,
> - MAX30102_REG_FIFO_DATA_ENTRY_LEN,
> + 2 * MAX30102_REG_FIFO_DATA_BYTES,
> buffer);
>
> - memcpy(&data->processed_buffer[0], &buffer[0], 3);
> - memcpy(&data->processed_buffer[1], &buffer[3], 3);
> + MAX30102_COPY_DATA(0);
> + MAX30102_COPY_DATA(1);
>
> - return (ret == MAX30102_REG_FIFO_DATA_ENTRY_LEN) ? 0 : -EINVAL;
> + return (ret == 2 * MAX30102_REG_FIFO_DATA_BYTES) ? 0 : -EINVAL;
> }
>
> static irqreturn_t max30102_interrupt_handler(int irq, void *private)
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 10/13] iio: health: max30102: Move mode setting to buffer_postenable
2017-10-27 19:45 ` [PATCH v2 10/13] iio: health: max30102: Move mode setting to buffer_postenable Peter Meerwald-Stadler
@ 2017-11-19 20:56 ` Matt Ranostay
2017-11-25 14:17 ` Jonathan Cameron
0 siblings, 1 reply; 41+ messages in thread
From: Matt Ranostay @ 2017-11-19 20:56 UTC (permalink / raw)
To: Peter Meerwald-Stadler; +Cc: Jonathan Cameron, linux-iio
On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
<pmeerw@pmeerw.net> wrote:
> Move the programming of the mode setting from init() to
> buffer_postenable()
>
> Split out a separate function to
> only update the power/shutdown bit
>
> This changes permits to more easily implement different
> modes of measurements in further patches
>
> Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> Cc: Matt Ranostay <matt.ranostay@konsulko.com>
Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
> ---
> drivers/iio/health/max30102.c | 44 +++++++++++++++++++++++++++----------------
> 1 file changed, 28 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> index 37176c2..1c7fe63 100644
> --- a/drivers/iio/health/max30102.c
> +++ b/drivers/iio/health/max30102.c
> @@ -66,6 +66,7 @@ enum max3012_led_idx {
> #define MAX30102_REG_FIFO_CONFIG_AFULL BIT(0)
>
> #define MAX30102_REG_MODE_CONFIG 0x09
> +#define MAX30102_REG_MODE_CONFIG_MODE_NONE 0x00
> #define MAX30102_REG_MODE_CONFIG_MODE_HR 0x02 /* red LED */
> #define MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2 0x03 /* red + IR LED */
> #define MAX30102_REG_MODE_CONFIG_MODE_MULTI 0x07 /* multi-LED mode */
> @@ -139,25 +140,41 @@ static const struct iio_chan_spec max30102_channels[] = {
> },
> };
>
> -static int max30102_set_powermode(struct max30102_data *data, bool state)
> +static int max30102_set_power(struct max30102_data *data, bool en)
> {
> return regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
> MAX30102_REG_MODE_CONFIG_PWR,
> - state ? 0 : MAX30102_REG_MODE_CONFIG_PWR);
> + en ? 0 : MAX30102_REG_MODE_CONFIG_PWR);
> +}
> +
> +static int max30102_set_powermode(struct max30102_data *data, u8 mode, bool en)
> +{
> + u8 reg = mode;
> +
> + if (!en)
> + reg |= MAX30102_REG_MODE_CONFIG_PWR;
> +
> + return regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
> + MAX30102_REG_MODE_CONFIG_PWR |
> + MAX30102_REG_MODE_CONFIG_MODE_MASK, reg);
> }
>
> static int max30102_buffer_postenable(struct iio_dev *indio_dev)
> {
> struct max30102_data *data = iio_priv(indio_dev);
> + u8 reg;
> +
> + reg = MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2;
>
> - return max30102_set_powermode(data, true);
> + return max30102_set_powermode(data, reg, true);
> }
>
> static int max30102_buffer_predisable(struct iio_dev *indio_dev)
> {
> struct max30102_data *data = iio_priv(indio_dev);
>
> - return max30102_set_powermode(data, false);
> + return max30102_set_powermode(data, MAX30102_REG_MODE_CONFIG_MODE_NONE,
> + false);
> }
>
> static const struct iio_buffer_setup_ops max30102_buffer_setup_ops = {
> @@ -278,7 +295,7 @@ static int max30102_chip_init(struct max30102_data *data)
> if (ret)
> return ret;
>
> - /* enable 18-bit HR + SPO2 readings at 400Hz */
> + /* configure 18-bit HR + SpO2 readings at 400Hz */
> ret = regmap_write(data->regmap, MAX30102_REG_SPO2_CONFIG,
> (MAX30102_REG_SPO2_CONFIG_ADC_4096_STEPS
> << MAX30102_REG_SPO2_CONFIG_ADC_MASK_SHIFT) |
> @@ -288,13 +305,6 @@ static int max30102_chip_init(struct max30102_data *data)
> if (ret)
> return ret;
>
> - /* enable HR + SPO2 mode */
> - ret = regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
> - MAX30102_REG_MODE_CONFIG_MODE_MASK,
> - MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2);
> - if (ret)
> - return ret;
> -
> /* average 4 samples + generate FIFO interrupt */
> ret = regmap_write(data->regmap, MAX30102_REG_FIFO_CONFIG,
> (MAX30102_REG_FIFO_CONFIG_AVG_4SAMPLES
> @@ -334,7 +344,7 @@ static int max30102_get_temp(struct max30102_data *data, int *val, bool en)
> int ret;
>
> if (en) {
> - ret = max30102_set_powermode(data, true);
> + ret = max30102_set_power(data, true);
> if (ret)
> return ret;
> }
> @@ -351,7 +361,7 @@ static int max30102_get_temp(struct max30102_data *data, int *val, bool en)
>
> out:
> if (en)
> - max30102_set_powermode(data, false);
> + max30102_set_power(data, false);
>
> return ret;
> }
> @@ -448,7 +458,9 @@ static int max30102_probe(struct i2c_client *client,
> return ret;
> dev_dbg(&client->dev, "max3010x revision %02x\n", reg);
>
> - ret = max30102_set_powermode(data, false);
> + /* clear mode setting, chip shutdown */
> + ret = max30102_set_powermode(data, MAX30102_REG_MODE_CONFIG_MODE_NONE,
> + false);
> if (ret)
> return ret;
>
> @@ -479,7 +491,7 @@ static int max30102_remove(struct i2c_client *client)
> struct max30102_data *data = iio_priv(indio_dev);
>
> iio_device_unregister(indio_dev);
> - max30102_set_powermode(data, false);
> + max30102_set_power(data, false);
>
> return 0;
> }
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 12/13] iio: health: max30102: Add MAX30105 support
2017-10-27 19:45 ` [PATCH v2 12/13] iio: health: max30102: Add MAX30105 support Peter Meerwald-Stadler
@ 2017-11-19 21:00 ` Matt Ranostay
2017-11-25 14:19 ` Jonathan Cameron
0 siblings, 1 reply; 41+ messages in thread
From: Matt Ranostay @ 2017-11-19 21:00 UTC (permalink / raw)
To: Peter Meerwald-Stadler; +Cc: Jonathan Cameron, linux-iio
On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
<pmeerw@pmeerw.net> wrote:
> The Maxim MAX30105 part adds a third LED (green) and uses a multi-LED
> measuring mode producing three measurements
>
> Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> Cc: Matt Ranostay <matt.ranostay@konsulko.com>
Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
> ---
> drivers/iio/health/max30102.c | 144 ++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 130 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> index 86058f0..15ccadc 100644
> --- a/drivers/iio/health/max30102.c
> +++ b/drivers/iio/health/max30102.c
> @@ -3,6 +3,9 @@
> *
> * Copyright (C) 2017 Matt Ranostay <matt@ranostay.consulting>
> *
> + * Support for MAX30105 optical particle sensor
> + * Copyright (C) 2017 Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> + *
> * This program is free software; you can redistribute it and/or modify
> * it under the terms of the GNU General Public License as published by
> * the Free Software Foundation; either version 2 of the License, or
> @@ -13,6 +16,7 @@
> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> * GNU General Public License for more details.
> *
> + * 7-bit I2C chip address: 0x57
> * TODO: proximity power saving feature
> */
>
> @@ -34,9 +38,15 @@
> #define MAX30102_DRV_NAME "max30102"
> #define MAX30102_PART_NUMBER 0x15
>
> +enum max30102_chip_id {
> + max30102,
> + max30105,
> +};
> +
> enum max3012_led_idx {
> MAX30102_LED_RED,
> MAX30102_LED_IR,
> + MAX30105_LED_GREEN,
> };
>
> #define MAX30102_REG_INT_STATUS 0x00
> @@ -73,6 +83,11 @@ enum max3012_led_idx {
> #define MAX30102_REG_MODE_CONFIG_MODE_MASK GENMASK(2, 0)
> #define MAX30102_REG_MODE_CONFIG_PWR BIT(7)
>
> +#define MAX30102_REG_MODE_CONTROL_SLOT21 0x11 /* multi-LED control */
> +#define MAX30102_REG_MODE_CONTROL_SLOT43 0x12
> +#define MAX30102_REG_MODE_CONTROL_SLOT_MASK (GENMASK(6, 4) | GENMASK(2, 0))
> +#define MAX30102_REG_MODE_CONTROL_SLOT_SHIFT 4
I assume slot is some time multiplexing of the LEDs?
> +
> #define MAX30102_REG_SPO2_CONFIG 0x0a
> #define MAX30102_REG_SPO2_CONFIG_PULSE_411_US 0x03
> #define MAX30102_REG_SPO2_CONFIG_SR_400HZ 0x03
> @@ -83,6 +98,7 @@ enum max3012_led_idx {
>
> #define MAX30102_REG_RED_LED_CONFIG 0x0c
> #define MAX30102_REG_IR_LED_CONFIG 0x0d
> +#define MAX30105_REG_GREEN_LED_CONFIG 0x0e
>
> #define MAX30102_REG_TEMP_CONFIG 0x21
> #define MAX30102_REG_TEMP_CONFIG_TEMP_EN BIT(0)
> @@ -98,9 +114,10 @@ struct max30102_data {
> struct iio_dev *indio_dev;
> struct mutex lock;
> struct regmap *regmap;
> + enum max30102_chip_id chip_id;
>
> - u8 buffer[8];
> - __be32 processed_buffer[2]; /* 2 x 18-bit (padded to 32-bits) */
> + u8 buffer[12];
> + __be32 processed_buffer[3]; /* 3 x 18-bit (padded to 32-bits) */
> };
>
> static const struct regmap_config max30102_regmap_config = {
> @@ -115,6 +132,13 @@ static const unsigned long max30102_scan_masks[] = {
> 0
> };
>
> +static const unsigned long max30105_scan_masks[] = {
> + BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR),
> + BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR) |
> + BIT(MAX30105_LED_GREEN),
> + 0
> +};
> +
> #define MAX30102_INTENSITY_CHANNEL(_si, _mod) { \
> .type = IIO_INTENSITY, \
> .channel2 = _mod, \
> @@ -140,6 +164,18 @@ static const struct iio_chan_spec max30102_channels[] = {
> },
> };
>
> +static const struct iio_chan_spec max30105_channels[] = {
> + MAX30102_INTENSITY_CHANNEL(MAX30102_LED_RED, IIO_MOD_LIGHT_RED),
> + MAX30102_INTENSITY_CHANNEL(MAX30102_LED_IR, IIO_MOD_LIGHT_IR),
> + MAX30102_INTENSITY_CHANNEL(MAX30105_LED_GREEN, IIO_MOD_LIGHT_GREEN),
> + {
> + .type = IIO_TEMP,
> + .info_mask_separate =
> + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
> + .scan_index = -1,
> + },
> +};
> +
> static int max30102_set_power(struct max30102_data *data, bool en)
> {
> return regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
> @@ -159,12 +195,40 @@ static int max30102_set_powermode(struct max30102_data *data, u8 mode, bool en)
> MAX30102_REG_MODE_CONFIG_MODE_MASK, reg);
> }
>
> +#define MAX30102_MODE_CONTROL_LED_SLOTS(slot2, slot1) \
> + ((slot2 << MAX30102_REG_MODE_CONTROL_SLOT_SHIFT) | slot1)
> +
> static int max30102_buffer_postenable(struct iio_dev *indio_dev)
> {
> struct max30102_data *data = iio_priv(indio_dev);
> + int ret;
> u8 reg;
>
> - reg = MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2;
> + switch (*indio_dev->active_scan_mask) {
> + case BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR):
> + reg = MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2;
> + break;
> + case BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR) |
> + BIT(MAX30105_LED_GREEN):
> + ret = regmap_update_bits(data->regmap,
> + MAX30102_REG_MODE_CONTROL_SLOT21,
> + MAX30102_REG_MODE_CONTROL_SLOT_MASK,
> + MAX30102_MODE_CONTROL_LED_SLOTS(2, 1));
> + if (ret)
> + return ret;
> +
> + ret = regmap_update_bits(data->regmap,
> + MAX30102_REG_MODE_CONTROL_SLOT43,
> + MAX30102_REG_MODE_CONTROL_SLOT_MASK,
> + MAX30102_MODE_CONTROL_LED_SLOTS(0, 3));
> + if (ret)
> + return ret;
> +
> + reg = MAX30102_REG_MODE_CONFIG_MODE_MULTI;
> + break;
> + default:
> + return -EINVAL;
> + }
>
> return max30102_set_powermode(data, reg, true);
> }
> @@ -203,32 +267,46 @@ static inline int max30102_fifo_count(struct max30102_data *data)
> &buffer[(i) * MAX30102_REG_FIFO_DATA_BYTES], \
> MAX30102_REG_FIFO_DATA_BYTES)
>
> -static int max30102_read_measurement(struct max30102_data *data)
> +static int max30102_read_measurement(struct max30102_data *data,
> + unsigned int measurements)
> {
> int ret;
> u8 *buffer = (u8 *) &data->buffer;
>
> ret = i2c_smbus_read_i2c_block_data(data->client,
> MAX30102_REG_FIFO_DATA,
> - 2 * MAX30102_REG_FIFO_DATA_BYTES,
> + measurements *
> + MAX30102_REG_FIFO_DATA_BYTES,
> buffer);
>
> - MAX30102_COPY_DATA(0);
> - MAX30102_COPY_DATA(1);
> + switch (measurements) {
> + case 3:
> + MAX30102_COPY_DATA(2);
> + case 2: /* fall-through */
> + MAX30102_COPY_DATA(1);
> + case 1: /* fall-through */
> + MAX30102_COPY_DATA(0);
> + break;
> + default:
> + return -EINVAL;
> + }
>
> - return (ret == 2 * MAX30102_REG_FIFO_DATA_BYTES) ? 0 : -EINVAL;
> + return (ret == measurements * MAX30102_REG_FIFO_DATA_BYTES) ?
> + 0 : -EINVAL;
> }
>
> static irqreturn_t max30102_interrupt_handler(int irq, void *private)
> {
> struct iio_dev *indio_dev = private;
> struct max30102_data *data = iio_priv(indio_dev);
> + unsigned int measurements = bitmap_weight(indio_dev->active_scan_mask,
> + indio_dev->masklength);
> int ret, cnt = 0;
>
> mutex_lock(&data->lock);
>
> while (cnt || (cnt = max30102_fifo_count(data)) > 0) {
> - ret = max30102_read_measurement(data);
> + ret = max30102_read_measurement(data, measurements);
> if (ret)
> break;
>
> @@ -274,6 +352,29 @@ static int max30102_led_init(struct max30102_data *data)
> if (ret)
> return ret;
>
> + if (data->chip_id == max30105) {
> + ret = of_property_read_u32(np,
> + "maxim,green-led-current-microamp", &val);
> + if (ret) {
> + dev_info(dev, "no green-led-current-microamp set\n");
> +
> + /* Default to 7 mA green LED */
> + val = 7000;
> + }
> +
> + ret = max30102_get_current_idx(val, ®);
> + if (ret) {
> + dev_err(dev, "invalid green LED current setting %d\n",
> + val);
> + return ret;
> + }
> +
> + ret = regmap_write(data->regmap, MAX30105_REG_GREEN_LED_CONFIG,
> + reg);
> + if (ret)
> + return ret;
> + }
> +
> ret = of_property_read_u32(np, "maxim,ir-led-current-microamp", &val);
> if (ret) {
> dev_info(dev, "no ir-led-current-microamp set\n");
> @@ -429,10 +530,7 @@ static int max30102_probe(struct i2c_client *client,
> iio_device_attach_buffer(indio_dev, buffer);
>
> indio_dev->name = MAX30102_DRV_NAME;
> - indio_dev->channels = max30102_channels;
> indio_dev->info = &max30102_info;
> - indio_dev->num_channels = ARRAY_SIZE(max30102_channels);
> - indio_dev->available_scan_masks = max30102_scan_masks;
> indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
> indio_dev->setup_ops = &max30102_buffer_setup_ops;
> indio_dev->dev.parent = &client->dev;
> @@ -440,10 +538,26 @@ static int max30102_probe(struct i2c_client *client,
> data = iio_priv(indio_dev);
> data->indio_dev = indio_dev;
> data->client = client;
> + data->chip_id = id->driver_data;
>
> mutex_init(&data->lock);
> i2c_set_clientdata(client, indio_dev);
>
> + switch (data->chip_id) {
> + case max30105:
> + indio_dev->channels = max30105_channels;
> + indio_dev->num_channels = ARRAY_SIZE(max30105_channels);
> + indio_dev->available_scan_masks = max30105_scan_masks;
> + break;
> + case max30102:
> + indio_dev->channels = max30102_channels;
> + indio_dev->num_channels = ARRAY_SIZE(max30102_channels);
> + indio_dev->available_scan_masks = max30102_scan_masks;
> + break;
> + default:
> + return -ENODEV;
> + }
> +
> data->regmap = devm_regmap_init_i2c(client, &max30102_regmap_config);
> if (IS_ERR(data->regmap)) {
> dev_err(&client->dev, "regmap initialization failed\n");
> @@ -502,13 +616,15 @@ static int max30102_remove(struct i2c_client *client)
> }
>
> static const struct i2c_device_id max30102_id[] = {
> - { "max30102", 0 },
> + { "max30102", max30102 },
> + { "max30105", max30105 },
> {}
> };
> MODULE_DEVICE_TABLE(i2c, max30102_id);
>
> static const struct of_device_id max30102_dt_ids[] = {
> { .compatible = "maxim,max30102" },
> + { .compatible = "maxim,max30105" },
> { }
> };
> MODULE_DEVICE_TABLE(of, max30102_dt_ids);
> @@ -525,5 +641,5 @@ static struct i2c_driver max30102_driver = {
> module_i2c_driver(max30102_driver);
>
> MODULE_AUTHOR("Matt Ranostay <matt@ranostay.consulting>");
> -MODULE_DESCRIPTION("MAX30102 heart rate and pulse oximeter sensor");
> +MODULE_DESCRIPTION("MAX30102 heart rate/pulse oximeter and MAX30105 particle sensor driver");
> MODULE_LICENSE("GPL");
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 01/13] iio: health: max30102: Temperature should be in milli Celsius
2017-10-27 19:45 ` [PATCH v2 01/13] iio: health: max30102: Temperature should be in milli Celsius Peter Meerwald-Stadler
@ 2017-11-19 21:09 ` Matt Ranostay
2017-11-25 14:04 ` Jonathan Cameron
0 siblings, 1 reply; 41+ messages in thread
From: Matt Ranostay @ 2017-11-19 21:09 UTC (permalink / raw)
To: Peter Meerwald-Stadler; +Cc: Jonathan Cameron, linux-iio
On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
<pmeerw@pmeerw.net> wrote:
> As per ABI temperature should be in milli Celsius after scaling,
> not Celsius
Good catch...Thanks
Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
>
> Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> Cc: Matt Ranostay <matt.ranostay@konsulko.com>
> ---
> drivers/iio/health/max30102.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> index 203ffb9..147a8c1 100644
> --- a/drivers/iio/health/max30102.c
> +++ b/drivers/iio/health/max30102.c
> @@ -371,7 +371,7 @@ static int max30102_read_raw(struct iio_dev *indio_dev,
> mutex_unlock(&indio_dev->mlock);
> break;
> case IIO_CHAN_INFO_SCALE:
> - *val = 1; /* 0.0625 */
> + *val = 1000; /* 62.5 */
> *val2 = 16;
> ret = IIO_VAL_FRACTIONAL;
> break;
> --
> 2.7.4
>
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 01/13] iio: health: max30102: Temperature should be in milli Celsius
2017-11-19 21:09 ` Matt Ranostay
@ 2017-11-25 14:04 ` Jonathan Cameron
0 siblings, 0 replies; 41+ messages in thread
From: Jonathan Cameron @ 2017-11-25 14:04 UTC (permalink / raw)
To: Matt Ranostay; +Cc: Peter Meerwald-Stadler, linux-iio
On Sun, 19 Nov 2017 13:09:34 -0800
Matt Ranostay <matt.ranostay@konsulko.com> wrote:
> On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
> <pmeerw@pmeerw.net> wrote:
> > As per ABI temperature should be in milli Celsius after scaling,
> > not Celsius
>
> Good catch...Thanks
>
> Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
Applied to the fixes-togreg branch of iio.git and marked for stable.
I've also added a brief not to emphasise that is breaking the ABI
hence I want it fixed in stable... (just hammering the point
home ;)
Thanks
Jonathan
>
> >
> > Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> > Cc: Matt Ranostay <matt.ranostay@konsulko.com>
> > ---
> > drivers/iio/health/max30102.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> > index 203ffb9..147a8c1 100644
> > --- a/drivers/iio/health/max30102.c
> > +++ b/drivers/iio/health/max30102.c
> > @@ -371,7 +371,7 @@ static int max30102_read_raw(struct iio_dev *indio_dev,
> > mutex_unlock(&indio_dev->mlock);
> > break;
> > case IIO_CHAN_INFO_SCALE:
> > - *val = 1; /* 0.0625 */
> > + *val = 1000; /* 62.5 */
> > *val2 = 16;
> > ret = IIO_VAL_FRACTIONAL;
> > break;
> > --
> > 2.7.4
> >
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 02/13] iio: health: max30102: Fix missing newline in dev_err
2017-11-19 20:28 ` Matt Ranostay
@ 2017-11-25 14:05 ` Jonathan Cameron
0 siblings, 0 replies; 41+ messages in thread
From: Jonathan Cameron @ 2017-11-25 14:05 UTC (permalink / raw)
To: Matt Ranostay; +Cc: Peter Meerwald-Stadler, linux-iio
On Sun, 19 Nov 2017 12:28:08 -0800
Matt Ranostay <matt.ranostay@konsulko.com> wrote:
> On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
> <pmeerw@pmeerw.net> wrote:
> > Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> > Cc: Matt Ranostay <matt.ranostay@konsulko.com>
>
> Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
Applied to the togreg branch of iio.git.
Thanks,
Jonathan
>
> > ---
> > drivers/iio/health/max30102.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> > index 147a8c1..62b1b35 100644
> > --- a/drivers/iio/health/max30102.c
> > +++ b/drivers/iio/health/max30102.c
> > @@ -261,7 +261,7 @@ static int max30102_led_init(struct max30102_data *data)
> >
> > ret = max30102_get_current_idx(val, ®);
> > if (ret) {
> > - dev_err(dev, "invalid IR LED current setting %d", val);
> > + dev_err(dev, "invalid IR LED current setting %d\n", val);
> > return ret;
> > }
> >
> > --
> > 2.7.4
> >
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 03/13] iio: health: max30102: Remove inconsistent full stop in error message
2017-11-19 20:28 ` Matt Ranostay
@ 2017-11-25 14:06 ` Jonathan Cameron
0 siblings, 0 replies; 41+ messages in thread
From: Jonathan Cameron @ 2017-11-25 14:06 UTC (permalink / raw)
To: Matt Ranostay; +Cc: Peter Meerwald-Stadler, linux-iio
On Sun, 19 Nov 2017 12:28:46 -0800
Matt Ranostay <matt.ranostay@konsulko.com> wrote:
> On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
> <pmeerw@pmeerw.net> wrote:
> > Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> > Cc: Matt Ranostay <matt.ranostay@konsulko.com>
>
> Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
Applied.
>
> > ---
> > drivers/iio/health/max30102.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> > index 62b1b35..6ca6182 100644
> > --- a/drivers/iio/health/max30102.c
> > +++ b/drivers/iio/health/max30102.c
> > @@ -420,7 +420,7 @@ static int max30102_probe(struct i2c_client *client,
> >
> > data->regmap = devm_regmap_init_i2c(client, &max30102_regmap_config);
> > if (IS_ERR(data->regmap)) {
> > - dev_err(&client->dev, "regmap initialization failed.\n");
> > + dev_err(&client->dev, "regmap initialization failed\n");
> > return PTR_ERR(data->regmap);
> > }
> > max30102_set_powermode(data, false);
> > --
> > 2.7.4
> >
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 04/13] iio: health: max30102: Fix mode config values
2017-11-19 20:46 ` Matt Ranostay
@ 2017-11-25 14:07 ` Jonathan Cameron
0 siblings, 0 replies; 41+ messages in thread
From: Jonathan Cameron @ 2017-11-25 14:07 UTC (permalink / raw)
To: Matt Ranostay; +Cc: Peter Meerwald-Stadler, linux-iio
On Sun, 19 Nov 2017 12:46:40 -0800
Matt Ranostay <matt.ranostay@konsulko.com> wrote:
> On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
> <pmeerw@pmeerw.net> wrote:
> > Table 4 of the datasheet specifies the mode control, these are not
> > individual bits; add multi LED mode
> >
> > Add multi-LED mode and fix MODE_MASK (3 bits wide, not 2)
>
> Yeah this much cleaner than the macros I had defined
>
> Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
>
Applied.
> >
> > Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> > Cc: Matt Ranostay <matt.ranostay@konsulko.com>
> > ---
> > drivers/iio/health/max30102.c | 12 ++++++------
> > 1 file changed, 6 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> > index 6ca6182..13d5312 100644
> > --- a/drivers/iio/health/max30102.c
> > +++ b/drivers/iio/health/max30102.c
> > @@ -60,9 +60,10 @@
> > #define MAX30102_REG_FIFO_CONFIG_AFULL BIT(0)
> >
> > #define MAX30102_REG_MODE_CONFIG 0x09
> > -#define MAX30102_REG_MODE_CONFIG_MODE_SPO2_EN BIT(0)
> > -#define MAX30102_REG_MODE_CONFIG_MODE_HR_EN BIT(1)
> > -#define MAX30102_REG_MODE_CONFIG_MODE_MASK 0x03
> > +#define MAX30102_REG_MODE_CONFIG_MODE_HR 0x02 /* red LED */
> > +#define MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2 0x03 /* red + IR LED */
> > +#define MAX30102_REG_MODE_CONFIG_MODE_MULTI 0x07 /* multi-LED mode */
> > +#define MAX30102_REG_MODE_CONFIG_MODE_MASK GENMASK(2, 0)
> > #define MAX30102_REG_MODE_CONFIG_PWR BIT(7)
> >
> > #define MAX30102_REG_SPO2_CONFIG 0x0a
> > @@ -287,11 +288,10 @@ static int max30102_chip_init(struct max30102_data *data)
> > if (ret)
> > return ret;
> >
> > - /* enable SPO2 mode */
> > + /* enable HR + SPO2 mode */
> > ret = regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
> > MAX30102_REG_MODE_CONFIG_MODE_MASK,
> > - MAX30102_REG_MODE_CONFIG_MODE_HR_EN |
> > - MAX30102_REG_MODE_CONFIG_MODE_SPO2_EN);
> > + MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2);
> > if (ret)
> > return ret;
> >
> > --
> > 2.7.4
> >
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 05/13] iio: health: max30102: Check retval of powermode function
2017-11-19 20:43 ` Matt Ranostay
@ 2017-11-25 14:08 ` Jonathan Cameron
0 siblings, 0 replies; 41+ messages in thread
From: Jonathan Cameron @ 2017-11-25 14:08 UTC (permalink / raw)
To: Matt Ranostay; +Cc: Peter Meerwald-Stadler, linux-iio
On Sun, 19 Nov 2017 12:43:09 -0800
Matt Ranostay <matt.ranostay@konsulko.com> wrote:
> On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
> <pmeerw@pmeerw.net> wrote:
> > Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> > Cc: Matt Ranostay <matt.ranostay@konsulko.com>
>
> Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
Applied.
>
> > ---
> > drivers/iio/health/max30102.c | 5 ++++-
> > 1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> > index 13d5312..389a483 100644
> > --- a/drivers/iio/health/max30102.c
> > +++ b/drivers/iio/health/max30102.c
> > @@ -423,7 +423,10 @@ static int max30102_probe(struct i2c_client *client,
> > dev_err(&client->dev, "regmap initialization failed\n");
> > return PTR_ERR(data->regmap);
> > }
> > - max30102_set_powermode(data, false);
> > +
> > + ret = max30102_set_powermode(data, false);
> > + if (ret)
> > + return ret;
> >
> > ret = max30102_chip_init(data);
> > if (ret)
> > --
> > 2.7.4
> >
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 06/13] iio: health: max30102: Add check for part ID
2017-11-19 20:38 ` Matt Ranostay
@ 2017-11-25 14:11 ` Jonathan Cameron
0 siblings, 0 replies; 41+ messages in thread
From: Jonathan Cameron @ 2017-11-25 14:11 UTC (permalink / raw)
To: Matt Ranostay; +Cc: Peter Meerwald-Stadler, linux-iio
On Sun, 19 Nov 2017 12:38:50 -0800
Matt Ranostay <matt.ranostay@konsulko.com> wrote:
> On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
> <pmeerw@pmeerw.net> wrote:
> > Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> > Cc: Matt Ranostay <matt.ranostay@konsulko.com>
>
>
> Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
>
Applied.
> > ---
> > drivers/iio/health/max30102.c | 18 ++++++++++++++++++
> > 1 file changed, 18 insertions(+)
> >
> > diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> > index 389a483..c43957e 100644
> > --- a/drivers/iio/health/max30102.c
> > +++ b/drivers/iio/health/max30102.c
> > @@ -32,6 +32,7 @@
> >
> > #define MAX30102_REGMAP_NAME "max30102_regmap"
> > #define MAX30102_DRV_NAME "max30102"
> > +#define MAX30102_PART_NUMBER 0x15
> >
> > #define MAX30102_REG_INT_STATUS 0x00
> > #define MAX30102_REG_INT_STATUS_PWR_RDY BIT(0)
> > @@ -83,6 +84,9 @@
> > #define MAX30102_REG_TEMP_INTEGER 0x1f
> > #define MAX30102_REG_TEMP_FRACTION 0x20
> >
> > +#define MAX30102_REG_REV_ID 0xfe
> > +#define MAX30102_REG_PART_ID 0xff
> > +
> > struct max30102_data {
> > struct i2c_client *client;
> > struct iio_dev *indio_dev;
> > @@ -391,6 +395,7 @@ static int max30102_probe(struct i2c_client *client,
> > struct iio_buffer *buffer;
> > struct iio_dev *indio_dev;
> > int ret;
> > + unsigned int reg;
> >
> > indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> > if (!indio_dev)
> > @@ -424,6 +429,19 @@ static int max30102_probe(struct i2c_client *client,
> > return PTR_ERR(data->regmap);
> > }
> >
> > + /* check part ID */
> > + ret = regmap_read(data->regmap, MAX30102_REG_PART_ID, ®);
> > + if (ret)
> > + return ret;
> > + if (reg != MAX30102_PART_NUMBER)
> > + return -ENODEV;
> > +
> > + /* show revision ID */
> > + ret = regmap_read(data->regmap, MAX30102_REG_REV_ID, ®);
> > + if (ret)
> > + return ret;
> > + dev_dbg(&client->dev, "max3010x revision %02x\n", reg);
> > +
> > ret = max30102_set_powermode(data, false);
> > if (ret)
> > return ret;
> > --
> > 2.7.4
> >
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 07/13] iio: health: max30102: Introduce intensity channel macro
2017-11-19 20:37 ` Matt Ranostay
@ 2017-11-25 14:12 ` Jonathan Cameron
0 siblings, 0 replies; 41+ messages in thread
From: Jonathan Cameron @ 2017-11-25 14:12 UTC (permalink / raw)
To: Matt Ranostay; +Cc: Peter Meerwald-Stadler, linux-iio
On Sun, 19 Nov 2017 12:37:00 -0800
Matt Ranostay <matt.ranostay@konsulko.com> wrote:
> On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
> <pmeerw@pmeerw.net> wrote:
> > Signed-off-by: Peter Meerwald-Stalder <pmeerw@pmeerw.net>
> > Cc: Matt Ranostay <matt.ranostay@konsulko.com>
>
> Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
Applied.
>
> > ---
> > drivers/iio/health/max30102.c | 44 ++++++++++++++++---------------------------
> > 1 file changed, 16 insertions(+), 28 deletions(-)
> >
> > diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> > index c43957e..968b54b 100644
> > --- a/drivers/iio/health/max30102.c
> > +++ b/drivers/iio/health/max30102.c
> > @@ -106,35 +106,23 @@ static const struct regmap_config max30102_regmap_config = {
> >
> > static const unsigned long max30102_scan_masks[] = {0x3, 0};
> >
> > +#define MAX30102_INTENSITY_CHANNEL(_si, _mod) { \
> > + .type = IIO_INTENSITY, \
> > + .channel2 = _mod, \
> > + .modified = 1, \
> > + .scan_index = _si, \
> > + .scan_type = { \
> > + .sign = 'u', \
> > + .shift = 8, \
> > + .realbits = 18, \
> > + .storagebits = 32, \
> > + .endianness = IIO_BE, \
> > + }, \
> > + }
> > +
> > static const struct iio_chan_spec max30102_channels[] = {
> > - {
> > - .type = IIO_INTENSITY,
> > - .channel2 = IIO_MOD_LIGHT_RED,
> > - .modified = 1,
> > -
> > - .scan_index = 0,
> > - .scan_type = {
> > - .sign = 'u',
> > - .shift = 8,
> > - .realbits = 18,
> > - .storagebits = 32,
> > - .endianness = IIO_BE,
> > - },
> > - },
> > - {
> > - .type = IIO_INTENSITY,
> > - .channel2 = IIO_MOD_LIGHT_IR,
> > - .modified = 1,
> > -
> > - .scan_index = 1,
> > - .scan_type = {
> > - .sign = 'u',
> > - .shift = 8,
> > - .realbits = 18,
> > - .storagebits = 32,
> > - .endianness = IIO_BE,
> > - },
> > - },
> > + MAX30102_INTENSITY_CHANNEL(0, IIO_MOD_LIGHT_RED),
> > + MAX30102_INTENSITY_CHANNEL(1, IIO_MOD_LIGHT_IR),
> > {
> > .type = IIO_TEMP,
> > .info_mask_separate =
> > --
> > 2.7.4
> >
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 08/13] iio: health: max30102: Add power enable parameter to get_temp function
2017-11-19 20:41 ` Matt Ranostay
@ 2017-11-25 14:15 ` Jonathan Cameron
0 siblings, 0 replies; 41+ messages in thread
From: Jonathan Cameron @ 2017-11-25 14:15 UTC (permalink / raw)
To: Matt Ranostay; +Cc: Peter Meerwald-Stadler, linux-iio
On Sun, 19 Nov 2017 12:41:37 -0800
Matt Ranostay <matt.ranostay@konsulko.com> wrote:
> On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
> <pmeerw@pmeerw.net> wrote:
> > Chip must not be in shutdown for reading temperature, so briefly leave
> > shutdown if buffer is not already running
> >
>
> Looks good to me. I assume there is no setup delay required for power on though?
I assuming not but if there is then a follow up patch now...
>
>
> Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
Applied to togreg branch of iio.git. A bit of fuzz given the other
temperature related patch that went via the fixes tree.
Jonathan
>
>
> > Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> > Cc: Matt Ranostay <matt.ranostay@konsulko.com>
> > ---
> > drivers/iio/health/max30102.c | 36 +++++++++++++++++++++++-------------
> > 1 file changed, 23 insertions(+), 13 deletions(-)
> >
> > diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> > index 968b54b..520d905 100644
> > --- a/drivers/iio/health/max30102.c
> > +++ b/drivers/iio/health/max30102.c
> > @@ -321,20 +321,31 @@ static int max30102_read_temp(struct max30102_data *data, int *val)
> > return 0;
> > }
> >
> > -static int max30102_get_temp(struct max30102_data *data, int *val)
> > +static int max30102_get_temp(struct max30102_data *data, int *val, bool en)
> > {
> > int ret;
> >
> > + if (en) {
> > + ret = max30102_set_powermode(data, true);
> > + if (ret)
> > + return ret;
> > + }
> > +
> > /* start acquisition */
> > ret = regmap_update_bits(data->regmap, MAX30102_REG_TEMP_CONFIG,
> > MAX30102_REG_TEMP_CONFIG_TEMP_EN,
> > MAX30102_REG_TEMP_CONFIG_TEMP_EN);
> > if (ret)
> > - return ret;
> > + goto out;
> >
> > msleep(35);
> > + ret = max30102_read_temp(data, val);
> > +
> > +out:
> > + if (en)
> > + max30102_set_powermode(data, false);
> >
> > - return max30102_read_temp(data, val);
> > + return ret;
> > }
> >
> > static int max30102_read_raw(struct iio_dev *indio_dev,
> > @@ -347,20 +358,19 @@ static int max30102_read_raw(struct iio_dev *indio_dev,
> > switch (mask) {
> > case IIO_CHAN_INFO_RAW:
> > /*
> > - * Temperature reading can only be acquired while engine
> > - * is running
> > + * Temperature reading can only be acquired when not in
> > + * shutdown; leave shutdown briefly when buffer not running
> > */
> > mutex_lock(&indio_dev->mlock);
> > -
> > if (!iio_buffer_enabled(indio_dev))
> > - ret = -EBUSY;
> > - else {
> > - ret = max30102_get_temp(data, val);
> > - if (!ret)
> > - ret = IIO_VAL_INT;
> > - }
> > -
> > + ret = max30102_get_temp(data, val, true);
> > + else
> > + ret = max30102_get_temp(data, val, false);
> > mutex_unlock(&indio_dev->mlock);
> > + if (ret)
> > + return ret;
> > +
> > + ret = IIO_VAL_INT;
> > break;
> > case IIO_CHAN_INFO_SCALE:
> > *val = 1000; /* 62.5 */
> > --
> > 2.7.4
> >
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 09/13] iio: health: max30102: Introduce indices for LED channels
2017-11-19 20:42 ` Matt Ranostay
@ 2017-11-25 14:16 ` Jonathan Cameron
0 siblings, 0 replies; 41+ messages in thread
From: Jonathan Cameron @ 2017-11-25 14:16 UTC (permalink / raw)
To: Matt Ranostay; +Cc: Peter Meerwald-Stadler, linux-iio
On Sun, 19 Nov 2017 12:42:35 -0800
Matt Ranostay <matt.ranostay@konsulko.com> wrote:
> On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
> <pmeerw@pmeerw.net> wrote:
> > Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> > Cc: Matt Ranostay <matt.ranostay@konsulko.com>
>
> Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
Applied. Thanks,
>
> > ---
> > drivers/iio/health/max30102.c | 14 +++++++++++---
> > 1 file changed, 11 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> > index 520d905..37176c2 100644
> > --- a/drivers/iio/health/max30102.c
> > +++ b/drivers/iio/health/max30102.c
> > @@ -34,6 +34,11 @@
> > #define MAX30102_DRV_NAME "max30102"
> > #define MAX30102_PART_NUMBER 0x15
> >
> > +enum max3012_led_idx {
> > + MAX30102_LED_RED,
> > + MAX30102_LED_IR,
> > +};
> > +
> > #define MAX30102_REG_INT_STATUS 0x00
> > #define MAX30102_REG_INT_STATUS_PWR_RDY BIT(0)
> > #define MAX30102_REG_INT_STATUS_PROX_INT BIT(4)
> > @@ -104,7 +109,10 @@ static const struct regmap_config max30102_regmap_config = {
> > .val_bits = 8,
> > };
> >
> > -static const unsigned long max30102_scan_masks[] = {0x3, 0};
> > +static const unsigned long max30102_scan_masks[] = {
> > + BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR),
> > + 0
> > +};
> >
> > #define MAX30102_INTENSITY_CHANNEL(_si, _mod) { \
> > .type = IIO_INTENSITY, \
> > @@ -121,8 +129,8 @@ static const unsigned long max30102_scan_masks[] = {0x3, 0};
> > }
> >
> > static const struct iio_chan_spec max30102_channels[] = {
> > - MAX30102_INTENSITY_CHANNEL(0, IIO_MOD_LIGHT_RED),
> > - MAX30102_INTENSITY_CHANNEL(1, IIO_MOD_LIGHT_IR),
> > + MAX30102_INTENSITY_CHANNEL(MAX30102_LED_RED, IIO_MOD_LIGHT_RED),
> > + MAX30102_INTENSITY_CHANNEL(MAX30102_LED_IR, IIO_MOD_LIGHT_IR),
> > {
> > .type = IIO_TEMP,
> > .info_mask_separate =
> > --
> > 2.7.4
> >
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 10/13] iio: health: max30102: Move mode setting to buffer_postenable
2017-11-19 20:56 ` Matt Ranostay
@ 2017-11-25 14:17 ` Jonathan Cameron
0 siblings, 0 replies; 41+ messages in thread
From: Jonathan Cameron @ 2017-11-25 14:17 UTC (permalink / raw)
To: Matt Ranostay; +Cc: Peter Meerwald-Stadler, linux-iio
On Sun, 19 Nov 2017 12:56:28 -0800
Matt Ranostay <matt.ranostay@konsulko.com> wrote:
> On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
> <pmeerw@pmeerw.net> wrote:
> > Move the programming of the mode setting from init() to
> > buffer_postenable()
> >
> > Split out a separate function to
> > only update the power/shutdown bit
> >
> > This changes permits to more easily implement different
> > modes of measurements in further patches
> >
> > Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> > Cc: Matt Ranostay <matt.ranostay@konsulko.com>
>
> Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
Applied.
>
> > ---
> > drivers/iio/health/max30102.c | 44 +++++++++++++++++++++++++++----------------
> > 1 file changed, 28 insertions(+), 16 deletions(-)
> >
> > diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> > index 37176c2..1c7fe63 100644
> > --- a/drivers/iio/health/max30102.c
> > +++ b/drivers/iio/health/max30102.c
> > @@ -66,6 +66,7 @@ enum max3012_led_idx {
> > #define MAX30102_REG_FIFO_CONFIG_AFULL BIT(0)
> >
> > #define MAX30102_REG_MODE_CONFIG 0x09
> > +#define MAX30102_REG_MODE_CONFIG_MODE_NONE 0x00
> > #define MAX30102_REG_MODE_CONFIG_MODE_HR 0x02 /* red LED */
> > #define MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2 0x03 /* red + IR LED */
> > #define MAX30102_REG_MODE_CONFIG_MODE_MULTI 0x07 /* multi-LED mode */
> > @@ -139,25 +140,41 @@ static const struct iio_chan_spec max30102_channels[] = {
> > },
> > };
> >
> > -static int max30102_set_powermode(struct max30102_data *data, bool state)
> > +static int max30102_set_power(struct max30102_data *data, bool en)
> > {
> > return regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
> > MAX30102_REG_MODE_CONFIG_PWR,
> > - state ? 0 : MAX30102_REG_MODE_CONFIG_PWR);
> > + en ? 0 : MAX30102_REG_MODE_CONFIG_PWR);
> > +}
> > +
> > +static int max30102_set_powermode(struct max30102_data *data, u8 mode, bool en)
> > +{
> > + u8 reg = mode;
> > +
> > + if (!en)
> > + reg |= MAX30102_REG_MODE_CONFIG_PWR;
> > +
> > + return regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
> > + MAX30102_REG_MODE_CONFIG_PWR |
> > + MAX30102_REG_MODE_CONFIG_MODE_MASK, reg);
> > }
> >
> > static int max30102_buffer_postenable(struct iio_dev *indio_dev)
> > {
> > struct max30102_data *data = iio_priv(indio_dev);
> > + u8 reg;
> > +
> > + reg = MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2;
> >
> > - return max30102_set_powermode(data, true);
> > + return max30102_set_powermode(data, reg, true);
> > }
> >
> > static int max30102_buffer_predisable(struct iio_dev *indio_dev)
> > {
> > struct max30102_data *data = iio_priv(indio_dev);
> >
> > - return max30102_set_powermode(data, false);
> > + return max30102_set_powermode(data, MAX30102_REG_MODE_CONFIG_MODE_NONE,
> > + false);
> > }
> >
> > static const struct iio_buffer_setup_ops max30102_buffer_setup_ops = {
> > @@ -278,7 +295,7 @@ static int max30102_chip_init(struct max30102_data *data)
> > if (ret)
> > return ret;
> >
> > - /* enable 18-bit HR + SPO2 readings at 400Hz */
> > + /* configure 18-bit HR + SpO2 readings at 400Hz */
> > ret = regmap_write(data->regmap, MAX30102_REG_SPO2_CONFIG,
> > (MAX30102_REG_SPO2_CONFIG_ADC_4096_STEPS
> > << MAX30102_REG_SPO2_CONFIG_ADC_MASK_SHIFT) |
> > @@ -288,13 +305,6 @@ static int max30102_chip_init(struct max30102_data *data)
> > if (ret)
> > return ret;
> >
> > - /* enable HR + SPO2 mode */
> > - ret = regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
> > - MAX30102_REG_MODE_CONFIG_MODE_MASK,
> > - MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2);
> > - if (ret)
> > - return ret;
> > -
> > /* average 4 samples + generate FIFO interrupt */
> > ret = regmap_write(data->regmap, MAX30102_REG_FIFO_CONFIG,
> > (MAX30102_REG_FIFO_CONFIG_AVG_4SAMPLES
> > @@ -334,7 +344,7 @@ static int max30102_get_temp(struct max30102_data *data, int *val, bool en)
> > int ret;
> >
> > if (en) {
> > - ret = max30102_set_powermode(data, true);
> > + ret = max30102_set_power(data, true);
> > if (ret)
> > return ret;
> > }
> > @@ -351,7 +361,7 @@ static int max30102_get_temp(struct max30102_data *data, int *val, bool en)
> >
> > out:
> > if (en)
> > - max30102_set_powermode(data, false);
> > + max30102_set_power(data, false);
> >
> > return ret;
> > }
> > @@ -448,7 +458,9 @@ static int max30102_probe(struct i2c_client *client,
> > return ret;
> > dev_dbg(&client->dev, "max3010x revision %02x\n", reg);
> >
> > - ret = max30102_set_powermode(data, false);
> > + /* clear mode setting, chip shutdown */
> > + ret = max30102_set_powermode(data, MAX30102_REG_MODE_CONFIG_MODE_NONE,
> > + false);
> > if (ret)
> > return ret;
> >
> > @@ -479,7 +491,7 @@ static int max30102_remove(struct i2c_client *client)
> > struct max30102_data *data = iio_priv(indio_dev);
> >
> > iio_device_unregister(indio_dev);
> > - max30102_set_powermode(data, false);
> > + max30102_set_power(data, false);
> >
> > return 0;
> > }
> > --
> > 2.7.4
> >
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 11/13] iio: health: max30102: Prepare for copying varying number of measurements
2017-11-19 20:52 ` Matt Ranostay
@ 2017-11-25 14:18 ` Jonathan Cameron
0 siblings, 0 replies; 41+ messages in thread
From: Jonathan Cameron @ 2017-11-25 14:18 UTC (permalink / raw)
To: Matt Ranostay; +Cc: Peter Meerwald-Stadler, linux-iio
On Sun, 19 Nov 2017 12:52:56 -0800
Matt Ranostay <matt.ranostay@konsulko.com> wrote:
> On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
> <pmeerw@pmeerw.net> wrote:
> > Current code assumes always 2 measurements (6 bytes) have to be copied,
> > prepare for more flexibility
>
>
> Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
Applied.
>
> >
> > Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> > Cc: Matt Ranostay <matt.ranostay@konsulko.com>
> > ---
> > drivers/iio/health/max30102.c | 15 ++++++++++-----
> > 1 file changed, 10 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> > index 1c7fe63..86058f0 100644
> > --- a/drivers/iio/health/max30102.c
> > +++ b/drivers/iio/health/max30102.c
> > @@ -58,7 +58,7 @@ enum max3012_led_idx {
> > #define MAX30102_REG_FIFO_OVR_CTR 0x05
> > #define MAX30102_REG_FIFO_RD_PTR 0x06
> > #define MAX30102_REG_FIFO_DATA 0x07
> > -#define MAX30102_REG_FIFO_DATA_ENTRY_LEN 6
> > +#define MAX30102_REG_FIFO_DATA_BYTES 3
> >
> > #define MAX30102_REG_FIFO_CONFIG 0x08
> > #define MAX30102_REG_FIFO_CONFIG_AVG_4SAMPLES BIT(1)
> > @@ -198,6 +198,11 @@ static inline int max30102_fifo_count(struct max30102_data *data)
> > return 0;
> > }
> >
> > +#define MAX30102_COPY_DATA(i) \
> > + memcpy(&data->processed_buffer[(i)], \
> > + &buffer[(i) * MAX30102_REG_FIFO_DATA_BYTES], \
> > + MAX30102_REG_FIFO_DATA_BYTES)
> > +
> > static int max30102_read_measurement(struct max30102_data *data)
> > {
> > int ret;
> > @@ -205,13 +210,13 @@ static int max30102_read_measurement(struct max30102_data *data)
> >
> > ret = i2c_smbus_read_i2c_block_data(data->client,
> > MAX30102_REG_FIFO_DATA,
> > - MAX30102_REG_FIFO_DATA_ENTRY_LEN,
> > + 2 * MAX30102_REG_FIFO_DATA_BYTES,
> > buffer);
> >
> > - memcpy(&data->processed_buffer[0], &buffer[0], 3);
> > - memcpy(&data->processed_buffer[1], &buffer[3], 3);
> > + MAX30102_COPY_DATA(0);
> > + MAX30102_COPY_DATA(1);
> >
> > - return (ret == MAX30102_REG_FIFO_DATA_ENTRY_LEN) ? 0 : -EINVAL;
> > + return (ret == 2 * MAX30102_REG_FIFO_DATA_BYTES) ? 0 : -EINVAL;
> > }
> >
> > static irqreturn_t max30102_interrupt_handler(int irq, void *private)
> > --
> > 2.7.4
> >
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 12/13] iio: health: max30102: Add MAX30105 support
2017-11-19 21:00 ` Matt Ranostay
@ 2017-11-25 14:19 ` Jonathan Cameron
0 siblings, 0 replies; 41+ messages in thread
From: Jonathan Cameron @ 2017-11-25 14:19 UTC (permalink / raw)
To: Matt Ranostay; +Cc: Peter Meerwald-Stadler, linux-iio
On Sun, 19 Nov 2017 13:00:51 -0800
Matt Ranostay <matt.ranostay@konsulko.com> wrote:
> On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
> <pmeerw@pmeerw.net> wrote:
> > The Maxim MAX30105 part adds a third LED (green) and uses a multi-LED
> > measuring mode producing three measurements
> >
> > Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> > Cc: Matt Ranostay <matt.ranostay@konsulko.com>
>
> Acked-by: Matt Ranostay <matt.ranostay@konsulko.com>
Applied.
>
> > ---
> > drivers/iio/health/max30102.c | 144 ++++++++++++++++++++++++++++++++++++++----
> > 1 file changed, 130 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c
> > index 86058f0..15ccadc 100644
> > --- a/drivers/iio/health/max30102.c
> > +++ b/drivers/iio/health/max30102.c
> > @@ -3,6 +3,9 @@
> > *
> > * Copyright (C) 2017 Matt Ranostay <matt@ranostay.consulting>
> > *
> > + * Support for MAX30105 optical particle sensor
> > + * Copyright (C) 2017 Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> > + *
> > * This program is free software; you can redistribute it and/or modify
> > * it under the terms of the GNU General Public License as published by
> > * the Free Software Foundation; either version 2 of the License, or
> > @@ -13,6 +16,7 @@
> > * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > * GNU General Public License for more details.
> > *
> > + * 7-bit I2C chip address: 0x57
> > * TODO: proximity power saving feature
> > */
> >
> > @@ -34,9 +38,15 @@
> > #define MAX30102_DRV_NAME "max30102"
> > #define MAX30102_PART_NUMBER 0x15
> >
> > +enum max30102_chip_id {
> > + max30102,
> > + max30105,
> > +};
> > +
> > enum max3012_led_idx {
> > MAX30102_LED_RED,
> > MAX30102_LED_IR,
> > + MAX30105_LED_GREEN,
> > };
> >
> > #define MAX30102_REG_INT_STATUS 0x00
> > @@ -73,6 +83,11 @@ enum max3012_led_idx {
> > #define MAX30102_REG_MODE_CONFIG_MODE_MASK GENMASK(2, 0)
> > #define MAX30102_REG_MODE_CONFIG_PWR BIT(7)
> >
> > +#define MAX30102_REG_MODE_CONTROL_SLOT21 0x11 /* multi-LED control */
> > +#define MAX30102_REG_MODE_CONTROL_SLOT43 0x12
> > +#define MAX30102_REG_MODE_CONTROL_SLOT_MASK (GENMASK(6, 4) | GENMASK(2, 0))
> > +#define MAX30102_REG_MODE_CONTROL_SLOT_SHIFT 4
>
> I assume slot is some time multiplexing of the LEDs?
>
> > +
> > #define MAX30102_REG_SPO2_CONFIG 0x0a
> > #define MAX30102_REG_SPO2_CONFIG_PULSE_411_US 0x03
> > #define MAX30102_REG_SPO2_CONFIG_SR_400HZ 0x03
> > @@ -83,6 +98,7 @@ enum max3012_led_idx {
> >
> > #define MAX30102_REG_RED_LED_CONFIG 0x0c
> > #define MAX30102_REG_IR_LED_CONFIG 0x0d
> > +#define MAX30105_REG_GREEN_LED_CONFIG 0x0e
> >
> > #define MAX30102_REG_TEMP_CONFIG 0x21
> > #define MAX30102_REG_TEMP_CONFIG_TEMP_EN BIT(0)
> > @@ -98,9 +114,10 @@ struct max30102_data {
> > struct iio_dev *indio_dev;
> > struct mutex lock;
> > struct regmap *regmap;
> > + enum max30102_chip_id chip_id;
> >
> > - u8 buffer[8];
> > - __be32 processed_buffer[2]; /* 2 x 18-bit (padded to 32-bits) */
> > + u8 buffer[12];
> > + __be32 processed_buffer[3]; /* 3 x 18-bit (padded to 32-bits) */
> > };
> >
> > static const struct regmap_config max30102_regmap_config = {
> > @@ -115,6 +132,13 @@ static const unsigned long max30102_scan_masks[] = {
> > 0
> > };
> >
> > +static const unsigned long max30105_scan_masks[] = {
> > + BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR),
> > + BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR) |
> > + BIT(MAX30105_LED_GREEN),
> > + 0
> > +};
> > +
> > #define MAX30102_INTENSITY_CHANNEL(_si, _mod) { \
> > .type = IIO_INTENSITY, \
> > .channel2 = _mod, \
> > @@ -140,6 +164,18 @@ static const struct iio_chan_spec max30102_channels[] = {
> > },
> > };
> >
> > +static const struct iio_chan_spec max30105_channels[] = {
> > + MAX30102_INTENSITY_CHANNEL(MAX30102_LED_RED, IIO_MOD_LIGHT_RED),
> > + MAX30102_INTENSITY_CHANNEL(MAX30102_LED_IR, IIO_MOD_LIGHT_IR),
> > + MAX30102_INTENSITY_CHANNEL(MAX30105_LED_GREEN, IIO_MOD_LIGHT_GREEN),
> > + {
> > + .type = IIO_TEMP,
> > + .info_mask_separate =
> > + BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
> > + .scan_index = -1,
> > + },
> > +};
> > +
> > static int max30102_set_power(struct max30102_data *data, bool en)
> > {
> > return regmap_update_bits(data->regmap, MAX30102_REG_MODE_CONFIG,
> > @@ -159,12 +195,40 @@ static int max30102_set_powermode(struct max30102_data *data, u8 mode, bool en)
> > MAX30102_REG_MODE_CONFIG_MODE_MASK, reg);
> > }
> >
> > +#define MAX30102_MODE_CONTROL_LED_SLOTS(slot2, slot1) \
> > + ((slot2 << MAX30102_REG_MODE_CONTROL_SLOT_SHIFT) | slot1)
> > +
> > static int max30102_buffer_postenable(struct iio_dev *indio_dev)
> > {
> > struct max30102_data *data = iio_priv(indio_dev);
> > + int ret;
> > u8 reg;
> >
> > - reg = MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2;
> > + switch (*indio_dev->active_scan_mask) {
> > + case BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR):
> > + reg = MAX30102_REG_MODE_CONFIG_MODE_HR_SPO2;
> > + break;
> > + case BIT(MAX30102_LED_RED) | BIT(MAX30102_LED_IR) |
> > + BIT(MAX30105_LED_GREEN):
> > + ret = regmap_update_bits(data->regmap,
> > + MAX30102_REG_MODE_CONTROL_SLOT21,
> > + MAX30102_REG_MODE_CONTROL_SLOT_MASK,
> > + MAX30102_MODE_CONTROL_LED_SLOTS(2, 1));
> > + if (ret)
> > + return ret;
> > +
> > + ret = regmap_update_bits(data->regmap,
> > + MAX30102_REG_MODE_CONTROL_SLOT43,
> > + MAX30102_REG_MODE_CONTROL_SLOT_MASK,
> > + MAX30102_MODE_CONTROL_LED_SLOTS(0, 3));
> > + if (ret)
> > + return ret;
> > +
> > + reg = MAX30102_REG_MODE_CONFIG_MODE_MULTI;
> > + break;
> > + default:
> > + return -EINVAL;
> > + }
> >
> > return max30102_set_powermode(data, reg, true);
> > }
> > @@ -203,32 +267,46 @@ static inline int max30102_fifo_count(struct max30102_data *data)
> > &buffer[(i) * MAX30102_REG_FIFO_DATA_BYTES], \
> > MAX30102_REG_FIFO_DATA_BYTES)
> >
> > -static int max30102_read_measurement(struct max30102_data *data)
> > +static int max30102_read_measurement(struct max30102_data *data,
> > + unsigned int measurements)
> > {
> > int ret;
> > u8 *buffer = (u8 *) &data->buffer;
> >
> > ret = i2c_smbus_read_i2c_block_data(data->client,
> > MAX30102_REG_FIFO_DATA,
> > - 2 * MAX30102_REG_FIFO_DATA_BYTES,
> > + measurements *
> > + MAX30102_REG_FIFO_DATA_BYTES,
> > buffer);
> >
> > - MAX30102_COPY_DATA(0);
> > - MAX30102_COPY_DATA(1);
> > + switch (measurements) {
> > + case 3:
> > + MAX30102_COPY_DATA(2);
> > + case 2: /* fall-through */
> > + MAX30102_COPY_DATA(1);
> > + case 1: /* fall-through */
> > + MAX30102_COPY_DATA(0);
> > + break;
> > + default:
> > + return -EINVAL;
> > + }
> >
> > - return (ret == 2 * MAX30102_REG_FIFO_DATA_BYTES) ? 0 : -EINVAL;
> > + return (ret == measurements * MAX30102_REG_FIFO_DATA_BYTES) ?
> > + 0 : -EINVAL;
> > }
> >
> > static irqreturn_t max30102_interrupt_handler(int irq, void *private)
> > {
> > struct iio_dev *indio_dev = private;
> > struct max30102_data *data = iio_priv(indio_dev);
> > + unsigned int measurements = bitmap_weight(indio_dev->active_scan_mask,
> > + indio_dev->masklength);
> > int ret, cnt = 0;
> >
> > mutex_lock(&data->lock);
> >
> > while (cnt || (cnt = max30102_fifo_count(data)) > 0) {
> > - ret = max30102_read_measurement(data);
> > + ret = max30102_read_measurement(data, measurements);
> > if (ret)
> > break;
> >
> > @@ -274,6 +352,29 @@ static int max30102_led_init(struct max30102_data *data)
> > if (ret)
> > return ret;
> >
> > + if (data->chip_id == max30105) {
> > + ret = of_property_read_u32(np,
> > + "maxim,green-led-current-microamp", &val);
> > + if (ret) {
> > + dev_info(dev, "no green-led-current-microamp set\n");
> > +
> > + /* Default to 7 mA green LED */
> > + val = 7000;
> > + }
> > +
> > + ret = max30102_get_current_idx(val, ®);
> > + if (ret) {
> > + dev_err(dev, "invalid green LED current setting %d\n",
> > + val);
> > + return ret;
> > + }
> > +
> > + ret = regmap_write(data->regmap, MAX30105_REG_GREEN_LED_CONFIG,
> > + reg);
> > + if (ret)
> > + return ret;
> > + }
> > +
> > ret = of_property_read_u32(np, "maxim,ir-led-current-microamp", &val);
> > if (ret) {
> > dev_info(dev, "no ir-led-current-microamp set\n");
> > @@ -429,10 +530,7 @@ static int max30102_probe(struct i2c_client *client,
> > iio_device_attach_buffer(indio_dev, buffer);
> >
> > indio_dev->name = MAX30102_DRV_NAME;
> > - indio_dev->channels = max30102_channels;
> > indio_dev->info = &max30102_info;
> > - indio_dev->num_channels = ARRAY_SIZE(max30102_channels);
> > - indio_dev->available_scan_masks = max30102_scan_masks;
> > indio_dev->modes = (INDIO_BUFFER_SOFTWARE | INDIO_DIRECT_MODE);
> > indio_dev->setup_ops = &max30102_buffer_setup_ops;
> > indio_dev->dev.parent = &client->dev;
> > @@ -440,10 +538,26 @@ static int max30102_probe(struct i2c_client *client,
> > data = iio_priv(indio_dev);
> > data->indio_dev = indio_dev;
> > data->client = client;
> > + data->chip_id = id->driver_data;
> >
> > mutex_init(&data->lock);
> > i2c_set_clientdata(client, indio_dev);
> >
> > + switch (data->chip_id) {
> > + case max30105:
> > + indio_dev->channels = max30105_channels;
> > + indio_dev->num_channels = ARRAY_SIZE(max30105_channels);
> > + indio_dev->available_scan_masks = max30105_scan_masks;
> > + break;
> > + case max30102:
> > + indio_dev->channels = max30102_channels;
> > + indio_dev->num_channels = ARRAY_SIZE(max30102_channels);
> > + indio_dev->available_scan_masks = max30102_scan_masks;
> > + break;
> > + default:
> > + return -ENODEV;
> > + }
> > +
> > data->regmap = devm_regmap_init_i2c(client, &max30102_regmap_config);
> > if (IS_ERR(data->regmap)) {
> > dev_err(&client->dev, "regmap initialization failed\n");
> > @@ -502,13 +616,15 @@ static int max30102_remove(struct i2c_client *client)
> > }
> >
> > static const struct i2c_device_id max30102_id[] = {
> > - { "max30102", 0 },
> > + { "max30102", max30102 },
> > + { "max30105", max30105 },
> > {}
> > };
> > MODULE_DEVICE_TABLE(i2c, max30102_id);
> >
> > static const struct of_device_id max30102_dt_ids[] = {
> > { .compatible = "maxim,max30102" },
> > + { .compatible = "maxim,max30105" },
> > { }
> > };
> > MODULE_DEVICE_TABLE(of, max30102_dt_ids);
> > @@ -525,5 +641,5 @@ static struct i2c_driver max30102_driver = {
> > module_i2c_driver(max30102_driver);
> >
> > MODULE_AUTHOR("Matt Ranostay <matt@ranostay.consulting>");
> > -MODULE_DESCRIPTION("MAX30102 heart rate and pulse oximeter sensor");
> > +MODULE_DESCRIPTION("MAX30102 heart rate/pulse oximeter and MAX30105 particle sensor driver");
> > MODULE_LICENSE("GPL");
> > --
> > 2.7.4
> >
^ permalink raw reply [flat|nested] 41+ messages in thread
* Re: [PATCH v2 13/13] dt-bindings: iio: health: Add MAX30105 support to max30102.txt
2017-11-19 20:35 ` Matt Ranostay
@ 2017-11-25 14:20 ` Jonathan Cameron
0 siblings, 0 replies; 41+ messages in thread
From: Jonathan Cameron @ 2017-11-25 14:20 UTC (permalink / raw)
To: Matt Ranostay; +Cc: Peter Meerwald-Stadler, linux-iio, Rob Herring
On Sun, 19 Nov 2017 12:35:04 -0800
Matt Ranostay <matt.ranostay@konsulko.com> wrote:
> On Fri, Oct 27, 2017 at 12:45 PM, Peter Meerwald-Stadler
> <pmeerw@pmeerw.net> wrote:
> > Signed-off-by: Peter Meerwald-Stadler <pmeerw@pmeerw.net>
> > Cc: Matt Ranostay <matt.ranostay@konsulko.com>
> > Cc: Rob Herring <robh+dt@kernel.org>
>
> Reviewed-by: Matt Ranostay <matt.ranostay@konsulko.com>
>
Applied to the togreg branch of iio.git and pushed out as testing for
the autobuilders to play with it.
Thanks,
Jonathan
> > ---
> > Documentation/devicetree/bindings/iio/health/max30102.txt | 8 ++++++--
> > 1 file changed, 6 insertions(+), 2 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/iio/health/max30102.txt b/Documentation/devicetree/bindings/iio/health/max30102.txt
> > index 8629c18..ef2ca0a 100644
> > --- a/Documentation/devicetree/bindings/iio/health/max30102.txt
> > +++ b/Documentation/devicetree/bindings/iio/health/max30102.txt
> > @@ -1,9 +1,11 @@
> > Maxim MAX30102 heart rate and pulse oximeter sensor
> > +Maxim MAX30105 optical particle-sensing module
> >
> > * https://datasheets.maximintegrated.com/en/ds/MAX30102.pdf
> > +* https://datasheets.maximintegrated.com/en/ds/MAX30105.pdf
> >
> > Required properties:
> > - - compatible: must be "maxim,max30102"
> > + - compatible: must be "maxim,max30102" or "maxim,max30105"
> > - reg: the I2C address of the sensor
> > - interrupt-parent: should be the phandle for the interrupt controller
> > - interrupts: the sole interrupt generated by the device
> > @@ -12,8 +14,10 @@ Required properties:
> > interrupt client node bindings.
> >
> > Optional properties:
> > - - maxim,red-led-current-microamp: configuration for RED LED current
> > + - maxim,red-led-current-microamp: configuration for red LED current
> > - maxim,ir-led-current-microamp: configuration for IR LED current
> > + - maxim,green-led-current-microamp: configuration for green LED current
> > + (max30105 only)
> >
> > Note that each step is approximately 200 microamps, ranging from 0 uA to
> > 50800 uA.
> > --
> > 2.7.4
> >
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 41+ messages in thread
end of thread, other threads:[~2017-11-25 14:21 UTC | newest]
Thread overview: 41+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-10-27 19:45 [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver Peter Meerwald-Stadler
2017-10-27 19:45 ` [PATCH v2 01/13] iio: health: max30102: Temperature should be in milli Celsius Peter Meerwald-Stadler
2017-11-19 21:09 ` Matt Ranostay
2017-11-25 14:04 ` Jonathan Cameron
2017-10-27 19:45 ` [PATCH v2 02/13] iio: health: max30102: Fix missing newline in dev_err Peter Meerwald-Stadler
2017-11-19 20:28 ` Matt Ranostay
2017-11-25 14:05 ` Jonathan Cameron
2017-10-27 19:45 ` [PATCH v2 03/13] iio: health: max30102: Remove inconsistent full stop in error message Peter Meerwald-Stadler
2017-11-19 20:28 ` Matt Ranostay
2017-11-25 14:06 ` Jonathan Cameron
2017-10-27 19:45 ` [PATCH v2 04/13] iio: health: max30102: Fix mode config values Peter Meerwald-Stadler
2017-11-19 20:46 ` Matt Ranostay
2017-11-25 14:07 ` Jonathan Cameron
2017-10-27 19:45 ` [PATCH v2 05/13] iio: health: max30102: Check retval of powermode function Peter Meerwald-Stadler
2017-11-19 20:43 ` Matt Ranostay
2017-11-25 14:08 ` Jonathan Cameron
2017-10-27 19:45 ` [PATCH v2 06/13] iio: health: max30102: Add check for part ID Peter Meerwald-Stadler
2017-11-19 20:38 ` Matt Ranostay
2017-11-25 14:11 ` Jonathan Cameron
2017-10-27 19:45 ` [PATCH v2 07/13] iio: health: max30102: Introduce intensity channel macro Peter Meerwald-Stadler
2017-11-19 20:37 ` Matt Ranostay
2017-11-25 14:12 ` Jonathan Cameron
2017-10-27 19:45 ` [PATCH v2 08/13] iio: health: max30102: Add power enable parameter to get_temp function Peter Meerwald-Stadler
2017-11-19 20:41 ` Matt Ranostay
2017-11-25 14:15 ` Jonathan Cameron
2017-10-27 19:45 ` [PATCH v2 09/13] iio: health: max30102: Introduce indices for LED channels Peter Meerwald-Stadler
2017-11-19 20:42 ` Matt Ranostay
2017-11-25 14:16 ` Jonathan Cameron
2017-10-27 19:45 ` [PATCH v2 10/13] iio: health: max30102: Move mode setting to buffer_postenable Peter Meerwald-Stadler
2017-11-19 20:56 ` Matt Ranostay
2017-11-25 14:17 ` Jonathan Cameron
2017-10-27 19:45 ` [PATCH v2 11/13] iio: health: max30102: Prepare for copying varying number of measurements Peter Meerwald-Stadler
2017-11-19 20:52 ` Matt Ranostay
2017-11-25 14:18 ` Jonathan Cameron
2017-10-27 19:45 ` [PATCH v2 12/13] iio: health: max30102: Add MAX30105 support Peter Meerwald-Stadler
2017-11-19 21:00 ` Matt Ranostay
2017-11-25 14:19 ` Jonathan Cameron
2017-10-27 19:45 ` [PATCH v2 13/13] dt-bindings: iio: health: Add MAX30105 support to max30102.txt Peter Meerwald-Stadler
2017-11-19 20:35 ` Matt Ranostay
2017-11-25 14:20 ` Jonathan Cameron
2017-11-02 14:44 ` [PATCH v2 00/13] iio: health: Add MAX30105 support to max30102 driver Jonathan Cameron
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.