diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 6ea5bc6e6af..e33e4340741 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -46,6 +46,8 @@ config SENSOR_DEBUG source "drivers/sensor/Kconfig.bma280" +source "drivers/sensor/Kconfig.isl29035" + source "drivers/sensor/Kconfig.mcp9808" source "drivers/sensor/Kconfig.sx9500" diff --git a/drivers/sensor/Kconfig.isl29035 b/drivers/sensor/Kconfig.isl29035 new file mode 100644 index 00000000000..25db6e91b91 --- /dev/null +++ b/drivers/sensor/Kconfig.isl29035 @@ -0,0 +1,225 @@ +# Kconfig.isl29035 - ISL29035 light sensor configuration options + +# +# Copyright (c) 2016 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +menuconfig ISL29035 + bool + prompt "ISL29035 light sensor" + default n + depends on SENSOR && I2C && NANO_TIMERS && NANO_TIMEOUTS + help + Enable driver for the ISL29035 light sensor. + +config ISL29035_NAME + string + prompt "Driver name" + default "ISL29035" + depends on ISL29035 + help + Device name with which the ISL29035 sensor is identified. + +config ISL29035_INIT_PRIORITY + int + prompt "Init priority" + default 70 + depends on ISL29035 + help + Device driver initialization priority for ISL29035. + The device should be initialized after I2C. + +config ISL29035_I2C_MASTER_DEV_NAME + string + prompt "I2C Master" + depends on ISL29035 + default "I2C0" + help + The device name of the I2C master device to which the ISL29035 + chip is connected. + +config ISL29035_FIBER_PRIORITY + int + prompt "Fiber priority" + depends on ISL29035 + default 10 + help + Priority of fiber used to handle the timer and threshold triggers. + +choice + prompt "Full scale lux range" + default ISL29035_LUX_RANGE_1K + depends on ISL29035 + help + Maximum allowable lux value. Lower range values offer better + resolution. + +config ISL29035_LUX_RANGE_1K + bool + prompt "1000" + +config ISL29035_LUX_RANGE_4K + bool + prompt "4000" + +config ISL29035_LUX_RANGE_16K + bool + prompt "16000" + +config ISL29035_LUX_RANGE_64K + bool + prompt "64000" + +endchoice + +choice + prompt "Integration time" + default ISL29035_INTEGRATION_TIME_105K + depends on ISL29035 + help + The sampling period of the internal ADC of the light sensor. + Lower integration time values mean lower ADC resolution. + +config ISL29035_INTEGRATION_TIME_26 + bool + prompt "0.0256 ms" + +config ISL29035_INTEGRATION_TIME_410 + bool + prompt "0.41 ms" + +config ISL29035_INTEGRATION_TIME_6500 + bool + prompt "6.5 ms" + +config ISL29035_INTEGRATION_TIME_105K + bool + prompt "105 ms" + +endchoice + +choice + prompt "Active sensing mode" + depends on ISL29035 + default ISL29035_MODE_ALS + help + Sensing mode in which the ISL29035 will function. The chip can be + configured either for either ambinet light or infrared sensing. + +config ISL29035_MODE_ALS + bool + prompt "ambient light" + help + Sensing mode for ambient light spectrum. + +config ISL29035_MODE_IR + bool + prompt "infrared" + help + Sensing mode for infrared spectrum. + +endchoice + +choice + prompt "Trigger mode" + depends on ISL29035 && ISL29035_MODE_ALS && GPIO + default ISL29035_TRIGGER_NONE + help + Specify the type of triggering to be used by the driver. + Only available for ambient light sensing mode. + +config ISL29035_TRIGGER_NONE + bool + prompt "No trigger" + +config ISL29035_TRIGGER_GLOBAL_FIBER + bool + prompt "Use global fiber" + depends on GPIO + select ISL29035_TRIGGER + select SENSOR_DELAYED_WORK + +config ISL29035_TRIGGER_OWN_FIBER + bool + prompt "Use own fiber" + depends on GPIO + select ISL29035_TRIGGER + +endchoice + +config ISL29035_TRIGGER + bool + depends on ISL29035 + +config ISL29035_GPIO_DEV_NAME + string + prompt "GPIO device" + default "GPIO_0" + depends on ISL29035 && ISL29035_TRIGGER + help + The device name of the GPIO device to which the ISL29035 interrupt + pin is connected. + +config ISL29035_GPIO_PIN_NUM + int + prompt "GPIO pin number" + default 0 + depends on ISL29035 && ISL29035_TRIGGER + help + The number of the GPIO pin to which the ISL29035 interrupt pin is + connected. + +config ISL29035_FIBER_PRIORITY + int + prompt "Fiber priority" + depends on ISL29035 && ISL29035_TRIGGER_OWN_FIBER + default 10 + help + Priority of fiber used by the driver to handle interrupts. + +config ISL29035_FIBER_STACK_SIZE + int + prompt "Fiber stack size" + depends on ISL29035 && ISL29035_TRIGGER_OWN_FIBER + default 1024 + help + Stack size of fiber used by the driver to handle interrupts. + +choice + prompt "Interrupt persist cycles" + depends on ISL29035 && ISL29035_TRIGGER + default ISL29035_INT_PERSIST_1 + help + Number of consecutive intergration cycles for which the data samples + need to remain outside the threshold window in order for the interrupt + to be triggered. + +config ISL29035_INT_PERSIST_1 + bool + prompt "1" + +config ISL29035_INT_PERSIST_4 + bool + prompt "4" + +config ISL29035_INT_PERSIST_8 + bool + prompt "8" + +config ISL29035_INT_PERSIST_16 + bool + prompt "16" + +endchoice diff --git a/drivers/sensor/Makefile b/drivers/sensor/Makefile index 8fb03d70c3b..0c29f6179cd 100644 --- a/drivers/sensor/Makefile +++ b/drivers/sensor/Makefile @@ -4,6 +4,8 @@ obj-$(CONFIG_SENSOR_DELAYED_WORK) += sensor.o obj-$(CONFIG_BMA280) += sensor_bma280.o obj-$(CONFIG_BMA280_TRIGGER) += sensor_bma280_trigger.o +obj-$(CONFIG_ISL29035) += sensor_isl29035.o +obj-$(CONFIG_ISL29035_TRIGGER) += sensor_isl29035_trigger.o obj-$(CONFIG_MCP9808) += sensor_mcp9808.o obj-$(CONFIG_MCP9808_TRIGGER) += sensor_mcp9808_trigger.o obj-$(CONFIG_SX9500) += sensor_sx9500.o diff --git a/drivers/sensor/sensor_isl29035.c b/drivers/sensor/sensor_isl29035.c new file mode 100644 index 00000000000..263599174b2 --- /dev/null +++ b/drivers/sensor/sensor_isl29035.c @@ -0,0 +1,202 @@ +/* sensor_isl29035.c - driver for ISL29035 light sensor */ + +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "sensor_isl29035.h" + +int isl29035_write_reg(struct isl29035_driver_data *drv_data, + uint8_t reg, uint8_t val) +{ + uint8_t tx_buf[2] = {reg, val}; + + return i2c_write(drv_data->i2c, tx_buf, sizeof(tx_buf), + ISL29035_I2C_ADDRESS); +} + +int isl29035_read_reg(struct isl29035_driver_data *drv_data, + uint8_t reg, uint8_t *val) +{ + struct i2c_msg msgs[2] = { + { + .buf = ®, + .len = 1, + .flags = I2C_MSG_WRITE | I2C_MSG_RESTART, + }, + { + .buf = val, + .len = 1, + .flags = I2C_MSG_READ | I2C_MSG_STOP, + } + }; + + return i2c_transfer(drv_data->i2c, msgs, 2, ISL29035_I2C_ADDRESS); +} + +int isl29035_update_reg(struct isl29035_driver_data *drv_data, + uint8_t reg, uint8_t mask, uint8_t val) +{ + uint8_t old_val = 0; + uint8_t new_val; + + if (isl29035_read_reg(drv_data, reg, &old_val) != DEV_OK) { + return DEV_FAIL; + } + + new_val = old_val & ~mask; + new_val |= val & mask; + + return isl29035_write_reg(drv_data, reg, new_val); +} + +static int isl29035_sample_fetch(struct device *dev) +{ + struct isl29035_driver_data *drv_data = dev->driver_data; + uint8_t msb, lsb; + int ret; + + ret = isl29035_read_reg(drv_data, ISL29035_DATA_MSB_REG, &msb); + if (ret != DEV_OK) { + return DEV_FAIL; + } + + ret = isl29035_read_reg(drv_data, ISL29035_DATA_LSB_REG, &lsb); + if (ret != DEV_OK) { + return DEV_FAIL; + } + + drv_data->data_sample = (msb << 8) + lsb; + + return DEV_OK; +} + +static int isl29035_channel_get(struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + struct isl29035_driver_data *drv_data = dev->driver_data; + uint64_t tmp; + +#if CONFIG_ISL29035_MODE_ALS + /* val = sample_val * lux_range / (2 ^ adc_data_bits) */ + tmp = (uint64_t)drv_data->data_sample * ISL29035_LUX_RANGE; + val->type = SENSOR_TYPE_INT_PLUS_MICRO; + val->val1 = tmp >> ISL29035_ADC_DATA_BITS; + tmp = (tmp & ISL29035_ADC_DATA_MASK) * 1000000; + val->val2 = tmp >> ISL29035_ADC_DATA_BITS; +#elif CONFIG_ISL29035_MODE_IR + ARG_UNUSED(tmp); + val->type = SENSOR_TYPE_INT; + val->val1 = drv_data->data_sample; +#endif + + return DEV_OK; +} + +static struct sensor_driver_api isl29035_api = { +#if CONFIG_ISL29035_TRIGGER + .attr_set = &isl29035_attr_set, + .trigger_set = &isl29035_trigger_set, +#endif + .sample_fetch = &isl29035_sample_fetch, + .channel_get = &isl29035_channel_get, +}; + +static int isl29035_init(struct device *dev) +{ + struct isl29035_driver_data *drv_data = dev->driver_data; + int ret; + + drv_data->i2c = device_get_binding(CONFIG_ISL29035_I2C_MASTER_DEV_NAME); + if (drv_data->i2c == NULL) { + DBG("Failed to get I2C device.\n"); + return DEV_INVALID_CONF; + } + + dev->driver_api = &isl29035_api; + drv_data->data_sample = 0; + + /* clear blownout status bit */ + ret = isl29035_update_reg(drv_data, ISL29035_ID_REG, + ISL29035_BOUT_MASK, 0); + if (ret != DEV_OK) { + DBG("Failed to clear blownout status bit.\n"); + return ret; + } + + /* set command registers to set default attributes */ + ret = isl29035_write_reg(drv_data, ISL29035_COMMAND_I_REG, 0); + if (ret != DEV_OK) { + DBG("Failed to clear COMMAND-I.\n"); + return ret; + } + + ret = isl29035_write_reg(drv_data, ISL29035_COMMAND_II_REG, 0); + if (ret != DEV_OK) { + DBG("Failed to clear COMMAND-II.\n"); + return ret; + } + + /* set operation mode */ + ret = isl29035_update_reg(drv_data, + ISL29035_COMMAND_I_REG, ISL29035_OPMODE_MASK, + ISL29035_ACTIVE_OPMODE << ISL29035_OPMODE_SHIFT); + if (ret != DEV_OK) { + DBG("Failed to set opmode.\n"); + return ret; + } + + /* set lux range */ + ret = isl29035_update_reg(drv_data, + ISL29035_COMMAND_II_REG, ISL29035_LUX_RANGE_MASK, + ISL29035_LUX_RANGE_IDX << ISL29035_LUX_RANGE_SHIFT); + if (ret != DEV_OK) { + DBG("Failed to set lux range.\n"); + return ret; + } + + /* set ADC resolution */ + ret = isl29035_update_reg(drv_data, + ISL29035_COMMAND_II_REG, ISL29035_ADC_RES_MASK, + ISL29035_ADC_RES_IDX << ISL29035_ADC_RES_SHIFT); + if (ret != DEV_OK) { + DBG("Failed to set ADC resolution.\n"); + return ret; + } + +#ifdef CONFIG_ISL29035_TRIGGER + ret = isl29035_init_interrupt(dev); + if (ret != DEV_OK) { + DBG("Failed to initialize interrupt.\n"); + return ret; + } +#endif + + return DEV_OK; +} + +struct isl29035_driver_data isl29035_data; + +DEVICE_INIT(isl29035_dev, CONFIG_ISL29035_NAME, &isl29035_init, + &isl29035_data, NULL, SECONDARY, CONFIG_ISL29035_INIT_PRIORITY); diff --git a/drivers/sensor/sensor_isl29035.h b/drivers/sensor/sensor_isl29035.h new file mode 100644 index 00000000000..db8ee804f49 --- /dev/null +++ b/drivers/sensor/sensor_isl29035.h @@ -0,0 +1,159 @@ +/* sensor_isl29035.h - header file for ISL29035 light sensor driver */ + +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SENSOR_ISL29035_H_ +#define _SENSOR_ISL29035_H_ + +#include +#include +#include + +#ifndef CONFIG_SENSOR_DEBUG +#define DBG(...) { ; } +#else +#include +#define DBG printk +#endif /* CONFIG_SENSOR_DEBUG */ + +#define ISL29035_I2C_ADDRESS 0x44 + +#define ISL29035_COMMAND_I_REG 0x00 +#define ISL29035_OPMODE_SHIFT 5 +#define ISL29035_OPMODE_MASK (7 << ISL29035_OPMODE_SHIFT) +#define ISL29035_INT_BIT_SHIFT 2 +#define ISL29035_INT_BIT_MASK (1 << ISL29035_INT_BIT_SHIFT) +#define ISL29035_INT_PRST_SHIFT 0 +#define ISL29035_INT_PRST_MASK (3 << ISL29035_INT_BIT_SHIFT) + +#define ISL29035_OPMODE_OFF 0 +#define ISL29035_OPMODE_ALS_ONCE 1 +#define ISL29035_OPMODE_IR_ONCE 2 +#define ISL29035_OPMODE_ALS_CONT 5 +#define ISL29035_OPMODE_IR_CONT 6 + +#define ISL29035_COMMAND_II_REG 0x01 +#define ISL29035_LUX_RANGE_SHIFT 0 +#define ISL29035_LUX_RANGE_MASK (3 << ISL29035_LUX_RANGE_SHIFT) +#define ISL29035_ADC_RES_SHIFT 2 +#define ISL29035_ADC_RES_MASK (3 << ISL29035_ADC_RES_SHIFT) + +#define ISL29035_DATA_LSB_REG 0x02 +#define ISL29035_DATA_MSB_REG 0x03 +#define ISL29035_INT_LT_LSB_REG 0x04 +#define ISL29035_INT_LT_MSB_REG 0x05 +#define ISL29035_INT_HT_LSB_REG 0x06 +#define ISL29035_INT_HT_MSB_REG 0x07 + +#define ISL29035_ID_REG 0x0F +#define ISL29035_BOUT_SHIFT 7 +#define ISL29035_BOUT_MASK (1 << ISL29035_BOUT_SHIFT) +#define ISL29035_ID_SHIFT 3 +#define ISL29035_ID_MASK (3 << ISL29035_ID_SHIFT) + +#if CONFIG_ISL29035_MODE_ALS + #define ISL29035_ACTIVE_OPMODE ISL29035_OPMODE_ALS_CONT + #define ISL29035_ACTIVE_CHAN SENSOR_CHAN_LIGHT +#elif CONFIG_ISL29035_MODE_IR + #define ISL29035_ACTIVE_OPMODE ISL29035_OPMODE_IR_CONT + #define ISL29035_ACTIVE_CHAN SENSOR_CHAN_IR +#endif + +#if CONFIG_ISL29035_LUX_RANGE_1K + #define ISL29035_LUX_RANGE_IDX 0 + #define ISL29035_LUX_RANGE 1000 +#elif CONFIG_ISL29035_LUX_RANGE_4 + #define ISL29035_LUX_RANGE_IDX 1 + #define ISL29035_LUX_RANGE 4000 +#elif CONFIG_ISL29035_LUX_RANGE_16K + #define ISL29035_LUX_RANGE_IDX 2 + #define ISL29035_LUX_RANGE 16000 +#elif CONFIG_ISL29035_LUX_RANGE_64K + #define ISL29035_LUX_RANGE_IDX 3 + #define ISL29035_LUX_RANGE 64000 +#endif + +#if CONFIG_ISL29035_INTEGRATION_TIME_26 + #define ISL29035_ADC_RES_IDX 3 +#elif CONFIG_ISL29035_INTEGRATION_TIME_410 + #define ISL29035_ADC_RES_IDX 2 +#elif CONFIG_ISL29035_INTEGRATION_TIME_6500 + #define ISL29035_ADC_RES_IDX 1 +#elif CONFIG_ISL29035_INTEGRATION_TIME_105K + #define ISL29035_ADC_RES_IDX 0 +#endif + +#define ISL29035_ADC_DATA_BITS (16 - 4 * ISL29035_ADC_RES_IDX) +#define ISL29035_ADC_DATA_MASK (0xFFFF >> (16 - ISL29035_ADC_DATA_BITS)) + +#if CONFIG_ISL29035_INT_PERSIST_1 + #define ISL29035_INT_PRST_IDX 0 + #define ISL29035_INT_PRST_CYCLES 1 +#elif CONFIG_ISL29035_INT_PERSIST_4 + #define ISL29035_INT_PRST_IDX 1 + #define ISL29035_INT_PRST_CYCLES 4 +#elif CONFIG_ISL29035_INT_PERSIST_8 + #define ISL29035_INT_PRST_IDX 2 + #define ISL29035_INT_PRST_CYCLES 8 +#elif CONFIG_ISL29035_INT_PERSIST_16 + #define ISL29035_INT_PRST_IDX 3 + #define ISL29035_INT_PRST_CYCLES 16 +#endif + +struct isl29035_driver_data { + struct device *i2c; + uint16_t data_sample; + +#if CONFIG_ISL29035_TRIGGER + struct device *gpio; + + struct sensor_trigger th_trigger; + sensor_trigger_handler_t th_handler; + +#if defined(CONFIG_ISL29035_TRIGGER_OWN_FIBER) + char __stack fiber_stack[CONFIG_ISL29035_FIBER_STACK_SIZE]; + struct nano_sem gpio_sem; +#elif defined(CONFIG_ISL29035_TRIGGER_GLOBAL_FIBER) + struct sensor_work work; +#endif + +#endif /* CONFIG_ISL29035_TRIGGER */ +}; + +#ifdef CONFIG_ISL29035_TRIGGER +int isl29035_write_reg(struct isl29035_driver_data *drv_data, + uint8_t reg, uint8_t val); + +int isl29035_read_reg(struct isl29035_driver_data *drv_data, + uint8_t reg, uint8_t *val); + +int isl29035_update_reg(struct isl29035_driver_data *drv_data, + uint8_t reg, uint8_t mask, uint8_t val); + +int isl29035_attr_set(struct device *dev, + enum sensor_channel chan, + enum sensor_attribute attr, + const struct sensor_value *val); + +int isl29035_trigger_set(struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); + +int isl29035_init_interrupt(struct device *dev); +#endif + +#endif /* _SENSOR_ISL29035_H_ */ diff --git a/drivers/sensor/sensor_isl29035_trigger.c b/drivers/sensor/sensor_isl29035_trigger.c new file mode 100644 index 00000000000..cbf66790e6c --- /dev/null +++ b/drivers/sensor/sensor_isl29035_trigger.c @@ -0,0 +1,178 @@ +/* sensor_isl29035.c - trigger support for ISL29035 light sensor */ + +/* + * Copyright (c) 2016 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "sensor_isl29035.h" + +extern struct isl29035_driver_data isl29035_data; + +static uint16_t isl29035_lux_processed_to_raw(struct sensor_value const *val) +{ + uint64_t raw_val, ival, uval; + + ival = val->val1; + if (val->type == SENSOR_TYPE_INT) { + uval = 0; + } else { + uval = val->val2; + } + + /* raw_val = val * (2 ^ adc_data_bits) / lux_range */ + raw_val = (ival << ISL29035_ADC_DATA_BITS) + + (uval << ISL29035_ADC_DATA_BITS) / 1000000; + + return raw_val / ISL29035_LUX_RANGE; +} + +int isl29035_attr_set(struct device *dev, + enum sensor_channel chan, + enum sensor_attribute attr, + const struct sensor_value *val) +{ + struct isl29035_driver_data *drv_data = dev->driver_data; + uint8_t lsb_reg, msb_reg; + uint16_t raw_val; + + if (attr == SENSOR_ATTR_UPPER_THRESH) { + lsb_reg = ISL29035_INT_HT_LSB_REG; + msb_reg = ISL29035_INT_HT_MSB_REG; + } else if (attr == SENSOR_ATTR_LOWER_THRESH) { + lsb_reg = ISL29035_INT_LT_LSB_REG; + msb_reg = ISL29035_INT_LT_MSB_REG; + } else { + return DEV_INVALID_OP; + } + + raw_val = isl29035_lux_processed_to_raw(val); + + if (isl29035_write_reg(drv_data, lsb_reg, raw_val & 0xFF) != DEV_OK || + isl29035_write_reg(drv_data, msb_reg, raw_val >> 8) != DEV_OK) { + DBG("Failed to set attribute.\n"); + return DEV_FAIL; + } + + return DEV_OK; +} + +static void isl29035_gpio_callback(struct device *dev, uint32_t pin) +{ + gpio_pin_disable_callback(dev, pin); + +#if defined(CONFIG_ISL29035_TRIGGER_OWN_FIBER) + nano_sem_give(&isl29035_data.gpio_sem); +#elif defined(CONFIG_ISL29035_TRIGGER_GLOBAL_FIBER) + nano_isr_fifo_put(sensor_get_work_fifo(), &isl29035_data.work); +#endif +} + +static void isl29035_fiber_cb(void *arg) +{ + struct device *dev = arg; + struct isl29035_driver_data *drv_data = dev->driver_data; + uint8_t val; + + /* clear interrupt */ + isl29035_read_reg(drv_data, ISL29035_COMMAND_I_REG, &val); + + if (drv_data->th_handler != NULL) { + drv_data->th_handler(dev, &drv_data->th_trigger); + } + + gpio_pin_enable_callback(drv_data->gpio, CONFIG_ISL29035_GPIO_PIN_NUM); +} + +#ifdef CONFIG_ISL29035_TRIGGER_OWN_FIBER +static void isl29035_fiber(int ptr, int unused) +{ + struct device *dev = INT_TO_POINTER(ptr); + struct isl29035_driver_data *drv_data = dev->driver_data; + + ARG_UNUSED(unused); + + while (1) { + nano_fiber_sem_take(&drv_data->gpio_sem, TICKS_UNLIMITED); + isl29035_fiber_cb(dev); + } +} +#endif + +int isl29035_trigger_set(struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + struct isl29035_driver_data *drv_data = dev->driver_data; + + /* disable interrupt callback while changing parameters */ + gpio_pin_disable_callback(drv_data->gpio, CONFIG_ISL29035_GPIO_PIN_NUM); + + drv_data->th_handler = handler; + drv_data->th_trigger = *trig; + + /* enable interrupt callback */ + gpio_pin_enable_callback(drv_data->gpio, CONFIG_ISL29035_GPIO_PIN_NUM); + + return DEV_OK; +} + +int isl29035_init_interrupt(struct device *dev) +{ + struct isl29035_driver_data *drv_data = dev->driver_data; + int ret; + + /* set interrupt persistence */ + ret = isl29035_update_reg(drv_data, + ISL29035_COMMAND_I_REG, ISL29035_INT_PRST_MASK, + ISL29035_INT_PRST_IDX << ISL29035_INT_PRST_SHIFT); + if (ret != DEV_OK) { + DBG("Failed to set interrupt persistence cycles.\n"); + return DEV_FAIL; + } + + /* setup gpio interrupt */ + drv_data->gpio = device_get_binding(CONFIG_ISL29035_GPIO_DEV_NAME); + if (drv_data->gpio == NULL) { + DBG("Failed to get GPIO device.\n"); + return DEV_INVALID_CONF; + } + + gpio_pin_configure(drv_data->gpio, CONFIG_ISL29035_GPIO_PIN_NUM, + GPIO_DIR_IN | GPIO_INT | GPIO_INT_LEVEL | + GPIO_INT_ACTIVE_LOW | GPIO_INT_DEBOUNCE); + + ret = gpio_set_callback(drv_data->gpio, isl29035_gpio_callback); + if (ret != DEV_OK) { + DBG("Failed to set gpio callback.\n"); + return DEV_FAIL; + } + +#if defined(CONFIG_ISL29035_TRIGGER_OWN_FIBER) + nano_sem_init(&drv_data->gpio_sem); + + fiber_start(drv_data->fiber_stack, CONFIG_ISL29035_FIBER_STACK_SIZE, + (nano_fiber_entry_t)isl29035_fiber, POINTER_TO_INT(dev), + 0, CONFIG_ISL29035_FIBER_PRIORITY, 0); +#elif defined(CONFIG_ISL29035_TRIGGER_GLOBAL_FIBER) + drv_data->work.handler = isl29035_fiber_cb; + drv_data->work.arg = dev; +#endif + + return DEV_OK; +}