* [PATCH 0/2] iio: proximity: Add Vishay VCNL36829 driver
@ 2026-10-03 5:04 Liu Yufei
2026-10-03 5:04 ` [PATCH 1/2] dt-bindings: iio: proximity: Add Vishay VCNL36829 Liu Yufei
2026-10-03 5:04 ` [PATCH 2/2] iio: proximity: Add driver for " Liu Yufei
0 siblings, 2 replies; 4+ messages in thread
From: Liu Yufei @ 2026-10-03 5:04 UTC (permalink / raw)
To: Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: David Lechner, Nuno Sá,
Andy Shevchenko, linux-iio, devicetree, linux-kernel, Liu Yufei
From: Liu Yufei <lyf98405@gmail.com>
This series adds support for the Vishay VCNL36829, an I2C proximity
sensor with an integrated VCSEL emitter.
Patch 1 adds the devicetree binding.
Patch 2 adds the IIO driver, which exposes the proximity reading and
a configurable integration time.
Tested on Orange Pi Zero 2W.
Liu Yufei (2):
dt-bindings: iio: proximity: Add Vishay VCNL36829
iio: proximity: Add driver for Vishay VCNL36829
.../iio/proximity/vishay,vcnl36829.yaml | 55 ++++
MAINTAINERS | 6 +
drivers/iio/proximity/Kconfig | 11 +
drivers/iio/proximity/Makefile | 1 +
drivers/iio/proximity/vcnl36829.c | 278 ++++++++++++++++++
5 files changed, 351 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iio/proximity/vishay,vcnl36829.yaml
create mode 100644 drivers/iio/proximity/vcnl36829.c
base-commit: 52c36105f76e96b638152a42e735f2e7767ed946
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/2] dt-bindings: iio: proximity: Add Vishay VCNL36829
2026-10-03 5:04 [PATCH 0/2] iio: proximity: Add Vishay VCNL36829 driver Liu Yufei
@ 2026-10-03 5:04 ` Liu Yufei
2026-10-03 5:04 ` [PATCH 2/2] iio: proximity: Add driver for " Liu Yufei
1 sibling, 0 replies; 4+ messages in thread
From: Liu Yufei @ 2026-10-03 5:04 UTC (permalink / raw)
To: Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: David Lechner, Nuno Sá,
Andy Shevchenko, linux-iio, devicetree, linux-kernel, Liu Yufei
From: Liu Yufei <lyf98405@gmail.com>
Add devicetree binding for the Vishay VCNL36829 proximity sensor.
The VCNL36829 is a proximity sensor with an integrated VCSEL emitter
in a small package. It is controlled over I2C and has an interrupt
output. It is powered by two supplies, vdd and vddio.
Signed-off-by: Liu Yufei <lyf98405@gmail.com>
---
.../iio/proximity/vishay,vcnl36829.yaml | 55 +++++++++++++++++++
MAINTAINERS | 5 ++
2 files changed, 60 insertions(+)
create mode 100644 Documentation/devicetree/bindings/iio/proximity/vishay,vcnl36829.yaml
diff --git a/Documentation/devicetree/bindings/iio/proximity/vishay,vcnl36829.yaml b/Documentation/devicetree/bindings/iio/proximity/vishay,vcnl36829.yaml
new file mode 100644
index 000000000..6f20537ad
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/proximity/vishay,vcnl36829.yaml
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/proximity/vishay,vcnl36829.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: VISHAY VCNL36829 Proximity Sensor
+
+maintainers:
+ - Liu Yufei <lyf98405@gmail.com>
+
+description: |
+ Proximity sensor with VCSEL in an ultra thin small package with I2C
+ interface.
+ Datasheet: https://www.vishay.com/docs/80580/vcnl36829um.pdf
+
+properties:
+ compatible:
+ const: vishay,vcnl36829
+
+ reg:
+ maxItems: 1
+
+ vdd-supply: true
+
+ vddio-supply: true
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - vdd-supply
+ - vddio-supply
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ proximity@60 {
+ compatible = "vishay,vcnl36829";
+ reg = <0x60>;
+ vdd-supply = <&vdd_reg>;
+ vddio-supply = <&vddio_reg>;
+ interrupt-parent = <&gpio>;
+ interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
+ };
+ };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 8014b9f82..e6ef84b49 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -28754,6 +28754,11 @@ S: Maintained
F: drivers/input/serio/userio.c
F: include/uapi/linux/userio.h
+VISHAY VCNL36829 PROXIMITY SENSOR DRIVER
+M: Liu Yufei <lyf98405@gmail.com>
+S: Maintained
+F: Documentation/devicetree/bindings/iio/proximity/vishay,vcnl36829.yaml
+
VISHAY VEML3235 AMBIENT LIGHT SENSOR DRIVER
M: Javier Carrasco <javier.carrasco.cruz@gmail.com>
S: Maintained
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 2/2] iio: proximity: Add driver for Vishay VCNL36829
2026-10-03 5:04 [PATCH 0/2] iio: proximity: Add Vishay VCNL36829 driver Liu Yufei
2026-10-03 5:04 ` [PATCH 1/2] dt-bindings: iio: proximity: Add Vishay VCNL36829 Liu Yufei
@ 2026-10-03 5:04 ` Liu Yufei
2026-10-03 19:03 ` Andy Shevchenko
1 sibling, 1 reply; 4+ messages in thread
From: Liu Yufei @ 2026-10-03 5:04 UTC (permalink / raw)
To: Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: David Lechner, Nuno Sá,
Andy Shevchenko, linux-iio, devicetree, linux-kernel, Liu Yufei
From: Liu Yufei <lyf98405@gmail.com>
Add an IIO driver for the Vishay VCNL36829 proximity sensor with
integrated VCSEL, connected over I2C.
At probe the driver enables the vdd and vddio supplies, waits for the
sensor to power up, checks the device ID, configures the VCSEL current
and photodiodes, and turns the proximity engine on. The sensor is put
back into shutdown when the device is removed.
The following attributes are exposed:
- in_proximity0_raw
- in_proximity_integration_time
- in_proximity_integration_time_available
The datasheet is available at:
https://www.vishay.com/docs/80580/vcnl36829um.pdf
Assisted-by: Claude:claude-opus-5-5 checkpatch dtschema
Signed-off-by: Liu Yufei <lyf98405@gmail.com>
---
MAINTAINERS | 1 +
drivers/iio/proximity/Kconfig | 11 ++
drivers/iio/proximity/Makefile | 1 +
drivers/iio/proximity/vcnl36829.c | 278 ++++++++++++++++++++++++++++++
4 files changed, 291 insertions(+)
create mode 100644 drivers/iio/proximity/vcnl36829.c
diff --git a/MAINTAINERS b/MAINTAINERS
index e6ef84b49..5612b9371 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -28758,6 +28758,7 @@ VISHAY VCNL36829 PROXIMITY SENSOR DRIVER
M: Liu Yufei <lyf98405@gmail.com>
S: Maintained
F: Documentation/devicetree/bindings/iio/proximity/vishay,vcnl36829.yaml
+F: drivers/iio/proximity/vcnl36829.c
VISHAY VEML3235 AMBIENT LIGHT SENSOR DRIVER
M: Javier Carrasco <javier.carrasco.cruz@gmail.com>
diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig
index bb77fad2a..f3cec799d 100644
--- a/drivers/iio/proximity/Kconfig
+++ b/drivers/iio/proximity/Kconfig
@@ -233,6 +233,17 @@ config VCNL3020
To compile this driver as a module, choose M here: the
module will be called vcnl3020.
+config VCNL36829
+ tristate "Vishay VCNL36829 proximity sensor"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Say Y here if you want to build a driver for the Vishay VCNL36829
+ proximity sensor with integrated VCSEL.
+
+ To compile this driver as a module, choose M here: the
+ module will be called vcnl36829.
+
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 4352833dd..8a65e42fb 100644
--- a/drivers/iio/proximity/Makefile
+++ b/drivers/iio/proximity/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_SX9360) += sx9360.o
obj-$(CONFIG_SX_COMMON) += sx_common.o
obj-$(CONFIG_SX9500) += sx9500.o
obj-$(CONFIG_VCNL3020) += vcnl3020.o
+obj-$(CONFIG_VCNL36829) += vcnl36829.o
obj-$(CONFIG_VL53L0X_I2C) += vl53l0x-i2c.o
obj-$(CONFIG_VL53L1X_I2C) += vl53l1x-i2c.o
obj-$(CONFIG_AW96103) += aw96103.o
diff --git a/drivers/iio/proximity/vcnl36829.c b/drivers/iio/proximity/vcnl36829.c
new file mode 100644
index 000000000..c9958a594
--- /dev/null
+++ b/drivers/iio/proximity/vcnl36829.c
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Vishay VCNL36829 Proximity Sensor driver
+ *
+ * Copyright (C) 2026 Liu Yufei <lyf98405@gmail.com>
+ */
+#include <linux/i2c.h>
+#include <linux/mod_devicetable.h>
+#include <linux/iio/iio.h>
+#include <linux/regmap.h>
+#include <linux/bitfield.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/delay.h>
+
+#define VCNL36829_PS_CONF1 0x00
+#define VCNL36829_PS_ON_MSK BIT(0)
+#define VCNL36829_PS_SD_MSK BIT(8)
+
+#define VCNL36829_PS_CONF2 0x01
+#define VCNL36829_PS_IT_MSK GENMASK(11, 8)
+
+#define VCNL36829_PS_CONF3 0x02
+#define VCNL36829_PS_CURRENT_EN_MSK BIT(3)
+#define VCNL36829_PS_CURRENT_MSK GENMASK(2, 0)
+#define VCNL36829_PD1_EN_MSK BIT(8)
+#define VCNL36829_PD2_EN_MSK BIT(9)
+#define VCNL36829_PD3_EN_MSK BIT(10)
+
+#define VCNL36829_PS_CONF5 0x08
+
+/* VCNL36829 Read Only Registers */
+#define VCNL36829_DATA 0xF8
+#define VCNL36829_DEV_ID 0xFA
+
+#define VCNL36829_PS_CONF5_INIT 0x00A0
+#define VCNL36829_PS_CURRENT_18MA 0x7
+#define VCNL36829_PS_INT_TIME_25 0x1
+#define VCNL36829_DEV_ID_VAL 0x29
+
+static const int vcnl36829_it_range[] = {0, 25, 0, 25, 0, 375};
+
+struct vcnl36829_data {
+ struct i2c_client *client;
+ struct regmap *regmap;
+};
+
+static const struct regmap_config vcnl36829_regmap_config = {
+ .name = "vcnl36829_regmap",
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = VCNL36829_DEV_ID,
+ .val_format_endian = REGMAP_ENDIAN_LITTLE,
+};
+
+static int vcnl36829_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ int ret;
+ unsigned int reg;
+ struct vcnl36829_data *data = iio_priv(indio_dev);
+ struct regmap *regmap = data->regmap;
+ struct device *dev = &data->client->dev;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = regmap_read(regmap, chan->address, ®);
+ if (ret) {
+ dev_err(dev, "Data read failed: %d\n", ret);
+ return ret;
+ }
+ *val = reg;
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_INT_TIME:
+ ret = regmap_read(regmap, VCNL36829_PS_CONF2, ®);
+ if (ret) {
+ dev_err(dev, "Data read failed: %d\n", ret);
+ return ret;
+ }
+ /*
+ * PS_IT=0 (12.5us) is intentionally not exposed; the driver
+ * uses 25us as the minimum so the step stays a clean 25us.
+ */
+ *val = 0;
+ *val2 = FIELD_GET(VCNL36829_PS_IT_MSK, reg) * 25;
+ return IIO_VAL_INT_PLUS_MICRO;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int vcnl36829_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val,
+ int val2, long mask)
+{
+ struct vcnl36829_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ if (val != 0)
+ return -EINVAL;
+ if (val2 >= 25 && val2 <= 375 && val2 % 25 == 0)
+ return regmap_update_bits(data->regmap,
+ VCNL36829_PS_CONF2,
+ VCNL36829_PS_IT_MSK,
+ FIELD_PREP(VCNL36829_PS_IT_MSK, val2 / 25));
+ return -EINVAL;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int vcnl36829_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ *length = 6;
+ *vals = vcnl36829_it_range;
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ return IIO_AVAIL_RANGE;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info vcnl36829_info = {
+ .read_raw = vcnl36829_read_raw,
+ .write_raw = vcnl36829_write_raw,
+ .read_avail = vcnl36829_read_avail,
+};
+
+static const struct iio_chan_spec vcnl36829_channels[] = {
+ {
+ .type = IIO_PROXIMITY,
+ .address = VCNL36829_DATA,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_INT_TIME),
+ .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_INT_TIME),
+ }
+};
+
+static void vcnl36829_shutdown_action(void *data)
+{
+ struct vcnl36829_data *vcnl36829_data = data;
+
+ regmap_update_bits(vcnl36829_data->regmap,
+ VCNL36829_PS_CONF1,
+ VCNL36829_PS_ON_MSK | VCNL36829_PS_SD_MSK,
+ FIELD_PREP(VCNL36829_PS_ON_MSK, 0) |
+ FIELD_PREP(VCNL36829_PS_SD_MSK, 1));
+}
+
+static int vcnl36829_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct vcnl36829_data *data;
+ struct iio_dev *indio_dev;
+ struct regmap *regmap;
+
+ int ret;
+ unsigned int reg;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return dev_err_probe(dev, -EOPNOTSUPP,
+ "I2C adapter doesn't support plain I2C\n");
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ regmap = devm_regmap_init_i2c(client, &vcnl36829_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Regmap setup failed\n");
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ data->client = client;
+ data->regmap = regmap;
+
+ indio_dev->name = "vcnl36829";
+ indio_dev->info = &vcnl36829_info;
+ indio_dev->channels = vcnl36829_channels;
+ indio_dev->num_channels = ARRAY_SIZE(vcnl36829_channels);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ ret = devm_regulator_get_enable(dev, "vdd");
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to enable vdd\n");
+
+ ret = devm_regulator_get_enable(dev, "vddio");
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to enable vddio\n");
+
+ fsleep(3000);
+
+ ret = regmap_read(regmap, VCNL36829_DEV_ID, ®);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to read device ID\n");
+ if ((reg & 0xFF) != VCNL36829_DEV_ID_VAL)
+ return dev_err_probe(dev, -ENODEV,
+ "Unknown device ID 0x%x\n", reg);
+
+ ret = regmap_update_bits(regmap, VCNL36829_PS_CONF2,
+ VCNL36829_PS_IT_MSK,
+ FIELD_PREP(VCNL36829_PS_IT_MSK, VCNL36829_PS_INT_TIME_25));
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Could not configure PS_IT\n");
+
+ ret = regmap_update_bits(regmap, VCNL36829_PS_CONF3,
+ VCNL36829_PS_CURRENT_EN_MSK |
+ VCNL36829_PS_CURRENT_MSK |
+ VCNL36829_PD1_EN_MSK |
+ VCNL36829_PD2_EN_MSK |
+ VCNL36829_PD3_EN_MSK,
+ FIELD_PREP(VCNL36829_PS_CURRENT_EN_MSK, 1) |
+ FIELD_PREP(VCNL36829_PS_CURRENT_MSK, VCNL36829_PS_CURRENT_18MA) |
+ FIELD_PREP(VCNL36829_PD1_EN_MSK, 1) |
+ FIELD_PREP(VCNL36829_PD2_EN_MSK, 1) |
+ FIELD_PREP(VCNL36829_PD3_EN_MSK, 1));
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Could not configure VCSEL/PD\n");
+
+ ret = regmap_write(regmap, VCNL36829_PS_CONF5, VCNL36829_PS_CONF5_INIT);
+ if (ret)
+ return dev_err_probe(dev, ret, "Could not set PS_CONF5\n");
+
+ ret = regmap_update_bits(regmap, VCNL36829_PS_CONF1,
+ VCNL36829_PS_ON_MSK | VCNL36829_PS_SD_MSK,
+ FIELD_PREP(VCNL36829_PS_ON_MSK, 1) |
+ FIELD_PREP(VCNL36829_PS_SD_MSK, 0));
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Could not set initial config\n");
+
+ ret = devm_add_action_or_reset(dev, vcnl36829_shutdown_action, data);
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static const struct i2c_device_id vcnl36829_id_table[] = {
+ { .name = "vcnl36829" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, vcnl36829_id_table);
+
+static const struct of_device_id vcnl36829_of_match[] = {
+ { .compatible = "vishay,vcnl36829" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, vcnl36829_of_match);
+
+static struct i2c_driver vcnl36829_driver = {
+ .probe = vcnl36829_probe,
+ .id_table = vcnl36829_id_table,
+ .driver = {
+ .name = "vcnl36829",
+ .of_match_table = vcnl36829_of_match,
+ },
+};
+module_i2c_driver(vcnl36829_driver);
+
+MODULE_DESCRIPTION("Vishay VCNL36829 proximity sensor driver");
+MODULE_AUTHOR("Liu Yufei <lyf98405@gmail.com>");
+MODULE_LICENSE("GPL");
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 2/2] iio: proximity: Add driver for Vishay VCNL36829
2026-10-03 5:04 ` [PATCH 2/2] iio: proximity: Add driver for " Liu Yufei
@ 2026-10-03 19:03 ` Andy Shevchenko
0 siblings, 0 replies; 4+ messages in thread
From: Andy Shevchenko @ 2026-10-03 19:03 UTC (permalink / raw)
To: Liu Yufei
Cc: Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
David Lechner, Nuno Sá,
Andy Shevchenko, linux-iio, devicetree, linux-kernel
On Sat, Oct 03, 2026 at 01:04:53PM +0800, Liu Yufei wrote:
> Add an IIO driver for the Vishay VCNL36829 proximity sensor with
> integrated VCSEL, connected over I2C.
>
> At probe the driver enables the vdd and vddio supplies, waits for the
> sensor to power up, checks the device ID, configures the VCSEL current
> and photodiodes, and turns the proximity engine on. The sensor is put
> back into shutdown when the device is removed.
>
> The following attributes are exposed:
> - in_proximity0_raw
> - in_proximity_integration_time
> - in_proximity_integration_time_available
> The datasheet is available at:
> https://www.vishay.com/docs/80580/vcnl36829um.pdf
Make it a Datasheet: tag.
> Assisted-by: Claude:claude-opus-5-5 checkpatch dtschema
Assisted-by: LLM
...
> +#include <linux/i2c.h>
> +#include <linux/mod_devicetable.h>
In the new code we rely on the bus header to provide the ID definitions.
> +#include <linux/iio/iio.h>
> +#include <linux/regmap.h>
> +#include <linux/bitfield.h>
> +#include <linux/module.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/delay.h>
Keep it sorted, also follow the IWYU principle.
...
> +struct vcnl36829_data {
> + struct i2c_client *client;
> + struct regmap *regmap;
One can be derived through the other, no need to keep client here.
> +};
> +
> +static const struct regmap_config vcnl36829_regmap_config = {
> + .name = "vcnl36829_regmap",
> + .reg_bits = 8,
> + .val_bits = 16,
> + .max_register = VCNL36829_DEV_ID,
> + .val_format_endian = REGMAP_ENDIAN_LITTLE,
No cache?
> +};
...
> +static int vcnl36829_write_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan, int val,
> + int val2, long mask)
> +{
> + struct vcnl36829_data *data = iio_priv(indio_dev);
> +
> + switch (mask) {
> + case IIO_CHAN_INFO_INT_TIME:
> + if (val != 0)
> + return -EINVAL;
> + if (val2 >= 25 && val2 <= 375 && val2 % 25 == 0)
> + return regmap_update_bits(data->regmap,
> + VCNL36829_PS_CONF2,
> + VCNL36829_PS_IT_MSK,
> + FIELD_PREP(VCNL36829_PS_IT_MSK, val2 / 25));
Compiler might utilise some specific assembler instructions on some CPUs
to do % and / at once. To make it happen we can hint compiler with locating
these two operations next to each other. Also use standard pattern to check
for an error first and correct indentation.
int ival = val2 / 25;
int fval = val2 % 25;
...
if (val != 0)
return -EINVAL;
if (ival < 1 && ival > 15)
return -EINVAL;
if (fval != 0)
return -EINVAL;
return regmap_update_bits(data->regmap, VCNL36829_PS_CONF2,
VCNL36829_PS_IT_MSK,
FIELD_PREP(VCNL36829_PS_IT_MSK, ival));
> + return -EINVAL;
> + default:
> + return -EINVAL;
> + }
> +}
...
> +static int vcnl36829_probe(struct i2c_client *client)
> +{
> + struct device *dev = &client->dev;
> + struct vcnl36829_data *data;
> + struct iio_dev *indio_dev;
> + struct regmap *regmap;
> +
> + int ret;
> + unsigned int reg;
No blank lines in the definition block, also keep it in reversed xmas tree
order.
> + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
> + return dev_err_probe(dev, -EOPNOTSUPP,
> + "I2C adapter doesn't support plain I2C\n");
> +
> + indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
> + if (!indio_dev)
> + return -ENOMEM;
> +
> + regmap = devm_regmap_init_i2c(client, &vcnl36829_regmap_config);
> + if (IS_ERR(regmap))
> + return dev_err_probe(dev, PTR_ERR(regmap),
> + "Regmap setup failed\n");
> +
> + data = iio_priv(indio_dev);
> + i2c_set_clientdata(client, indio_dev);
Is this being used?
> + data->client = client;
> + data->regmap = regmap;
> +
> + indio_dev->name = "vcnl36829";
> + indio_dev->info = &vcnl36829_info;
> + indio_dev->channels = vcnl36829_channels;
> + indio_dev->num_channels = ARRAY_SIZE(vcnl36829_channels);
> + indio_dev->modes = INDIO_DIRECT_MODE;
> +
> + ret = devm_regulator_get_enable(dev, "vdd");
> + if (ret)
> + return dev_err_probe(dev, ret, "failed to enable vdd\n");
> +
> + ret = devm_regulator_get_enable(dev, "vddio");
> + if (ret)
> + return dev_err_probe(dev, ret, "failed to enable vddio\n");
The following sleep needs a comment with a reference to the specific section
and/or table in the datasheet.
> + fsleep(3000);
3 * USEC_PER_MSEC
(will require time.h to be included)
> + ret = regmap_read(regmap, VCNL36829_DEV_ID, ®);
> + if (ret)
> + return dev_err_probe(dev, ret, "Failed to read device ID\n");
> + if ((reg & 0xFF) != VCNL36829_DEV_ID_VAL)
> + return dev_err_probe(dev, -ENODEV,
> + "Unknown device ID 0x%x\n", reg);
Don't we simply warn and continue in this case?
> + ret = regmap_update_bits(regmap, VCNL36829_PS_CONF2,
> + VCNL36829_PS_IT_MSK,
> + FIELD_PREP(VCNL36829_PS_IT_MSK, VCNL36829_PS_INT_TIME_25));
> + if (ret)
> + return dev_err_probe(dev, ret,
> + "Could not configure PS_IT\n");
It's perfectly a single line.
> +
> + ret = regmap_update_bits(regmap, VCNL36829_PS_CONF3,
> + VCNL36829_PS_CURRENT_EN_MSK |
> + VCNL36829_PS_CURRENT_MSK |
> + VCNL36829_PD1_EN_MSK |
> + VCNL36829_PD2_EN_MSK |
> + VCNL36829_PD3_EN_MSK,
> + FIELD_PREP(VCNL36829_PS_CURRENT_EN_MSK, 1) |
> + FIELD_PREP(VCNL36829_PS_CURRENT_MSK, VCNL36829_PS_CURRENT_18MA) |
> + FIELD_PREP(VCNL36829_PD1_EN_MSK, 1) |
> + FIELD_PREP(VCNL36829_PD2_EN_MSK, 1) |
> + FIELD_PREP(VCNL36829_PD3_EN_MSK, 1));
> + if (ret)
> + return dev_err_probe(dev, ret,
> + "Could not configure VCSEL/PD\n");
> +
> + ret = regmap_write(regmap, VCNL36829_PS_CONF5, VCNL36829_PS_CONF5_INIT);
> + if (ret)
> + return dev_err_probe(dev, ret, "Could not set PS_CONF5\n");
> +
> + ret = regmap_update_bits(regmap, VCNL36829_PS_CONF1,
> + VCNL36829_PS_ON_MSK | VCNL36829_PS_SD_MSK,
> + FIELD_PREP(VCNL36829_PS_ON_MSK, 1) |
> + FIELD_PREP(VCNL36829_PS_SD_MSK, 0));
> + if (ret)
> + return dev_err_probe(dev, ret,
> + "Could not set initial config\n");
> +
> + ret = devm_add_action_or_reset(dev, vcnl36829_shutdown_action, data);
> + if (ret)
> + return ret;
> +
> + return devm_iio_device_register(dev, indio_dev);
> +}
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-03 19:03 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-03 5:04 [PATCH 0/2] iio: proximity: Add Vishay VCNL36829 driver Liu Yufei
2026-10-03 5:04 ` [PATCH 1/2] dt-bindings: iio: proximity: Add Vishay VCNL36829 Liu Yufei
2026-10-03 5:04 ` [PATCH 2/2] iio: proximity: Add driver for " Liu Yufei
2026-10-03 19:03 ` Andy Shevchenko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®