/*
 * Copyright (c) 2015 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 <init.h>
#include <device.h>
#include <watchdog.h>
#include <ioapic.h>

#include "clk.h"
#include "qm_interrupt.h"
#include "qm_isr.h"
#include "qm_wdt.h"

struct wdt_data {
	struct nano_sem sem;
};

#ifdef CONFIG_WDT_QMSI_API_REENTRANCY
static struct wdt_data wdt_context;
#define WDT_CONTEXT (&wdt_context)
static const int reentrancy_protection = 1;
#else
#define WDT_CONTEXT (NULL)
static const int reentrancy_protection;
#endif /* CONFIG_WDT_QMSI_API_REENTRANCY */

static void wdt_reentrancy_init(struct device *dev)
{
	struct wdt_data *context = dev->driver_data;

	if (!reentrancy_protection) {
		return;
	}

	nano_sem_init(&context->sem);
	nano_sem_give(&context->sem);
}

static void wdt_critical_region_start(struct device *dev)
{
	struct wdt_data *context = dev->driver_data;

	if (!reentrancy_protection) {
		return;
	}

	nano_sem_take(&context->sem, TICKS_UNLIMITED);
}

static void wdt_critical_region_end(struct device *dev)
{
	struct wdt_data *context = dev->driver_data;

	if (!reentrancy_protection) {
		return;
	}

	nano_sem_give(&context->sem);
}

static void (*user_cb)(struct device *dev);

static void get_config(struct device *dev, struct wdt_config *cfg)
{
	cfg->timeout = QM_WDT[QM_WDT_0].wdt_torr;
	cfg->mode = ((QM_WDT[QM_WDT_0].wdt_cr & QM_WDT_MODE) >>
			QM_WDT_MODE_OFFSET);
	cfg->interrupt_fn = user_cb;
}

static int set_config(struct device *dev, struct wdt_config *cfg)
{
	int ret_val = 0;
	qm_wdt_config_t qm_cfg;

	user_cb = cfg->interrupt_fn;
	qm_cfg.timeout = cfg->timeout;
	qm_cfg.mode = (cfg->mode == WDT_MODE_RESET) ?
			QM_WDT_MODE_RESET : QM_WDT_MODE_INTERRUPT_RESET;
	qm_cfg.callback = (void *)user_cb;
	qm_cfg.callback_data = dev;

	wdt_critical_region_start(dev);

	if (qm_wdt_set_config(QM_WDT_0, &qm_cfg)) {
		ret_val = -EIO;
		goto wdt_config_return;
	}

	if (qm_wdt_start(QM_WDT_0)) {
		ret_val = -EIO;
	}

wdt_config_return:
	wdt_critical_region_end(dev);

	return ret_val;
}

static void reload(struct device *dev)
{
	qm_wdt_reload(QM_WDT_0);
}

static void enable(struct device *dev)
{
	clk_periph_enable(CLK_PERIPH_WDT_REGISTER | CLK_PERIPH_CLK);
}

static void disable(struct device *dev)
{
	clk_periph_disable(CLK_PERIPH_WDT_REGISTER);
}

static struct wdt_driver_api api = {
	.enable = enable,
	.disable = disable,
	.get_config = get_config,
	.set_config = set_config,
	.reload = reload,
};

static int init(struct device *dev)
{
	wdt_reentrancy_init(dev);

	IRQ_CONNECT(QM_IRQ_WDT_0, CONFIG_WDT_0_IRQ_PRI,
		    qm_wdt_isr_0, 0, IOAPIC_EDGE | IOAPIC_HIGH);

	/* Unmask watchdog interrupt */
	irq_enable(QM_IRQ_WDT_0);

	/* Route watchdog interrupt to Lakemont */
	QM_SCSS_INT->int_watchdog_mask &= ~BIT(0);

	return 0;
}

DEVICE_AND_API_INIT(wdt, CONFIG_WDT_0_NAME, init, WDT_CONTEXT, 0,
		    PRIMARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
		    (void *)&api);
