/*
 * wdt.c
 *
 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
 *
 * IO dispatcher for a shared memory channel driver.
 *
 * Copyright (C) 2010 Texas Instruments, Inc.
 *
 * This package is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */
#include <linux/types.h>

#include <dspbridge/dbdefs.h>
#include <dspbridge/dspdeh.h>
#include <dspbridge/dev.h>
#include <dspbridge/_chnl_sm.h>
#include <dspbridge/wdt.h>
#include <dspbridge/host_os.h>


#define OMAP34XX_WDT3_BASE 		(0x49000000 + 0x30000)
#define INT_34XX_WDT3_IRQ 		(36 + NR_IRQS)

static struct dsp_wdt_setting dsp_wdt;

void dsp_wdt_dpc(unsigned long data)
{
	struct deh_mgr *deh_mgr;
	dev_get_deh_mgr(dev_get_first(), &deh_mgr);
	if (deh_mgr)
		bridge_deh_notify(deh_mgr, DSP_WDTOVERFLOW, 0);
}

irqreturn_t dsp_wdt_isr(int irq, void *data)
{
	u32 value;
	/* ack wdt3 interrupt */
	value = __raw_readl(dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);
	__raw_writel(value, dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);

	tasklet_schedule(&dsp_wdt.wdt3_tasklet);
	return IRQ_HANDLED;
}

int dsp_wdt_init(void)
{
	int ret = 0;

	dsp_wdt.sm_wdt = NULL;
	dsp_wdt.reg_base = ioremap(OMAP34XX_WDT3_BASE, SZ_4K);
	if (!dsp_wdt.reg_base)
		return -ENOMEM;

	tasklet_init(&dsp_wdt.wdt3_tasklet, dsp_wdt_dpc, 0);

	dsp_wdt.fclk = clk_get(NULL, "wdt3_fck");

	if (!IS_ERR(dsp_wdt.fclk)) {
		dsp_wdt.iclk = clk_get(NULL, "wdt3_ick");
		if (IS_ERR(dsp_wdt.iclk)) {
			clk_put(dsp_wdt.fclk);
			dsp_wdt.fclk = NULL;
			ret = -EFAULT;
		}
	} else
		ret = -EFAULT;

	if (!ret)
		ret = request_irq(INT_34XX_WDT3_IRQ, dsp_wdt_isr, 0,
							"dsp_wdt", &dsp_wdt);

	/* Disable at this moment, it will be enabled when DSP starts */
	if (!ret)
		disable_irq(INT_34XX_WDT3_IRQ);

	return ret;
}

void dsp_wdt_sm_set(void *data)
{
	dsp_wdt.sm_wdt = data;
	dsp_wdt.sm_wdt->wdt_overflow = 5;	/* in seconds */
}


void dsp_wdt_exit(void)
{
	free_irq(INT_34XX_WDT3_IRQ, &dsp_wdt);
	tasklet_kill(&dsp_wdt.wdt3_tasklet);

	if (dsp_wdt.fclk)
		clk_put(dsp_wdt.fclk);
	if (dsp_wdt.iclk)
		clk_put(dsp_wdt.iclk);

	dsp_wdt.fclk = NULL;
	dsp_wdt.iclk = NULL;
	dsp_wdt.sm_wdt = NULL;

	if (dsp_wdt.reg_base)
		iounmap(dsp_wdt.reg_base);
	dsp_wdt.reg_base = NULL;
}

void dsp_wdt_enable(bool enable)
{
	u32 tmp;
	static bool wdt_enable;

	if (wdt_enable == enable || !dsp_wdt.fclk || !dsp_wdt.iclk)
		return;

	wdt_enable = enable;

	if (enable) {
		clk_enable(dsp_wdt.fclk);
		clk_enable(dsp_wdt.iclk);
		dsp_wdt.sm_wdt->wdt_setclocks = 1;
		tmp = __raw_readl(dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);
		__raw_writel(tmp, dsp_wdt.reg_base + OMAP3_WDT3_ISR_OFFSET);
		enable_irq(INT_34XX_WDT3_IRQ);
	} else {
		disable_irq(INT_34XX_WDT3_IRQ);
		dsp_wdt.sm_wdt->wdt_setclocks = 0;
		clk_disable(dsp_wdt.iclk);
		clk_disable(dsp_wdt.fclk);
	}
}
