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 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.