Skip to content

Commit 5032f09

Browse files
margheritamilaninashif
authored andcommitted
drivers: sensor: add apds9253 driver
Add all the necessary files to add apds9253 Avago sensor driver. Sensor available at https://docs.broadcom.com/doc/APDS-9253-001-DS Signed-off-by: Margherita Milani <[email protected]> Signed-off-by: Michael Trimarchi <[email protected]>
1 parent 12a437c commit 5032f09

File tree

9 files changed

+522
-0
lines changed

9 files changed

+522
-0
lines changed

drivers/sensor/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ add_subdirectory(wsen)
3030
add_subdirectory_ifdef(CONFIG_A01NYUB a01nyub)
3131
add_subdirectory_ifdef(CONFIG_AMD_SB_TSI amd_sb_tsi)
3232
add_subdirectory_ifdef(CONFIG_AMG88XX amg88xx)
33+
add_subdirectory_ifdef(CONFIG_APDS9253 apds9253)
3334
add_subdirectory_ifdef(CONFIG_APDS9960 apds9960)
3435
add_subdirectory_ifdef(CONFIG_CURRENT_AMP current_amp)
3536
add_subdirectory_ifdef(CONFIG_ENS160 ens160)

drivers/sensor/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ source "drivers/sensor/wsen/Kconfig"
114114
source "drivers/sensor/a01nyub/Kconfig"
115115
source "drivers/sensor/amd_sb_tsi/Kconfig"
116116
source "drivers/sensor/amg88xx/Kconfig"
117+
source "drivers/sensor/apds9253/Kconfig"
117118
source "drivers/sensor/apds9960/Kconfig"
118119
source "drivers/sensor/current_amp/Kconfig"
119120
source "drivers/sensor/ens160/Kconfig"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
zephyr_library()
4+
5+
zephyr_library_sources(apds9253.c)

drivers/sensor/apds9253/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright(c) 2017 Intel Corporation
2+
# Copyright(c) 2018 Phytec Messtechnik GmbH
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
config APDS9253
6+
bool "APDS9253 Sensor"
7+
default y
8+
depends on DT_HAS_AVAGO_APDS9253_ENABLED
9+
select I2C
10+
help
11+
Enable driver for APDS9253 sensors.

drivers/sensor/apds9253/apds9253.c

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
/*
2+
* Copyright (c) 2017 Intel Corporation
3+
* Copyright (c) 2018 Phytec Messtechnik GmbH
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
#define DT_DRV_COMPAT avago_apds9253
9+
10+
/* @file
11+
* @brief driver for APDS9253 ALS/RGB/
12+
*/
13+
14+
#include <zephyr/drivers/sensor.h>
15+
#include <zephyr/drivers/i2c.h>
16+
#include <zephyr/sys/byteorder.h>
17+
#include <zephyr/logging/log.h>
18+
19+
#include "apds9253.h"
20+
21+
#define BYTES_PER_VALUE 3
22+
#define VALUES_PER_SAMPLE 4
23+
24+
LOG_MODULE_REGISTER(APDS9253, CONFIG_SENSOR_LOG_LEVEL);
25+
26+
static inline void apds9253_setup_int(const struct apds9253_config *cfg, bool enable)
27+
{
28+
gpio_flags_t flags = enable ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE;
29+
30+
gpio_pin_interrupt_configure_dt(&cfg->int_gpio, flags);
31+
}
32+
33+
static void apds9253_handle_cb(struct apds9253_data *drv_data)
34+
{
35+
apds9253_setup_int(drv_data->dev->config, false);
36+
}
37+
38+
static void apds9253_gpio_callback(const struct device *dev, struct gpio_callback *cb,
39+
uint32_t pins)
40+
{
41+
struct apds9253_data *drv_data = CONTAINER_OF(cb, struct apds9253_data, gpio_cb);
42+
43+
apds9253_handle_cb(drv_data);
44+
}
45+
46+
static uint32_t get_value_from_buf(int idx, const uint8_t *buf)
47+
{
48+
size_t offset = BYTES_PER_VALUE * idx;
49+
50+
return sys_get_le24(&buf[offset]);
51+
}
52+
53+
static int apds9253_sample_fetch(const struct device *dev, enum sensor_channel chan)
54+
{
55+
const struct apds9253_config *config = dev->config;
56+
struct apds9253_data *data = dev->data;
57+
uint8_t tmp;
58+
uint8_t buf[BYTES_PER_VALUE * VALUES_PER_SAMPLE];
59+
60+
if (chan != SENSOR_CHAN_ALL) {
61+
LOG_ERR("Unsupported sensor channel");
62+
return -ENOTSUP;
63+
}
64+
65+
if (i2c_reg_update_byte_dt(&config->i2c, APDS9253_MAIN_CTRL_REG, APDS9253_MAIN_CTRL_LS_EN,
66+
APDS9253_MAIN_CTRL_LS_EN)) {
67+
LOG_ERR("Power on bit not set.");
68+
return -EIO;
69+
}
70+
71+
if (config->interrupt_enabled) {
72+
k_sem_take(&data->data_sem, K_FOREVER);
73+
}
74+
75+
if (i2c_reg_read_byte_dt(&config->i2c, APDS9253_MAIN_STATUS_REG, &tmp)) {
76+
return -EIO;
77+
}
78+
79+
LOG_DBG("status: 0x%x", tmp);
80+
81+
if (tmp & APDS9253_MAIN_STATUS_LS_STATUS) {
82+
if (i2c_burst_read_dt(&config->i2c, APDS9253_LS_DATA_BASE, buf, sizeof(buf))) {
83+
return -EIO;
84+
}
85+
86+
for (int i = 0; i < VALUES_PER_SAMPLE; ++i) {
87+
data->sample_crgb[i] = get_value_from_buf(i, buf);
88+
}
89+
90+
LOG_DBG("IR 0x%x GREEN 0x%x BLUE 0x%x RED 0x%x\n", data->sample_crgb[0],
91+
data->sample_crgb[1], data->sample_crgb[2], data->sample_crgb[3]);
92+
}
93+
94+
return 0;
95+
}
96+
97+
static int apds9253_channel_get(const struct device *dev, enum sensor_channel chan,
98+
struct sensor_value *val)
99+
{
100+
struct apds9253_data *data = dev->data;
101+
102+
val->val2 = 0;
103+
104+
switch (chan) {
105+
case SENSOR_CHAN_IR:
106+
val->val1 = sys_le32_to_cpu(data->sample_crgb[0]);
107+
break;
108+
case SENSOR_CHAN_GREEN:
109+
val->val1 = sys_le32_to_cpu(data->sample_crgb[1]);
110+
break;
111+
case SENSOR_CHAN_BLUE:
112+
val->val1 = sys_le32_to_cpu(data->sample_crgb[2]);
113+
break;
114+
case SENSOR_CHAN_RED:
115+
val->val1 = sys_le32_to_cpu(data->sample_crgb[3]);
116+
break;
117+
default:
118+
return -ENOTSUP;
119+
}
120+
121+
return 0;
122+
}
123+
124+
static int apds9253_sensor_setup(const struct device *dev)
125+
{
126+
const struct apds9253_config *config = dev->config;
127+
uint8_t chip_id;
128+
129+
if (i2c_reg_read_byte_dt(&config->i2c, APDS9253_PART_ID, &chip_id)) {
130+
LOG_ERR("Failed reading chip id");
131+
return -EIO;
132+
}
133+
134+
if ((chip_id & APDS9253_PART_ID_ID_MASK) != APDS9253_DEVICE_PART_ID) {
135+
LOG_ERR("Invalid chip id 0x%x", chip_id);
136+
return -EIO;
137+
}
138+
139+
if (i2c_reg_update_byte_dt(&config->i2c, APDS9253_LS_GAIN_REG, APDS9253_LS_GAIN_MASK,
140+
(config->ls_gain & APDS9253_LS_GAIN_MASK))) {
141+
LOG_ERR("Light sensor gain is not set");
142+
return -EIO;
143+
}
144+
145+
if (i2c_reg_update_byte_dt(&config->i2c, APDS9253_LS_MEAS_RATE_REG,
146+
APDS9253_LS_MEAS_RATE_RES_MASK,
147+
(config->ls_resolution & APDS9253_LS_MEAS_RATE_RES_MASK))) {
148+
LOG_ERR("Light sensor resolution is not set");
149+
return -EIO;
150+
}
151+
152+
if (i2c_reg_update_byte_dt(&config->i2c, APDS9253_LS_MEAS_RATE_REG,
153+
APDS9253_LS_MEAS_RATE_MES_MASK,
154+
(config->ls_rate & APDS9253_LS_MEAS_RATE_MES_MASK))) {
155+
LOG_ERR("Light sensor rate is not set");
156+
return -EIO;
157+
}
158+
159+
if (i2c_reg_update_byte_dt(&config->i2c, APDS9253_MAIN_CTRL_REG,
160+
APDS9253_MAIN_CTRL_RGB_MODE, APDS9253_MAIN_CTRL_RGB_MODE)) {
161+
LOG_ERR("Enable RGB mode failed");
162+
return -EIO;
163+
}
164+
165+
return 0;
166+
}
167+
168+
static int apds9253_init_interrupt(const struct device *dev)
169+
{
170+
const struct apds9253_config *config = dev->config;
171+
struct apds9253_data *drv_data = dev->data;
172+
int ret = 0;
173+
174+
if (!gpio_is_ready_dt(&config->int_gpio)) {
175+
LOG_ERR("%s: device %s is not ready", dev->name, config->int_gpio.port->name);
176+
return -ENODEV;
177+
}
178+
179+
ret = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT);
180+
if (!ret) {
181+
LOG_ERR("Failed to configure gpio direction");
182+
return ret;
183+
}
184+
185+
gpio_init_callback(&drv_data->gpio_cb, apds9253_gpio_callback, BIT(config->int_gpio.pin));
186+
187+
if (gpio_add_callback(config->int_gpio.port, &drv_data->gpio_cb) < 0) {
188+
LOG_ERR("Failed to set gpio callback!");
189+
return -EIO;
190+
}
191+
192+
drv_data->dev = dev;
193+
194+
k_sem_init(&drv_data->data_sem, 0, K_SEM_MAX_LIMIT);
195+
apds9253_setup_int(config, true);
196+
197+
if (gpio_pin_get_dt(&config->int_gpio) > 0) {
198+
apds9253_handle_cb(drv_data);
199+
}
200+
201+
return 0;
202+
}
203+
204+
static int apds9253_init(const struct device *dev)
205+
{
206+
const struct apds9253_config *config = dev->config;
207+
208+
/* Initialize time 500 us */
209+
k_msleep(1);
210+
211+
if (!i2c_is_ready_dt(&config->i2c)) {
212+
LOG_ERR("Bus device is not ready");
213+
return -EINVAL;
214+
}
215+
216+
if (apds9253_sensor_setup(dev) < 0) {
217+
LOG_ERR("Failed to setup device!");
218+
return -EIO;
219+
}
220+
221+
if (config->interrupt_enabled && apds9253_init_interrupt(dev) < 0) {
222+
LOG_ERR("Failed to initialize interrupt!");
223+
return -EIO;
224+
}
225+
226+
return 0;
227+
}
228+
229+
static const struct sensor_driver_api apds9253_driver_api = {
230+
.sample_fetch = &apds9253_sample_fetch,
231+
.channel_get = &apds9253_channel_get,
232+
};
233+
234+
#define APDS9253_INIT(n) \
235+
static struct apds9253_data apds9253_data_##n = { \
236+
.sample_crgb = {0}, \
237+
.pdata = 0U, \
238+
}; \
239+
\
240+
static const struct apds9253_config apds9253_config_##n = { \
241+
.i2c = I2C_DT_SPEC_INST_GET(n), \
242+
.interrupt_enabled = DT_INST_NODE_HAS_PROP(n, int_gpios), \
243+
.int_gpio = GPIO_DT_SPEC_INST_GET_OR(n, int_gpios, {}), \
244+
.ls_rate = DT_INST_PROP(n, rate), \
245+
.ls_resolution = DT_INST_PROP(n, resolution), \
246+
.ls_gain = DT_INST_PROP(n, gain), \
247+
}; \
248+
\
249+
SENSOR_DEVICE_DT_INST_DEFINE(n, apds9253_init, NULL, &apds9253_data_##n, \
250+
&apds9253_config_##n, POST_KERNEL, \
251+
CONFIG_SENSOR_INIT_PRIORITY, &apds9253_driver_api);
252+
253+
DT_INST_FOREACH_STATUS_OKAY(APDS9253_INIT)

drivers/sensor/apds9253/apds9253.h

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Copyright (c) 2017 Intel Corporation
3+
* Copyright (c) 2018 PHYTEC Messtechnik GmbH
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
#ifndef ZEPHYR_DRIVERS_SENSOR_APDS9253_APDS9253_H_
9+
#define ZEPHYR_DRIVERS_SENSOR_APDS9253_APDS9253_H_
10+
11+
#include <zephyr/drivers/gpio.h>
12+
13+
#define APDS9253_MAIN_CTRL_REG 0x00
14+
#define APDS9253_MAIN_CTRL_REG_MASK GENMASK(5, 0)
15+
#define APDS9253_MAIN_CTRL_SAI_LS BIT(5)
16+
#define APDS9253_MAIN_CTRL_SW_RESET BIT(4)
17+
#define APDS9253_MAIN_CTRL_RGB_MODE BIT(2)
18+
#define APDS9253_MAIN_CTRL_LS_EN BIT(1)
19+
20+
#define APDS9253_LS_MEAS_RATE_REG 0x04
21+
#define APDS9253_LS_MEAS_RATE_RES_MASK GENMASK(6, 4)
22+
#define APDS9253_LS_MEAS_RATE_RES_20BIT_400MS 0
23+
#define APDS9253_LS_MEAS_RATE_RES_19BIT_200MS BIT(4)
24+
#define APDS9253_LS_MEAS_RATE_RES_18BIT_100MS BIT(5) /* default */
25+
#define APDS9253_LS_MEAS_RATE_RES_17BIT_50MS (BIT(5) | BIT(4))
26+
#define APDS9253_LS_MEAS_RATE_RES_16BIT_25MS BIT(6)
27+
#define APDS9253_LS_MEAS_RATE_RES_13_3MS (BIT(6) | BIT(4))
28+
#define APDS9253_LS_MEAS_RATE_MES_MASK GENMASK(2, 0)
29+
#define APDS9253_LS_MEAS_RATE_MES_2000MS (BIT(2) | BIT(1) | BIT(0))
30+
#define APDS9253_LS_MEAS_RATE_MES_1000MS (BIT(2) | BIT(0))
31+
#define APDS9253_LS_MEAS_RATE_MES_500MS BIT(2)
32+
#define APDS9253_LS_MEAS_RATE_MES_200MS (BIT(1) | BIT(0))
33+
#define APDS9253_LS_MEAS_RATE_MES_100MS BIT(1) /* default */
34+
#define APDS9253_LS_MEAS_RATE_MES_50MS BIT(0)
35+
#define APDS9253_LS_MEAS_RATE_MES_25MS 0
36+
37+
#define APDS9253_LS_GAIN_REG 0x05
38+
#define APDS9253_LS_GAIN_MASK GENMASK(2, 0)
39+
#define APDS9253_LS_GAIN_RANGE_18 BIT(2)
40+
#define APDS9253_LS_GAIN_RANGE_9 (BIT(1) | BIT(0))
41+
#define APDS9253_LS_GAIN_RANGE_6 BIT(1)
42+
#define APDS9253_LS_GAIN_RANGE_3 BIT(0) /* default */
43+
#define APDS9253_LS_GAIN_RANGE_1 0
44+
45+
#define APDS9253_PART_ID 0x06
46+
#define APDS9253_DEVICE_PART_ID 0xC0
47+
#define APDS9253_PART_ID_REV_MASK GENMASK(3, 0)
48+
#define APDS9253_PART_ID_ID_MASK GENMASK(7, 4)
49+
50+
#define APDS9253_MAIN_STATUS_REG 0x07
51+
#define APDS9253_MAIN_STATUS_POWER_ON BIT(5)
52+
#define APDS9253_MAIN_STATUS_LS_INTERRUPT BIT(4)
53+
#define APDS9253_MAIN_STATUS_LS_STATUS BIT(3)
54+
55+
/* Channels data */
56+
#define APDS9253_LS_DATA_BASE 0x0A
57+
#define APDS9253_LS_DATA_IR_0 0x0A
58+
#define APDS9253_LS_DATA_IR_1 0x0B
59+
#define APDS9253_LS_DATA_IR_2 0x0C
60+
#define APDS9253_LS_DATA_GREEN_0 0x0D
61+
#define APDS9253_LS_DATA_GREEN_1 0x0E
62+
#define APDS9253_LS_DATA_GREEN_2 0x0F
63+
#define APDS9253_LS_DATA_BLUE_0 0x10
64+
#define APDS9253_LS_DATA_BLUE_1 0x11
65+
#define APDS9253_LS_DATA_BLUE_2 0x12
66+
#define APDS9253_LS_DATA_RED_0 0x13
67+
#define APDS9253_LS_DATA_RED_1 0x14
68+
#define APDS9253_LS_DATA_RED_2 0x15
69+
70+
#define APDS9253_INT_CFG 0x19
71+
#define APDS9253_INT_CFG_LS_INT_SEL_IR 0
72+
#define APDS9253_INT_CFG_LS_INT_SEL_ALS BIT(4) /* default */
73+
#define APDS9253_INT_CFG_LS_INT_SEL_RED BIT(5)
74+
#define APDS9253_INT_CFG_LS_INT_SEL_BLUE (BIT(5) | BIT(4))
75+
#define APDS9253_INT_CFG_LS_VAR_MODE_EN BIT(3)
76+
#define APDS9253_INT_CFG_LS_INT_MODE_EN BIT(3)
77+
78+
#define APDS9253_INT_PST 0x1A
79+
#define APDS9253_LS_THRES_UP_0 0x21
80+
#define APDS9253_LS_THRES_UP_1 0x22
81+
#define APDS9253_LS_THRES_UP_2 0x23
82+
#define APDS9253_LS_THRES_LOW_0 0x24
83+
#define APDS9253_LS_THRES_LOW_1 0x25
84+
#define APDS9253_LS_THRES_LOW_2 0x26
85+
#define APDS9253_LS_THRES_VAR 0x27
86+
#define APDS9253_DK_CNT_STOR 0x29
87+
88+
struct apds9253_config {
89+
struct i2c_dt_spec i2c;
90+
struct gpio_dt_spec int_gpio;
91+
uint8_t ls_gain;
92+
uint8_t ls_rate;
93+
uint8_t ls_resolution;
94+
bool interrupt_enabled;
95+
};
96+
97+
struct apds9253_data {
98+
struct gpio_callback gpio_cb;
99+
struct k_work work;
100+
const struct device *dev;
101+
uint32_t sample_crgb[4];
102+
uint8_t pdata;
103+
struct k_sem data_sem;
104+
};
105+
106+
#endif /* ZEPHYR_DRIVERS_SENSOR_APDS9253_APDS9253_H_*/

0 commit comments

Comments
 (0)