/*
 * ue_deh.c
 *
 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
 *
 * Implements upper edge DSP exception handling (DEH) functions.
 *
 * Copyright (C) 2005-2006 Texas Instruments, Inc.
 * Copyright (C) 2010 Felipe Contreras
 *
 * 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/kernel.h>
#include <linux/interrupt.h>
#include <plat/dmtimer.h>

#include <dspbridge/dbdefs.h>
#include <dspbridge/dspdeh.h>
#include <dspbridge/dev.h>
#include "_tiomap.h"
#include "_deh.h"

#include <dspbridge/io_sm.h>
#include <dspbridge/drv.h>
#include <dspbridge/wdt.h>

static u32 fault_addr;

static void mmu_fault_dpc(unsigned long data)
{
	struct deh_mgr *deh = (void *)data;

	if (!deh)
		return;

	bridge_deh_notify(deh, DSP_MMUFAULT, 0);
}

static irqreturn_t mmu_fault_isr(int irq, void *data)
{
	struct deh_mgr *deh = data;
	struct cfg_hostres *resources;
	u32 event;

	if (!deh)
		return IRQ_HANDLED;

	resources = deh->hbridge_context->resources;
	if (!resources) {
		dev_dbg(bridge, "%s: Failed to get Host Resources\n",
				__func__);
		return IRQ_HANDLED;
	}

	hw_mmu_event_status(resources->dw_dmmu_base, &event);
	if (event == HW_MMU_TRANSLATION_FAULT) {
		hw_mmu_fault_addr_read(resources->dw_dmmu_base, &fault_addr);
		dev_dbg(bridge, "%s: event=0x%x, fault_addr=0x%x\n", __func__,
				event, fault_addr);
		/*
		 * Schedule a DPC directly. In the future, it may be
		 * necessary to check if DSP MMU fault is intended for
		 * Bridge.
		 */
		tasklet_schedule(&deh->dpc_tasklet);

		/* Disable the MMU events, else once we clear it will
		 * start to raise INTs again */
		hw_mmu_event_disable(resources->dw_dmmu_base,
				HW_MMU_TRANSLATION_FAULT);
	} else {
		hw_mmu_event_disable(resources->dw_dmmu_base,
				HW_MMU_ALL_INTERRUPTS);
	}
	return IRQ_HANDLED;
}

int bridge_deh_create(struct deh_mgr **ret_deh,
		struct dev_object *hdev_obj)
{
	int status;
	struct deh_mgr *deh;
	struct bridge_dev_context *hbridge_context = NULL;

	/*  Message manager will be created when a file is loaded, since
	 *  size of message buffer in shared memory is configurable in
	 *  the base image. */
	/* Get Bridge context info. */
	dev_get_bridge_context(hdev_obj, &hbridge_context);
	/* Allocate IO manager object: */
	deh = kzalloc(sizeof(*deh), GFP_KERNEL);
	if (!deh) {
		status = -ENOMEM;
		goto err;
	}

	/* Create an NTFY object to manage notifications */
	deh->ntfy_obj = kmalloc(sizeof(struct ntfy_object), GFP_KERNEL);
	if (!deh->ntfy_obj) {
		status = -ENOMEM;
		goto err;
	}
	ntfy_init(deh->ntfy_obj);

	/* Create a MMUfault DPC */
	tasklet_init(&deh->dpc_tasklet, mmu_fault_dpc, (u32) deh);

	/* Fill in context structure */
	deh->hbridge_context = hbridge_context;

	/* Install ISR function for DSP MMU fault */
	status = request_irq(INT_DSP_MMU_IRQ, mmu_fault_isr, 0,
			"DspBridge\tiommu fault", deh);
	if (status < 0)
		goto err;

	*ret_deh = deh;
	return 0;

err:
	bridge_deh_destroy(deh);
	*ret_deh = NULL;
	return status;
}

int bridge_deh_destroy(struct deh_mgr *deh)
{
	if (!deh)
		return -EFAULT;

	/* If notification object exists, delete it */
	if (deh->ntfy_obj) {
		ntfy_delete(deh->ntfy_obj);
		kfree(deh->ntfy_obj);
	}
	/* Disable DSP MMU fault */
	free_irq(INT_DSP_MMU_IRQ, deh);

	/* Free DPC object */
	tasklet_kill(&deh->dpc_tasklet);

	/* Deallocate the DEH manager object */
	kfree(deh);

	return 0;
}

int bridge_deh_register_notify(struct deh_mgr *deh, u32 event_mask,
		u32 notify_type,
		struct dsp_notification *hnotification)
{
	if (!deh)
		return -EFAULT;

	if (event_mask)
		return ntfy_register(deh->ntfy_obj, hnotification,
				event_mask, notify_type);
	else
		return ntfy_unregister(deh->ntfy_obj, hnotification);
}

#ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
static void mmu_fault_print_stack(struct bridge_dev_context *dev_context)
{
	struct cfg_hostres *resources;
	struct hw_mmu_map_attrs_t map_attrs = {
		.endianism = HW_LITTLE_ENDIAN,
		.element_size = HW_ELEM_SIZE16BIT,
		.mixed_size = HW_MMU_CPUES,
	};
	void *dummy_va_addr;

	resources = dev_context->resources;
	dummy_va_addr = (void*)__get_free_page(GFP_ATOMIC);

	/*
	 * Before acking the MMU fault, let's make sure MMU can only
	 * access entry #0. Then add a new entry so that the DSP OS
	 * can continue in order to dump the stack.
	 */
	hw_mmu_twl_disable(resources->dw_dmmu_base);
	hw_mmu_tlb_flush_all(resources->dw_dmmu_base);

	hw_mmu_tlb_add(resources->dw_dmmu_base,
			virt_to_phys(dummy_va_addr), fault_addr,
			HW_PAGE_SIZE4KB, 1,
			&map_attrs, HW_SET, HW_SET);

	dsp_clk_enable(DSP_CLK_GPT8);

	dsp_gpt_wait_overflow(DSP_CLK_GPT8, 0xfffffffe);

	/* Clear MMU interrupt */
	hw_mmu_event_ack(resources->dw_dmmu_base,
			HW_MMU_TRANSLATION_FAULT);
	dump_dsp_stack(dev_context);
	dsp_clk_disable(DSP_CLK_GPT8);

	hw_mmu_disable(resources->dw_dmmu_base);
	free_page((unsigned long)dummy_va_addr);
}
#endif

static inline const char *event_to_string(int event)
{
	switch (event) {
	case DSP_SYSERROR: return "DSP_SYSERROR"; break;
	case DSP_MMUFAULT: return "DSP_MMUFAULT"; break;
	case DSP_PWRERROR: return "DSP_PWRERROR"; break;
	case DSP_WDTOVERFLOW: return "DSP_WDTOVERFLOW"; break;
	default: return "unkown event"; break;
	}
}

void bridge_deh_notify(struct deh_mgr *deh, int event, int info)
{
	struct bridge_dev_context *dev_context;
	const char *str = event_to_string(event);

	if (!deh)
		return;

	dev_dbg(bridge, "%s: device exception", __func__);
	dev_context = deh->hbridge_context;

	switch (event) {
	case DSP_SYSERROR:
		dev_err(bridge, "%s: %s, info=0x%x", __func__,
				str, info);
#ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
		dump_dl_modules(dev_context);
		dump_dsp_stack(dev_context);
#endif
		break;
	case DSP_MMUFAULT:
		dev_err(bridge, "%s: %s, addr=0x%x", __func__,
				str, fault_addr);
#ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
		print_dsp_trace_buffer(dev_context);
		dump_dl_modules(dev_context);
		mmu_fault_print_stack(dev_context);
#endif
		break;
	default:
		dev_err(bridge, "%s: %s", __func__, str);
		break;
	}

	/* Filter subsequent notifications when an error occurs */
	if (dev_context->dw_brd_state != BRD_ERROR) {
		ntfy_notify(deh->ntfy_obj, event);
#ifdef CONFIG_TIDSPBRIDGE_RECOVERY
		bridge_recover_schedule();
#endif
	}

	/* Set the Board state as ERROR */
	dev_context->dw_brd_state = BRD_ERROR;
	/* Disable all the clocks that were enabled by DSP */
	dsp_clock_disable_all(dev_context->dsp_per_clks);
	/*
	 * Avoid the subsequent WDT if it happens once,
	 * also if fatal error occurs.
	 */
	dsp_wdt_enable(false);
}
