From: Linus Walleij <linusw@kernel.org>
To: linux-iio@vger.kernel.org, "Jonathan Cameron" <jic23@kernel.org>,
"David Lechner" <dlechner@baylibre.com>,
"Nuno Sá" <nuno.sa@analog.com>,
"Andy Shevchenko" <andy@kernel.org>,
"Rob Herring" <robh@kernel.org>,
"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
"Conor Dooley" <conor+dt@kernel.org>,
"Kyungmin Park" <kyungmin.park@samsung.com>
Cc: devicetree@vger.kernel.org, Linus Walleij <linusw@kernel.org>
Subject: [PATCH v2 5/5] iio: light: gp2ap020a00f: Add GP2AP030A00F support
Date: Sun, 08 Nov 2026 22:44:03 +0100 [thread overview]
Message-ID: <20261108-gp2ap030-v2-5-24eaa1b9fe59@kernel.org> (raw)
In-Reply-To: <20261108-gp2ap030-v2-0-24eaa1b9fe59@kernel.org>
The GP2AP030A00F has the same register addresses and interrupt modes
as the GP2AP020A00F, but does not implement its automatic
illuminance calculation or selectable ambient-light cancellation.
Datasheet: https://jp.sharp/products/device/doc/opto/gp2ap030a00f_appl_e.pdf
Signed-off-by: Linus Walleij <linusw@kernel.org>
---
drivers/iio/light/Kconfig | 6 +--
drivers/iio/light/gp2ap020a00f.c | 100 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 101 insertions(+), 5 deletions(-)
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index 462fff1ddef2..89fe003371b8 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -259,15 +259,15 @@ config GP2AP002
module will be called gp2ap002.
config GP2AP020A00F
- tristate "Sharp GP2AP020A00F Proximity/ALS sensor"
+ tristate "Sharp GP2AP020A00F and similar Proximity/ALS sensors"
depends on I2C
select REGMAP_I2C
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select IRQ_WORK
help
- Say Y here if you have a Sharp GP2AP020A00F proximity/ALS combo-chip
- hooked to an I2C bus.
+ Say Y here to enable support for the Sharp GP2AP020A00F and similar
+ proximity/ALS combo-chips hooked to an I2C bus.
To compile this driver as a module, choose M here: the
module will be called gp2ap020a00f.
diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c
index 5464311515c7..813a64ee627c 100644
--- a/drivers/iio/light/gp2ap020a00f.c
+++ b/drivers/iio/light/gp2ap020a00f.c
@@ -54,6 +54,11 @@
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
+/*
+ * The GP2AP030A00F shares the register layout, but has no TYPE or ALC bit.
+ * Its D0 and D1 registers always contain raw clear and infrared counts.
+ */
+
/* Registers */
#define GP2AP020A00F_OP_REG 0x00 /* Basic operations */
#define GP2AP020A00F_ALS_REG 0x01 /* ALS related settings */
@@ -137,6 +142,7 @@
#define GP2AP020A00F_RES_P_6_25ms_x2 0x28
#define GP2AP020A00F_RES_P_1_56ms_x2 0x30
#define GP2AP020A00F_RES_P_0_39ms_x2 0x38
+#define GP2AP030A00F_RES_P_1_56ms_x2 0x18
#define GP2AP020A00F_RANGE_P_MASK 0x07 /* PS: Max measurable range */
#define GP2AP020A00F_RANGE_P_x1 0x00
#define GP2AP020A00F_RANGE_P_x2 0x01
@@ -158,6 +164,7 @@
#define GP2AP020A00F_IS_27_5mA 0x10
#define GP2AP020A00F_IS_55mA 0x20
#define GP2AP020A00F_IS_110mA 0x30
+#define GP2AP030A00F_IS_130mA 0x30
#define GP2AP020A00F_PIN_MASK 0x0c /* INT terminal setting */
#define GP2AP020A00F_PIN_ALS_OR_PS 0x00
#define GP2AP020A00F_PIN_ALS 0x04
@@ -239,6 +246,7 @@ struct gp2ap020a00f_chip_info {
const u8 *reg_init_tab;
const struct iio_chan_spec *channels;
unsigned int num_channels;
+ bool has_als_auto;
};
struct gp2ap020a00f_data {
@@ -276,6 +284,17 @@ static const u8 gp2ap020a00f_reg_init_tab[] = {
[GP2AP020A00F_PH_H_REG] = 0,
};
+static const u8 gp2ap030a00f_reg_init_tab[ARRAY_SIZE(gp2ap020a00f_reg_init_tab)] = {
+ [GP2AP020A00F_OP_REG] = GP2AP020A00F_OP3_SHUTDOWN,
+ [GP2AP020A00F_ALS_REG] = GP2AP020A00F_RES_A_100ms |
+ GP2AP020A00F_RANGE_A_x8,
+ [GP2AP020A00F_PS_REG] = GP2AP030A00F_RES_P_1_56ms_x2 |
+ GP2AP020A00F_RANGE_P_x4,
+ [GP2AP020A00F_LED_REG] = GP2AP020A00F_INTVAL_0 |
+ GP2AP030A00F_IS_130mA |
+ GP2AP020A00F_FREQ_327_5kHz,
+};
+
static bool gp2ap020a00f_is_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
@@ -371,6 +390,7 @@ static const struct gp2ap020a00f_mutable_config_regs {
static int gp2ap020a00f_set_operation_mode(struct gp2ap020a00f_data *data,
enum gp2ap020a00f_opmode op)
{
+ u8 op_reg = opmode_regs_settings[op].op_reg;
unsigned int op_reg_val;
int err;
@@ -409,12 +429,16 @@ static int gp2ap020a00f_set_operation_mode(struct gp2ap020a00f_data *data,
return err;
}
+ if (!data->chip_info->has_als_auto)
+ op_reg = (op_reg & ~GP2AP020A00F_TYPE_MASK) |
+ GP2AP020A00F_TYPE_MANUAL_CALC;
+
/* Set OP_REG and apply operation mode (power on / off) */
err = regmap_update_bits(data->regmap,
GP2AP020A00F_OP_REG,
GP2AP020A00F_OP_MASK | GP2AP020A00F_OP2_MASK |
GP2AP020A00F_OP3_MASK | GP2AP020A00F_TYPE_MASK,
- opmode_regs_settings[op].op_reg);
+ op_reg);
if (err < 0)
return err;
@@ -446,6 +470,8 @@ static int gp2ap020a00f_write_event_threshold(struct gp2ap020a00f_data *data,
if (!enable)
thresh_reg_val = 0;
+ else if (!data->chip_info->has_als_auto)
+ thresh_reg_val = min(data->thresh_val[th_val_id], 65535U);
else if (test_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags) &&
th_val_id != GP2AP020A00F_THRESH_PL &&
th_val_id != GP2AP020A00F_THRESH_PH)
@@ -709,6 +735,10 @@ static bool gp2ap020a00f_adjust_lux_mode(struct gp2ap020a00f_data *data,
u8 new_range = 0xff;
int err;
+ /* GP2AP030A00F thresholds and samples are raw counts at a fixed range. */
+ if (!data->chip_info->has_als_auto)
+ return false;
+
if (!test_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags)) {
if (output_val > 16000) {
set_bit(GP2AP020A00F_FLAG_LUX_MODE_HI, &data->flags);
@@ -1317,11 +1347,71 @@ static const struct iio_chan_spec gp2ap020a00f_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(GP2AP020A00F_CHAN_TIMESTAMP),
};
+static const struct iio_chan_spec gp2ap030a00f_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .channel2 = IIO_MOD_LIGHT_CLEAR,
+ .modified = 1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .shift = 0,
+ .storagebits = 32,
+ .endianness = IIO_LE,
+ },
+ .scan_index = GP2AP020A00F_SCAN_MODE_LIGHT_CLEAR,
+ .address = GP2AP020A00F_D0_L_REG,
+ .event_spec = gp2ap020a00f_event_spec_light,
+ .num_event_specs = ARRAY_SIZE(gp2ap020a00f_event_spec_light),
+ },
+ {
+ .type = IIO_LIGHT,
+ .channel2 = IIO_MOD_LIGHT_IR,
+ .modified = 1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .shift = 0,
+ .storagebits = 32,
+ .endianness = IIO_LE,
+ },
+ .scan_index = GP2AP020A00F_SCAN_MODE_LIGHT_IR,
+ .address = GP2AP020A00F_D1_L_REG,
+ },
+ {
+ .type = IIO_PROXIMITY,
+ .modified = 0,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .shift = 0,
+ .storagebits = 16,
+ .endianness = IIO_LE,
+ },
+ .scan_index = GP2AP020A00F_SCAN_MODE_PROXIMITY,
+ .address = GP2AP020A00F_D2_L_REG,
+ .event_spec = gp2ap020a00f_event_spec_prox,
+ .num_event_specs = ARRAY_SIZE(gp2ap020a00f_event_spec_prox),
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(GP2AP020A00F_CHAN_TIMESTAMP),
+};
+
static const struct gp2ap020a00f_chip_info gp2ap020a00f_chip_info = {
.name = "gp2ap020a00f",
.reg_init_tab = gp2ap020a00f_reg_init_tab,
.channels = gp2ap020a00f_channels,
.num_channels = ARRAY_SIZE(gp2ap020a00f_channels),
+ .has_als_auto = true,
+};
+
+static const struct gp2ap020a00f_chip_info gp2ap030a00f_chip_info = {
+ .name = "gp2ap030a00f",
+ .reg_init_tab = gp2ap030a00f_reg_init_tab,
+ .channels = gp2ap030a00f_channels,
+ .num_channels = ARRAY_SIZE(gp2ap030a00f_channels),
};
static const struct iio_info gp2ap020a00f_info = {
@@ -1450,6 +1540,9 @@ static int gp2ap020a00f_probe(struct i2c_client *client)
goto error_regulator_disable;
}
+ if (!data->chip_info->has_als_auto)
+ fsleep(1000);
+
/* Initialize device registers */
err = regmap_bulk_write(regmap, GP2AP020A00F_OP_REG,
data->chip_info->reg_init_tab,
@@ -1549,12 +1642,15 @@ static void gp2ap020a00f_remove(struct i2c_client *client)
static const struct i2c_device_id gp2ap020a00f_id[] = {
{ .name = "gp2ap020a00f",
.driver_data = (kernel_ulong_t)&gp2ap020a00f_chip_info },
+ { .name = "gp2ap030a00f",
+ .driver_data = (kernel_ulong_t)&gp2ap030a00f_chip_info },
{ }
};
MODULE_DEVICE_TABLE(i2c, gp2ap020a00f_id);
static const struct of_device_id gp2ap020a00f_of_match[] = {
{ .compatible = "sharp,gp2ap020a00f", .data = &gp2ap020a00f_chip_info },
+ { .compatible = "sharp,gp2ap030a00f", .data = &gp2ap030a00f_chip_info },
{ }
};
MODULE_DEVICE_TABLE(of, gp2ap020a00f_of_match);
@@ -1571,5 +1667,5 @@ static struct i2c_driver gp2ap020a00f_driver = {
module_i2c_driver(gp2ap020a00f_driver);
MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
-MODULE_DESCRIPTION("Sharp GP2AP020A00F Proximity/ALS sensor driver");
+MODULE_DESCRIPTION("Sharp GP2AP020A00F and similar proximity/ALS sensor driver");
MODULE_LICENSE("GPL v2");
--
2.56.0
next prev parent reply other threads:[~2026-11-08 21:44 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-08 21:43 [PATCH v2 0/5] iio: light: gp2ap020a00f: Add VCC supply and GP2AP030A00F support Linus Walleij
2026-11-08 21:43 ` [PATCH v2 1/5] dt-bindings: iio: light: sharp,gp2ap020a00f: Add VCC supply Linus Walleij
2026-11-09 12:54 ` Krzysztof Kozlowski
2026-11-08 21:44 ` [PATCH v2 2/5] dt-bindings: iio: light: sharp,gp2ap020a00f: Add GP2AP030A00F Linus Walleij
2026-11-09 12:54 ` Krzysztof Kozlowski
2026-11-08 21:44 ` [PATCH v2 3/5] iio: light: gp2ap020a00f: Enable the VCC supply Linus Walleij
2026-11-09 9:21 ` Joshua Crofts
2026-11-08 21:44 ` [PATCH v2 4/5] iio: light: gp2ap020a00f: Prepare for chip variants Linus Walleij
2026-11-09 9:20 ` Joshua Crofts
2026-11-09 23:14 ` Andy Shevchenko
2026-11-08 21:44 ` Linus Walleij [this message]
2026-11-09 9:25 ` [PATCH v2 5/5] iio: light: gp2ap020a00f: Add GP2AP030A00F support Joshua Crofts
2026-11-09 23:17 ` Andy Shevchenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261108-gp2ap030-v2-5-24eaa1b9fe59@kernel.org \
--to=linusw@kernel.org \
--cc=andy@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=dlechner@baylibre.com \
--cc=jic23@kernel.org \
--cc=krzk+dt@kernel.org \
--cc=kyungmin.park@samsung.com \
--cc=linux-iio@vger.kernel.org \
--cc=nuno.sa@analog.com \
--cc=robh@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox