All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v9 0/2] iio: proximity: driver for vcnl3020
@ 2020-04-17 18:20 Ivan Mikhaylov
  2020-04-17 18:20 ` [PATCH v9 1/2] iio: proximity: provide device tree binding document Ivan Mikhaylov
  2020-04-17 18:20 ` [PATCH v9 2/2] iio: proximity: Add driver support for vcnl3020 proximity sensor Ivan Mikhaylov
  0 siblings, 2 replies; 7+ messages in thread
From: Ivan Mikhaylov @ 2020-04-17 18:20 UTC (permalink / raw)
  Cc: Ivan Mikhaylov, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, linux-iio,
	linux-kernel, devicetree, Mark Rutland, Rob Herring,
	Andy Shevchenko

Add proximity sensor driver for Vishay vcnl3020. Only on-demand
measurement is supported for now.

Changes from v8:
   1. add vcnl3020 prefix into get_and_apply_property function.
   2. add bsd license into yaml.
   3. vishay,led-current-milliamp -> vishay,led-current-microamp.
   4. add default value into vishay,led-current-microamp and change
      register values into microamps.

Changes from v7:
   1. forgot to add Reviewed-by tag.

Changes from v6:
   1. minor changes
     1.1 remove VCNL_DRV_NAME
     1.2 add braces in get_and_apply_property

Changes from v5:
   1. add get_and_apply_property function for optional parameters.
   2. minor changes.

Changes from v4:
   1. add vdd-supply,vddio-supply,interrupts properties into yaml.
   2. led-current -> vishay,led-current-milliamp in yaml.
   3. add possible values enum list.
   4. add bulk_read for result hi/lo registers.
   5. add description of vcnl3020_data structure.
   6. vcnl3020 id table is removed.
   7. make "vishay,led-current-milliamp" optional in yaml and code.

Changes from v3:
   1. minor changes.
   2. add i2c block to fix dts section in yaml.

Changes from v2:
   1. using regmap_read_poll_timeout instead of do-while in measurement
      function.
   2. change struct i2client* in vcnl3020_data to struct dev*
   3. enable REGMAP_I2C in Kconfig

Changes from v1:
   1. using regmap interface instead of i2c_smbus_* calls.
   2. switch from probe to probe_new.
   3. s32/int32_t -> int

Ivan Mikhaylov (2):
  iio: proximity: provide device tree binding document
  iio: proximity: Add driver support for vcnl3020 proximity sensor

 .../bindings/iio/proximity/vcnl3020.yaml      |  64 +++++
 drivers/iio/proximity/Kconfig                 |  11 +
 drivers/iio/proximity/Makefile                |   1 +
 drivers/iio/proximity/vcnl3020.c              | 235 ++++++++++++++++++
 4 files changed, 311 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/proximity/vcnl3020.yaml
 create mode 100644 drivers/iio/proximity/vcnl3020.c

-- 
2.21.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v9 1/2] iio: proximity: provide device tree binding document
  2020-04-17 18:20 [PATCH v9 0/2] iio: proximity: driver for vcnl3020 Ivan Mikhaylov
@ 2020-04-17 18:20 ` Ivan Mikhaylov
  2020-04-20 17:54   ` Rob Herring
  2020-04-17 18:20 ` [PATCH v9 2/2] iio: proximity: Add driver support for vcnl3020 proximity sensor Ivan Mikhaylov
  1 sibling, 1 reply; 7+ messages in thread
From: Ivan Mikhaylov @ 2020-04-17 18:20 UTC (permalink / raw)
  Cc: Ivan Mikhaylov, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, linux-iio,
	linux-kernel, devicetree, Mark Rutland, Rob Herring,
	Andy Shevchenko

Mostly standard i2c driver with some additional led-current option
for vcnl3020.

Signed-off-by: Ivan Mikhaylov <i.mikhaylov@yadro.com>
---
 .../bindings/iio/proximity/vcnl3020.yaml      | 64 +++++++++++++++++++
 1 file changed, 64 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/proximity/vcnl3020.yaml

diff --git a/Documentation/devicetree/bindings/iio/proximity/vcnl3020.yaml b/Documentation/devicetree/bindings/iio/proximity/vcnl3020.yaml
new file mode 100644
index 000000000000..cfaf36b26a62
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/proximity/vcnl3020.yaml
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/proximity/vcnl3020.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Integrated Proximity Sensor With Infrared Emitter
+
+maintainers:
+  - Ivan Mikhaylov <i.mikhaylov@yadro.com>
+
+description: |
+  The VCNL3020 is a fully integrated proximity sensor. Fully integrated means
+  that the infrared emitter is included in the package. It has 16-bit
+  resolution. It includes a signal processing IC and features standard I2C
+  communication interface. It features an interrupt function.
+
+  Specifications about the devices can be found at:
+  https://www.vishay.com/docs/84150/vcnl3020.pdf
+
+properties:
+  compatible:
+    enum:
+      - vishay,vcnl3020
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  vdd-supply:
+    description: Regulator that provides power to the sensor
+
+  vddio-supply:
+    description: Regulator that provides power to the bus
+
+  vishay,led-current-microamp:
+    description:
+      IR LED current value with valid Range = 0 to 20d. e.g. 0 = 0 mA,
+      1 = 10 mA, 20 = 200 mA. LED Current is limited to 200 mA for values
+      higher than decimal 20.
+    enum: [0, 10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000,
+          100000, 110000, 120000, 130000, 140000, 150000, 160000, 170000,
+          180000, 190000, 200000]
+    default: 20000
+
+required:
+  - compatible
+  - reg
+
+examples:
+  - |
+    i2c {
+
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        proximity@13 {
+              compatible = "vishay,vcnl3020";
+              reg = <0x13>;
+              vishay,led-current-microamp = <0x14>;
+        };
+    };
-- 
2.21.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v9 2/2] iio: proximity: Add driver support for vcnl3020 proximity sensor
  2020-04-17 18:20 [PATCH v9 0/2] iio: proximity: driver for vcnl3020 Ivan Mikhaylov
  2020-04-17 18:20 ` [PATCH v9 1/2] iio: proximity: provide device tree binding document Ivan Mikhaylov
@ 2020-04-17 18:20 ` Ivan Mikhaylov
  2020-04-17 21:35   ` Peter Meerwald-Stadler
  1 sibling, 1 reply; 7+ messages in thread
From: Ivan Mikhaylov @ 2020-04-17 18:20 UTC (permalink / raw)
  Cc: Ivan Mikhaylov, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, linux-iio,
	linux-kernel, devicetree, Mark Rutland, Rob Herring,
	Andy Shevchenko

Proximity sensor driver based on light/vcnl4000.c code.
For now supports only the single on-demand measurement.

The VCNL3020 is a fully integrated proximity sensor. Fully
integrated means that the infrared emitter is included in the
package. It has 16-bit resolution. It includes a signal
processing IC and features standard I2C communication
interface. It features an interrupt function.

Datasheet: http://www.vishay.com/docs/84150/vcnl3020.pdf
Signed-off-by: Ivan Mikhaylov <i.mikhaylov@yadro.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
---
 drivers/iio/proximity/Kconfig    |  11 ++
 drivers/iio/proximity/Makefile   |   1 +
 drivers/iio/proximity/vcnl3020.c | 235 +++++++++++++++++++++++++++++++
 3 files changed, 247 insertions(+)
 create mode 100644 drivers/iio/proximity/vcnl3020.c

diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig
index d53601447da4..b8d2b17e60ac 100644
--- a/drivers/iio/proximity/Kconfig
+++ b/drivers/iio/proximity/Kconfig
@@ -112,6 +112,17 @@ config SRF08
 	  To compile this driver as a module, choose M here: the
 	  module will be called srf08.
 
+config VCNL3020
+	tristate "VCNL3020 proximity sensor"
+	select REGMAP_I2C
+	depends on I2C
+	help
+	  Say Y here if you want to build a driver for the Vishay VCNL3020
+	  proximity sensor.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called vcnl3020.
+
 config VL53L0X_I2C
 	tristate "STMicroelectronics VL53L0X ToF ranger sensor (I2C)"
 	depends on I2C
diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile
index 0bb5f9de13d6..8245978ced30 100644
--- a/drivers/iio/proximity/Makefile
+++ b/drivers/iio/proximity/Makefile
@@ -12,5 +12,6 @@ obj-$(CONFIG_RFD77402)		+= rfd77402.o
 obj-$(CONFIG_SRF04)		+= srf04.o
 obj-$(CONFIG_SRF08)		+= srf08.o
 obj-$(CONFIG_SX9500)		+= sx9500.o
+obj-$(CONFIG_VCNL3020)		+= vcnl3020.o
 obj-$(CONFIG_VL53L0X_I2C)	+= vl53l0x-i2c.o
 
diff --git a/drivers/iio/proximity/vcnl3020.c b/drivers/iio/proximity/vcnl3020.c
new file mode 100644
index 000000000000..59e1f59a3ed2
--- /dev/null
+++ b/drivers/iio/proximity/vcnl3020.c
@@ -0,0 +1,235 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Support for Vishay VCNL3020 proximity sensor on i2c bus.
+ * Based on Vishay VCNL4000 driver code.
+ *
+ * TODO: interrupts.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/regmap.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define VCNL3020_PROD_ID	0x21
+
+#define VCNL_COMMAND		0x80 /* Command register */
+#define VCNL_PROD_REV		0x81 /* Product ID and Revision ID */
+#define VCNL_PROXIMITY_RATE	0x82 /* Rate of Proximity Measurement */
+#define VCNL_LED_CURRENT	0x83 /* IR LED current for proximity mode */
+#define VCNL_PS_RESULT_HI	0x87 /* Proximity result register, MSB */
+#define VCNL_PS_RESULT_LO	0x88 /* Proximity result register, LSB */
+#define VCNL_PS_ICR		0x89 /* Interrupt Control Register  */
+
+#define VCNL_PS_LO_THR_HI	0x8a /* High byte of low threshold value */
+#define VCNL_PS_LO_THR_LO	0x8b /* Low byte of low threshold value */
+#define VCNL_PS_HI_THR_HI	0x8c /* High byte of high threshold value */
+#define VCNL_PS_HI_THR_LO	0x8d /* Low byte of high threshold value */
+#define VCNL_ISR		0x8e /* Interrupt Status Register */
+#define VCNL_PS_MOD_ADJ		0x8f /* Proximity Modulator Timing Adjustment */
+
+/* Bit masks for COMMAND register */
+#define VCNL_PS_RDY		BIT(5) /* proximity data ready? */
+#define VCNL_PS_OD		BIT(3) /* start on-demand proximity
+					* measurement
+					*/
+
+#define VCNL_ON_DEMAND_TIMEOUT_US	100000
+#define VCNL_POLL_US			20000
+
+/**
+ * struct vcnl3020_data - vcnl3020 specific data.
+ * @regmap:	device register map.
+ * @dev:	vcnl3020 device.
+ * @rev:	revision id.
+ * @lock:	lock for protecting access to device hardware registers.
+ */
+struct vcnl3020_data {
+	struct regmap *regmap;
+	struct device *dev;
+	u8 rev;
+	struct mutex lock;
+};
+
+static int vcnl3020_get_and_apply_property(struct vcnl3020_data *data,
+					   const char *prop, u32 reg)
+{
+	int rc;
+	u32 val;
+
+	rc = device_property_read_u32(data->dev, prop, &val);
+	if (rc)
+		return 0;
+
+	rc = regmap_write(data->regmap, reg, val);
+	if (rc) {
+		dev_err(data->dev, "Error (%d) setting property (%s)",
+			rc, prop);
+	}
+
+	return rc;
+}
+
+static int vcnl3020_init(struct vcnl3020_data *data)
+{
+	int rc;
+	unsigned int reg;
+
+	rc = regmap_read(data->regmap, VCNL_PROD_REV, &reg);
+	if (rc) {
+		dev_err(data->dev,
+			"Error (%d) reading product revision", rc);
+		return rc;
+	}
+
+	if (reg != VCNL3020_PROD_ID) {
+		dev_err(data->dev,
+			"Product id (%x) did not match vcnl3020 (%x)", reg,
+			VCNL3020_PROD_ID);
+		return -ENODEV;
+	}
+
+	data->rev = reg;
+	mutex_init(&data->lock);
+
+	return vcnl3020_get_and_apply_property(data,
+					       "vishay,led-current-microamp",
+					       VCNL_LED_CURRENT);
+};
+
+static int vcnl3020_measure_proximity(struct vcnl3020_data *data, int *val)
+{
+	int rc;
+	unsigned int reg;
+	__be16 res;
+
+	mutex_lock(&data->lock);
+
+	rc = regmap_write(data->regmap, VCNL_COMMAND, VCNL_PS_OD);
+	if (rc)
+		goto err_unlock;
+
+	/* wait for data to become ready */
+	rc = regmap_read_poll_timeout(data->regmap, VCNL_COMMAND, reg,
+				      reg & VCNL_PS_RDY, VCNL_POLL_US,
+				      VCNL_ON_DEMAND_TIMEOUT_US);
+	if (rc) {
+		dev_err(data->dev,
+			"Error (%d) reading vcnl3020 command register", rc);
+		goto err_unlock;
+	}
+
+	/* high & low result bytes read */
+	rc = regmap_bulk_read(data->regmap, VCNL_PS_RESULT_HI, &res,
+			      sizeof(res));
+	if (rc)
+		goto err_unlock;
+
+	*val = be16_to_cpu(res);
+
+err_unlock:
+	mutex_unlock(&data->lock);
+
+	return rc;
+}
+
+static const struct iio_chan_spec vcnl3020_channels[] = {
+	{
+		.type = IIO_PROXIMITY,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+	},
+};
+
+static int vcnl3020_read_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan, int *val,
+			     int *val2, long mask)
+{
+	int rc;
+	struct vcnl3020_data *data = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		switch (chan->type) {
+		case IIO_PROXIMITY:
+			rc = vcnl3020_measure_proximity(data, val);
+			if (rc)
+				return rc;
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_info vcnl3020_info = {
+	.read_raw = vcnl3020_read_raw,
+};
+
+static const struct regmap_config vcnl3020_regmap_config = {
+	.reg_bits	= 8,
+	.val_bits	= 8,
+	.max_register	= VCNL_PS_MOD_ADJ,
+};
+
+static int vcnl3020_probe(struct i2c_client *client)
+{
+	struct vcnl3020_data *data;
+	struct iio_dev *indio_dev;
+	struct regmap *regmap;
+	int rc;
+
+	regmap = devm_regmap_init_i2c(client, &vcnl3020_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(&client->dev, "regmap_init failed!");
+		return PTR_ERR(regmap);
+	}
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	i2c_set_clientdata(client, indio_dev);
+	data->regmap = regmap;
+	data->dev = &client->dev;
+
+	rc = vcnl3020_init(data);
+	if (rc)
+		return rc;
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &vcnl3020_info;
+	indio_dev->channels = vcnl3020_channels;
+	indio_dev->num_channels = ARRAY_SIZE(vcnl3020_channels);
+	indio_dev->name = "vcnl3020";
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct of_device_id vcnl3020_of_match[] = {
+	{
+		.compatible = "vishay,vcnl3020",
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, vcnl3020_of_match);
+
+static struct i2c_driver vcnl3020_driver = {
+	.driver = {
+		.name   = "vcnl3020",
+		.of_match_table = vcnl3020_of_match,
+	},
+	.probe_new  = vcnl3020_probe,
+};
+module_i2c_driver(vcnl3020_driver);
+
+MODULE_AUTHOR("Ivan Mikhaylov <i.mikhaylov@yadro.com>");
+MODULE_DESCRIPTION("Vishay VCNL3020 proximity sensor driver");
+MODULE_LICENSE("GPL");
-- 
2.21.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v9 2/2] iio: proximity: Add driver support for vcnl3020 proximity sensor
  2020-04-17 18:20 ` [PATCH v9 2/2] iio: proximity: Add driver support for vcnl3020 proximity sensor Ivan Mikhaylov
@ 2020-04-17 21:35   ` Peter Meerwald-Stadler
  2020-04-18 19:00     ` Jonathan Cameron
  0 siblings, 1 reply; 7+ messages in thread
From: Peter Meerwald-Stadler @ 2020-04-17 21:35 UTC (permalink / raw)
  To: Ivan Mikhaylov; +Cc: Jonathan Cameron, Andy Shevchenko, linux-iio

On Fri, 17 Apr 2020, Ivan Mikhaylov wrote:

some minor comments below

> Proximity sensor driver based on light/vcnl4000.c code.
> For now supports only the single on-demand measurement.
> 
> The VCNL3020 is a fully integrated proximity sensor. Fully
> integrated means that the infrared emitter is included in the
> package. It has 16-bit resolution. It includes a signal
> processing IC and features standard I2C communication
> interface. It features an interrupt function.
> 
> Datasheet: http://www.vishay.com/docs/84150/vcnl3020.pdf
> Signed-off-by: Ivan Mikhaylov <i.mikhaylov@yadro.com>
> Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
> ---
>  drivers/iio/proximity/Kconfig    |  11 ++
>  drivers/iio/proximity/Makefile   |   1 +
>  drivers/iio/proximity/vcnl3020.c | 235 +++++++++++++++++++++++++++++++
>  3 files changed, 247 insertions(+)
>  create mode 100644 drivers/iio/proximity/vcnl3020.c
> 
> diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig
> index d53601447da4..b8d2b17e60ac 100644
> --- a/drivers/iio/proximity/Kconfig
> +++ b/drivers/iio/proximity/Kconfig
> @@ -112,6 +112,17 @@ config SRF08
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called srf08.
>  
> +config VCNL3020
> +	tristate "VCNL3020 proximity sensor"
> +	select REGMAP_I2C
> +	depends on I2C
> +	help
> +	  Say Y here if you want to build a driver for the Vishay VCNL3020
> +	  proximity sensor.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called vcnl3020.
> +
>  config VL53L0X_I2C
>  	tristate "STMicroelectronics VL53L0X ToF ranger sensor (I2C)"
>  	depends on I2C
> diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile
> index 0bb5f9de13d6..8245978ced30 100644
> --- a/drivers/iio/proximity/Makefile
> +++ b/drivers/iio/proximity/Makefile
> @@ -12,5 +12,6 @@ obj-$(CONFIG_RFD77402)		+= rfd77402.o
>  obj-$(CONFIG_SRF04)		+= srf04.o
>  obj-$(CONFIG_SRF08)		+= srf08.o
>  obj-$(CONFIG_SX9500)		+= sx9500.o
> +obj-$(CONFIG_VCNL3020)		+= vcnl3020.o
>  obj-$(CONFIG_VL53L0X_I2C)	+= vl53l0x-i2c.o
>  
> diff --git a/drivers/iio/proximity/vcnl3020.c b/drivers/iio/proximity/vcnl3020.c
> new file mode 100644
> index 000000000000..59e1f59a3ed2
> --- /dev/null
> +++ b/drivers/iio/proximity/vcnl3020.c
> @@ -0,0 +1,235 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Support for Vishay VCNL3020 proximity sensor on i2c bus.
> + * Based on Vishay VCNL4000 driver code.
> + *
> + * TODO: interrupts.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/i2c.h>
> +#include <linux/err.h>
> +#include <linux/delay.h>
> +#include <linux/regmap.h>
> +
> +#include <linux/iio/iio.h>
> +#include <linux/iio/sysfs.h>
> +
> +#define VCNL3020_PROD_ID	0x21
> +
> +#define VCNL_COMMAND		0x80 /* Command register */
> +#define VCNL_PROD_REV		0x81 /* Product ID and Revision ID */
> +#define VCNL_PROXIMITY_RATE	0x82 /* Rate of Proximity Measurement */
> +#define VCNL_LED_CURRENT	0x83 /* IR LED current for proximity mode */
> +#define VCNL_PS_RESULT_HI	0x87 /* Proximity result register, MSB */
> +#define VCNL_PS_RESULT_LO	0x88 /* Proximity result register, LSB */
> +#define VCNL_PS_ICR		0x89 /* Interrupt Control Register  */

remove one space before */

> +
> +#define VCNL_PS_LO_THR_HI	0x8a /* High byte of low threshold value */
> +#define VCNL_PS_LO_THR_LO	0x8b /* Low byte of low threshold value */
> +#define VCNL_PS_HI_THR_HI	0x8c /* High byte of high threshold value */
> +#define VCNL_PS_HI_THR_LO	0x8d /* Low byte of high threshold value */
> +#define VCNL_ISR		0x8e /* Interrupt Status Register */
> +#define VCNL_PS_MOD_ADJ		0x8f /* Proximity Modulator Timing Adjustment */
> +
> +/* Bit masks for COMMAND register */
> +#define VCNL_PS_RDY		BIT(5) /* proximity data ready? */
> +#define VCNL_PS_OD		BIT(3) /* start on-demand proximity
> +					* measurement
> +					*/
> +
> +#define VCNL_ON_DEMAND_TIMEOUT_US	100000
> +#define VCNL_POLL_US			20000
> +
> +/**
> + * struct vcnl3020_data - vcnl3020 specific data.
> + * @regmap:	device register map.
> + * @dev:	vcnl3020 device.
> + * @rev:	revision id.
> + * @lock:	lock for protecting access to device hardware registers.
> + */
> +struct vcnl3020_data {
> +	struct regmap *regmap;
> +	struct device *dev;
> +	u8 rev;
> +	struct mutex lock;
> +};
> +
> +static int vcnl3020_get_and_apply_property(struct vcnl3020_data *data,
> +					   const char *prop, u32 reg)
> +{
> +	int rc;
> +	u32 val;
> +
> +	rc = device_property_read_u32(data->dev, prop, &val);
> +	if (rc)
> +		return 0;
> +
> +	rc = regmap_write(data->regmap, reg, val);
> +	if (rc) {
> +		dev_err(data->dev, "Error (%d) setting property (%s)",

dev_err() needs \n (here and elsewhere)

> +			rc, prop);
> +	}
> +
> +	return rc;
> +}
> +
> +static int vcnl3020_init(struct vcnl3020_data *data)
> +{
> +	int rc;
> +	unsigned int reg;
> +
> +	rc = regmap_read(data->regmap, VCNL_PROD_REV, &reg);
> +	if (rc) {
> +		dev_err(data->dev,
> +			"Error (%d) reading product revision", rc);
> +		return rc;
> +	}
> +
> +	if (reg != VCNL3020_PROD_ID) {
> +		dev_err(data->dev,
> +			"Product id (%x) did not match vcnl3020 (%x)", reg,
> +			VCNL3020_PROD_ID);
> +		return -ENODEV;
> +	}
> +
> +	data->rev = reg;
> +	mutex_init(&data->lock);
> +
> +	return vcnl3020_get_and_apply_property(data,
> +					       "vishay,led-current-microamp",
> +					       VCNL_LED_CURRENT);
> +};
> +
> +static int vcnl3020_measure_proximity(struct vcnl3020_data *data, int *val)
> +{
> +	int rc;
> +	unsigned int reg;
> +	__be16 res;
> +
> +	mutex_lock(&data->lock);
> +
> +	rc = regmap_write(data->regmap, VCNL_COMMAND, VCNL_PS_OD);
> +	if (rc)
> +		goto err_unlock;
> +
> +	/* wait for data to become ready */
> +	rc = regmap_read_poll_timeout(data->regmap, VCNL_COMMAND, reg,
> +				      reg & VCNL_PS_RDY, VCNL_POLL_US,
> +				      VCNL_ON_DEMAND_TIMEOUT_US);
> +	if (rc) {
> +		dev_err(data->dev,
> +			"Error (%d) reading vcnl3020 command register", rc);
> +		goto err_unlock;
> +	}
> +
> +	/* high & low result bytes read */
> +	rc = regmap_bulk_read(data->regmap, VCNL_PS_RESULT_HI, &res,
> +			      sizeof(res));
> +	if (rc)
> +		goto err_unlock;
> +
> +	*val = be16_to_cpu(res);
> +
> +err_unlock:
> +	mutex_unlock(&data->lock);
> +
> +	return rc;
> +}
> +
> +static const struct iio_chan_spec vcnl3020_channels[] = {
> +	{
> +		.type = IIO_PROXIMITY,
> +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> +	},
> +};
> +
> +static int vcnl3020_read_raw(struct iio_dev *indio_dev,
> +			     struct iio_chan_spec const *chan, int *val,
> +			     int *val2, long mask)
> +{
> +	int rc;
> +	struct vcnl3020_data *data = iio_priv(indio_dev);
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		switch (chan->type) {
> +		case IIO_PROXIMITY:

there is only one channel, check not needed

> +			rc = vcnl3020_measure_proximity(data, val);
> +			if (rc)
> +				return rc;
> +			return IIO_VAL_INT;
> +		default:
> +			return -EINVAL;
> +		}
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static const struct iio_info vcnl3020_info = {
> +	.read_raw = vcnl3020_read_raw,
> +};
> +
> +static const struct regmap_config vcnl3020_regmap_config = {
> +	.reg_bits	= 8,
> +	.val_bits	= 8,
> +	.max_register	= VCNL_PS_MOD_ADJ,
> +};
> +
> +static int vcnl3020_probe(struct i2c_client *client)
> +{
> +	struct vcnl3020_data *data;
> +	struct iio_dev *indio_dev;
> +	struct regmap *regmap;
> +	int rc;
> +
> +	regmap = devm_regmap_init_i2c(client, &vcnl3020_regmap_config);
> +	if (IS_ERR(regmap)) {
> +		dev_err(&client->dev, "regmap_init failed!");
> +		return PTR_ERR(regmap);
> +	}
> +
> +	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> +	if (!indio_dev)
> +		return -ENOMEM;
> +
> +	data = iio_priv(indio_dev);
> +	i2c_set_clientdata(client, indio_dev);
> +	data->regmap = regmap;
> +	data->dev = &client->dev;
> +
> +	rc = vcnl3020_init(data);
> +	if (rc)
> +		return rc;
> +
> +	indio_dev->dev.parent = &client->dev;
> +	indio_dev->info = &vcnl3020_info;
> +	indio_dev->channels = vcnl3020_channels;
> +	indio_dev->num_channels = ARRAY_SIZE(vcnl3020_channels);
> +	indio_dev->name = "vcnl3020";
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +
> +	return devm_iio_device_register(&client->dev, indio_dev);
> +}
> +
> +static const struct of_device_id vcnl3020_of_match[] = {
> +	{
> +		.compatible = "vishay,vcnl3020",
> +	},
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, vcnl3020_of_match);
> +
> +static struct i2c_driver vcnl3020_driver = {
> +	.driver = {
> +		.name   = "vcnl3020",
> +		.of_match_table = vcnl3020_of_match,
> +	},
> +	.probe_new  = vcnl3020_probe,
> +};
> +module_i2c_driver(vcnl3020_driver);
> +
> +MODULE_AUTHOR("Ivan Mikhaylov <i.mikhaylov@yadro.com>");
> +MODULE_DESCRIPTION("Vishay VCNL3020 proximity sensor driver");
> +MODULE_LICENSE("GPL");
> 

-- 

Peter Meerwald-Stadler
Mobile: +43 664 24 44 418

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v9 2/2] iio: proximity: Add driver support for vcnl3020 proximity sensor
  2020-04-17 21:35   ` Peter Meerwald-Stadler
@ 2020-04-18 19:00     ` Jonathan Cameron
  2020-04-20 15:11       ` Ivan Mikhaylov
  0 siblings, 1 reply; 7+ messages in thread
From: Jonathan Cameron @ 2020-04-18 19:00 UTC (permalink / raw)
  To: Peter Meerwald-Stadler; +Cc: Ivan Mikhaylov, Andy Shevchenko, linux-iio

On Fri, 17 Apr 2020 23:35:31 +0200 (CEST)
Peter Meerwald-Stadler <pmeerw@pmeerw.net> wrote:

> On Fri, 17 Apr 2020, Ivan Mikhaylov wrote:
> 
> some minor comments below

I may just fix these up whilst applying but I would like to leave
more time for Rob to take another look at the binding. So if you want
to do another version Ivan incorporating these little bits from Peter
then feel free! It'll make my life a tiny bit easier ;)

Jonathan

> 
> > Proximity sensor driver based on light/vcnl4000.c code.
> > For now supports only the single on-demand measurement.
> > 
> > The VCNL3020 is a fully integrated proximity sensor. Fully
> > integrated means that the infrared emitter is included in the
> > package. It has 16-bit resolution. It includes a signal
> > processing IC and features standard I2C communication
> > interface. It features an interrupt function.
> > 
> > Datasheet: http://www.vishay.com/docs/84150/vcnl3020.pdf
> > Signed-off-by: Ivan Mikhaylov <i.mikhaylov@yadro.com>
> > Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
> > ---
> >  drivers/iio/proximity/Kconfig    |  11 ++
> >  drivers/iio/proximity/Makefile   |   1 +
> >  drivers/iio/proximity/vcnl3020.c | 235 +++++++++++++++++++++++++++++++
> >  3 files changed, 247 insertions(+)
> >  create mode 100644 drivers/iio/proximity/vcnl3020.c
> > 
> > diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig
> > index d53601447da4..b8d2b17e60ac 100644
> > --- a/drivers/iio/proximity/Kconfig
> > +++ b/drivers/iio/proximity/Kconfig
> > @@ -112,6 +112,17 @@ config SRF08
> >  	  To compile this driver as a module, choose M here: the
> >  	  module will be called srf08.
> >  
> > +config VCNL3020
> > +	tristate "VCNL3020 proximity sensor"
> > +	select REGMAP_I2C
> > +	depends on I2C
> > +	help
> > +	  Say Y here if you want to build a driver for the Vishay VCNL3020
> > +	  proximity sensor.
> > +
> > +	  To compile this driver as a module, choose M here: the
> > +	  module will be called vcnl3020.
> > +
> >  config VL53L0X_I2C
> >  	tristate "STMicroelectronics VL53L0X ToF ranger sensor (I2C)"
> >  	depends on I2C
> > diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile
> > index 0bb5f9de13d6..8245978ced30 100644
> > --- a/drivers/iio/proximity/Makefile
> > +++ b/drivers/iio/proximity/Makefile
> > @@ -12,5 +12,6 @@ obj-$(CONFIG_RFD77402)		+= rfd77402.o
> >  obj-$(CONFIG_SRF04)		+= srf04.o
> >  obj-$(CONFIG_SRF08)		+= srf08.o
> >  obj-$(CONFIG_SX9500)		+= sx9500.o
> > +obj-$(CONFIG_VCNL3020)		+= vcnl3020.o
> >  obj-$(CONFIG_VL53L0X_I2C)	+= vl53l0x-i2c.o
> >  
> > diff --git a/drivers/iio/proximity/vcnl3020.c b/drivers/iio/proximity/vcnl3020.c
> > new file mode 100644
> > index 000000000000..59e1f59a3ed2
> > --- /dev/null
> > +++ b/drivers/iio/proximity/vcnl3020.c
> > @@ -0,0 +1,235 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Support for Vishay VCNL3020 proximity sensor on i2c bus.
> > + * Based on Vishay VCNL4000 driver code.
> > + *
> > + * TODO: interrupts.
> > + */
> > +
> > +#include <linux/module.h>
> > +#include <linux/i2c.h>
> > +#include <linux/err.h>
> > +#include <linux/delay.h>
> > +#include <linux/regmap.h>
> > +
> > +#include <linux/iio/iio.h>
> > +#include <linux/iio/sysfs.h>
> > +
> > +#define VCNL3020_PROD_ID	0x21
> > +
> > +#define VCNL_COMMAND		0x80 /* Command register */
> > +#define VCNL_PROD_REV		0x81 /* Product ID and Revision ID */
> > +#define VCNL_PROXIMITY_RATE	0x82 /* Rate of Proximity Measurement */
> > +#define VCNL_LED_CURRENT	0x83 /* IR LED current for proximity mode */
> > +#define VCNL_PS_RESULT_HI	0x87 /* Proximity result register, MSB */
> > +#define VCNL_PS_RESULT_LO	0x88 /* Proximity result register, LSB */
> > +#define VCNL_PS_ICR		0x89 /* Interrupt Control Register  */  
> 
> remove one space before */
> 
> > +
> > +#define VCNL_PS_LO_THR_HI	0x8a /* High byte of low threshold value */
> > +#define VCNL_PS_LO_THR_LO	0x8b /* Low byte of low threshold value */
> > +#define VCNL_PS_HI_THR_HI	0x8c /* High byte of high threshold value */
> > +#define VCNL_PS_HI_THR_LO	0x8d /* Low byte of high threshold value */
> > +#define VCNL_ISR		0x8e /* Interrupt Status Register */
> > +#define VCNL_PS_MOD_ADJ		0x8f /* Proximity Modulator Timing Adjustment */
> > +
> > +/* Bit masks for COMMAND register */
> > +#define VCNL_PS_RDY		BIT(5) /* proximity data ready? */
> > +#define VCNL_PS_OD		BIT(3) /* start on-demand proximity
> > +					* measurement
> > +					*/
> > +
> > +#define VCNL_ON_DEMAND_TIMEOUT_US	100000
> > +#define VCNL_POLL_US			20000
> > +
> > +/**
> > + * struct vcnl3020_data - vcnl3020 specific data.
> > + * @regmap:	device register map.
> > + * @dev:	vcnl3020 device.
> > + * @rev:	revision id.
> > + * @lock:	lock for protecting access to device hardware registers.
> > + */
> > +struct vcnl3020_data {
> > +	struct regmap *regmap;
> > +	struct device *dev;
> > +	u8 rev;
> > +	struct mutex lock;
> > +};
> > +
> > +static int vcnl3020_get_and_apply_property(struct vcnl3020_data *data,
> > +					   const char *prop, u32 reg)
> > +{
> > +	int rc;
> > +	u32 val;
> > +
> > +	rc = device_property_read_u32(data->dev, prop, &val);
> > +	if (rc)
> > +		return 0;
> > +
> > +	rc = regmap_write(data->regmap, reg, val);
> > +	if (rc) {
> > +		dev_err(data->dev, "Error (%d) setting property (%s)",  
> 
> dev_err() needs \n (here and elsewhere)
> 
> > +			rc, prop);
> > +	}
> > +
> > +	return rc;
> > +}
> > +
> > +static int vcnl3020_init(struct vcnl3020_data *data)
> > +{
> > +	int rc;
> > +	unsigned int reg;
> > +
> > +	rc = regmap_read(data->regmap, VCNL_PROD_REV, &reg);
> > +	if (rc) {
> > +		dev_err(data->dev,
> > +			"Error (%d) reading product revision", rc);
> > +		return rc;
> > +	}
> > +
> > +	if (reg != VCNL3020_PROD_ID) {
> > +		dev_err(data->dev,
> > +			"Product id (%x) did not match vcnl3020 (%x)", reg,
> > +			VCNL3020_PROD_ID);
> > +		return -ENODEV;
> > +	}
> > +
> > +	data->rev = reg;
> > +	mutex_init(&data->lock);
> > +
> > +	return vcnl3020_get_and_apply_property(data,
> > +					       "vishay,led-current-microamp",
> > +					       VCNL_LED_CURRENT);
> > +};
> > +
> > +static int vcnl3020_measure_proximity(struct vcnl3020_data *data, int *val)
> > +{
> > +	int rc;
> > +	unsigned int reg;
> > +	__be16 res;
> > +
> > +	mutex_lock(&data->lock);
> > +
> > +	rc = regmap_write(data->regmap, VCNL_COMMAND, VCNL_PS_OD);
> > +	if (rc)
> > +		goto err_unlock;
> > +
> > +	/* wait for data to become ready */
> > +	rc = regmap_read_poll_timeout(data->regmap, VCNL_COMMAND, reg,
> > +				      reg & VCNL_PS_RDY, VCNL_POLL_US,
> > +				      VCNL_ON_DEMAND_TIMEOUT_US);
> > +	if (rc) {
> > +		dev_err(data->dev,
> > +			"Error (%d) reading vcnl3020 command register", rc);
> > +		goto err_unlock;
> > +	}
> > +
> > +	/* high & low result bytes read */
> > +	rc = regmap_bulk_read(data->regmap, VCNL_PS_RESULT_HI, &res,
> > +			      sizeof(res));
> > +	if (rc)
> > +		goto err_unlock;
> > +
> > +	*val = be16_to_cpu(res);
> > +
> > +err_unlock:
> > +	mutex_unlock(&data->lock);
> > +
> > +	return rc;
> > +}
> > +
> > +static const struct iio_chan_spec vcnl3020_channels[] = {
> > +	{
> > +		.type = IIO_PROXIMITY,
> > +		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> > +	},
> > +};
> > +
> > +static int vcnl3020_read_raw(struct iio_dev *indio_dev,
> > +			     struct iio_chan_spec const *chan, int *val,
> > +			     int *val2, long mask)
> > +{
> > +	int rc;
> > +	struct vcnl3020_data *data = iio_priv(indio_dev);
> > +
> > +	switch (mask) {
> > +	case IIO_CHAN_INFO_RAW:
> > +		switch (chan->type) {
> > +		case IIO_PROXIMITY:  
> 
> there is only one channel, check not needed
> 
> > +			rc = vcnl3020_measure_proximity(data, val);
> > +			if (rc)
> > +				return rc;
> > +			return IIO_VAL_INT;
> > +		default:
> > +			return -EINVAL;
> > +		}
> > +	default:
> > +		return -EINVAL;
> > +	}
> > +}
> > +
> > +static const struct iio_info vcnl3020_info = {
> > +	.read_raw = vcnl3020_read_raw,
> > +};
> > +
> > +static const struct regmap_config vcnl3020_regmap_config = {
> > +	.reg_bits	= 8,
> > +	.val_bits	= 8,
> > +	.max_register	= VCNL_PS_MOD_ADJ,
> > +};
> > +
> > +static int vcnl3020_probe(struct i2c_client *client)
> > +{
> > +	struct vcnl3020_data *data;
> > +	struct iio_dev *indio_dev;
> > +	struct regmap *regmap;
> > +	int rc;
> > +
> > +	regmap = devm_regmap_init_i2c(client, &vcnl3020_regmap_config);
> > +	if (IS_ERR(regmap)) {
> > +		dev_err(&client->dev, "regmap_init failed!");
> > +		return PTR_ERR(regmap);
> > +	}
> > +
> > +	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> > +	if (!indio_dev)
> > +		return -ENOMEM;
> > +
> > +	data = iio_priv(indio_dev);
> > +	i2c_set_clientdata(client, indio_dev);
> > +	data->regmap = regmap;
> > +	data->dev = &client->dev;
> > +
> > +	rc = vcnl3020_init(data);
> > +	if (rc)
> > +		return rc;
> > +
> > +	indio_dev->dev.parent = &client->dev;
> > +	indio_dev->info = &vcnl3020_info;
> > +	indio_dev->channels = vcnl3020_channels;
> > +	indio_dev->num_channels = ARRAY_SIZE(vcnl3020_channels);
> > +	indio_dev->name = "vcnl3020";
> > +	indio_dev->modes = INDIO_DIRECT_MODE;
> > +
> > +	return devm_iio_device_register(&client->dev, indio_dev);
> > +}
> > +
> > +static const struct of_device_id vcnl3020_of_match[] = {
> > +	{
> > +		.compatible = "vishay,vcnl3020",
> > +	},
> > +	{}
> > +};
> > +MODULE_DEVICE_TABLE(of, vcnl3020_of_match);
> > +
> > +static struct i2c_driver vcnl3020_driver = {
> > +	.driver = {
> > +		.name   = "vcnl3020",
> > +		.of_match_table = vcnl3020_of_match,
> > +	},
> > +	.probe_new  = vcnl3020_probe,
> > +};
> > +module_i2c_driver(vcnl3020_driver);
> > +
> > +MODULE_AUTHOR("Ivan Mikhaylov <i.mikhaylov@yadro.com>");
> > +MODULE_DESCRIPTION("Vishay VCNL3020 proximity sensor driver");
> > +MODULE_LICENSE("GPL");
> >   
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v9 2/2] iio: proximity: Add driver support for vcnl3020 proximity sensor
  2020-04-18 19:00     ` Jonathan Cameron
@ 2020-04-20 15:11       ` Ivan Mikhaylov
  0 siblings, 0 replies; 7+ messages in thread
From: Ivan Mikhaylov @ 2020-04-20 15:11 UTC (permalink / raw)
  To: Jonathan Cameron, Peter Meerwald-Stadler; +Cc: Andy Shevchenko, linux-iio

On Sat, 2020-04-18 at 20:00 +0100, Jonathan Cameron wrote:
> On Fri, 17 Apr 2020 23:35:31 +0200 (CEST)
> Peter Meerwald-Stadler <pmeerw@pmeerw.net> wrote:
> 
> > On Fri, 17 Apr 2020, Ivan Mikhaylov wrote:
> > 
> > some minor comments below
> 
> I may just fix these up whilst applying but I would like to leave
> more time for Rob to take another look at the binding. So if you want
> to do another version Ivan incorporating these little bits from Peter
> then feel free! It'll make my life a tiny bit easier ;)
> 
> Jonathan
> 

Jonathan, Peter, I'll fix it after Rob's review, maybe he will add something.

Thanks.


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v9 1/2] iio: proximity: provide device tree binding document
  2020-04-17 18:20 ` [PATCH v9 1/2] iio: proximity: provide device tree binding document Ivan Mikhaylov
@ 2020-04-20 17:54   ` Rob Herring
  0 siblings, 0 replies; 7+ messages in thread
From: Rob Herring @ 2020-04-20 17:54 UTC (permalink / raw)
  To: Ivan Mikhaylov
  Cc: Ivan Mikhaylov, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, linux-iio,
	linux-kernel, devicetree, Mark Rutland, Rob Herring,
	Andy Shevchenko

On Fri, 17 Apr 2020 21:20:52 +0300, Ivan Mikhaylov wrote:
> Mostly standard i2c driver with some additional led-current option
> for vcnl3020.
> 
> Signed-off-by: Ivan Mikhaylov <i.mikhaylov@yadro.com>
> ---
>  .../bindings/iio/proximity/vcnl3020.yaml      | 64 +++++++++++++++++++
>  1 file changed, 64 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/iio/proximity/vcnl3020.yaml
> 

My bot found errors running 'make dt_binding_check' on your patch:

/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/iio/proximity/vcnl3020.example.dt.yaml: proximity@13: vishay,led-current-microamp:0:0: 20 is not one of [0, 10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000, 100000, 110000, 120000, 130000, 140000, 150000, 160000, 170000, 180000, 190000, 200000]

See https://patchwork.ozlabs.org/patch/1272391

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure dt-schema is up to date:

pip3 install git+https://github.com/devicetree-org/dt-schema.git@master --upgrade

Please check and re-submit.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-04-20 17:54 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-17 18:20 [PATCH v9 0/2] iio: proximity: driver for vcnl3020 Ivan Mikhaylov
2020-04-17 18:20 ` [PATCH v9 1/2] iio: proximity: provide device tree binding document Ivan Mikhaylov
2020-04-20 17:54   ` Rob Herring
2020-04-17 18:20 ` [PATCH v9 2/2] iio: proximity: Add driver support for vcnl3020 proximity sensor Ivan Mikhaylov
2020-04-17 21:35   ` Peter Meerwald-Stadler
2020-04-18 19:00     ` Jonathan Cameron
2020-04-20 15:11       ` Ivan Mikhaylov

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.