forked from zephyrproject-rtos/zephyr
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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]>
- Loading branch information
1 parent
12a437c
commit 5032f09
Showing
9 changed files
with
522 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
zephyr_library() | ||
|
||
zephyr_library_sources(apds9253.c) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Copyright(c) 2017 Intel Corporation | ||
# Copyright(c) 2018 Phytec Messtechnik GmbH | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
config APDS9253 | ||
bool "APDS9253 Sensor" | ||
default y | ||
depends on DT_HAS_AVAGO_APDS9253_ENABLED | ||
select I2C | ||
help | ||
Enable driver for APDS9253 sensors. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,253 @@ | ||
/* | ||
* Copyright (c) 2017 Intel Corporation | ||
* Copyright (c) 2018 Phytec Messtechnik GmbH | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#define DT_DRV_COMPAT avago_apds9253 | ||
|
||
/* @file | ||
* @brief driver for APDS9253 ALS/RGB/ | ||
*/ | ||
|
||
#include <zephyr/drivers/sensor.h> | ||
#include <zephyr/drivers/i2c.h> | ||
#include <zephyr/sys/byteorder.h> | ||
#include <zephyr/logging/log.h> | ||
|
||
#include "apds9253.h" | ||
|
||
#define BYTES_PER_VALUE 3 | ||
#define VALUES_PER_SAMPLE 4 | ||
|
||
LOG_MODULE_REGISTER(APDS9253, CONFIG_SENSOR_LOG_LEVEL); | ||
|
||
static inline void apds9253_setup_int(const struct apds9253_config *cfg, bool enable) | ||
{ | ||
gpio_flags_t flags = enable ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE; | ||
|
||
gpio_pin_interrupt_configure_dt(&cfg->int_gpio, flags); | ||
} | ||
|
||
static void apds9253_handle_cb(struct apds9253_data *drv_data) | ||
{ | ||
apds9253_setup_int(drv_data->dev->config, false); | ||
} | ||
|
||
static void apds9253_gpio_callback(const struct device *dev, struct gpio_callback *cb, | ||
uint32_t pins) | ||
{ | ||
struct apds9253_data *drv_data = CONTAINER_OF(cb, struct apds9253_data, gpio_cb); | ||
|
||
apds9253_handle_cb(drv_data); | ||
} | ||
|
||
static uint32_t get_value_from_buf(int idx, const uint8_t *buf) | ||
{ | ||
size_t offset = BYTES_PER_VALUE * idx; | ||
|
||
return sys_get_le24(&buf[offset]); | ||
} | ||
|
||
static int apds9253_sample_fetch(const struct device *dev, enum sensor_channel chan) | ||
{ | ||
const struct apds9253_config *config = dev->config; | ||
struct apds9253_data *data = dev->data; | ||
uint8_t tmp; | ||
uint8_t buf[BYTES_PER_VALUE * VALUES_PER_SAMPLE]; | ||
|
||
if (chan != SENSOR_CHAN_ALL) { | ||
LOG_ERR("Unsupported sensor channel"); | ||
return -ENOTSUP; | ||
} | ||
|
||
if (i2c_reg_update_byte_dt(&config->i2c, APDS9253_MAIN_CTRL_REG, APDS9253_MAIN_CTRL_LS_EN, | ||
APDS9253_MAIN_CTRL_LS_EN)) { | ||
LOG_ERR("Power on bit not set."); | ||
return -EIO; | ||
} | ||
|
||
if (config->interrupt_enabled) { | ||
k_sem_take(&data->data_sem, K_FOREVER); | ||
} | ||
|
||
if (i2c_reg_read_byte_dt(&config->i2c, APDS9253_MAIN_STATUS_REG, &tmp)) { | ||
return -EIO; | ||
} | ||
|
||
LOG_DBG("status: 0x%x", tmp); | ||
|
||
if (tmp & APDS9253_MAIN_STATUS_LS_STATUS) { | ||
if (i2c_burst_read_dt(&config->i2c, APDS9253_LS_DATA_BASE, buf, sizeof(buf))) { | ||
return -EIO; | ||
} | ||
|
||
for (int i = 0; i < VALUES_PER_SAMPLE; ++i) { | ||
data->sample_crgb[i] = get_value_from_buf(i, buf); | ||
} | ||
|
||
LOG_DBG("IR 0x%x GREEN 0x%x BLUE 0x%x RED 0x%x\n", data->sample_crgb[0], | ||
data->sample_crgb[1], data->sample_crgb[2], data->sample_crgb[3]); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int apds9253_channel_get(const struct device *dev, enum sensor_channel chan, | ||
struct sensor_value *val) | ||
{ | ||
struct apds9253_data *data = dev->data; | ||
|
||
val->val2 = 0; | ||
|
||
switch (chan) { | ||
case SENSOR_CHAN_IR: | ||
val->val1 = sys_le32_to_cpu(data->sample_crgb[0]); | ||
break; | ||
case SENSOR_CHAN_GREEN: | ||
val->val1 = sys_le32_to_cpu(data->sample_crgb[1]); | ||
break; | ||
case SENSOR_CHAN_BLUE: | ||
val->val1 = sys_le32_to_cpu(data->sample_crgb[2]); | ||
break; | ||
case SENSOR_CHAN_RED: | ||
val->val1 = sys_le32_to_cpu(data->sample_crgb[3]); | ||
break; | ||
default: | ||
return -ENOTSUP; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int apds9253_sensor_setup(const struct device *dev) | ||
{ | ||
const struct apds9253_config *config = dev->config; | ||
uint8_t chip_id; | ||
|
||
if (i2c_reg_read_byte_dt(&config->i2c, APDS9253_PART_ID, &chip_id)) { | ||
LOG_ERR("Failed reading chip id"); | ||
return -EIO; | ||
} | ||
|
||
if ((chip_id & APDS9253_PART_ID_ID_MASK) != APDS9253_DEVICE_PART_ID) { | ||
LOG_ERR("Invalid chip id 0x%x", chip_id); | ||
return -EIO; | ||
} | ||
|
||
if (i2c_reg_update_byte_dt(&config->i2c, APDS9253_LS_GAIN_REG, APDS9253_LS_GAIN_MASK, | ||
(config->ls_gain & APDS9253_LS_GAIN_MASK))) { | ||
LOG_ERR("Light sensor gain is not set"); | ||
return -EIO; | ||
} | ||
|
||
if (i2c_reg_update_byte_dt(&config->i2c, APDS9253_LS_MEAS_RATE_REG, | ||
APDS9253_LS_MEAS_RATE_RES_MASK, | ||
(config->ls_resolution & APDS9253_LS_MEAS_RATE_RES_MASK))) { | ||
LOG_ERR("Light sensor resolution is not set"); | ||
return -EIO; | ||
} | ||
|
||
if (i2c_reg_update_byte_dt(&config->i2c, APDS9253_LS_MEAS_RATE_REG, | ||
APDS9253_LS_MEAS_RATE_MES_MASK, | ||
(config->ls_rate & APDS9253_LS_MEAS_RATE_MES_MASK))) { | ||
LOG_ERR("Light sensor rate is not set"); | ||
return -EIO; | ||
} | ||
|
||
if (i2c_reg_update_byte_dt(&config->i2c, APDS9253_MAIN_CTRL_REG, | ||
APDS9253_MAIN_CTRL_RGB_MODE, APDS9253_MAIN_CTRL_RGB_MODE)) { | ||
LOG_ERR("Enable RGB mode failed"); | ||
return -EIO; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int apds9253_init_interrupt(const struct device *dev) | ||
{ | ||
const struct apds9253_config *config = dev->config; | ||
struct apds9253_data *drv_data = dev->data; | ||
int ret = 0; | ||
|
||
if (!gpio_is_ready_dt(&config->int_gpio)) { | ||
LOG_ERR("%s: device %s is not ready", dev->name, config->int_gpio.port->name); | ||
return -ENODEV; | ||
} | ||
|
||
ret = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT); | ||
if (!ret) { | ||
LOG_ERR("Failed to configure gpio direction"); | ||
return ret; | ||
} | ||
|
||
gpio_init_callback(&drv_data->gpio_cb, apds9253_gpio_callback, BIT(config->int_gpio.pin)); | ||
|
||
if (gpio_add_callback(config->int_gpio.port, &drv_data->gpio_cb) < 0) { | ||
LOG_ERR("Failed to set gpio callback!"); | ||
return -EIO; | ||
} | ||
|
||
drv_data->dev = dev; | ||
|
||
k_sem_init(&drv_data->data_sem, 0, K_SEM_MAX_LIMIT); | ||
apds9253_setup_int(config, true); | ||
|
||
if (gpio_pin_get_dt(&config->int_gpio) > 0) { | ||
apds9253_handle_cb(drv_data); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static int apds9253_init(const struct device *dev) | ||
{ | ||
const struct apds9253_config *config = dev->config; | ||
|
||
/* Initialize time 500 us */ | ||
k_msleep(1); | ||
|
||
if (!i2c_is_ready_dt(&config->i2c)) { | ||
LOG_ERR("Bus device is not ready"); | ||
return -EINVAL; | ||
} | ||
|
||
if (apds9253_sensor_setup(dev) < 0) { | ||
LOG_ERR("Failed to setup device!"); | ||
return -EIO; | ||
} | ||
|
||
if (config->interrupt_enabled && apds9253_init_interrupt(dev) < 0) { | ||
LOG_ERR("Failed to initialize interrupt!"); | ||
return -EIO; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
static const struct sensor_driver_api apds9253_driver_api = { | ||
.sample_fetch = &apds9253_sample_fetch, | ||
.channel_get = &apds9253_channel_get, | ||
}; | ||
|
||
#define APDS9253_INIT(n) \ | ||
static struct apds9253_data apds9253_data_##n = { \ | ||
.sample_crgb = {0}, \ | ||
.pdata = 0U, \ | ||
}; \ | ||
\ | ||
static const struct apds9253_config apds9253_config_##n = { \ | ||
.i2c = I2C_DT_SPEC_INST_GET(n), \ | ||
.interrupt_enabled = DT_INST_NODE_HAS_PROP(n, int_gpios), \ | ||
.int_gpio = GPIO_DT_SPEC_INST_GET_OR(n, int_gpios, {}), \ | ||
.ls_rate = DT_INST_PROP(n, rate), \ | ||
.ls_resolution = DT_INST_PROP(n, resolution), \ | ||
.ls_gain = DT_INST_PROP(n, gain), \ | ||
}; \ | ||
\ | ||
SENSOR_DEVICE_DT_INST_DEFINE(n, apds9253_init, NULL, &apds9253_data_##n, \ | ||
&apds9253_config_##n, POST_KERNEL, \ | ||
CONFIG_SENSOR_INIT_PRIORITY, &apds9253_driver_api); | ||
|
||
DT_INST_FOREACH_STATUS_OKAY(APDS9253_INIT) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/* | ||
* Copyright (c) 2017 Intel Corporation | ||
* Copyright (c) 2018 PHYTEC Messtechnik GmbH | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#ifndef ZEPHYR_DRIVERS_SENSOR_APDS9253_APDS9253_H_ | ||
#define ZEPHYR_DRIVERS_SENSOR_APDS9253_APDS9253_H_ | ||
|
||
#include <zephyr/drivers/gpio.h> | ||
|
||
#define APDS9253_MAIN_CTRL_REG 0x00 | ||
#define APDS9253_MAIN_CTRL_REG_MASK GENMASK(5, 0) | ||
#define APDS9253_MAIN_CTRL_SAI_LS BIT(5) | ||
#define APDS9253_MAIN_CTRL_SW_RESET BIT(4) | ||
#define APDS9253_MAIN_CTRL_RGB_MODE BIT(2) | ||
#define APDS9253_MAIN_CTRL_LS_EN BIT(1) | ||
|
||
#define APDS9253_LS_MEAS_RATE_REG 0x04 | ||
#define APDS9253_LS_MEAS_RATE_RES_MASK GENMASK(6, 4) | ||
#define APDS9253_LS_MEAS_RATE_RES_20BIT_400MS 0 | ||
#define APDS9253_LS_MEAS_RATE_RES_19BIT_200MS BIT(4) | ||
#define APDS9253_LS_MEAS_RATE_RES_18BIT_100MS BIT(5) /* default */ | ||
#define APDS9253_LS_MEAS_RATE_RES_17BIT_50MS (BIT(5) | BIT(4)) | ||
#define APDS9253_LS_MEAS_RATE_RES_16BIT_25MS BIT(6) | ||
#define APDS9253_LS_MEAS_RATE_RES_13_3MS (BIT(6) | BIT(4)) | ||
#define APDS9253_LS_MEAS_RATE_MES_MASK GENMASK(2, 0) | ||
#define APDS9253_LS_MEAS_RATE_MES_2000MS (BIT(2) | BIT(1) | BIT(0)) | ||
#define APDS9253_LS_MEAS_RATE_MES_1000MS (BIT(2) | BIT(0)) | ||
#define APDS9253_LS_MEAS_RATE_MES_500MS BIT(2) | ||
#define APDS9253_LS_MEAS_RATE_MES_200MS (BIT(1) | BIT(0)) | ||
#define APDS9253_LS_MEAS_RATE_MES_100MS BIT(1) /* default */ | ||
#define APDS9253_LS_MEAS_RATE_MES_50MS BIT(0) | ||
#define APDS9253_LS_MEAS_RATE_MES_25MS 0 | ||
|
||
#define APDS9253_LS_GAIN_REG 0x05 | ||
#define APDS9253_LS_GAIN_MASK GENMASK(2, 0) | ||
#define APDS9253_LS_GAIN_RANGE_18 BIT(2) | ||
#define APDS9253_LS_GAIN_RANGE_9 (BIT(1) | BIT(0)) | ||
#define APDS9253_LS_GAIN_RANGE_6 BIT(1) | ||
#define APDS9253_LS_GAIN_RANGE_3 BIT(0) /* default */ | ||
#define APDS9253_LS_GAIN_RANGE_1 0 | ||
|
||
#define APDS9253_PART_ID 0x06 | ||
#define APDS9253_DEVICE_PART_ID 0xC0 | ||
#define APDS9253_PART_ID_REV_MASK GENMASK(3, 0) | ||
#define APDS9253_PART_ID_ID_MASK GENMASK(7, 4) | ||
|
||
#define APDS9253_MAIN_STATUS_REG 0x07 | ||
#define APDS9253_MAIN_STATUS_POWER_ON BIT(5) | ||
#define APDS9253_MAIN_STATUS_LS_INTERRUPT BIT(4) | ||
#define APDS9253_MAIN_STATUS_LS_STATUS BIT(3) | ||
|
||
/* Channels data */ | ||
#define APDS9253_LS_DATA_BASE 0x0A | ||
#define APDS9253_LS_DATA_IR_0 0x0A | ||
#define APDS9253_LS_DATA_IR_1 0x0B | ||
#define APDS9253_LS_DATA_IR_2 0x0C | ||
#define APDS9253_LS_DATA_GREEN_0 0x0D | ||
#define APDS9253_LS_DATA_GREEN_1 0x0E | ||
#define APDS9253_LS_DATA_GREEN_2 0x0F | ||
#define APDS9253_LS_DATA_BLUE_0 0x10 | ||
#define APDS9253_LS_DATA_BLUE_1 0x11 | ||
#define APDS9253_LS_DATA_BLUE_2 0x12 | ||
#define APDS9253_LS_DATA_RED_0 0x13 | ||
#define APDS9253_LS_DATA_RED_1 0x14 | ||
#define APDS9253_LS_DATA_RED_2 0x15 | ||
|
||
#define APDS9253_INT_CFG 0x19 | ||
#define APDS9253_INT_CFG_LS_INT_SEL_IR 0 | ||
#define APDS9253_INT_CFG_LS_INT_SEL_ALS BIT(4) /* default */ | ||
#define APDS9253_INT_CFG_LS_INT_SEL_RED BIT(5) | ||
#define APDS9253_INT_CFG_LS_INT_SEL_BLUE (BIT(5) | BIT(4)) | ||
#define APDS9253_INT_CFG_LS_VAR_MODE_EN BIT(3) | ||
#define APDS9253_INT_CFG_LS_INT_MODE_EN BIT(3) | ||
|
||
#define APDS9253_INT_PST 0x1A | ||
#define APDS9253_LS_THRES_UP_0 0x21 | ||
#define APDS9253_LS_THRES_UP_1 0x22 | ||
#define APDS9253_LS_THRES_UP_2 0x23 | ||
#define APDS9253_LS_THRES_LOW_0 0x24 | ||
#define APDS9253_LS_THRES_LOW_1 0x25 | ||
#define APDS9253_LS_THRES_LOW_2 0x26 | ||
#define APDS9253_LS_THRES_VAR 0x27 | ||
#define APDS9253_DK_CNT_STOR 0x29 | ||
|
||
struct apds9253_config { | ||
struct i2c_dt_spec i2c; | ||
struct gpio_dt_spec int_gpio; | ||
uint8_t ls_gain; | ||
uint8_t ls_rate; | ||
uint8_t ls_resolution; | ||
bool interrupt_enabled; | ||
}; | ||
|
||
struct apds9253_data { | ||
struct gpio_callback gpio_cb; | ||
struct k_work work; | ||
const struct device *dev; | ||
uint32_t sample_crgb[4]; | ||
uint8_t pdata; | ||
struct k_sem data_sem; | ||
}; | ||
|
||
#endif /* ZEPHYR_DRIVERS_SENSOR_APDS9253_APDS9253_H_*/ |
Oops, something went wrong.