drivers: sensor: tsl2591
Add the tsl2591 sensor to drivers. Signed-off-by: Kurtis Dinelle <kurtisdinelle@gmail.com>
This commit is contained in:
parent
136a3d3671
commit
3c3bee96ef
13 changed files with 1007 additions and 0 deletions
|
|
@ -158,6 +158,7 @@ add_subdirectory_ifdef(CONFIG_TMP112 tmp112)
|
|||
add_subdirectory_ifdef(CONFIG_TMP116 tmp116)
|
||||
add_subdirectory_ifdef(CONFIG_TSL2540 tsl2540)
|
||||
add_subdirectory_ifdef(CONFIG_TSL2561 tsl2561)
|
||||
add_subdirectory_ifdef(CONFIG_TSL2591 tsl2591)
|
||||
add_subdirectory_ifdef(CONFIG_VCMP_IT8XXX2 ite_vcmp_it8xxx2)
|
||||
add_subdirectory_ifdef(CONFIG_VCNL4040 vcnl4040)
|
||||
add_subdirectory_ifdef(CONFIG_VCNL36825T vcnl36825t)
|
||||
|
|
|
|||
|
|
@ -238,6 +238,7 @@ source "drivers/sensor/tmp112/Kconfig"
|
|||
source "drivers/sensor/tmp116/Kconfig"
|
||||
source "drivers/sensor/tsl2540/Kconfig"
|
||||
source "drivers/sensor/tsl2561/Kconfig"
|
||||
source "drivers/sensor/tsl2591/Kconfig"
|
||||
source "drivers/sensor/vcnl4040/Kconfig"
|
||||
source "drivers/sensor/vcnl36825t/Kconfig"
|
||||
source "drivers/sensor/veml7700/Kconfig"
|
||||
|
|
|
|||
6
drivers/sensor/tsl2591/CMakeLists.txt
Normal file
6
drivers/sensor/tsl2591/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources(tsl2591.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_TSL2591_TRIGGER tsl2591_trigger.c)
|
||||
63
drivers/sensor/tsl2591/Kconfig
Normal file
63
drivers/sensor/tsl2591/Kconfig
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# Copyright (c) 2023 Kurtis Dinelle
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
menuconfig TSL2591
|
||||
bool "OSRAM-AMS TSL2591 light sensor"
|
||||
default y
|
||||
depends on DT_HAS_AMS_TSL2591_ENABLED
|
||||
select I2C
|
||||
help
|
||||
Enable driver for TSL2591 sensor.
|
||||
|
||||
if TSL2591
|
||||
config TSL2591_FETCH_WAIT
|
||||
bool "Wait for valid sensor reading before fetch"
|
||||
help
|
||||
If set, the driver will automatically wait for the duration of an integration cycle
|
||||
during a fetch call if necessary.
|
||||
|
||||
config TSL2591_WARN_SATURATED
|
||||
bool "Warn if sensor is potentially saturated"
|
||||
help
|
||||
If set, the driver will warn if the sensor ADC is
|
||||
potentially saturated after a data fetch.
|
||||
|
||||
config TSL2591_TRIGGER
|
||||
bool
|
||||
|
||||
choice
|
||||
prompt "Trigger mode"
|
||||
default TSL2591_TRIGGER_NONE
|
||||
help
|
||||
Specify the type of triggering to be used by the driver.
|
||||
|
||||
config TSL2591_TRIGGER_NONE
|
||||
bool "No trigger"
|
||||
|
||||
config TSL2591_TRIGGER_GLOBAL_THREAD
|
||||
bool "Use global thread"
|
||||
depends on GPIO
|
||||
select TSL2591_TRIGGER
|
||||
|
||||
config TSL2591_TRIGGER_OWN_THREAD
|
||||
bool "Use own thread"
|
||||
depends on GPIO
|
||||
select TSL2591_TRIGGER
|
||||
|
||||
endchoice
|
||||
|
||||
config TSL2591_THREAD_PRIORITY
|
||||
int "Thread priority"
|
||||
depends on TSL2591_TRIGGER_OWN_THREAD
|
||||
default 10
|
||||
help
|
||||
Priority of thread used by the driver to handle interrupts.
|
||||
|
||||
config TSL2591_THREAD_STACK_SIZE
|
||||
int "Thread stack size"
|
||||
depends on TSL2591_TRIGGER_OWN_THREAD
|
||||
default 1024
|
||||
help
|
||||
Stack size of thread used by the driver to handle interrupts.
|
||||
|
||||
endif # TSL2591
|
||||
535
drivers/sensor/tsl2591/tsl2591.c
Normal file
535
drivers/sensor/tsl2591/tsl2591.c
Normal file
|
|
@ -0,0 +1,535 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Kurtis Dinelle
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT ams_tsl2591
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/pm/device.h>
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
#include "tsl2591.h"
|
||||
|
||||
LOG_MODULE_REGISTER(TSL2591, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static int tsl2591_reg_read(const struct device *dev, uint8_t reg, uint8_t *buf, uint8_t size)
|
||||
{
|
||||
const struct tsl2591_config *config = dev->config;
|
||||
uint8_t cmd = TSL2591_NORMAL_CMD | reg;
|
||||
|
||||
return i2c_write_read_dt(&config->i2c, &cmd, 1U, buf, size);
|
||||
}
|
||||
|
||||
static int tsl2591_reg_write(const struct device *dev, uint8_t reg, uint8_t val)
|
||||
{
|
||||
const struct tsl2591_config *config = dev->config;
|
||||
uint8_t cmd[2] = {TSL2591_NORMAL_CMD | reg, val};
|
||||
|
||||
return i2c_write_dt(&config->i2c, cmd, 2U);
|
||||
}
|
||||
|
||||
int tsl2591_reg_update(const struct device *dev, uint8_t reg, uint8_t mask, uint8_t val)
|
||||
{
|
||||
uint8_t old_value, new_value;
|
||||
int ret;
|
||||
|
||||
ret = tsl2591_reg_read(dev, reg, &old_value, 1U);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
new_value = (old_value & ~mask) | (val & mask);
|
||||
if (new_value == old_value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return tsl2591_reg_write(dev, reg, new_value);
|
||||
}
|
||||
|
||||
static int tsl2591_sample_fetch(const struct device *dev, enum sensor_channel chan)
|
||||
{
|
||||
struct tsl2591_data *data = dev->data;
|
||||
uint8_t als_data[4];
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_TSL2591_FETCH_WAIT
|
||||
uint8_t status;
|
||||
|
||||
ret = tsl2591_reg_read(dev, TSL2591_REG_STATUS, &status, 1U);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to read status register");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check if ALS has completed an integration cycle since AEN asserted.
|
||||
* If not, sleep for the duration of an integration cycle to ensure valid reading.
|
||||
*/
|
||||
if (!(status & TSL2591_AVALID_MASK)) {
|
||||
k_msleep((data->atime / 100) * TSL2591_MAX_TIME_STEP);
|
||||
}
|
||||
|
||||
/* Reassert AEN to determine if next reading is valid */
|
||||
ret = tsl2591_reg_update(dev, TSL2591_REG_ENABLE, TSL2591_AEN_MASK, TSL2591_AEN_OFF);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to disable ALS");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = tsl2591_reg_update(dev, TSL2591_REG_ENABLE, TSL2591_AEN_MASK, TSL2591_AEN_ON);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to re-enable ALS");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_ALL:
|
||||
ret = tsl2591_reg_read(dev, TSL2591_REG_C0DATAL, als_data, 4U);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to read ALS data");
|
||||
return ret;
|
||||
}
|
||||
|
||||
data->vis_count = sys_get_le16(als_data);
|
||||
data->ir_count = sys_get_le16(als_data + 2);
|
||||
break;
|
||||
case SENSOR_CHAN_LIGHT:
|
||||
ret = tsl2591_reg_read(dev, TSL2591_REG_C0DATAL, als_data, 2U);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to read ALS visible light data");
|
||||
return ret;
|
||||
}
|
||||
|
||||
data->vis_count = sys_get_le16(als_data);
|
||||
break;
|
||||
case SENSOR_CHAN_IR:
|
||||
ret = tsl2591_reg_read(dev, TSL2591_REG_C1DATAL, als_data, 2U);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to read ALS infrared data");
|
||||
return ret;
|
||||
}
|
||||
|
||||
data->ir_count = sys_get_le16(als_data);
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("Unsupported sensor channel");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TSL2591_WARN_SATURATED
|
||||
uint16_t max_count = data->atime == 100 ? TSL2591_MAX_ADC_100 : TSL2591_MAX_ADC;
|
||||
bool vis_saturated = (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_LIGHT) &&
|
||||
(data->vis_count >= max_count);
|
||||
bool ir_saturated = (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_IR) &&
|
||||
(data->ir_count >= max_count);
|
||||
if (vis_saturated || ir_saturated) {
|
||||
LOG_WRN("Sensor ADC potentially saturated, reading may be invalid");
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tsl2591_channel_get(const struct device *dev, enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
const struct tsl2591_data *data = dev->data;
|
||||
int64_t cpl = data->atime * data->again;
|
||||
int64_t strength;
|
||||
|
||||
/* Unfortunately, datasheet does not provide a lux conversion formula for this particular
|
||||
* device. There is still ongoing discussion about the proper formula, though this
|
||||
* implementation uses a slightly modified version of the Adafruit library formula:
|
||||
* https://github.com/adafruit/Adafruit_TSL2591_Library/
|
||||
*
|
||||
* Since the device relies on both visible and IR readings to calculate lux,
|
||||
* read SENSOR_CHAN_ALL to get a closer approximation of lux. Reading SENSOR_CHAN_LIGHT or
|
||||
* SENSOR_CHAN_IR individually can be more closely thought of as relative strength
|
||||
* as opposed to true lux.
|
||||
*/
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_ALL:
|
||||
if (data->vis_count > 0) {
|
||||
cpl *= 1000000;
|
||||
strength =
|
||||
(data->vis_count - data->ir_count) *
|
||||
(1000000 - (((int64_t)data->ir_count * 1000000) / data->vis_count));
|
||||
} else {
|
||||
strength = 0;
|
||||
}
|
||||
break;
|
||||
case SENSOR_CHAN_LIGHT:
|
||||
strength = data->vis_count;
|
||||
break;
|
||||
case SENSOR_CHAN_IR:
|
||||
strength = data->ir_count;
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("Unsupported sensor channel");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
strength *= TSL2591_LUX_DF;
|
||||
val->val1 = strength / cpl;
|
||||
val->val2 = ((strength % cpl) * 1000000) / cpl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TSL2591_TRIGGER
|
||||
static int tsl2591_set_threshold(const struct device *dev, enum sensor_attribute attr,
|
||||
const struct sensor_value *val)
|
||||
{
|
||||
const struct tsl2591_data *data = dev->data;
|
||||
const struct tsl2591_config *config = dev->config;
|
||||
uint64_t cpl;
|
||||
uint32_t raw;
|
||||
uint16_t thld;
|
||||
uint8_t thld_reg;
|
||||
uint8_t cmd[3];
|
||||
int ret;
|
||||
|
||||
/* Convert from relative strength of visible light to raw value */
|
||||
cpl = data->atime * data->again;
|
||||
raw = ((val->val1 * cpl) / TSL2591_LUX_DF) +
|
||||
((val->val2 * cpl) / (1000000U * TSL2591_LUX_DF));
|
||||
|
||||
if (raw > TSL2591_MAX_ADC) {
|
||||
LOG_ERR("Given value would overflow threshold register");
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
thld = sys_cpu_to_le16(raw);
|
||||
thld_reg = attr == SENSOR_ATTR_LOWER_THRESH ? TSL2591_REG_AILTL : TSL2591_REG_AIHTL;
|
||||
|
||||
cmd[0] = TSL2591_NORMAL_CMD | thld_reg;
|
||||
bytecpy(cmd + 1, &thld, 2U);
|
||||
|
||||
ret = i2c_write_dt(&config->i2c, cmd, 3U);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to set interrupt threshold");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tsl2591_set_persist(const struct device *dev, int32_t persist_filter)
|
||||
{
|
||||
uint8_t persist_mode;
|
||||
int ret;
|
||||
|
||||
switch (persist_filter) {
|
||||
case 0:
|
||||
persist_mode = TSL2591_PERSIST_EVERY;
|
||||
break;
|
||||
case 1:
|
||||
persist_mode = TSL2591_PERSIST_1;
|
||||
break;
|
||||
case 2:
|
||||
persist_mode = TSL2591_PERSIST_2;
|
||||
break;
|
||||
case 3:
|
||||
persist_mode = TSL2591_PERSIST_3;
|
||||
break;
|
||||
case 5:
|
||||
persist_mode = TSL2591_PERSIST_5;
|
||||
break;
|
||||
case 10:
|
||||
persist_mode = TSL2591_PERSIST_10;
|
||||
break;
|
||||
case 15:
|
||||
persist_mode = TSL2591_PERSIST_15;
|
||||
break;
|
||||
case 20:
|
||||
persist_mode = TSL2591_PERSIST_20;
|
||||
break;
|
||||
case 25:
|
||||
persist_mode = TSL2591_PERSIST_25;
|
||||
break;
|
||||
case 30:
|
||||
persist_mode = TSL2591_PERSIST_30;
|
||||
break;
|
||||
case 35:
|
||||
persist_mode = TSL2591_PERSIST_35;
|
||||
break;
|
||||
case 40:
|
||||
persist_mode = TSL2591_PERSIST_40;
|
||||
break;
|
||||
case 45:
|
||||
persist_mode = TSL2591_PERSIST_45;
|
||||
break;
|
||||
case 50:
|
||||
persist_mode = TSL2591_PERSIST_50;
|
||||
break;
|
||||
case 55:
|
||||
persist_mode = TSL2591_PERSIST_55;
|
||||
break;
|
||||
case 60:
|
||||
persist_mode = TSL2591_PERSIST_60;
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("Invalid persist filter");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = tsl2591_reg_write(dev, TSL2591_REG_PERSIST, persist_mode);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to set persist filter");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int tsl2591_set_gain(const struct device *dev, enum sensor_gain_tsl2591 gain)
|
||||
{
|
||||
struct tsl2591_data *data = dev->data;
|
||||
uint8_t gain_mode;
|
||||
int ret;
|
||||
|
||||
switch (gain) {
|
||||
case TSL2591_SENSOR_GAIN_LOW:
|
||||
data->again = TSL2591_GAIN_SCALE_LOW;
|
||||
gain_mode = TSL2591_GAIN_MODE_LOW;
|
||||
break;
|
||||
case TSL2591_SENSOR_GAIN_MED:
|
||||
data->again = TSL2591_GAIN_SCALE_MED;
|
||||
gain_mode = TSL2591_GAIN_MODE_MED;
|
||||
break;
|
||||
case TSL2591_SENSOR_GAIN_HIGH:
|
||||
data->again = TSL2591_GAIN_SCALE_HIGH;
|
||||
gain_mode = TSL2591_GAIN_MODE_HIGH;
|
||||
break;
|
||||
case TSL2591_SENSOR_GAIN_MAX:
|
||||
data->again = TSL2591_GAIN_SCALE_MAX;
|
||||
gain_mode = TSL2591_GAIN_MODE_MAX;
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("Invalid gain mode");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = tsl2591_reg_update(dev, TSL2591_REG_CONFIG, TSL2591_AGAIN_MASK, gain_mode);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to set gain mode");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tsl2591_set_integration(const struct device *dev, int32_t integration_time)
|
||||
{
|
||||
struct tsl2591_data *data = dev->data;
|
||||
uint8_t atime_mode;
|
||||
int ret;
|
||||
|
||||
switch (integration_time) {
|
||||
case 100:
|
||||
atime_mode = TSL2591_INTEGRATION_100MS;
|
||||
break;
|
||||
case 200:
|
||||
atime_mode = TSL2591_INTEGRATION_200MS;
|
||||
break;
|
||||
case 300:
|
||||
atime_mode = TSL2591_INTEGRATION_300MS;
|
||||
break;
|
||||
case 400:
|
||||
atime_mode = TSL2591_INTEGRATION_400MS;
|
||||
break;
|
||||
case 500:
|
||||
atime_mode = TSL2591_INTEGRATION_500MS;
|
||||
break;
|
||||
case 600:
|
||||
atime_mode = TSL2591_INTEGRATION_600MS;
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("Invalid integration time");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = tsl2591_reg_update(dev, TSL2591_REG_CONFIG, TSL2591_ATIME_MASK, atime_mode);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to set integration time");
|
||||
return ret;
|
||||
}
|
||||
|
||||
data->atime = integration_time;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tsl2591_attr_set(const struct device *dev, enum sensor_channel chan,
|
||||
enum sensor_attribute attr, const struct sensor_value *val)
|
||||
{
|
||||
const struct tsl2591_data *data = dev->data;
|
||||
int ret;
|
||||
|
||||
ret = tsl2591_reg_update(dev, TSL2591_REG_ENABLE, TSL2591_POWER_MASK, TSL2591_POWER_OFF);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Unable to power down device");
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TSL2591_TRIGGER
|
||||
if (attr == SENSOR_ATTR_UPPER_THRESH || attr == SENSOR_ATTR_LOWER_THRESH) {
|
||||
if (chan == SENSOR_CHAN_LIGHT) {
|
||||
ret = tsl2591_set_threshold(dev, attr, val);
|
||||
} else {
|
||||
LOG_ERR("Attribute not supported for channel");
|
||||
ret = -ENOTSUP;
|
||||
}
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch ((enum sensor_attribute_tsl2591)attr) {
|
||||
case SENSOR_ATTR_GAIN_MODE:
|
||||
ret = tsl2591_set_gain(dev, (enum sensor_gain_tsl2591)val->val1);
|
||||
break;
|
||||
case SENSOR_ATTR_INTEGRATION_TIME:
|
||||
ret = tsl2591_set_integration(dev, val->val1);
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_TSL2591_TRIGGER
|
||||
case SENSOR_ATTR_INT_PERSIST:
|
||||
ret = tsl2591_set_persist(dev, val->val1);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
LOG_ERR("Invalid sensor attribute");
|
||||
ret = -EINVAL;
|
||||
goto exit; /* So the compiler doesn't warn if triggers not enabled */
|
||||
}
|
||||
|
||||
exit:
|
||||
if (data->powered_on) {
|
||||
ret = tsl2591_reg_update(dev, TSL2591_REG_ENABLE, TSL2591_POWER_MASK,
|
||||
TSL2591_POWER_ON);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tsl2591_setup(const struct device *dev)
|
||||
{
|
||||
struct tsl2591_data *data = dev->data;
|
||||
uint8_t device_id;
|
||||
int ret;
|
||||
|
||||
ret = tsl2591_reg_write(dev, TSL2591_REG_CONFIG, TSL2591_SRESET);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to reset device");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = tsl2591_reg_read(dev, TSL2591_REG_ID, &device_id, 1U);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to read device ID");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (device_id != TSL2591_DEV_ID) {
|
||||
LOG_ERR("Device with ID 0x%02x is not supported", device_id);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* Set initial values to match sensor values on reset */
|
||||
data->again = TSL2591_GAIN_SCALE_LOW;
|
||||
data->atime = 100U;
|
||||
|
||||
ret = tsl2591_reg_write(dev, TSL2591_REG_ENABLE, TSL2591_POWER_ON);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to perform initial power up of device");
|
||||
return ret;
|
||||
}
|
||||
|
||||
data->powered_on = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tsl2591_init(const struct device *dev)
|
||||
{
|
||||
const struct tsl2591_config *config = dev->config;
|
||||
int ret;
|
||||
|
||||
if (!i2c_is_ready_dt(&config->i2c)) {
|
||||
LOG_ERR("I2C dev %s not ready", config->i2c.bus->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = tsl2591_setup(dev);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to setup device");
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TSL2591_TRIGGER
|
||||
ret = tsl2591_initialize_int(dev);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to initialize interrupt!");
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sensor_driver_api tsl2591_driver_api = {
|
||||
#ifdef CONFIG_TSL2591_TRIGGER
|
||||
.trigger_set = tsl2591_trigger_set,
|
||||
#endif
|
||||
.attr_set = tsl2591_attr_set,
|
||||
.sample_fetch = tsl2591_sample_fetch,
|
||||
.channel_get = tsl2591_channel_get};
|
||||
|
||||
#ifdef CONFIG_PM_DEVICE
|
||||
static int tsl2591_pm_action(const struct device *dev, enum pm_device_action action)
|
||||
{
|
||||
struct tsl2591_data *data = dev->data;
|
||||
int ret;
|
||||
|
||||
switch (action) {
|
||||
case PM_DEVICE_ACTION_RESUME:
|
||||
ret = tsl2591_reg_update(dev, TSL2591_REG_ENABLE, TSL2591_POWER_MASK,
|
||||
TSL2591_POWER_ON);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to power on device");
|
||||
return ret;
|
||||
}
|
||||
|
||||
data->powered_on = true;
|
||||
break;
|
||||
case PM_DEVICE_ACTION_SUSPEND:
|
||||
ret = tsl2591_reg_update(dev, TSL2591_REG_ENABLE, TSL2591_POWER_MASK,
|
||||
TSL2591_POWER_OFF);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to power off device");
|
||||
return ret;
|
||||
}
|
||||
|
||||
data->powered_on = false;
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("Unsupported PM action");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define TSL2591_INIT_INST(n) \
|
||||
static struct tsl2591_data tsl2591_data_##n; \
|
||||
static const struct tsl2591_config tsl2591_config_##n = { \
|
||||
.i2c = I2C_DT_SPEC_INST_GET(n), \
|
||||
IF_ENABLED(CONFIG_TSL2591_TRIGGER, \
|
||||
(.int_gpio = GPIO_DT_SPEC_INST_GET_OR(n, int_gpios, {0}),))}; \
|
||||
PM_DEVICE_DT_INST_DEFINE(n, tsl2591_pm_action); \
|
||||
SENSOR_DEVICE_DT_INST_DEFINE(n, tsl2591_init, PM_DEVICE_DT_INST_GET(n), &tsl2591_data_##n, \
|
||||
&tsl2591_config_##n, POST_KERNEL, \
|
||||
CONFIG_SENSOR_INIT_PRIORITY, &tsl2591_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(TSL2591_INIT_INST)
|
||||
151
drivers/sensor/tsl2591/tsl2591.h
Normal file
151
drivers/sensor/tsl2591/tsl2591.h
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Kurtis Dinelle
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_SENSOR_TSL2591_TSL2591_H_
|
||||
#define ZEPHYR_DRIVERS_SENSOR_TSL2591_TSL2591_H_
|
||||
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/drivers/sensor/tsl2591.h>
|
||||
|
||||
/* Device Identification */
|
||||
#define TSL2591_DEV_ID 0x50
|
||||
|
||||
/* Command: CMD:7 | TRANSACTION:6:5 | ADDR/SF:4:0 */
|
||||
#define TSL2591_NORMAL_CMD (BIT(7) | BIT(5))
|
||||
#define TSL2591_SPECIAL_CMD (BIT(7) | BIT(6) | BIT(5))
|
||||
#define TSL2591_CLEAR_INT_CMD (TSL2591_SPECIAL_CMD | 0x7)
|
||||
|
||||
/* Enable: (0x00): NPIEN:7 | SAI:6 | Reserved:5 | AIEN:4 | Reserved:3:2 | AEN:1 | PON:0 */
|
||||
#define TSL2591_POWER_MASK (BIT(1) | BIT(0))
|
||||
#define TSL2591_POWER_ON (BIT(1) | BIT(0))
|
||||
#define TSL2591_POWER_OFF (0)
|
||||
#define TSL2591_AEN_MASK (BIT(1))
|
||||
#define TSL2591_AEN_ON (BIT(1))
|
||||
#define TSL2591_AEN_OFF (0)
|
||||
#define TSL2591_AIEN_MASK (BIT(4))
|
||||
#define TSL2591_AIEN_ON (BIT(4))
|
||||
#define TSL2591_AIEN_OFF (0)
|
||||
|
||||
/* Config/Control: (0x01): SRESET:7 | Reserved:6 | AGAIN:5:4 | Reserved:3 | ATIME:2:0 */
|
||||
#define TSL2591_SRESET (BIT(7))
|
||||
#define TSL2591_AGAIN_MASK (BIT(5) | BIT(4))
|
||||
#define TSL2591_ATIME_MASK (BIT(2) | BIT(1) | BIT(0))
|
||||
|
||||
/* Status: (0x13): Reserved:7:6 | NPINTR:5 | AINT:4 | Reserved:3:1 | AVALID:0 */
|
||||
#define TSL2591_AVALID_MASK (BIT(0))
|
||||
|
||||
/* Register Addresses */
|
||||
#define TSL2591_REG_ENABLE 0x00
|
||||
#define TSL2591_REG_CONFIG 0x01
|
||||
#define TSL2591_REG_AILTL 0x04
|
||||
#define TSL2591_REG_AILTH 0x05
|
||||
#define TSL2591_REG_AIHTL 0x06
|
||||
#define TSL2591_REG_AIHTH 0x07
|
||||
#define TSL2591_REG_NPAILTL 0x08
|
||||
#define TSL2591_REG_NPAILTH 0x09
|
||||
#define TSL2591_REG_NPAIHTL 0x0A
|
||||
#define TSL2591_REG_NPAIHTH 0x0B
|
||||
#define TSL2591_REG_PERSIST 0x0C
|
||||
#define TSL2591_REG_PID 0x11
|
||||
#define TSL2591_REG_ID 0x12
|
||||
#define TSL2591_REG_STATUS 0x13
|
||||
#define TSL2591_REG_C0DATAL 0x14
|
||||
#define TSL2591_REG_C0DATAH 0x15
|
||||
#define TSL2591_REG_C1DATAL 0x16
|
||||
#define TSL2591_REG_C1DATAH 0x17
|
||||
|
||||
/* Integration Time Modes */
|
||||
#define TSL2591_INTEGRATION_100MS 0x00
|
||||
#define TSL2591_INTEGRATION_200MS 0x01
|
||||
#define TSL2591_INTEGRATION_300MS 0x02
|
||||
#define TSL2591_INTEGRATION_400MS 0x03
|
||||
#define TSL2591_INTEGRATION_500MS 0x04
|
||||
#define TSL2591_INTEGRATION_600MS 0x05
|
||||
|
||||
/* Gain Modes */
|
||||
#define TSL2591_GAIN_MODE_LOW 0x00
|
||||
#define TSL2591_GAIN_MODE_MED 0x10
|
||||
#define TSL2591_GAIN_MODE_HIGH 0x20
|
||||
#define TSL2591_GAIN_MODE_MAX 0x30
|
||||
|
||||
/* Gain Scales (Typical Values)
|
||||
* See datasheet, used only for lux calculation.
|
||||
*/
|
||||
#define TSL2591_GAIN_SCALE_LOW 1U
|
||||
#define TSL2591_GAIN_SCALE_MED 25U
|
||||
#define TSL2591_GAIN_SCALE_HIGH 400U
|
||||
#define TSL2591_GAIN_SCALE_MAX 9200U
|
||||
|
||||
/* Persistence Filters */
|
||||
#define TSL2591_PERSIST_EVERY 0x00
|
||||
#define TSL2591_PERSIST_1 0x01
|
||||
#define TSL2591_PERSIST_2 0x02
|
||||
#define TSL2591_PERSIST_3 0x03
|
||||
#define TSL2591_PERSIST_5 0x04
|
||||
#define TSL2591_PERSIST_10 0x05
|
||||
#define TSL2591_PERSIST_15 0x06
|
||||
#define TSL2591_PERSIST_20 0x07
|
||||
#define TSL2591_PERSIST_25 0x08
|
||||
#define TSL2591_PERSIST_30 0x09
|
||||
#define TSL2591_PERSIST_35 0x0A
|
||||
#define TSL2591_PERSIST_40 0x0B
|
||||
#define TSL2591_PERSIST_45 0x0C
|
||||
#define TSL2591_PERSIST_50 0x0D
|
||||
#define TSL2591_PERSIST_55 0x0E
|
||||
#define TSL2591_PERSIST_60 0x0F
|
||||
|
||||
/* Device factor coefficient for lux calculations */
|
||||
#define TSL2591_LUX_DF 408
|
||||
|
||||
/* Max integration time (in ms) for single step */
|
||||
#define TSL2591_MAX_TIME_STEP 105
|
||||
|
||||
/* Max ADC Counts */
|
||||
#define TSL2591_MAX_ADC 65535
|
||||
#define TSL2591_MAX_ADC_100 36863
|
||||
|
||||
struct tsl2591_config {
|
||||
const struct i2c_dt_spec i2c;
|
||||
#ifdef CONFIG_TSL2591_TRIGGER
|
||||
const struct gpio_dt_spec int_gpio;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct tsl2591_data {
|
||||
uint16_t vis_count;
|
||||
uint16_t ir_count;
|
||||
uint16_t again;
|
||||
uint16_t atime;
|
||||
bool powered_on;
|
||||
|
||||
#ifdef CONFIG_TSL2591_TRIGGER
|
||||
const struct device *dev;
|
||||
struct gpio_callback gpio_cb;
|
||||
sensor_trigger_handler_t th_handler;
|
||||
const struct sensor_trigger *th_trigger;
|
||||
|
||||
#if defined(CONFIG_TSL2591_TRIGGER_OWN_THREAD)
|
||||
K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_TSL2591_THREAD_STACK_SIZE);
|
||||
struct k_sem trig_sem;
|
||||
struct k_thread thread;
|
||||
#elif defined(CONFIG_TSL2591_TRIGGER_GLOBAL_THREAD)
|
||||
struct k_work work;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
int tsl2591_reg_update(const struct device *dev, uint8_t reg, uint8_t mask, uint8_t val);
|
||||
|
||||
#ifdef CONFIG_TSL2591_TRIGGER
|
||||
int tsl2591_trigger_set(const struct device *dev, const struct sensor_trigger *trig,
|
||||
sensor_trigger_handler_t handler);
|
||||
int tsl2591_initialize_int(const struct device *dev);
|
||||
#endif
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_SENSOR_TSL2591_TSL2591_H_ */
|
||||
156
drivers/sensor/tsl2591/tsl2591_trigger.c
Normal file
156
drivers/sensor/tsl2591/tsl2591_trigger.c
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Kurtis Dinelle
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "tsl2591.h"
|
||||
|
||||
LOG_MODULE_DECLARE(TSL2591, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static inline void tsl2591_setup_int(const struct device *dev, bool enable)
|
||||
{
|
||||
const struct tsl2591_config *config = dev->config;
|
||||
gpio_flags_t flags = enable ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE;
|
||||
|
||||
gpio_pin_interrupt_configure_dt(&config->int_gpio, flags);
|
||||
}
|
||||
|
||||
static void tsl2591_gpio_callback(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
ARG_UNUSED(pins);
|
||||
|
||||
struct tsl2591_data *data = CONTAINER_OF(cb, struct tsl2591_data, gpio_cb);
|
||||
|
||||
tsl2591_setup_int(data->dev, false);
|
||||
|
||||
#if defined(CONFIG_TSL2591_TRIGGER_OWN_THREAD)
|
||||
k_sem_give(&data->trig_sem);
|
||||
#elif defined(CONFIG_TSL2591_TRIGGER_GLOBAL_THREAD)
|
||||
k_work_submit(&data->work);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void tsl2591_handle_int(const struct device *dev)
|
||||
{
|
||||
struct tsl2591_data *data = dev->data;
|
||||
const struct tsl2591_config *config = dev->config;
|
||||
uint8_t clear_cmd;
|
||||
int ret;
|
||||
|
||||
/* Interrupt must be cleared manually */
|
||||
clear_cmd = TSL2591_CLEAR_INT_CMD;
|
||||
ret = i2c_write_dt(&config->i2c, &clear_cmd, 1U);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to clear interrupt");
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->th_handler != NULL) {
|
||||
data->th_handler(dev, data->th_trigger);
|
||||
}
|
||||
|
||||
tsl2591_setup_int(dev, true);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TSL2591_TRIGGER_OWN_THREAD
|
||||
static void tsl2591_thread(void *p1, void *p2, void *p3)
|
||||
{
|
||||
ARG_UNUSED(p2);
|
||||
ARG_UNUSED(p3);
|
||||
|
||||
struct tsl2591_data *data = p1;
|
||||
|
||||
while (1) {
|
||||
k_sem_take(&data->trig_sem, K_FOREVER);
|
||||
tsl2591_handle_int(data->dev);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TSL2591_TRIGGER_GLOBAL_THREAD
|
||||
static void tsl2591_work_handler(struct k_work *work)
|
||||
{
|
||||
struct tsl2591_data *data = CONTAINER_OF(work, struct tsl2591_data, work);
|
||||
|
||||
tsl2591_handle_int(data->dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
int tsl2591_trigger_set(const struct device *dev, const struct sensor_trigger *trig,
|
||||
sensor_trigger_handler_t handler)
|
||||
{
|
||||
struct tsl2591_data *data = dev->data;
|
||||
const struct tsl2591_config *config = dev->config;
|
||||
int ret;
|
||||
|
||||
if (!config->int_gpio.port) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (trig->chan != SENSOR_CHAN_LIGHT) {
|
||||
LOG_ERR("Unsupported sensor trigger channel");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (trig->type != SENSOR_TRIG_THRESHOLD) {
|
||||
LOG_ERR("Unsupported sensor trigger type");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
data->th_handler = handler;
|
||||
data->th_trigger = trig;
|
||||
tsl2591_setup_int(dev, true);
|
||||
|
||||
ret = tsl2591_reg_update(dev, TSL2591_REG_ENABLE, TSL2591_AIEN_MASK, TSL2591_AIEN_ON);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to enable interrupt on sensor");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tsl2591_initialize_int(const struct device *dev)
|
||||
{
|
||||
struct tsl2591_data *data = dev->data;
|
||||
const struct tsl2591_config *config = dev->config;
|
||||
int ret;
|
||||
|
||||
if (!gpio_is_ready_dt(&config->int_gpio)) {
|
||||
LOG_ERR("%s: gpio controller %s not ready", dev->name, config->int_gpio.port->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT | config->int_gpio.dt_flags);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to configure gpio pin for input");
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpio_init_callback(&data->gpio_cb, tsl2591_gpio_callback, BIT(config->int_gpio.pin));
|
||||
|
||||
ret = gpio_add_callback(config->int_gpio.port, &data->gpio_cb);
|
||||
if (ret < 0) {
|
||||
LOG_DBG("Failed to set gpio callback");
|
||||
return ret;
|
||||
}
|
||||
|
||||
data->dev = dev;
|
||||
|
||||
#if defined(CONFIG_TSL2591_TRIGGER_OWN_THREAD)
|
||||
ret = k_sem_init(&data->trig_sem, 0, K_SEM_MAX_LIMIT);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to initialize trigger semaphore");
|
||||
return ret;
|
||||
}
|
||||
|
||||
k_thread_create(&data->thread, data->thread_stack, CONFIG_TSL2591_THREAD_STACK_SIZE,
|
||||
tsl2591_thread, data, NULL, NULL,
|
||||
K_PRIO_COOP(CONFIG_TSL2591_THREAD_PRIORITY), 0, K_NO_WAIT);
|
||||
#elif defined(CONFIG_TSL2591_TRIGGER_GLOBAL_THREAD)
|
||||
data->work.handler = tsl2591_work_handler;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
17
dts/bindings/sensor/ams,tsl2591.yaml
Normal file
17
dts/bindings/sensor/ams,tsl2591.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Copyright (c) 2023 Kurtis Dinelle
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
OSRAM ams TSL2591 ambient light sensor.
|
||||
|
||||
compatible: "ams,tsl2591"
|
||||
|
||||
include: [sensor-device.yaml, i2c-device.yaml]
|
||||
|
||||
properties:
|
||||
int-gpios:
|
||||
type: phandle-array
|
||||
description: |
|
||||
The interrupt pin of the TSL2591 is open-drain, active low.
|
||||
If connected directly, the MCU pin should be configured
|
||||
as pull-up, active low.
|
||||
68
include/zephyr/drivers/sensor/tsl2591.h
Normal file
68
include/zephyr/drivers/sensor/tsl2591.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Kurtis Dinelle
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Extended public API for AMS's TSL2591 ambient light sensor
|
||||
*
|
||||
* This exposes attributes for the TSL2591 which can be used for
|
||||
* setting the on-chip gain, integration time, and persist filter parameters.
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_TSL2591_H_
|
||||
#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_TSL2591_H_
|
||||
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum sensor_attribute_tsl2591 {
|
||||
/* Sensor ADC Gain Mode
|
||||
* Rather than set this value directly, can only be set to operate in one of four modes:
|
||||
*
|
||||
* TSL2591_SENSOR_GAIN_LOW
|
||||
* TSL2591_SENSOR_GAIN_MED
|
||||
* TSL2591_SENSOR_GAIN_HIGH
|
||||
* TSL2591_SENSOR_GAIN_MAX
|
||||
*
|
||||
* See datasheet for actual typical gain scales these modes correspond to.
|
||||
*/
|
||||
SENSOR_ATTR_GAIN_MODE = SENSOR_ATTR_PRIV_START + 1,
|
||||
|
||||
/* Sensor ADC Integration Time (in ms)
|
||||
* Can only be set to one of six values:
|
||||
*
|
||||
* 100, 200, 300, 400, 500, or 600
|
||||
*/
|
||||
SENSOR_ATTR_INTEGRATION_TIME,
|
||||
|
||||
/* Sensor ALS Interrupt Persist Filter
|
||||
* Represents the number of consecutive sensor readings outside of a set threshold
|
||||
* before triggering an interrupt. Can only be set to one of sixteen values:
|
||||
*
|
||||
* 0, 1, 2, 3, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, or 60
|
||||
*
|
||||
* Setting this to 0 causes an interrupt to generate every ALS cycle,
|
||||
* regardless of threshold.
|
||||
* Setting this to 1 is equivalent to the no-persist interrupt mode.
|
||||
*/
|
||||
SENSOR_ATTR_INT_PERSIST
|
||||
};
|
||||
|
||||
enum sensor_gain_tsl2591 {
|
||||
TSL2591_SENSOR_GAIN_LOW,
|
||||
TSL2591_SENSOR_GAIN_MED,
|
||||
TSL2591_SENSOR_GAIN_HIGH,
|
||||
TSL2591_SENSOR_GAIN_MAX
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_TSL2591_H_ */
|
||||
|
|
@ -932,3 +932,9 @@ test_i2c_ens160: ens160@83 {
|
|||
reg = <0x83>;
|
||||
int-gpios = <&test_gpio 0 0>;
|
||||
};
|
||||
|
||||
test_i2c_tsl2591: tsl2591@84 {
|
||||
compatible = "ams,tsl2591";
|
||||
reg = <0x84>;
|
||||
int-gpios = <&test_gpio 0 0>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ CONFIG_TMAG5170_TRIGGER_GLOBAL_THREAD=y
|
|||
CONFIG_TMD2620_TRIGGER_GLOBAL_THREAD=y
|
||||
CONFIG_TMP007_TRIGGER_GLOBAL_THREAD=y
|
||||
CONFIG_TSL2540_TRIGGER_GLOBAL_THREAD=y
|
||||
CONFIG_TSL2591_TRIGGER_GLOBAL_THREAD=y
|
||||
CONFIG_VCNL4040_TRIGGER_GLOBAL_THREAD=y
|
||||
CONFIG_WSEN_HIDS_TRIGGER_GLOBAL_THREAD=y
|
||||
CONFIG_WSEN_TIDS_TRIGGER_GLOBAL_THREAD=y
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ CONFIG_TMAG5170_TRIGGER_NONE=y
|
|||
CONFIG_TMD2620_TRIGGER_NONE=y
|
||||
CONFIG_TMP007_TRIGGER_NONE=y
|
||||
CONFIG_TSL2540_TRIGGER_NONE=y
|
||||
CONFIG_TSL2591_TRIGGER_NONE=y
|
||||
CONFIG_VCNL4040_TRIGGER_NONE=y
|
||||
CONFIG_WSEN_HIDS_TRIGGER_NONE=y
|
||||
CONFIG_WSEN_TIDS_TRIGGER_NONE=y
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ CONFIG_TCN75A_TRIGGER_OWN_THREAD=y
|
|||
CONFIG_TMAG5170_TRIGGER_OWN_THREAD=y
|
||||
CONFIG_TMP007_TRIGGER_OWN_THREAD=y
|
||||
CONFIG_TSL2540_TRIGGER_OWN_THREAD=y
|
||||
CONFIG_TSL2591_TRIGGER_OWN_THREAD=y
|
||||
CONFIG_VCNL4040_TRIGGER_OWN_THREAD=y
|
||||
CONFIG_WSEN_HIDS_TRIGGER_OWN_THREAD=y
|
||||
CONFIG_WSEN_TIDS_TRIGGER_OWN_THREAD=y
|
||||
|
|
|
|||
Loading…
Reference in a new issue