Skip to contentSkip to conversation

Add ISL29501 support.

PATCH New Mathieu Othacehe 1 participant 4 messages Jul 20, 2018

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

v6 cover Add ISL29501 support.

Hi,

Here's v6 of this serie, please find the changelog below.

Thanks,

Mathieu

v6:
* Extract floating registers support as a separated, wip patch.
* Style corrections
v5:
* Use IIO_MOD_LIGHT_CLEAR modifier for IIO_INTENSITY channel describing ambient light intensity and remove extended_names doing so.
* Fix a possible leakage in isl29501_trigger_handler function. v4:
* Fix build warnings and rebase on top of next-20180628
v3:
* Renamings to add isl29501 prefix
* Rename "amb" -> "light" in extended fields
* Move mutex lock/unlock to register_read and register_write functions
* Improve IIO_PHASE scale output with a better pi estimation v2:
* Add missing eof new line
* Do not set .indexed to true for all channels
* Add a .extended to differenciate "magnitude" and "ambient_light" intensity channels
* Return isl29501_begin_acquisition result in isl29501_init_chip
* Fix buffer size in isl29501_trigger_handler

Mathieu Othacehe (3):
iio: Add channel for Phase
iio: light: isl29501: Add support for the ISL29501 ToF sensor.
iio: light: isl29501: Add support floating registers.

 Documentation/ABI/testing/sysfs-bus-iio       |    7 +
 .../ABI/testing/sysfs-bus-iio-isl29501        |   47 +
 .../bindings/iio/light/isl29501.txt           |   13 +
 drivers/iio/industrialio-core.c               |    1 +
 drivers/iio/light/Kconfig                     |   13 +
 drivers/iio/light/Makefile                    |    1 +
 drivers/iio/light/isl29501.c                  | 1125 +++++++++++++++++
 include/uapi/linux/iio/types.h                |    1 +
 tools/iio/iio_event_monitor.c                 |    2 +
 9 files changed, 1210 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-isl29501
 create mode 100644 Documentation/devicetree/bindings/iio/light/isl29501.txt
 create mode 100644 drivers/iio/light/isl29501.c
Signature · 1 line
2.17.1
#1 lore raw

PATCH v6 1/3 iio: Add channel for Phase

Add new channel type support for phase.

This channel may be used by Time-of-flight sensors to express the phase difference between emitted and received signals. Those sensor will then use the phase shift of return signals to approximate the distance to objects.

---
 Documentation/ABI/testing/sysfs-bus-iio | 7 +++++++
 drivers/iio/industrialio-core.c         | 1 +
 include/uapi/linux/iio/types.h          | 1 +
 tools/iio/iio_event_monitor.c           | 2 ++
 4 files changed, 11 insertions(+)
Documentation/ABI/testing/sysfs-bus-iio +7 -0
index c7353030670a..c9cfa833cf47 100644
@@ -1675,3 +1675,10 @@ KernelVersion:	4.12
 Contact:	[email protected]
 Description:
 		Raw counter device counters direction for channel Y.
+
+What:		/sys/bus/iio/devices/iio:deviceX/in_phaseY_raw
+KernelVersion:	4.18
+Contact:	[email protected]
+Description:
+		Raw (unscaled) phase difference reading from channel Y
+		that can be processed to radians.
\ No newline at end of file
drivers/iio/industrialio-core.c +1 -0
index ed1b3ebade94..a16ad5a4ab0c 100644
@@ -86,6 +86,7 @@ static const char * const iio_chan_type_name_spec[] = {
 	[IIO_INDEX] = "index",
 	[IIO_GRAVITY]  = "gravity",
 	[IIO_POSITIONRELATIVE]  = "positionrelative",
+	[IIO_PHASE] = "phase",
 };
 
 static const char * const iio_modifier_names[] = {
include/uapi/linux/iio/types.h +1 -0
index 033c7d28924e..e4df3cc268db 100644
@@ -45,6 +45,7 @@ enum iio_chan_type {
 	IIO_INDEX,
 	IIO_GRAVITY,
 	IIO_POSITIONRELATIVE,
+	IIO_PHASE,
 };
 
 enum iio_modifier {
tools/iio/iio_event_monitor.c +2 -0
index 148f69dfae75..f478f5558720 100644
@@ -59,6 +59,7 @@ static const char * const iio_chan_type_name_spec[] = {
 	[IIO_UVINDEX] = "uvindex",
 	[IIO_GRAVITY] = "gravity",
 	[IIO_POSITIONRELATIVE] = "positionrelative",
+	[IIO_PHASE] = "phase",
 };
 
 static const char * const iio_ev_type_text[] = {
@@ -153,6 +154,7 @@ static bool event_is_known(struct iio_event_data *event)
 	case IIO_UVINDEX:
 	case IIO_GRAVITY:
 	case IIO_POSITIONRELATIVE:
+	case IIO_PHASE:
 		break;
 	default:
 		return false;
Signature · 1 line
2.17.1
#2 lore raw

PATCH v6 2/3 iio: light: isl29501: Add support for the ISL29501 ToF sensor.

In reply to Mathieu Othacehe

This patch adds support for the ISL29501 Time of Flight sensor.

---
 .../ABI/testing/sysfs-bus-iio-isl29501        |   47 +
 .../bindings/iio/light/isl29501.txt           |   13 +
 drivers/iio/light/Kconfig                     |   13 +
 drivers/iio/light/Makefile                    |    1 +
 drivers/iio/light/isl29501.c                  | 1022 +++++++++++++++++
 5 files changed, 1096 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-isl29501
 create mode 100644 Documentation/devicetree/bindings/iio/light/isl29501.txt
 create mode 100644 drivers/iio/light/isl29501.c
Documentation/ABI/testing/sysfs-bus-iio-isl29501 new file +47 -0
new file mode 100644
index 000000000000..d009cfbbd72b
@@ -0,0 +1,47 @@
+What:		/sys/bus/iio/devices/iio:deviceX/in_proximity0_agc_gain
+What:		/sys/bus/iio/devices/iio:deviceX/in_proximity0_agc_gain_bias
+KernelVersion:	4.18
+Contact:	[email protected]
+Description:
+		This sensor has an automatic gain control (agc) loop
+		which sets the analog signal levels at an optimum
+		level by controlling programmable gain amplifiers. The
+		criteria for optimal gain is determined by the sensor.
+
+		Return the actual gain value as an integer in [0; 65536]
+		range when read from.
+
+		The agc gain read when measuring crosstalk shall be
+		written into in_proximity0_agc_gain_bias.
+
+What:		/sys/bus/iio/devices/iio:deviceX/in_proximity0_calib_phase_temp_a
+What:		/sys/bus/iio/devices/iio:deviceX/in_proximity0_calib_phase_temp_b
+What:		/sys/bus/iio/devices/iio:deviceX/in_proximity0_calib_phase_light_a
+What:		/sys/bus/iio/devices/iio:deviceX/in_proximity0_calib_phase_light_b
+KernelVersion:	4.18
+Contact:	[email protected]
+Description:
+		The sensor is able to perform correction of distance
+		measurements due to changing temperature and ambient
+		light conditions. It can be programmed to correct for
+		a second order error polynomial.
+
+		Phase data has to be collected when temperature and
+		ambient light are modulated independently.
+
+		Then a least squares curve fit to a second order
+		polynomial has to be generated from the data. The
+		resultant curves have the form ax^2 + bx + c.
+
+		From those two curves, a and b coefficients shall be
+		stored in in_proximity0_calib_phase_temp_a and
+		in_proximity0_calib_phase_temp_b for temperature and
+		in in_proximity0_calib_phase_light_a and
+		in_proximity0_calib_phase_light_b for ambient light.
+
+		Those values must be integer in [0; 8355840] range.
+
+		Finally, the c constant is set by the sensor
+		internally.
+
+		The value stored in sensor is displayed when read from.
Documentation/devicetree/bindings/iio/light/isl29501.txt new file +13 -0
new file mode 100644
index 000000000000..46957997fee3
@@ -0,0 +1,13 @@
+* ISL29501 Time-of-flight sensor.
+
+Required properties:
+
+  - compatible : should be "renesas,isl29501"
+  - reg : the I2C address of the sensor
+
+Example:
+
+isl29501@57 {
+	compatible = "renesas,isl29501";
+	reg = <0x57>;
+};
drivers/iio/light/Kconfig +13 -0
index c7ef8d1862d6..3882bdc28525 100644
@@ -194,6 +194,19 @@ config ISL29125
 	  To compile this driver as a module, choose M here: the module will be
 	  called isl29125.
 
+config ISL29501
+	tristate "Intersil ISL29501 Time Of Flight sensor"
+	depends on I2C
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	select IIO_KFIFO_BUF
+	help
+	  Say Y here if you want to build a driver for the Intersil ISL29501
+	  Time of Flight sensor.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called isl29501.
+
 config HID_SENSOR_ALS
 	depends on HID_SENSOR_HUB
 	select IIO_BUFFER
drivers/iio/light/Makefile +1 -0
index 80943af5d627..81c06316a2be 100644
@@ -23,6 +23,7 @@ obj-$(CONFIG_HID_SENSOR_PROX)	+= hid-sensor-prox.o
 obj-$(CONFIG_SENSORS_ISL29018)	+= isl29018.o
 obj-$(CONFIG_SENSORS_ISL29028)	+= isl29028.o
 obj-$(CONFIG_ISL29125)		+= isl29125.o
+obj-$(CONFIG_ISL29501)		+= isl29501.o
 obj-$(CONFIG_JSA1212)		+= jsa1212.o
 obj-$(CONFIG_SENSORS_LM3533)	+= lm3533-als.o
 obj-$(CONFIG_LTR501)		+= ltr501.o
drivers/iio/light/isl29501.c new file +1022 -0

1,022 lines not on this page · raw message

Signature · 1 line
2.17.1
#3 lore raw

PATCH v6 3/3 iio: light: isl29501: Add support floating registers.

In reply to Mathieu Othacehe

This is work in progress. A new IIO ABI allowing floating value read and write through sysfs has to be defined first.

---
 drivers/iio/light/isl29501.c | 121 ++++++++++++++++++++++++++++++++---
 1 file changed, 112 insertions(+), 9 deletions(-)
drivers/iio/light/isl29501.c +112 -9
index ea4a2ced1004..8698b7caee9b 100644
@@ -112,11 +112,17 @@ struct isl29501_private {
 
 enum isl29501_register_name {
 	REG_DISTANCE,
+	REG_AMPLITUDE,
 	REG_PHASE,
+	REG_I_RAW,
+	REG_Q_RAW,
 	REG_TEMPERATURE,
 	REG_AMBIENT_LIGHT,
 	REG_GAIN,
+	REG_I_BIAS,
+	REG_Q_BIAS,
 	REG_GAIN_BIAS,
+	REG_AMPL_BIAS,
 	REG_PHASE_EXP,
 	REG_CALIB_PHASE_TEMP_A,
 	REG_CALIB_PHASE_TEMP_B,
@@ -133,6 +139,7 @@ enum isl29501_register_name {
 struct isl29501_register_desc {
 	u8 msb;
 	u8 lsb;
+	u8 exp;
 };
 
 static const struct isl29501_register_desc isl29501_registers[] = {
@@ -140,10 +147,25 @@ static const struct isl29501_register_desc isl29501_registers[] = {
 		.msb = ISL29501_DISTANCE_MSB_DATA,
 		.lsb = ISL29501_DISTANCE_LSB_DATA,
 	},
+	[REG_AMPLITUDE] = {
+		.msb = ISL29501_MAGNITUDE_MSB,
+		.lsb = ISL29501_MAGNITUDE_LSB,
+		.exp = ISL29501_MAGNITUDE_EXPONENT,
+	},
 	[REG_PHASE] = {
 		.msb = ISL29501_PHASE_MSB,
 		.lsb = ISL29501_PHASE_LSB,
 	},
+	[REG_I_RAW] = {
+		.msb = ISL29501_I_RAW_MSB,
+		.lsb = ISL29501_I_RAW_LSB,
+		.exp = ISL29501_I_RAW_EXPONENT,
+	},
+	[REG_Q_RAW] = {
+		.msb = ISL29501_Q_RAW_MSB,
+		.lsb = ISL29501_Q_RAW_LSB,
+		.exp = ISL29501_Q_RAW_EXPONENT,
+	},
 	[REG_TEMPERATURE] = {
 		.lsb = ISL29501_DIE_TEMPERATURE,
 	},
@@ -154,10 +176,25 @@ static const struct isl29501_register_desc isl29501_registers[] = {
 		.msb = ISL29501_GAIN_MSB,
 		.lsb = ISL29501_GAIN_LSB,
 	},
+	[REG_I_BIAS] = {
+		.msb = ISL29501_CROSSTALK_I_MSB,
+		.lsb = ISL29501_CROSSTALK_I_LSB,
+		.exp = ISL29501_CROSSTALK_I_EXPONENT,
+	},
+	[REG_Q_BIAS] = {
+		.msb = ISL29501_CROSSTALK_Q_MSB,
+		.lsb = ISL29501_CROSSTALK_Q_LSB,
+		.exp = ISL29501_CROSSTALK_Q_EXPONENT,
+	},
 	[REG_GAIN_BIAS] = {
 		.msb = ISL29501_CROSSTALK_GAIN_MSB,
 		.lsb = ISL29501_CROSSTALK_GAIN_LSB,
 	},
+	[REG_AMPL_BIAS] = {
+		.msb = ISL29501_MAGNITUDE_REF_MSB,
+		.lsb = ISL29501_MAGNITUDE_REF_LSB,
+		.exp = ISL29501_MAGNITUDE_REF_EXP,
+	},
 	[REG_PHASE_EXP] = {
 		.lsb = ISL29501_PHASE_EXPONENT,
 	},
@@ -199,7 +236,7 @@ static int isl29501_register_read(struct isl29501_private *isl29501,
 				  u32 *val)
 {
 	const struct isl29501_register_desc *reg = &isl29501_registers[name];
-	u8 msb = 0, lsb = 0;
+	u8 msb = 0, lsb = 0, exp = 0;
 	s32 ret;
 
 	mutex_lock(&isl29501->lock);
@@ -216,9 +253,16 @@ static int isl29501_register_read(struct isl29501_private *isl29501,
 			goto err;
 		lsb = ret;
 	}
+
+	if (reg->exp) {
+		ret = i2c_smbus_read_byte_data(isl29501->client, reg->exp);
+		if (ret < 0)
+			goto err;
+		exp = ret;
+	}
 	mutex_unlock(&isl29501->lock);
 
-	*val = (msb << 8) + lsb;
+	*val = ((msb << 8) + lsb) << exp;
 
 	return 0;
 err:
@@ -238,9 +282,14 @@ static u32 isl29501_register_write(struct isl29501_private *isl29501,
 	if (!reg->msb && value > U8_MAX)
 		return -ERANGE;
 
-	if (value > U16_MAX)
+	if (!reg->exp && value > U16_MAX)
 		return -ERANGE;
 
+	if (reg->exp) {
+		/* TODO: Implement float write */
+		return -EINVAL;
+	}
+
 	if (!reg->msb) {
 		lsb = value & 0xFF;
 	} else {
@@ -519,6 +568,28 @@ static const struct iio_chan_spec isl29501_channels[] = {
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 				BIT(IIO_CHAN_INFO_SCALE),
 	},
+	{
+		.type = IIO_INTENSITY,
+		.scan_index = -1,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				BIT(IIO_CHAN_INFO_CALIBBIAS),
+	},
+	{
+		.type = IIO_INTENSITY,
+		.scan_index = -1,
+		.modified = 1,
+		.channel2 = IIO_MOD_I,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				BIT(IIO_CHAN_INFO_CALIBBIAS),
+	},
+	{
+		.type = IIO_INTENSITY,
+		.scan_index = -1,
+		.modified = 1,
+		.channel2 = IIO_MOD_Q,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				BIT(IIO_CHAN_INFO_CALIBBIAS),
+	},
 	{
 		.type = IIO_CURRENT,
 		.scan_index = -1,
@@ -633,13 +704,23 @@ static int isl29501_get_raw(struct isl29501_private *isl29501,
 
 		return IIO_VAL_INT;
 	case IIO_INTENSITY:
-		ret = isl29501_register_read(isl29501,
-					     REG_AMBIENT_LIGHT,
-					     raw);
-		if (ret < 0)
-			return ret;
+		switch (chan->channel2) {
+		case IIO_NO_MOD:
+		case IIO_MOD_I:
+		case IIO_MOD_Q:
+			/* TODO: implement float read */
+			return -EINVAL;
+		case IIO_MOD_LIGHT_CLEAR:
+			ret = isl29501_register_read(isl29501,
+						     REG_AMBIENT_LIGHT,
+						     raw);
+			if (ret < 0)
+				return ret;
 
-		return IIO_VAL_INT;
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
 	case IIO_PHASE:
 		ret = isl29501_register_read(isl29501, REG_PHASE, raw);
 		if (ret < 0)
@@ -684,6 +765,8 @@ static int isl29501_get_scale(struct isl29501_private *isl29501,
 
 		return IIO_VAL_INT_PLUS_NANO;
 	case IIO_INTENSITY:
+		if (chan->channel2 != IIO_MOD_LIGHT_CLEAR)
+			return -EINVAL;
 		/* light = raw_light * 35 / 10000 (mA) */
 		*val = 35;
 		*val2 = 10000;
@@ -729,6 +812,16 @@ static int isl29501_get_calibbias(struct isl29501_private *isl29501,
 		return isl29501_register_read(isl29501,
 					      REG_DISTANCE_BIAS,
 					      bias);
+	case IIO_INTENSITY:
+		switch (chan->channel2) {
+		case IIO_NO_MOD:
+		case IIO_MOD_I:
+		case IIO_MOD_Q:
+			/* TODO: Implement float read */
+			return -EINVAL;
+		default:
+			return -EINVAL;
+		}
 	case IIO_TEMP:
 		return isl29501_register_read(isl29501,
 					      REG_TEMPERATURE_BIAS,
@@ -858,6 +951,16 @@ static int isl29501_set_calibbias(struct isl29501_private *isl29501,
 		return isl29501_register_write(isl29501,
 					      REG_DISTANCE_BIAS,
 					      bias);
+	case IIO_INTENSITY:
+		switch (chan->channel2) {
+		case IIO_NO_MOD:
+		case IIO_MOD_I:
+		case IIO_MOD_Q:
+			/* TODO: Implement float read */
+			return -EINVAL;
+		default:
+			return -EINVAL;
+		}
 	case IIO_TEMP:
 		return isl29501_register_write(isl29501,
 					       REG_TEMPERATURE_BIAS,
Signature · 1 line
2.17.1