/* ST Microelectronics STTS751 temperature sensor
 *
 * Copyright (c) 2019 STMicroelectronics
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Datasheet:
 * https://www.st.com/resource/en/datasheet/stts751.pdf
 */

#include <kernel.h>
#include <sensor.h>
#include <drivers/gpio.h>
#include <logging/log.h>

#include "stts751.h"

LOG_MODULE_DECLARE(STTS751, CONFIG_SENSOR_LOG_LEVEL);

/**
 * stts751_enable_int - enable selected int pin to generate interrupt
 */
static int stts751_enable_int(struct device *dev, int enable)
{
	struct stts751_data *stts751 = dev->driver_data;
	u8_t en = (enable) ? 0 : 1;

	return stts751_pin_event_route_set(stts751->ctx, en);
}

/**
 * stts751_trigger_set - link external trigger to event data ready
 */
int stts751_trigger_set(struct device *dev,
			  const struct sensor_trigger *trig,
			  sensor_trigger_handler_t handler)
{
	struct stts751_data *stts751 = dev->driver_data;

	if (trig->chan == SENSOR_CHAN_ALL) {
		stts751->thsld_handler = handler;
		if (handler) {
			return stts751_enable_int(dev, 1);
		} else {
			return stts751_enable_int(dev, 0);
		}
	}

	return -ENOTSUP;
}

/**
 * stts751_handle_interrupt - handle the thsld event
 * read data and call handler if registered any
 */
static void stts751_handle_interrupt(void *arg)
{
	struct device *dev = arg;
	struct stts751_data *stts751 = dev->driver_data;
	const struct stts751_config *cfg = dev->config->config_info;
	struct sensor_trigger thsld_trigger = {
		.type = SENSOR_TRIG_THRESHOLD,
	};
	stts751_status_t status;

	stts751_status_reg_get(stts751->ctx, &status);

	if (stts751->thsld_handler != NULL &&
	    (status.t_high || status.t_low)) {
		stts751->thsld_handler(dev, &thsld_trigger);
	}

	gpio_pin_enable_callback(stts751->gpio, cfg->event_pin);
}

static void stts751_gpio_callback(struct device *dev,
				  struct gpio_callback *cb, u32_t pins)
{
	const struct stts751_config *cfg = dev->config->config_info;
	struct stts751_data *stts751 =
		CONTAINER_OF(cb, struct stts751_data, gpio_cb);

	ARG_UNUSED(pins);

	gpio_pin_disable_callback(dev, cfg->event_pin);

#if defined(CONFIG_STTS751_TRIGGER_OWN_THREAD)
	k_sem_give(&stts751->gpio_sem);
#elif defined(CONFIG_STTS751_TRIGGER_GLOBAL_THREAD)
	k_work_submit(&stts751->work);
#endif /* CONFIG_STTS751_TRIGGER_OWN_THREAD */
}

#ifdef CONFIG_STTS751_TRIGGER_OWN_THREAD
static void stts751_thread(int dev_ptr, int unused)
{
	struct device *dev = INT_TO_POINTER(dev_ptr);
	struct stts751_data *stts751 = dev->driver_data;

	ARG_UNUSED(unused);

	while (1) {
		k_sem_take(&stts751->gpio_sem, K_FOREVER);
		stts751_handle_interrupt(dev);
	}
}
#endif /* CONFIG_STTS751_TRIGGER_OWN_THREAD */

#ifdef CONFIG_STTS751_TRIGGER_GLOBAL_THREAD
static void stts751_work_cb(struct k_work *work)
{
	struct stts751_data *stts751 =
		CONTAINER_OF(work, struct stts751_data, work);

	stts751_handle_interrupt(stts751->dev);
}
#endif /* CONFIG_STTS751_TRIGGER_GLOBAL_THREAD */

int stts751_init_interrupt(struct device *dev)
{
	struct stts751_data *stts751 = dev->driver_data;
	const struct stts751_config *cfg = dev->config->config_info;
	int ret;

	/* setup data ready gpio interrupt */
	stts751->gpio = device_get_binding(cfg->event_port);
	if (stts751->gpio == NULL) {
		LOG_DBG("Cannot get pointer to %s device", cfg->event_port);
		return -EINVAL;
	}

#if defined(CONFIG_STTS751_TRIGGER_OWN_THREAD)
	k_sem_init(&stts751->gpio_sem, 0, UINT_MAX);

	k_thread_create(&stts751->thread, stts751->thread_stack,
		       CONFIG_STTS751_THREAD_STACK_SIZE,
		       (k_thread_entry_t)stts751_thread, dev,
		       0, NULL, K_PRIO_COOP(CONFIG_STTS751_THREAD_PRIORITY),
		       0, K_NO_WAIT);
#elif defined(CONFIG_STTS751_TRIGGER_GLOBAL_THREAD)
	stts751->work.handler = stts751_work_cb;
	stts751->dev = dev;
#endif /* CONFIG_STTS751_TRIGGER_OWN_THREAD */

	ret = gpio_pin_configure(stts751->gpio, cfg->event_pin,
				 GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE |
				 GPIO_INT_ACTIVE_LOW | GPIO_INT_DEBOUNCE);
	if (ret < 0) {
		LOG_DBG("Could not configure gpio");
		return ret;
	}

	gpio_init_callback(&stts751->gpio_cb, stts751_gpio_callback,
			   BIT(cfg->event_pin));

	if (gpio_add_callback(stts751->gpio, &stts751->gpio_cb) < 0) {
		LOG_DBG("Could not set gpio callback");
		return -EIO;
	}

	/* Enable interrupt on high temperature */
	float temp_hi = (float) CONFIG_STTS751_TEMP_HI_THRESHOLD;
	float temp_lo = (float) CONFIG_STTS751_TEMP_LO_THRESHOLD;

	stts751_high_temperature_threshold_set(stts751->ctx,
					stts751_from_celsius_to_lsb(temp_hi));

	stts751_low_temperature_threshold_set(stts751->ctx,
					stts751_from_celsius_to_lsb(temp_lo));

	return gpio_pin_enable_callback(stts751->gpio, cfg->event_pin);
}
