All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/3] Add Sharp GP2AP070S Proximity Driver and enable it in Galaxy J6 (j6lte)
@ 2026-07-30 20:06 Kaustabh Chakraborty
  2026-07-30 20:07 ` [PATCH v3 1/3] dt-bindings: iio: proximity: add Sharp GP2AP070S proximity sensor Kaustabh Chakraborty
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Kaustabh Chakraborty @ 2026-07-30 20:06 UTC (permalink / raw)
  To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Kaustabh Chakraborty, Peter Griffin, Alim Akhtar
  Cc: linux-iio, devicetree, linux-kernel, linux-arm-kernel,
	linux-samsung-soc

Sharp GP2AP070S is a promixity sensor (NOT an ambient light sensor) in
mobile devices. This sensor chip is found in mobile devices, including
(but perhaps not limited to) Samsung Galaxy J6 (codename: j6lte).

To the best of my knowledge, there's no public documentation available
for this device. [1] is a downstream kernel implementation, which has
been the single source for developing this driver. Some bits have also
been stolen from existing GP2AP* drivers available in iio/light.

The last patch in this series touches the device tree sources to add the
light sensor node in j6lte. This needs to be accepted into next only
when the former patches are in next.

[1] https://github.com/Exynos7870/android_kernel_samsung_universal7870/blob/lineage-16.0/drivers/sensors/gp2ap070s.c

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
Changes in v3:
- Revoke stale patches sent erroneously, v2 changelog applies
- Link to v2: https://patch.msgid.link/20260731-gp2ap070s-v2-0-1bdfee07d5ea@disroot.org

Changes in v2:
- Reshuffle and add missing header inclusions (Joshua Crofts)
- Add missing regulators in driver and dt-schema
  (Joshua Crofts, Jonathan Cameron)
- Rename and rearrange register addresses, masks and values (Jonathan Cameron)
- Use regmap_get_device() for carrying dev pointer (Jonathan Cameron)
- Use FIELD_GET() instead of !! (Jonathan Cameron)
- Drop unused i2c_set_clientdata() (Jonathan Cameron)
- Use fsleep() instead of usleep_range() (Jonathan Cameron)
- Check if proximity-near-level is available before reading its value
  (Jonathan Cameron)
- Drop redundant dev_err_probe() from devm_request_threaded_irq()
  (Joshua Crofts)
- Use mutex guards for guarding concurrent read/write calls (Sashiko)
- Add reset chip action on removal (Sashiko)
- Ensure input value in iio_write_event_value() is 16-bit (Sashiko)
- Use regmap_bulk_*() instead of regmap_raw_*() (Jonathan Cameron)
- Hint volatile registers for regmap (Jonathan Cameron)
- Link to v1: https://patch.msgid.link/20260723-gp2ap070s-v1-0-b8ca3a4c10dd@disroot.org

---
Kaustabh Chakraborty (3):
      dt-bindings: iio: proximity: add Sharp GP2AP070S proximity sensor
      iio: proximity: add driver for Sharp GP2AP070S proximity sensor
      arm64: dts: exynos7870-j6lte: add Sharp GP2AP070S proximity sensor

 .../bindings/iio/proximity/sharp,gp2ap070s.yaml    |  60 +++
 arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts    |  55 ++-
 drivers/iio/proximity/Kconfig                      |  11 +
 drivers/iio/proximity/Makefile                     |   1 +
 drivers/iio/proximity/gp2ap070s.c                  | 505 +++++++++++++++++++++
 5 files changed, 630 insertions(+), 2 deletions(-)
---
base-commit: 290aaf24a551d5a0dce037e3fab30820f9113a10
change-id: 20260723-gp2ap070s-f7e0120970a5

Best regards,
--  
Kaustabh Chakraborty <kauschluss@disroot.org>


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

* [PATCH v3 1/3] dt-bindings: iio: proximity: add Sharp GP2AP070S proximity sensor
  2026-07-30 20:06 [PATCH v3 0/3] Add Sharp GP2AP070S Proximity Driver and enable it in Galaxy J6 (j6lte) Kaustabh Chakraborty
@ 2026-07-30 20:07 ` Kaustabh Chakraborty
  2026-07-30 20:12   ` sashiko-bot
  2026-07-30 20:07 ` [PATCH v3 2/3] iio: proximity: add driver for " Kaustabh Chakraborty
  2026-07-30 20:07 ` [PATCH v3 3/3] arm64: dts: exynos7870-j6lte: add " Kaustabh Chakraborty
  2 siblings, 1 reply; 7+ messages in thread
From: Kaustabh Chakraborty @ 2026-07-30 20:07 UTC (permalink / raw)
  To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Kaustabh Chakraborty, Peter Griffin, Alim Akhtar
  Cc: linux-iio, devicetree, linux-kernel, linux-arm-kernel,
	linux-samsung-soc

The GP2AP070S is a proximity sensor designed and manufactured by Sharp
Corporation. Unlike the other GP2AP* schemas, this is strictly a
proximity sensor and NOT an ambient light sensor.

For power supplies, it expects two voltage supplies, one for core and
other for driving the infrared LED which is used to measure proximity
distance.

This chip has been used in production mobile devices such as the Samsung
Galaxy J6.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
 .../bindings/iio/proximity/sharp,gp2ap070s.yaml    | 60 ++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/Documentation/devicetree/bindings/iio/proximity/sharp,gp2ap070s.yaml b/Documentation/devicetree/bindings/iio/proximity/sharp,gp2ap070s.yaml
new file mode 100644
index 000000000000..73f0abc1f09c
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/proximity/sharp,gp2ap070s.yaml
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/proximity/sharp,gp2ap070s.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Sharp GP2AP070S Proximity sensor
+
+maintainers:
+  - Kaustabh Chakraborty <kauschluss@disroot.org>
+
+allOf:
+  - $ref: ../common.yaml#
+
+properties:
+  compatible:
+    const: sharp,gp2ap070s
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  vdd-supply:
+    description: Voltage supply for the internal circuitry
+
+  vled-supply:
+    description: Voltage supply for the IR LED
+
+  proximity-near-level: true
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - vdd-supply
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    i2c {
+      #address-cells = <1>;
+      #size-cells = <0>;
+
+      proximity@39 {
+        compatible = "sharp,gp2ap070s";
+        reg = <0x39>;
+        interrupt-parent = <&gpio>;
+        interrupts = <1 IRQ_TYPE_EDGE_BOTH>;
+        vdd-supply = <&vdd_supply>;
+        vled-supply = <&vled_supply>;
+        proximity-near-level = <500>;
+      };
+    };
+
+...

-- 
2.54.0


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

* [PATCH v3 2/3] iio: proximity: add driver for Sharp GP2AP070S proximity sensor
  2026-07-30 20:06 [PATCH v3 0/3] Add Sharp GP2AP070S Proximity Driver and enable it in Galaxy J6 (j6lte) Kaustabh Chakraborty
  2026-07-30 20:07 ` [PATCH v3 1/3] dt-bindings: iio: proximity: add Sharp GP2AP070S proximity sensor Kaustabh Chakraborty
@ 2026-07-30 20:07 ` Kaustabh Chakraborty
  2026-07-30 20:18   ` sashiko-bot
  2026-07-30 20:07 ` [PATCH v3 3/3] arm64: dts: exynos7870-j6lte: add " Kaustabh Chakraborty
  2 siblings, 1 reply; 7+ messages in thread
From: Kaustabh Chakraborty @ 2026-07-30 20:07 UTC (permalink / raw)
  To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Kaustabh Chakraborty, Peter Griffin, Alim Akhtar
  Cc: linux-iio, devicetree, linux-kernel, linux-arm-kernel,
	linux-samsung-soc

The GP2AP070S is a proximity sensor designed and manufactured by Sharp
Corporation. This sensor is used in mobile devices, including, but not
limited to - the Samsung Galaxy J6.

The driver has been adopted from Samsung's downstream kernel
implementation [1]. Due to the lack of public documentation about the
schematics of this device. The downstream driver acts as the secondary
source of information. Driver clarity has also been improved with the
help of the GP2AP* drivers in iio/light.

Link: https://github.com/Exynos7870/android_kernel_samsung_universal7870/blob/lineage-16.0/drivers/sensors/gp2ap070s.c [1]
Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
 drivers/iio/proximity/Kconfig     |  11 +
 drivers/iio/proximity/Makefile    |   1 +
 drivers/iio/proximity/gp2ap070s.c | 505 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 517 insertions(+)

diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig
index bb77fad2a1b3..39db19e59650 100644
--- a/drivers/iio/proximity/Kconfig
+++ b/drivers/iio/proximity/Kconfig
@@ -41,6 +41,17 @@ config D3323AA
 	  To compile this driver as a module, choose M here: the module will be
 	  called d3323aa.
 
+config GP2AP070S
+	tristate "Sharp GP2AP070S proximity sensor"
+	depends on I2C
+	select REGMAP_I2C
+	help
+	  Say Y here to build a driver for the Sharp GP2AP070S proximity
+	  sensor.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called gp2ap070s.
+
 config HX9023S
 	tristate "TYHX HX9023S SAR sensor"
 	select IIO_BUFFER
diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile
index 4352833dd8a4..627ffb04acb2 100644
--- a/drivers/iio/proximity/Makefile
+++ b/drivers/iio/proximity/Makefile
@@ -7,6 +7,7 @@
 obj-$(CONFIG_AS3935)		+= as3935.o
 obj-$(CONFIG_CROS_EC_MKBP_PROXIMITY) += cros_ec_mkbp_proximity.o
 obj-$(CONFIG_D3323AA)		+= d3323aa.o
+obj-$(CONFIG_GP2AP070S)		+= gp2ap070s.o
 obj-$(CONFIG_HX9023S)		+= hx9023s.o
 obj-$(CONFIG_IRSD200)		+= irsd200.o
 obj-$(CONFIG_ISL29501)		+= isl29501.o
diff --git a/drivers/iio/proximity/gp2ap070s.c b/drivers/iio/proximity/gp2ap070s.c
new file mode 100644
index 000000000000..98fc12e5ccd5
--- /dev/null
+++ b/drivers/iio/proximity/gp2ap070s.c
@@ -0,0 +1,505 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * IIO driver for Sharp GP2AP070S proximity sensor.
+ *
+ * Based on Samsung G610FXXU1CRI4 kernel driver - drivers/sensors/gp2ap070s.c
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2026 Kaustabh Chakraborty <kauschluss@disroot.org>
+ */
+
+#include <linux/array_size.h>
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/types.h>
+
+#include <linux/iio/events.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/types.h>
+
+#define GP2AP070S_REG_COM1		0x80
+#define   GP2AP070S_COM1_WKUP		BIT(7)
+#define   GP2AP070S_COM1_EN		BIT(5)
+
+#define GP2AP070S_REG_COM2		0x81
+
+#define GP2AP070S_REG_COM3		0x82
+#define   GP2AP070S_COM3_INT_PULSE	BIT(1)
+
+#define GP2AP070S_REG_COM4		0x83
+#define   GP2AP070S_COM4_BLINK		GENMASK(2, 0)	/* LED Blink Interval */
+#define     GP2AP070S_COM4_BLINK_0ms	0
+#define     GP2AP070S_COM4_BLINK_2ms	1
+#define     GP2AP070S_COM4_BLINK_8ms	2
+#define     GP2AP070S_COM4_BLINK_33ms	3
+#define     GP2AP070S_COM4_BLINK_66ms	4
+#define     GP2AP070S_COM4_BLINK_131ms	5
+#define     GP2AP070S_COM4_BLINK_262ms	6
+#define     GP2AP070S_COM4_BLINK_524ms	7
+
+#define GP2AP070S_REG_PS1		0x85
+#define   GP2AP070S_PS1_RESOL		GENMASK(5, 4)	/* Resolution */
+#define     GP2AP070S_PS1_RESOL_14ms	0
+#define     GP2AP070S_PS1_RESOL_12ms	1
+#define     GP2AP070S_PS1_RESOL_10ms	2
+#define     GP2AP070S_PS1_RESOL_8ms	3
+
+#define GP2AP070S_REG_PS2		0x86
+#define   GP2AP070S_PS2_IOUT		GENMASK(6, 4)	/* Current Output */
+#define     GP2AP070S_PS2_IOUT_0mA	0
+#define     GP2AP070S_PS2_IOUT_24mA	1
+#define     GP2AP070S_PS2_IOUT_89mA	2
+#define     GP2AP070S_PS2_IOUT_130mA	3
+#define     GP2AP070S_PS2_IOUT_190mA	4
+#define   GP2AP070S_PS2_SUM32		BIT(2)
+
+#define GP2AP070S_REG_PS3		0x87
+#define   GP2AP070S_PS3_PRST		GENMASK(6, 4)	/* Repeating Measurements */
+
+#define GP2AP070S_REG_PS_THD_LO_LE16	0x88
+#define GP2AP070S_REG_PS_THD_HI_LE16	0x8a
+#define GP2AP070S_REG_D0_LE16		0x90
+
+struct gp2ap070s_drvdata {
+	struct regmap *regmap;
+	struct mutex mutex;
+	u32 near_level;
+};
+
+static bool gp2ap070s_regmap_volatile(struct device *dev, unsigned int reg)
+{
+	return reg == GP2AP070S_REG_D0_LE16;
+}
+
+static const struct regmap_config gp2ap070s_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.volatile_reg = gp2ap070s_regmap_volatile,
+};
+
+static const char *const gp2ap070s_regulator_names[] = {
+	"vdd",
+	"vled",
+};
+
+static ssize_t gp2ap070s_iio_read_near_level(struct iio_dev *indio_dev,
+					     uintptr_t priv,
+					     const struct iio_chan_spec *chan,
+					     char *buf)
+{
+	struct gp2ap070s_drvdata *drvdata = iio_priv(indio_dev);
+
+	return sysfs_emit(buf, "%u\n", drvdata->near_level);
+}
+
+static const struct iio_chan_spec_ext_info gp2ap070s_iio_chan_spec_ext_info[] = {
+	{
+		.name = "nearlevel",
+		.shared = IIO_SEPARATE,
+		.read = gp2ap070s_iio_read_near_level,
+	},
+	{ }
+};
+
+static const struct iio_event_spec gp2ap070s_iio_event_spec[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE),
+	},
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE),
+	},
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_EITHER,
+		.mask_separate = BIT(IIO_EV_INFO_ENABLE),
+	},
+};
+
+static const struct iio_chan_spec gp2ap070s_iio_chan_spec[] = {
+	{
+		.type = IIO_PROXIMITY,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.ext_info = gp2ap070s_iio_chan_spec_ext_info,
+		.event_spec = gp2ap070s_iio_event_spec,
+		.num_event_specs = ARRAY_SIZE(gp2ap070s_iio_event_spec),
+	},
+};
+
+static int gp2ap070s_iio_read_raw(struct iio_dev *indio_dev,
+				  struct iio_chan_spec const *chan, int *val,
+				  int *val2, long mask)
+{
+	struct gp2ap070s_drvdata *drvdata = iio_priv(indio_dev);
+	__le16 value;
+	int ret;
+
+	ret = regmap_bulk_read(drvdata->regmap, GP2AP070S_REG_D0_LE16, &value,
+			       sizeof(value));
+	if (ret)
+		return ret;
+
+	*val = le16_to_cpu(value);
+	return IIO_VAL_INT;
+}
+
+static int gp2ap070s_iio_read_event_value(struct iio_dev *indio_dev,
+					  const struct iio_chan_spec *chan,
+					  enum iio_event_type type,
+					  enum iio_event_direction dir,
+					  enum iio_event_info info, int *val,
+					  int *val2)
+{
+	struct gp2ap070s_drvdata *drvdata = iio_priv(indio_dev);
+	__le16 value;
+	int ret;
+
+	if (type != IIO_EV_TYPE_THRESH || info != IIO_EV_INFO_VALUE)
+		return -EINVAL;
+
+	guard(mutex)(&drvdata->mutex);
+
+	switch (dir) {
+	case IIO_EV_DIR_RISING:
+		ret = regmap_bulk_read(drvdata->regmap,
+				       GP2AP070S_REG_PS_THD_HI_LE16, &value,
+				       sizeof(value));
+		if (ret)
+			return ret;
+
+		*val = le16_to_cpu(value);
+		return IIO_VAL_INT;
+	case IIO_EV_DIR_FALLING:
+		ret = regmap_bulk_read(drvdata->regmap,
+				       GP2AP070S_REG_PS_THD_LO_LE16, &value,
+				       sizeof(value));
+		if (ret)
+			return ret;
+
+		*val = le16_to_cpu(value);
+		return IIO_VAL_INT;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int gp2ap070s_iio_write_event_value(struct iio_dev *indio_dev,
+					   const struct iio_chan_spec *chan,
+					   enum iio_event_type type,
+					   enum iio_event_direction dir,
+					   enum iio_event_info info, int val,
+					   int val2)
+{
+	struct gp2ap070s_drvdata *drvdata = iio_priv(indio_dev);
+	__le16 value;
+	u16 threshold_other;
+	int ret;
+
+	if (type != IIO_EV_TYPE_THRESH || info != IIO_EV_INFO_VALUE)
+		return -EINVAL;
+
+	/* Ensure val is a 16-bit value */
+	if (val < 0 || val >= (1 << 16))
+		return -EINVAL;
+
+	guard(mutex)(&drvdata->mutex);
+
+	switch (dir) {
+	case IIO_EV_DIR_RISING:
+		ret = regmap_bulk_read(drvdata->regmap,
+				       GP2AP070S_REG_PS_THD_LO_LE16, &value,
+				       sizeof(value));
+		if (ret)
+			return ret;
+
+		/* Ensure lo_threshold < hi_threshold */
+		threshold_other = le16_to_cpu(value);
+		if (threshold_other >= val)
+			return -EINVAL;
+
+		value = cpu_to_le16((u16)val);
+		ret = regmap_bulk_write(drvdata->regmap,
+					GP2AP070S_REG_PS_THD_HI_LE16, &value,
+					sizeof(value));
+		if (ret)
+			return ret;
+
+		return IIO_VAL_INT;
+	case IIO_EV_DIR_FALLING:
+		ret = regmap_bulk_read(drvdata->regmap,
+				       GP2AP070S_REG_PS_THD_HI_LE16, &value,
+				       sizeof(value));
+		if (ret)
+			return ret;
+
+		/* Ensure hi_threshold > lo_threshold */
+		threshold_other = le16_to_cpu(value);
+		if (threshold_other <= val)
+			return -EINVAL;
+
+		value = cpu_to_le16((u16)val);
+		ret = regmap_bulk_write(drvdata->regmap,
+					GP2AP070S_REG_PS_THD_LO_LE16, &value,
+					sizeof(value));
+		if (ret)
+			return ret;
+
+		return IIO_VAL_INT;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int gp2ap070s_read_event_config(struct iio_dev *indio_dev,
+				       const struct iio_chan_spec *chan,
+				       enum iio_event_type type,
+				       enum iio_event_direction dir)
+{
+	struct gp2ap070s_drvdata *drvdata = iio_priv(indio_dev);
+	unsigned int value;
+	int ret;
+
+	if (type != IIO_EV_TYPE_THRESH)
+		return -EINVAL;
+
+	guard(mutex)(&drvdata->mutex);
+
+	switch (dir) {
+	case IIO_EV_DIR_EITHER:
+		ret = regmap_read(drvdata->regmap, GP2AP070S_REG_COM3, &value);
+		if (ret)
+			return ret;
+
+		return FIELD_GET(GP2AP070S_COM3_INT_PULSE, value);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int gp2ap070s_write_event_config(struct iio_dev *indio_dev,
+					const struct iio_chan_spec *chan,
+					enum iio_event_type type,
+					enum iio_event_direction dir,
+					bool state)
+{
+	struct gp2ap070s_drvdata *drvdata = iio_priv(indio_dev);
+
+	if (type != IIO_EV_TYPE_THRESH)
+		return -EINVAL;
+
+	guard(mutex)(&drvdata->mutex);
+
+	switch (dir) {
+	case IIO_EV_DIR_EITHER:
+		if (state)
+			return regmap_set_bits(drvdata->regmap,
+					       GP2AP070S_REG_COM3,
+					       GP2AP070S_COM3_INT_PULSE);
+		else
+			return regmap_clear_bits(drvdata->regmap,
+						 GP2AP070S_REG_COM3,
+						 GP2AP070S_COM3_INT_PULSE);
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_info gp2ap070s_iio_info = {
+	.read_raw = gp2ap070s_iio_read_raw,
+	.read_event_value = gp2ap070s_iio_read_event_value,
+	.write_event_value = gp2ap070s_iio_write_event_value,
+	.read_event_config = gp2ap070s_read_event_config,
+	.write_event_config = gp2ap070s_write_event_config,
+};
+
+static irqreturn_t gp2ap070s_irq_handler(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	s64 timestamp = iio_get_time_ns(indio_dev);
+
+	iio_push_event(indio_dev,
+		       IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0, IIO_EV_TYPE_THRESH,
+					    IIO_EV_DIR_EITHER),
+		       timestamp);
+
+	return IRQ_HANDLED;
+}
+
+static int gp2ap070s_reset(struct gp2ap070s_drvdata *drvdata)
+{
+	int ret;
+
+	ret = regmap_write(drvdata->regmap, GP2AP070S_REG_COM1, 0);
+	if (ret)
+		return ret;
+
+	regcache_mark_dirty(drvdata->regmap);
+
+	return 0;
+}
+
+static void gp2ap070s_reset_action(void *private)
+{
+	struct gp2ap070s_drvdata *drvdata = private;
+
+	gp2ap070s_reset(drvdata);
+}
+
+static int gp2ap070s_probe_hw_register(struct gp2ap070s_drvdata *drvdata)
+{
+	struct device *dev = regmap_get_device(drvdata->regmap);
+	int ret;
+
+	ret = gp2ap070s_reset(drvdata);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to reset sensor\n");
+
+	ret = regmap_write(drvdata->regmap, GP2AP070S_REG_COM2, 0);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to enable interrupts\n");
+
+	ret = regmap_set_bits(drvdata->regmap, GP2AP070S_REG_COM3,
+			      GP2AP070S_COM3_INT_PULSE);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to unmask interrupts\n");
+
+	ret = regmap_write_bits(drvdata->regmap, GP2AP070S_REG_COM4,
+				GP2AP070S_COM4_BLINK,
+				FIELD_PREP_CONST(GP2AP070S_COM4_BLINK,
+						 GP2AP070S_COM4_BLINK_33ms));
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to set LED blink timing\n");
+
+	ret = regmap_write_bits(drvdata->regmap, GP2AP070S_REG_PS1,
+				GP2AP070S_PS1_RESOL,
+				FIELD_PREP_CONST(GP2AP070S_PS1_RESOL,
+						 GP2AP070S_PS1_RESOL_10ms));
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to set resolution\n");
+
+	ret = regmap_write_bits(drvdata->regmap, GP2AP070S_REG_PS2,
+				GP2AP070S_PS2_IOUT | GP2AP070S_PS2_SUM32,
+				FIELD_PREP_CONST(GP2AP070S_PS2_IOUT,
+						 GP2AP070S_PS2_IOUT_89mA) |
+				GP2AP070S_PS2_SUM32);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to set current output\n");
+
+	ret = regmap_write_bits(drvdata->regmap, GP2AP070S_REG_PS3,
+				GP2AP070S_PS3_PRST,
+				FIELD_PREP_CONST(GP2AP070S_PS3_PRST, 3));
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to set measurement repetitions\n");
+
+	ret = regmap_set_bits(drvdata->regmap, GP2AP070S_REG_COM1,
+			      GP2AP070S_COM1_WKUP | GP2AP070S_COM1_EN);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to enable sensor\n");
+
+	return 0;
+}
+
+static int gp2ap070s_probe(struct i2c_client *client)
+{
+	struct device *dev = &client->dev;
+	struct iio_dev *indio_dev;
+	struct gp2ap070s_drvdata *drvdata;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*drvdata));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	drvdata = iio_priv(indio_dev);
+	drvdata->regmap = devm_regmap_init_i2c(client, &gp2ap070s_regmap_config);
+	if (IS_ERR(drvdata->regmap))
+		return dev_err_probe(dev, PTR_ERR(drvdata->regmap), "Failed to create regmap\n");
+
+	ret = devm_mutex_init(dev, &drvdata->mutex);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to initialize mutex\n");
+
+	ret = devm_regulator_bulk_get_enable(dev,
+					     ARRAY_SIZE(gp2ap070s_regulator_names),
+					     gp2ap070s_regulator_names);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to get and enable regulators\n");
+
+	fsleep(10000);
+
+	indio_dev->name = "gp2ap070s";
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = gp2ap070s_iio_chan_spec;
+	indio_dev->num_channels = ARRAY_SIZE(gp2ap070s_iio_chan_spec);
+	indio_dev->info = &gp2ap070s_iio_info;
+
+	if (device_property_present(dev, "proximity-near-level")) {
+		ret = device_property_read_u32(dev, "proximity-near-level",
+					       &drvdata->near_level);
+		if (ret)
+			return dev_err_probe(dev, ret,
+					     "Failed to get value for proximity-near-level\n");
+	}
+
+	ret = gp2ap070s_probe_hw_register(drvdata);
+	if (ret)
+		goto hw_reset;
+
+	ret = devm_add_action_or_reset(dev, gp2ap070s_reset_action, drvdata);
+	if (ret) {
+		ret = dev_err_probe(dev, ret, "Failed to schedule reset on driver removal\n");
+		goto hw_reset;
+	}
+
+	ret = devm_request_threaded_irq(dev, client->irq, NULL,
+					gp2ap070s_irq_handler, IRQF_ONESHOT,
+					"gp2ap070s-irq", indio_dev);
+	if (ret)
+		goto hw_reset;
+
+	ret = devm_iio_device_register(dev, indio_dev);
+	if (ret)
+		goto hw_reset;
+
+	return 0;
+
+hw_reset:
+	gp2ap070s_reset(drvdata);
+
+	return ret;
+}
+
+static const struct of_device_id gp2ap070s_of_device_id[] = {
+	{ .compatible = "sharp,gp2ap070s" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, gp2ap070s_of_device_id);
+
+static const struct i2c_device_id gp2ap070s_i2c_device_id[] = {
+	{ .name = "gp2ap070s" },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, gp2ap070s_i2c_device_id);
+
+static struct i2c_driver gp2ap070s_i2c_driver = {
+	.driver = {
+		.name = "gp2ap070s",
+		.of_match_table = gp2ap070s_of_device_id,
+	},
+	.probe = gp2ap070s_probe,
+	.id_table = gp2ap070s_i2c_device_id,
+};
+module_i2c_driver(gp2ap070s_i2c_driver);
+
+MODULE_AUTHOR("Kaustabh Chakraborty <kauschluss@disroot.org>");
+MODULE_DESCRIPTION("Sharp GP2AP070S Proximity Sensor");
+MODULE_LICENSE("GPL");

-- 
2.54.0


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

* [PATCH v3 3/3] arm64: dts: exynos7870-j6lte: add Sharp GP2AP070S proximity sensor
  2026-07-30 20:06 [PATCH v3 0/3] Add Sharp GP2AP070S Proximity Driver and enable it in Galaxy J6 (j6lte) Kaustabh Chakraborty
  2026-07-30 20:07 ` [PATCH v3 1/3] dt-bindings: iio: proximity: add Sharp GP2AP070S proximity sensor Kaustabh Chakraborty
  2026-07-30 20:07 ` [PATCH v3 2/3] iio: proximity: add driver for " Kaustabh Chakraborty
@ 2026-07-30 20:07 ` Kaustabh Chakraborty
  2026-07-30 20:19   ` sashiko-bot
  2 siblings, 1 reply; 7+ messages in thread
From: Kaustabh Chakraborty @ 2026-07-30 20:07 UTC (permalink / raw)
  To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Kaustabh Chakraborty, Peter Griffin, Alim Akhtar
  Cc: linux-iio, devicetree, linux-kernel, linux-arm-kernel,
	linux-samsung-soc

The Sharp GP2AP070S is a proximity sensor, which is connected to a
GPIO-driven I2C line. Define the devicetree node for the sensor.

The sensor requires two voltage supplies, one of which is from the
primary regulator bank of the device, while the other one is controlled
by the GPIO. Add a regulator wrapping over the concerned GPIO so as to
feed it to the sensor node.

Signed-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>
---
 arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts | 55 ++++++++++++++++++++++++-
 1 file changed, 53 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts b/arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts
index de30d0970336..dd493138fed6 100644
--- a/arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts
+++ b/arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts
@@ -73,6 +73,35 @@ key-volup {
 		};
 	};
 
+	i2c-proximity {
+		compatible = "i2c-gpio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&i2c_proxm_bus>;
+
+		sda-gpios = <&gpf4 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+		scl-gpios = <&gpf4 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+
+		i2c-gpio,delay-us = <2>;
+
+		proximity@39 {
+			compatible = "sharp,gp2ap070s";
+			reg = <0x39>;
+			interrupt-parent = <&gpa0>;
+			interrupts = <5 IRQ_TYPE_EDGE_BOTH>;
+
+			pinctrl-names = "default";
+			pinctrl-0 = <&proxm_irq>;
+
+			vdd-supply = <&vdd_fixed_proxm>;
+			vled-supply = <&vdd_ldo33>;
+
+			proximity-near-level = <500>;
+		};
+	};
+
 	memory@40000000 {
 		device_type = "memory";
 		reg = <0x0 0x40000000 0x3d800000>,
@@ -94,6 +123,16 @@ vdd_fixed_mmc2: regulator-fixed-mmc2 {
 		enable-active-high;
 	};
 
+	/* proximity: vdd */
+	vdd_fixed_proxm: regulator-fixed-proxm {
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_fixed_proxm";
+		regulator-max-microvolt = <3300000>;
+		regulator-min-microvolt = <3300000>;
+		gpio = <&gpd2 3 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
 	reserved-memory {
 		#address-cells = <2>;
 		#size-cells = <1>;
@@ -354,13 +393,12 @@ vdd_ldo32: ldo32 {
 				regulator-ramp-delay = <12000>;
 			};
 
+			/* proximity: vled */
 			vdd_ldo33: ldo33 {
 				regulator-name = "vdd_ldo33";
 				regulator-min-microvolt = <3300000>;
 				regulator-max-microvolt = <3300000>;
 				regulator-ramp-delay = <12000>;
-				regulator-boot-on;
-				regulator-always-on;
 			};
 
 			/* touchscreen: vdd */
@@ -556,6 +594,13 @@ pmic_irq: pmic-irq-pins {
 		samsung,pin-drv = <EXYNOS5433_PIN_DRV_FAST_SR4>;
 	};
 
+	proxm_irq: proxm-irq-pins {
+		samsung,pins = "gpa0-5";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_EINT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS5433_PIN_DRV_FAST_SR1>;
+	};
+
 	touch_irq: touch-irq-pins {
 		samsung,pins = "gpa0-6";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_EINT>;
@@ -579,6 +624,12 @@ bt_enable: bt-enable-pins {
 		samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
 	};
 
+	i2c_proxm_bus: i2c-proxm-bus-pins {
+		samsung,pins = "gpf4-3", "gpf4-2";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+	};
+
 	wlan_enable: wlan-enable-pins {
 		samsung,pins = "gpd3-6";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;

-- 
2.54.0


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

* Re: [PATCH v3 1/3] dt-bindings: iio: proximity: add Sharp GP2AP070S proximity sensor
  2026-07-30 20:07 ` [PATCH v3 1/3] dt-bindings: iio: proximity: add Sharp GP2AP070S proximity sensor Kaustabh Chakraborty
@ 2026-07-30 20:12   ` sashiko-bot
  0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-07-30 20:12 UTC (permalink / raw)
  To: Kaustabh Chakraborty; +Cc: devicetree, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The `vled-supply` property is missing from the `required` list, despite the hardware requiring it for core functionality.
--

--- Patch [1]: [PATCH v3 1/3] dt-bindings: iio: proximity: add Sharp GP2AP070S proximity sensor ---
commit a5f76b868834c635a43cd3859fdfeb8667e96336
Author: Kaustabh Chakraborty <kauschluss@disroot.org>

dt-bindings: iio: proximity: add Sharp GP2AP070S proximity sensor

This commit introduces the device tree binding for the Sharp GP2AP070S
proximity sensor. The sensor expects two voltage supplies, one for the
core and one for the infrared LED.

> diff --git a/Documentation/devicetree/bindings/iio/proximity/sharp,gp2ap070s.yaml b/Documentation/devicetree/bindings/iio/proximity/sharp,gp2ap070s.yaml
> new file mode 100644
> index 0000000000000..73f0abc1f09cb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/proximity/sharp,gp2ap070s.yaml

[ ... ]

> +  vdd-supply:
> +    description: Voltage supply for the internal circuitry
> +
> +  vled-supply:
> +    description: Voltage supply for the IR LED
> +
> +  proximity-near-level: true
> +
> +required:
> +  - compatible
> +  - reg
> +  - interrupts
> +  - vdd-supply

[Severity: Medium]
Since the commit message indicates the hardware expects two voltage supplies,
should vled-supply also be included in this required list?

Without it, device trees missing the vled-supply property will silently pass
schema validation, which could lead to incomplete configurations.

> +
> +additionalProperties: false

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260731-gp2ap070s-v3-0-d1f5cecf9fe7@disroot.org?part=1

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

* Re: [PATCH v3 2/3] iio: proximity: add driver for Sharp GP2AP070S proximity sensor
  2026-07-30 20:07 ` [PATCH v3 2/3] iio: proximity: add driver for " Kaustabh Chakraborty
@ 2026-07-30 20:18   ` sashiko-bot
  0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-07-30 20:18 UTC (permalink / raw)
  To: Kaustabh Chakraborty; +Cc: devicetree, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
- [Medium] Double execution of hardware reset on probe error paths.
- [Medium] Meaningless regcache operations due to missing .cache_type, and incorrect volatile register definition.
- [Medium] Silent probe failure on IRQ request error.
- [Medium] write_event_value callback incorrectly returns IIO_VAL_INT on success.
- [Medium] Unconditional enablement of hardware events at probe.
- [Medium] Missing PM suspend/resume operations leaves the sensor active during system sleep.
--

--- Patch [2]: [PATCH v3 2/3] iio: proximity: add driver for Sharp GP2AP070S proximity sensor ---
commit 804bae46d93961c6260dcd9dc62d6687c6acc1bf
Author: Kaustabh Chakraborty <kauschluss@disroot.org>

    iio: proximity: add driver for Sharp GP2AP070S proximity sensor

This commit introduces a new IIO proximity driver for the Sharp GP2AP070S sensor.
It sets up regmap-based I2C communication and configures IIO events and channels
for reading proximity data.

Link: https://github.com/Exynos7870/android_kernel_samsung_universal7870/blob/lineage-16.0/drivers/sensors/gp2ap070s.c [1]

> diff --git a/drivers/iio/proximity/gp2ap070s.c b/drivers/iio/proximity/gp2ap070s.c
> new file mode 100644
> index 0000000000000..98fc12e5ccd58
> --- /dev/null
> +++ b/drivers/iio/proximity/gp2ap070s.c
[ ... ]
> +static bool gp2ap070s_regmap_volatile(struct device *dev, unsigned int reg)
> +{
> +	return reg == GP2AP070S_REG_D0_LE16;
> +}
> +
> +static const struct regmap_config gp2ap070s_regmap_config = {
> +	.reg_bits = 8,
> +	.val_bits = 8,
> +	.volatile_reg = gp2ap070s_regmap_volatile,
> +};

[Severity: Medium]
Does this regmap configuration intend to use caching? 

The driver calls regcache_mark_dirty() during gp2ap070s_reset(), but
gp2ap070s_regmap_config lacks a .cache_type assignment, so the regmap core
will bypass caching entirely. 

If caching is enabled in the future, will the current volatile_reg definition
cause data corruption? gp2ap070s_regmap_volatile() only marks 0x90 as volatile,
but a 16-bit value is read spanning 0x90 and 0x91. The upper byte (0x91) would
incorrectly be served from the cache, corrupting the proximity reading.

[ ... ]
> +static int gp2ap070s_iio_write_event_value(struct iio_dev *indio_dev,
> +					   const struct iio_chan_spec *chan,
> +					   enum iio_event_type type,
> +					   enum iio_event_direction dir,
> +					   enum iio_event_info info, int val,
> +					   int val2)
> +{
> +	struct gp2ap070s_drvdata *drvdata = iio_priv(indio_dev);
> +	__le16 value;
> +	u16 threshold_other;
> +	int ret;
[ ... ]
> +	switch (dir) {
> +	case IIO_EV_DIR_RISING:
[ ... ]
> +		value = cpu_to_le16((u16)val);
> +		ret = regmap_bulk_write(drvdata->regmap,
> +					GP2AP070S_REG_PS_THD_HI_LE16, &value,
> +					sizeof(value));
> +		if (ret)
> +			return ret;
> +
> +		return IIO_VAL_INT;

[Severity: Medium]
Should this return 0 instead of IIO_VAL_INT?

The IIO ABI requires write_event_value callbacks to return 0 on success.
IIO_VAL_INT is only meant for read_event_value to describe the returned data
type. Returning it here may break IIO consumers.

> +	case IIO_EV_DIR_FALLING:
[ ... ]
> +		value = cpu_to_le16((u16)val);
> +		ret = regmap_bulk_write(drvdata->regmap,
> +					GP2AP070S_REG_PS_THD_LO_LE16, &value,
> +					sizeof(value));
> +		if (ret)
> +			return ret;
> +
> +		return IIO_VAL_INT;

[Severity: Medium]
This also appears to incorrectly return IIO_VAL_INT instead of 0 on success.

[ ... ]
> +static int gp2ap070s_probe_hw_register(struct gp2ap070s_drvdata *drvdata)
> +{
> +	struct device *dev = regmap_get_device(drvdata->regmap);
> +	int ret;
> +
> +	ret = gp2ap070s_reset(drvdata);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "Failed to reset sensor\n");
> +
> +	ret = regmap_write(drvdata->regmap, GP2AP070S_REG_COM2, 0);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "Failed to enable interrupts\n");
> +
> +	ret = regmap_set_bits(drvdata->regmap, GP2AP070S_REG_COM3,
> +			      GP2AP070S_COM3_INT_PULSE);
> +	if (ret)
> +		return dev_err_probe(dev, ret, "Failed to unmask interrupts\n");

[Severity: Medium]
Does this unconditionally enable hardware interrupts at probe?

The IIO ABI specifies that events should be disabled by default and only
enabled when requested via sysfs by userspace. Enabling them unconditionally at
probe might cause unexpected system wakeups or interrupt load.

[ ... ]
> +static int gp2ap070s_probe(struct i2c_client *client)
> +{
[ ... ]
> +	ret = gp2ap070s_probe_hw_register(drvdata);
> +	if (ret)
> +		goto hw_reset;
> +
> +	ret = devm_add_action_or_reset(dev, gp2ap070s_reset_action, drvdata);
> +	if (ret) {
> +		ret = dev_err_probe(dev, ret, "Failed to schedule reset on driver removal\n");
> +		goto hw_reset;
> +	}
> +
> +	ret = devm_request_threaded_irq(dev, client->irq, NULL,
> +					gp2ap070s_irq_handler, IRQF_ONESHOT,
> +					"gp2ap070s-irq", indio_dev);
> +	if (ret)
> +		goto hw_reset;

[Severity: Medium]
Is it intentional that devm_request_threaded_irq() failure is silent?

If the requested interrupt is missing in the Device Tree or fails to be
requested, the driver fails to load without leaving any diagnostic messages in
the kernel log. This should likely use dev_err_probe().

> +
> +	ret = devm_iio_device_register(dev, indio_dev);
> +	if (ret)
> +		goto hw_reset;
> +
> +	return 0;
> +
> +hw_reset:
> +	gp2ap070s_reset(drvdata);

[Severity: Medium]
Will this cause a double execution of the hardware reset on probe error paths?

If devm_add_action_or_reset() succeeds, but a subsequent step like
devm_request_threaded_irq() fails, the code manually jumps to hw_reset and
calls gp2ap070s_reset(). 

When the probe function then returns the error code, the devres framework will
unwind and automatically invoke gp2ap070s_reset_action(), which calls
gp2ap070s_reset() a second time.

> +
> +	return ret;
> +}
[ ... ]
> +static struct i2c_driver gp2ap070s_i2c_driver = {
> +	.driver = {
> +		.name = "gp2ap070s",
> +		.of_match_table = gp2ap070s_of_device_id,
> +	},
> +	.probe = gp2ap070s_probe,
> +	.id_table = gp2ap070s_i2c_device_id,
> +};
> +module_i2c_driver(gp2ap070s_i2c_driver);

[Severity: Medium]
Is this driver missing power management suspend and resume operations?

Without a .pm structure to handle suspend/resume, the kernel cannot disable
the sensor or its regulators when the system enters suspend, which could
lead to power drain or spurious interrupts during system sleep.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260731-gp2ap070s-v3-0-d1f5cecf9fe7@disroot.org?part=2

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

* Re: [PATCH v3 3/3] arm64: dts: exynos7870-j6lte: add Sharp GP2AP070S proximity sensor
  2026-07-30 20:07 ` [PATCH v3 3/3] arm64: dts: exynos7870-j6lte: add " Kaustabh Chakraborty
@ 2026-07-30 20:19   ` sashiko-bot
  0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-07-30 20:19 UTC (permalink / raw)
  To: Kaustabh Chakraborty; +Cc: devicetree, robh, conor+dt

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The `i2c_proxm_bus` pinctrl node assigns a hardware alternate pin function (`EXYNOS_PIN_FUNC_3`) to pins that are driven by a software bit-banged `i2c-gpio` device.
--

--- Patch [3]: [PATCH v3 3/3] arm64: dts: exynos7870-j6lte: add Sharp GP2AP070S proximity sensor ---
commit 2279f9b3f632fe5641c2ffa9eb9b410688448a06
Author: Kaustabh Chakraborty <kauschluss@disroot.org>

arm64: dts: exynos7870-j6lte: add Sharp GP2AP070S proximity sensor

This commit adds the devicetree node for the Sharp GP2AP070S proximity sensor
which is connected to a GPIO-driven I2C line, alongside a new fixed regulator
for its VDD supply.

> diff --git a/arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts b/arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts
> index de30d0970336f..dd493138fed6e 100644
> --- a/arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts
> +++ b/arch/arm64/boot/dts/exynos/exynos7870-j6lte.dts
> @@ -73,6 +73,35 @@ key-volup {
>  		};
>  	};
>  
> +	i2c-proximity {
> +		compatible = "i2c-gpio";
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&i2c_proxm_bus>;
> +
> +		sda-gpios = <&gpf4 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
> +		scl-gpios = <&gpf4 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;

[ ... ]

> @@ -579,6 +624,12 @@ bt_enable: bt-enable-pins {
>  		samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
>  	};
>  

[Severity: Medium]
Is it intentional to configure a hardware alternate function for a bus that
is driven by a software i2c-gpio device?

The i2c-proximity node uses the i2c-gpio driver for software bit-banging, but
the i2c_proxm_bus pinctrl configuration below assigns EXYNOS_PIN_FUNC_3 instead
of a standard GPIO function.

This configuration can cause the pinctrl framework to briefly connect the pins
to a hardware IP block before the GPIO framework requests them and forces them
back to software mode. If the underlying hardware IP is active during this
initialization window, it could drive the lines and lead to transient bus
contention or glitches on the sensor during system probe.

> +	i2c_proxm_bus: i2c-proxm-bus-pins {
> +		samsung,pins = "gpf4-3", "gpf4-2";
> +		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
> +		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
> +	};
> +

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260731-gp2ap070s-v3-0-d1f5cecf9fe7@disroot.org?part=3

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

end of thread, other threads:[~2026-07-30 20:19 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-30 20:06 [PATCH v3 0/3] Add Sharp GP2AP070S Proximity Driver and enable it in Galaxy J6 (j6lte) Kaustabh Chakraborty
2026-07-30 20:07 ` [PATCH v3 1/3] dt-bindings: iio: proximity: add Sharp GP2AP070S proximity sensor Kaustabh Chakraborty
2026-07-30 20:12   ` sashiko-bot
2026-07-30 20:07 ` [PATCH v3 2/3] iio: proximity: add driver for " Kaustabh Chakraborty
2026-07-30 20:18   ` sashiko-bot
2026-07-30 20:07 ` [PATCH v3 3/3] arm64: dts: exynos7870-j6lte: add " Kaustabh Chakraborty
2026-07-30 20:19   ` sashiko-bot

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.