From nobody Fri Jul 24 04:50:44 2026 Received: from layka.disroot.org (layka.disroot.org [178.21.23.139]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C37713DBD5E; Thu, 23 Jul 2026 17:29:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.21.23.139 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784827743; cv=none; b=rIPfWLgBPvBe5AVojEXy5J2lj4vQGLuMQ3rxJWR3Prt9An+Gfb+gz/U2+zWH6azrcPHTs5tjabIB/HMN/myDP77L0NPqksj9iaoclybVSak3h1VXoL9n3ee2H1ohAKP/BQ2a77WeDIF0sDTN4m49fx0tPR/FDrgxMbdClImgQGU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784827743; c=relaxed/simple; bh=8RNNJicbOxkofsbn69rExkYA+ETIbn8fNyoaONjKg8o=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mdvEKUFcEuJu9cvTRykf3Yq4EGJeRTYqZz3jM35LyNOcWnQgfLJcDeWCHqp3Kpu8UMKdtwq6/d/DHfsf5f2puOJ37M855rYBWLNA6xTcyccvEE+AsAq11Z7lljPQweZQA4oRZ0CBcbDui8suwlbeJjDamoavJ7XRmqL/Qu/GJ3c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org; spf=pass smtp.mailfrom=disroot.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b=hH3b9XxY; arc=none smtp.client-ip=178.21.23.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=disroot.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b="hH3b9XxY" Received: from mail01.layka.lan (localhost [127.0.0.1]) by disroot.org (Postfix) with ESMTP id B9F2A887E7; Thu, 23 Jul 2026 19:28:59 +0200 (CEST) X-Virus-Scanned: SPAM Filter at disroot.org Received: from layka.disroot.org ([127.0.0.1]) by localhost (disroot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id FFMCgq-LND6L; Thu, 23 Jul 2026 19:28:58 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=disroot.org; s=mail; t=1784827738; bh=8RNNJicbOxkofsbn69rExkYA+ETIbn8fNyoaONjKg8o=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=hH3b9XxY/0b2Zcd3ud0DtNCxIiif6sJ+eNj/Fr01R53LX+MQKIF/y0+6nscDFHgQf fij/II88++vWilc2uxgxbRHb5FbkCfXgW+4ZsjdmlllYUdK5dk3yB8y/yYBv1BXMgH PgpeqHNruISJY9neyG+lPjEzIJIl1Wa7Sw5g++axg7FAN5jKhSGCHjvsXq+c+vrBlm rBdjhI8+IeTPhK6IqZjLFp5iqw9QkPZqGofloLrCgljcLuer4LaeL5i9A1UHwV9Jiz q2DR9swV0dIVGjyIb4GtS9VuW4cmlSrDywlYgykjl70GBR89KYomebyqB5NqeLsdxa bQ9mzbn0FDdHg== From: Kaustabh Chakraborty Date: Thu, 23 Jul 2026 22:58:33 +0530 Subject: [PATCH 1/3] dt-bindings: iio: proximity: add Sharp GP2AP070S proximity sensor Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260723-gp2ap070s-v1-1-b8ca3a4c10dd@disroot.org> References: <20260723-gp2ap070s-v1-0-b8ca3a4c10dd@disroot.org> In-Reply-To: <20260723-gp2ap070s-v1-0-b8ca3a4c10dd@disroot.org> To: Jonathan Cameron , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Peter Griffin , Alim Akhtar Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, Kaustabh Chakraborty 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 --- .../bindings/iio/proximity/sharp,gp2ap070s.yaml | 59 ++++++++++++++++++= ++++ 1 file changed, 59 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/proximity/sharp,gp2ap070= s.yaml b/Documentation/devicetree/bindings/iio/proximity/sharp,gp2ap070s.ya= ml new file mode 100644 index 000000000000..bcae68303b3f --- /dev/null +++ b/Documentation/devicetree/bindings/iio/proximity/sharp,gp2ap070s.yaml @@ -0,0 +1,59 @@ +# 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 + +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 + +additionalProperties: false + +examples: + - | + #include + + i2c { + #address-cells =3D <1>; + #size-cells =3D <0>; + + proximity@39 { + compatible =3D "sharp,gp2ap070s"; + reg =3D <0x39>; + interrupt-parent =3D <&gpio>; + interrupts =3D <1 IRQ_TYPE_EDGE_BOTH>; + vdd-supply =3D <&vdd_supply>; + vled-supply =3D <&vled_supply>; + proximity-near-level =3D <500>; + }; + }; + +... --=20 2.54.0 From nobody Fri Jul 24 04:50:44 2026 Received: from layka.disroot.org (layka.disroot.org [178.21.23.139]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 341BC13A3F7; Thu, 23 Jul 2026 17:29:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.21.23.139 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784827757; cv=none; b=t7ehRjR4mMnbl8CwcY+i3kji6t5hhymetG+H1j48IyYJjZwtFOirCxYIFdZuQyUrB58Bwr7fKyP5LIFyDHxTMU5EWBSZnPVKDNoyuGlBC1gMtetLZhVUL0AhOw/2ZaCtIRPrFC4Tia/BCoA/+H3/Y6lwsvdNUGE6LA3lQddVK38= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784827757; c=relaxed/simple; bh=7L2ejw0xtm7swpPJZwVGSBP6gmcPcH2N4Pa44Th2vWI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=j4VxV8P3YtAQYr5rM1EcZnXaVAyB0Nza9uFVsevdBcQDsfAt2zVmH3Fjq8eLIf2Yz3kJIDqah4KMYhopLnt3bNldysvwYdCC61s9uPpFKFRrFZyPLhOiNROkedOoDhr05FKkpmaeAYRK49Et8usSeoagpZnwkX75Y9jr3QIvPEQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org; spf=pass smtp.mailfrom=disroot.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b=c2h1sgBN; arc=none smtp.client-ip=178.21.23.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=disroot.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b="c2h1sgBN" Received: from mail01.layka.lan (localhost [127.0.0.1]) by disroot.org (Postfix) with ESMTP id 0E0E98432D; Thu, 23 Jul 2026 19:29:13 +0200 (CEST) X-Virus-Scanned: SPAM Filter at disroot.org Received: from layka.disroot.org ([127.0.0.1]) by localhost (disroot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id NwwVsvL6UqDq; Thu, 23 Jul 2026 19:29:11 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=disroot.org; s=mail; t=1784827751; bh=7L2ejw0xtm7swpPJZwVGSBP6gmcPcH2N4Pa44Th2vWI=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=c2h1sgBN/dpngWCZ8quI/ey/QYL2g/lnn0F2ezS5qWmeOJq06HlCnVXfl40IG5nXz 1bfjq6eFhwlWRud5D1+YEHHSM2uozA7qHoMY8UN+FJG9djLB8XGxFPUL0SP9Es29ri RXjZREYqtBOTJY4W9omHBqfnect/+lmDmSGLq336kG0sciikN06fggx/Iihve60+Ho G3PWHGVcAtdR3hxvMvom8M8PvpkwQ2WdFwI1rxRtspJpNusaFJWy4WP0X0rKqLyeoh Kk2WUFnsehsrp/hGpIoz8a4CvVeF1wuw3nP7mOT3zVe17dii8AKSpLtCLs7FpJHmU1 Iy50JrazKXd2A== From: Kaustabh Chakraborty Date: Thu, 23 Jul 2026 22:58:34 +0530 Subject: [PATCH 2/3] iio: proximity: add driver for Sharp GP2AP070S proximity sensor Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260723-gp2ap070s-v1-2-b8ca3a4c10dd@disroot.org> References: <20260723-gp2ap070s-v1-0-b8ca3a4c10dd@disroot.org> In-Reply-To: <20260723-gp2ap070s-v1-0-b8ca3a4c10dd@disroot.org> To: Jonathan Cameron , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Peter Griffin , Alim Akhtar Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, Kaustabh Chakraborty 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/bl= ob/lineage-16.0/drivers/sensors/gp2ap070s.c [1] Signed-off-by: Kaustabh Chakraborty --- drivers/iio/proximity/Kconfig | 11 + drivers/iio/proximity/Makefile | 1 + drivers/iio/proximity/gp2ap070s.c | 502 ++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 514 insertions(+) diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig index bb77fad2a1b3..3f30ebfc21bc 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. =20 +config GP2AP070S + tristate "Sharp GP2AP070S proximity sensor" + select REGMAP_I2C + depends on 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) +=3D as3935.o obj-$(CONFIG_CROS_EC_MKBP_PROXIMITY) +=3D cros_ec_mkbp_proximity.o obj-$(CONFIG_D3323AA) +=3D d3323aa.o +obj-$(CONFIG_GP2AP070S) +=3D gp2ap070s.o obj-$(CONFIG_HX9023S) +=3D hx9023s.o obj-$(CONFIG_IRSD200) +=3D irsd200.o obj-$(CONFIG_ISL29501) +=3D isl29501.o diff --git a/drivers/iio/proximity/gp2ap070s.c b/drivers/iio/proximity/gp2a= p070s.c new file mode 100644 index 000000000000..9625f53d956e --- /dev/null +++ b/drivers/iio/proximity/gp2ap070s.c @@ -0,0 +1,502 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * IIO driver for Sharp GP2AP070S proximity sensor. + * + * Copyright (C) 2026 Kaustabh Chakraborty + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GP2AP070S_REG_COM1 0x80 +#define GP2AP070S_REG_COM2 0x81 +#define GP2AP070S_REG_COM3 0x82 +#define GP2AP070S_REG_COM4 0x83 +#define GP2AP070S_REG_PS1 0x85 +#define GP2AP070S_REG_PS2 0x86 +#define GP2AP070S_REG_PS3 0x87 +#define GP2AP070S_REG_PS_THD_LO_LE16 0x88 +#define GP2AP070S_REG_PS_THD_HI_LE16 0x8a +#define GP2AP070S_REG_OS_D0_LE16 0x8c +#define GP2AP070S_REG_D0_LE16 0x90 + +/* GP2AP070S_REG_COM1 */ +#define GP2AP070S_VAL_COM1_WKUP BIT(7) +#define GP2AP070S_VAL_COM1_EN BIT(5) + +/* GP2AP070S_REG_COM3 */ +#define GP2AP070S_VAL_COM3_INT_PULSE BIT(1) + +/* GP2AP070S_REG_COM4 */ +#define GP2AP070S_VAL_COM1_BLINK GENMASK(2, 0) /* LED Blink Interval */ + +#define GP2AP070S_VAL_COM1_BLINK_0ms 0 +#define GP2AP070S_VAL_COM1_BLINK_2ms 1 +#define GP2AP070S_VAL_COM1_BLINK_8ms 2 +#define GP2AP070S_VAL_COM1_BLINK_33ms 3 +#define GP2AP070S_VAL_COM1_BLINK_66ms 4 +#define GP2AP070S_VAL_COM1_BLINK_131ms 5 +#define GP2AP070S_VAL_COM1_BLINK_262ms 6 +#define GP2AP070S_VAL_COM1_BLINK_524ms 7 + +/* GP2AP070S_REG_PS1 */ +#define GP2AP070S_VAL_PS1_RESOL GENMASK(5, 4) /* Resolution */ + +#define GP2AP070S_VAL_PS1_RESOL_14ms 0 +#define GP2AP070S_VAL_PS1_RESOL_12ms 1 +#define GP2AP070S_VAL_PS1_RESOL_10ms 2 +#define GP2AP070S_VAL_PS1_RESOL_8ms 3 + +/* GP2AP070S_REG_PS2 */ +#define GP2AP070S_VAL_PS2_IOUT GENMASK(6, 4) /* Current Output */ +#define GP2AP070S_VAL_PS2_SUM32 BIT(2) + +#define GP2AP070S_VAL_PS2_IOUT_0mA 0 +#define GP2AP070S_VAL_PS2_IOUT_24mA 1 +#define GP2AP070S_VAL_PS2_IOUT_89mA 2 +#define GP2AP070S_VAL_PS2_IOUT_130mA 3 +#define GP2AP070S_VAL_PS2_IOUT_190mA 4 + +/* GP2AP070S_REG_PS3 */ +#define GP2AP070S_VAL_PS3_PRST GENMASK(6, 4) /* Repeating Measurements */ + +struct gp2ap070s_drvdata { + struct device *dev; + struct regmap *regmap; + struct regulator_bulk_data *regulators; + u32 near_level; +}; + +static const struct regmap_config gp2ap070s_regmap_config =3D { + .reg_bits =3D 8, + .val_bits =3D 8, +}; + +static const char *const gp2ap070s_regulator_names[] =3D { + "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 =3D iio_priv(indio_dev); + + return sprintf(buf, "%u\n", drvdata->near_level); +} + +static const struct iio_chan_spec_ext_info gp2ap070s_iio_chan_spec_ext_inf= o[] =3D { + { + .name =3D "nearlevel", + .shared =3D IIO_SEPARATE, + .read =3D gp2ap070s_iio_read_near_level, + }, + { /* sentinel */ } +}; + +static const struct iio_event_spec gp2ap070s_iio_event_spec[] =3D { + { + .type =3D IIO_EV_TYPE_THRESH, + .dir =3D IIO_EV_DIR_RISING, + .mask_separate =3D BIT(IIO_EV_INFO_VALUE), + }, + { + .type =3D IIO_EV_TYPE_THRESH, + .dir =3D IIO_EV_DIR_FALLING, + .mask_separate =3D BIT(IIO_EV_INFO_VALUE), + }, + { + .type =3D IIO_EV_TYPE_THRESH, + .dir =3D IIO_EV_DIR_EITHER, + .mask_separate =3D BIT(IIO_EV_INFO_ENABLE), + }, +}; + +static const struct iio_chan_spec gp2ap070s_iio_chan_spec[] =3D { + { + .type =3D IIO_PROXIMITY, + .info_mask_separate =3D BIT(IIO_CHAN_INFO_RAW), + .ext_info =3D gp2ap070s_iio_chan_spec_ext_info, + .event_spec =3D gp2ap070s_iio_event_spec, + .num_event_specs =3D 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 =3D iio_priv(indio_dev); + __le16 value; + int ret; + + ret =3D regmap_raw_read(drvdata->regmap, GP2AP070S_REG_D0_LE16, &value, + sizeof(value)); + if (ret) + return ret; + + *val =3D 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 =3D iio_priv(indio_dev); + __le16 value; + int ret; + + if (type !=3D IIO_EV_TYPE_THRESH || info !=3D IIO_EV_INFO_VALUE) + return -EINVAL; + + switch (dir) { + case IIO_EV_DIR_RISING: + ret =3D regmap_raw_read(drvdata->regmap, + GP2AP070S_REG_PS_THD_HI_LE16, &value, + sizeof(value)); + if (ret) + return ret; + + *val =3D le16_to_cpu(value); + return IIO_VAL_INT; + case IIO_EV_DIR_FALLING: + ret =3D regmap_raw_read(drvdata->regmap, + GP2AP070S_REG_PS_THD_LO_LE16, &value, + sizeof(value)); + if (ret) + return ret; + + *val =3D 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 =3D iio_priv(indio_dev); + __le16 value; + u16 threshold_other; + int ret; + + if (type !=3D IIO_EV_TYPE_THRESH || info !=3D IIO_EV_INFO_VALUE) + return -EINVAL; + + switch (dir) { + case IIO_EV_DIR_RISING: + ret =3D regmap_raw_read(drvdata->regmap, + GP2AP070S_REG_PS_THD_LO_LE16, &value, + sizeof(value)); + if (ret) + return ret; + + /* Ensure lo_threshold < hi_threshold */ + threshold_other =3D le16_to_cpu(value); + if (threshold_other >=3D val) + return -EINVAL; + + value =3D cpu_to_le16((u16)val); + ret =3D regmap_raw_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 =3D regmap_raw_read(drvdata->regmap, + GP2AP070S_REG_PS_THD_HI_LE16, &value, + sizeof(value)); + if (ret) + return ret; + + /* Ensure hi_threshold > lo_threshold */ + threshold_other =3D le16_to_cpu(value); + if (threshold_other <=3D val) + return -EINVAL; + + value =3D cpu_to_le16((u16)val); + ret =3D regmap_raw_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 =3D iio_priv(indio_dev); + unsigned int value; + int ret; + + if (type !=3D IIO_EV_TYPE_THRESH) + return -EINVAL; + + switch (dir) { + case IIO_EV_DIR_EITHER: + ret =3D regmap_read(drvdata->regmap, GP2AP070S_REG_COM3, &value); + if (ret) + return ret; + + return !!(value & GP2AP070S_VAL_COM3_INT_PULSE); + default: + return -EINVAL; + } + + return 0; +} + +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 =3D iio_priv(indio_dev); + int ret; + + if (type !=3D IIO_EV_TYPE_THRESH) + return -EINVAL; + + switch (dir) { + case IIO_EV_DIR_EITHER: + if (state) + ret =3D regmap_set_bits(drvdata->regmap, + GP2AP070S_REG_COM3, + GP2AP070S_VAL_COM3_INT_PULSE); + else + ret =3D regmap_clear_bits(drvdata->regmap, + GP2AP070S_REG_COM3, + GP2AP070S_VAL_COM3_INT_PULSE); + if (ret) + return ret; + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct iio_info gp2ap070s_iio_info =3D { + .read_raw =3D gp2ap070s_iio_read_raw, + .read_event_value =3D gp2ap070s_iio_read_event_value, + .write_event_value =3D gp2ap070s_iio_write_event_value, + .read_event_config =3D gp2ap070s_read_event_config, + .write_event_config =3D gp2ap070s_write_event_config, +}; + +static irqreturn_t gp2ap070s_irq_handler(int irq, void *private) +{ + struct iio_dev *indio_dev =3D private; + struct gp2ap070s_drvdata *drvdata =3D iio_priv(indio_dev); + struct device *dev =3D drvdata->dev; + u16 threshold_lo, threshold_hi, distance; + __le16 value; + int ret; + + ret =3D regmap_raw_read(drvdata->regmap, GP2AP070S_REG_PS_THD_LO_LE16, + &value, sizeof(value)); + if (ret) { + dev_err(dev, "Failed to read low threshold value (%d)\n", ret); + return IRQ_HANDLED; + } + + threshold_lo =3D __le16_to_cpu(value); + + ret =3D regmap_raw_read(drvdata->regmap, GP2AP070S_REG_PS_THD_HI_LE16, + &value, sizeof(value)); + if (ret) { + dev_err(dev, "Failed to read high threshold value (%d)\n", ret); + return IRQ_HANDLED; + } + + threshold_hi =3D __le16_to_cpu(value); + + ret =3D regmap_raw_read(drvdata->regmap, GP2AP070S_REG_D0_LE16, &value, + sizeof(value)); + if (ret) { + dev_err(dev, "Failed to read proximity distance (%d)\n", ret); + return IRQ_HANDLED; + } + + distance =3D __le16_to_cpu(value); + + if (distance >=3D threshold_hi) { + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_RISING), + iio_get_time_ns(indio_dev)); + } else if (distance <=3D threshold_lo) { + iio_push_event(indio_dev, + IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0, + IIO_EV_TYPE_THRESH, + IIO_EV_DIR_FALLING), + iio_get_time_ns(indio_dev)); + } else { + /* + * If none match, then it's stuck in the threshold band gap. + * The hardware generally does not issue interrupts here. + */ + WARN_ONCE(true, "spurious interrupt issued in proximity threshold gap\n"= ); + } + + return IRQ_HANDLED; +} + +static int gp2ap070s_probe_hw_register(struct gp2ap070s_drvdata *drvdata) +{ + struct device *dev =3D drvdata->dev; + int ret; + + ret =3D regmap_clear_bits(drvdata->regmap, GP2AP070S_REG_COM1, ~0); + if (ret) + return dev_err_probe(drvdata->dev, ret, "Failed to reset sensor\n"); + + ret =3D regmap_clear_bits(drvdata->regmap, GP2AP070S_REG_COM2, ~0); + if (ret) + return dev_err_probe(drvdata->dev, ret, "Failed to unmask interrupts\n"); + + ret =3D regmap_set_bits(drvdata->regmap, GP2AP070S_REG_COM3, + GP2AP070S_VAL_COM3_INT_PULSE); + if (ret) + return dev_err_probe(drvdata->dev, ret, "Failed to enable interrupt\n"); + + ret =3D regmap_write_bits(drvdata->regmap, GP2AP070S_REG_COM4, + GP2AP070S_VAL_COM1_BLINK, + FIELD_PREP_CONST(GP2AP070S_VAL_COM1_BLINK, + GP2AP070S_VAL_COM1_BLINK_33ms)); + if (ret) + return dev_err_probe(drvdata->dev, ret, "Failed to set LED blink timing\= n"); + + ret =3D regmap_write_bits(drvdata->regmap, GP2AP070S_REG_PS1, + GP2AP070S_VAL_PS1_RESOL, + FIELD_PREP_CONST(GP2AP070S_VAL_PS1_RESOL, + GP2AP070S_VAL_PS1_RESOL_10ms)); + if (ret) + return dev_err_probe(drvdata->dev, ret, "Failed to set resolution\n"); + + ret =3D regmap_write_bits(drvdata->regmap, GP2AP070S_REG_PS2, + GP2AP070S_VAL_PS2_IOUT | GP2AP070S_VAL_PS2_SUM32, + FIELD_PREP_CONST(GP2AP070S_VAL_PS2_IOUT, + GP2AP070S_VAL_PS2_IOUT_89mA) | + GP2AP070S_VAL_PS2_SUM32); + if (ret) + return dev_err_probe(drvdata->dev, ret, "Failed to set current output\n"= ); + + ret =3D regmap_write_bits(drvdata->regmap, GP2AP070S_REG_PS3, + GP2AP070S_VAL_PS3_PRST, + FIELD_PREP_CONST(GP2AP070S_VAL_PS3_PRST, 3)); + if (ret) + return dev_err_probe(drvdata->dev, ret, "Failed to set measurement repet= itions\n"); + + ret =3D regmap_set_bits(drvdata->regmap, GP2AP070S_REG_COM1, + GP2AP070S_VAL_COM1_WKUP | GP2AP070S_VAL_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 =3D &client->dev; + struct iio_dev *indio_dev; + struct gp2ap070s_drvdata *drvdata; + int ret; + + indio_dev =3D devm_iio_device_alloc(dev, sizeof(*drvdata)); + if (!indio_dev) + return -ENOMEM; + + drvdata =3D iio_priv(indio_dev); + i2c_set_clientdata(client, drvdata); + + drvdata->dev =3D dev; + drvdata->regmap =3D 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 re= gmap\n"); + + ret =3D 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"); + + usleep_range(10000, 11000); + + indio_dev->name =3D "gp2ap070s"; + indio_dev->modes =3D INDIO_DIRECT_MODE; + indio_dev->channels =3D gp2ap070s_iio_chan_spec; + indio_dev->num_channels =3D ARRAY_SIZE(gp2ap070s_iio_chan_spec); + indio_dev->info =3D &gp2ap070s_iio_info; + + device_property_read_u32(&client->dev, "proximity-near-level", + &drvdata->near_level); + + ret =3D gp2ap070s_probe_hw_register(drvdata); + if (ret) + return ret; + + ret =3D devm_request_threaded_irq(dev, client->irq, NULL, + gp2ap070s_irq_handler, IRQF_ONESHOT, + "gp2ap070s-irq", indio_dev); + if (ret) + return dev_err_probe(dev, ret, "Failed to request IRQ"); + + return devm_iio_device_register(&client->dev, indio_dev); +} + +static const struct of_device_id gp2ap070s_of_device_id[] =3D { + { .compatible =3D "sharp,gp2ap070s" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, gp2ap070s_of_device_id); + +static const struct i2c_device_id gp2ap070s_i2c_device_id[] =3D { + { .name =3D "gp2ap070s" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(i2c, gp2ap070s_i2c_device_id); + +static struct i2c_driver gp2ap070s_i2c_driver =3D { + .driver =3D { + .name =3D "gp2ap070s", + .of_match_table =3D gp2ap070s_of_device_id, + }, + .probe =3D gp2ap070s_probe, + .id_table =3D gp2ap070s_i2c_device_id, +}; +module_i2c_driver(gp2ap070s_i2c_driver); + +MODULE_AUTHOR("Kaustabh Chakraborty "); +MODULE_DESCRIPTION("Sharp GP2AP070S Proximity Sensor"); +MODULE_LICENSE("GPL"); --=20 2.54.0 From nobody Fri Jul 24 04:50:45 2026 Received: from layka.disroot.org (layka.disroot.org [178.21.23.139]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C721C26980F; Thu, 23 Jul 2026 17:29:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.21.23.139 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784827766; cv=none; b=i8UOgxANqLcjNNgkH9Cr+ykQsRA3l8sfBIBLoDvf0EBtZ3tyDY1ZUF6GXeT13Q3ymH0W9IK1bhJ04ezcT5b+TQb1QDi7Bf6qaEVtPAODLwg/V0ctVYSpN6qTCEc1P5xqadvUVxo3Z0PcshTD4uNaVNdAaqocTZLcArQ7pNsOzVo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784827766; c=relaxed/simple; bh=HOw79g3ooG6NNzkyYSEvjfgfmCBbxswKnKtrHqLTX78=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mLath7Z+JgcunT/62F8TpEMxh4Tdcd0+wImaq9FtMU4PzSWqmRE9UDcmBXMy9o054t2ZXaRclgt4zC2S5tvTE3Ce25HzkTkpWHdg9d/N1fIiEcjoCQVNGtNhr9nxflsJtW7WtN2D4lxSgJjfiSNiwCvHz70GgcsP9bHFz3Gwnyw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org; spf=pass smtp.mailfrom=disroot.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b=RzUHcxyc; arc=none smtp.client-ip=178.21.23.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=disroot.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b="RzUHcxyc" Received: from mail01.layka.lan (localhost [127.0.0.1]) by disroot.org (Postfix) with ESMTP id 160328422B; Thu, 23 Jul 2026 19:29:23 +0200 (CEST) X-Virus-Scanned: SPAM Filter at disroot.org Received: from layka.disroot.org ([127.0.0.1]) by localhost (disroot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 5lBOqesrNlnk; Thu, 23 Jul 2026 19:29:22 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=disroot.org; s=mail; t=1784827762; bh=HOw79g3ooG6NNzkyYSEvjfgfmCBbxswKnKtrHqLTX78=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=RzUHcxycuXEGLDrrMTO9V+C3e4p7X+LYEB8EK/mhCTLlatUrmU44MOHSI4vyKn19F cg6+WqFxEx/ozRh2D4ZhCagxx3TWNeXpe8KzWAjGpbdUQjZKnVXZxdljUDZHuij2hI zvINWxQtImmzJ6cEfb+TNop7bvdVPmez88hnQkOE7rVY6cM86ppwmCkYIrnIfVJ5hF CT9fDsYqGa3Mx2NCDAozq8eyLl1S30oL4t+akMuFCv9L0GMEMN7WLNmh06sd9zGdCa UXurRgiJ9mUzmMtkBxMqWKb0jOv6x0l6uJ4iq5iQBQb7FAYGVvuhG/zhTeEceupw42 cl0Yd/Y32+tUQ== From: Kaustabh Chakraborty Date: Thu, 23 Jul 2026 22:58:35 +0530 Subject: [PATCH 3/3] arm64: dts: exynos7870-j6lte: add Sharp GP2AP070S proximity sensor Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260723-gp2ap070s-v1-3-b8ca3a4c10dd@disroot.org> References: <20260723-gp2ap070s-v1-0-b8ca3a4c10dd@disroot.org> In-Reply-To: <20260723-gp2ap070s-v1-0-b8ca3a4c10dd@disroot.org> To: Jonathan Cameron , David Lechner , =?utf-8?q?Nuno_S=C3=A1?= , Andy Shevchenko , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Peter Griffin , Alim Akhtar Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, Kaustabh Chakraborty 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 --- 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/b= oot/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 { }; }; =20 + i2c-proximity { + compatible =3D "i2c-gpio"; + #address-cells =3D <1>; + #size-cells =3D <0>; + + pinctrl-names =3D "default"; + pinctrl-0 =3D <&i2c_proxm_bus>; + + sda-gpios =3D <&gpf4 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + scl-gpios =3D <&gpf4 2 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + + i2c-gpio,delay-us =3D <2>; + + proximity@39 { + compatible =3D "sharp,gp2ap070s"; + reg =3D <0x39>; + interrupt-parent =3D <&gpa0>; + interrupts =3D <5 IRQ_TYPE_EDGE_BOTH>; + + pinctrl-names =3D "default"; + pinctrl-0 =3D <&proxm_irq>; + + vdd-supply =3D <&vdd_fixed_proxm>; + vled-supply =3D <&vdd_ldo33>; + + proximity-near-level =3D <500>; + }; + }; + memory@40000000 { device_type =3D "memory"; reg =3D <0x0 0x40000000 0x3d800000>, @@ -94,6 +123,16 @@ vdd_fixed_mmc2: regulator-fixed-mmc2 { enable-active-high; }; =20 + /* proximity: vdd */ + vdd_fixed_proxm: regulator-fixed-proxm { + compatible =3D "regulator-fixed"; + regulator-name =3D "vdd_fixed_proxm"; + regulator-max-microvolt =3D <3300000>; + regulator-min-microvolt =3D <3300000>; + gpio =3D <&gpd2 3 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + reserved-memory { #address-cells =3D <2>; #size-cells =3D <1>; @@ -354,13 +393,12 @@ vdd_ldo32: ldo32 { regulator-ramp-delay =3D <12000>; }; =20 + /* proximity: vled */ vdd_ldo33: ldo33 { regulator-name =3D "vdd_ldo33"; regulator-min-microvolt =3D <3300000>; regulator-max-microvolt =3D <3300000>; regulator-ramp-delay =3D <12000>; - regulator-boot-on; - regulator-always-on; }; =20 /* touchscreen: vdd */ @@ -556,6 +594,13 @@ pmic_irq: pmic-irq-pins { samsung,pin-drv =3D ; }; =20 + proxm_irq: proxm-irq-pins { + samsung,pins =3D "gpa0-5"; + samsung,pin-function =3D ; + samsung,pin-pud =3D ; + samsung,pin-drv =3D ; + }; + touch_irq: touch-irq-pins { samsung,pins =3D "gpa0-6"; samsung,pin-function =3D ; @@ -579,6 +624,12 @@ bt_enable: bt-enable-pins { samsung,pin-pud =3D ; }; =20 + i2c_proxm_bus: i2c-proxm-bus-pins { + samsung,pins =3D "gpf4-3", "gpf4-2"; + samsung,pin-function =3D ; + samsung,pin-pud =3D ; + }; + wlan_enable: wlan-enable-pins { samsung,pins =3D "gpd3-6"; samsung,pin-function =3D ; --=20 2.54.0