/*
 * Copyright (C) 2010-2016 ARM Limited. All rights reserved.
 *
 * This program is free software and is provided to you under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
 *
 * A copy of the licence is included with the program, and can also be obtained from Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

/**
 * @file mali_osk_irq.c
 * Implementation of the OS abstraction layer for the kernel device driver
 */

#include <linux/types.h>
#include <linux/version.h>
#if (KERNEL_VERSION(3, 14, 29) > LINUX_VERSION_CODE)
#include <mach/cpu.h>
#endif
#include <linux/slab.h>	/* For memory allocation */
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/sched.h>

#include "mali_osk.h"
#include "mali_kernel_common.h"

typedef struct _mali_osk_irq_t_struct {
	u32 irqnum;
	void *data;
	_mali_osk_irq_uhandler_t uhandler;
} mali_osk_irq_object_t;

typedef irqreturn_t (*irq_handler_func_t)(int, void *, struct pt_regs *);
static irqreturn_t irq_handler_upper_half(int port_name, void *dev_id);   /* , struct pt_regs *regs*/

#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESON6
u32 get_irqnum(struct _mali_osk_irq_t_struct *irq)
{
	if (irq)
		return irq->irqnum;
	else
		return 0;
}
#endif

#if defined(DEBUG)

struct test_interrupt_data {
	_mali_osk_irq_ack_t ack_func;
	void *probe_data;
	mali_bool interrupt_received;
	wait_queue_head_t wq;
};

static irqreturn_t test_interrupt_upper_half(int port_name, void *dev_id)
{
	irqreturn_t ret = IRQ_NONE;
	struct test_interrupt_data *data = (struct test_interrupt_data *)dev_id;

	if (data->ack_func(data->probe_data) == _MALI_OSK_ERR_OK) {
		data->interrupt_received = MALI_TRUE;
		wake_up(&data->wq);
		ret = IRQ_HANDLED;
	}

	return ret;
}

static _mali_osk_errcode_t test_interrupt(u32 irqnum,
		_mali_osk_irq_trigger_t trigger_func,
		_mali_osk_irq_ack_t ack_func,
		void *probe_data,
		const char *description)
{
	unsigned long irq_flags = 0;
	struct test_interrupt_data data = {
		.ack_func = ack_func,
		.probe_data = probe_data,
		.interrupt_received = MALI_FALSE,
	};

#if defined(CONFIG_MALI_SHARED_INTERRUPTS)
	irq_flags |= IRQF_SHARED;
#endif /* defined(CONFIG_MALI_SHARED_INTERRUPTS) */

	if (request_irq(irqnum, test_interrupt_upper_half, irq_flags, description, &data) != 0) {
		MALI_DEBUG_PRINT(2, ("Unable to install test IRQ handler for core '%s'\n", description));
		return _MALI_OSK_ERR_FAULT;
	}

	init_waitqueue_head(&data.wq);

	trigger_func(probe_data);
	wait_event_timeout(data.wq, data.interrupt_received, _mali_osk_time_mstoticks(1000));

	free_irq(irqnum, &data);

	if (data.interrupt_received) {
		MALI_DEBUG_PRINT(3, ("%s: Interrupt test OK\n", description));
		return _MALI_OSK_ERR_OK;
	} else {
		MALI_PRINT_ERROR(("%s: Failed interrupt test on %u\n", description, irqnum));
		return _MALI_OSK_ERR_FAULT;
	}
}

#endif /* defined(DEBUG) */

_mali_osk_irq_t *_mali_osk_irq_init(u32 irqnum, _mali_osk_irq_uhandler_t uhandler, void *int_data, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *probe_data, const char *description)
{
	mali_osk_irq_object_t *irq_object;
	unsigned long irq_flags = 0;

#if defined(CONFIG_MALI_SHARED_INTERRUPTS)
	irq_flags |= IRQF_SHARED;
#endif /* defined(CONFIG_MALI_SHARED_INTERRUPTS) */

	irq_object = kmalloc(sizeof(mali_osk_irq_object_t), GFP_KERNEL);
	if (irq_object == NULL) {
		return NULL;
	}

	if (-1 == irqnum) {
		/* Probe for IRQ */
		if ((NULL != trigger_func) && (ack_func != NULL)) {
			unsigned long probe_count = 3;
			_mali_osk_errcode_t err;
			int irq;

			MALI_DEBUG_PRINT(2, ("Probing for irq\n"));

			do {
				unsigned long mask;

				mask = probe_irq_on();
				trigger_func(probe_data);

				_mali_osk_time_ubusydelay(5);

				irq = probe_irq_off(mask);
				err = ack_func(probe_data);
			} while (irq < 0 && (err == _MALI_OSK_ERR_OK) && probe_count--);

			if (irq < 0 || (err != _MALI_OSK_ERR_OK)) irqnum = -1;
			else irqnum = irq;
		} else irqnum = -1; /* no probe functions, fault */

		if (-1 != irqnum) {
			/* found an irq */
			MALI_DEBUG_PRINT(2, ("Found irq %d\n", irqnum));
		} else {
			MALI_DEBUG_PRINT(2, ("Probe for irq failed\n"));
		}
	}

	irq_object->irqnum = irqnum;
	irq_object->uhandler = uhandler;
	irq_object->data = int_data;

	if (-1 == irqnum) {
		MALI_DEBUG_PRINT(2, ("No IRQ for core '%s' found during probe\n", description));
		kfree(irq_object);
		return NULL;
	}

#if defined(DEBUG)
	/* Verify that the configured interrupt settings are working */
	if (test_interrupt(irqnum, trigger_func, ack_func, probe_data, description) != _MALI_OSK_ERR_OK) {
		MALI_DEBUG_PRINT(2, ("Test of IRQ(%d) handler for core '%s' failed\n", irqnum, description));
		kfree(irq_object);
		return NULL;
	}
#endif

	if (request_irq(irqnum, irq_handler_upper_half, irq_flags, description, irq_object) != 0) {
		MALI_DEBUG_PRINT(2, ("Unable to install IRQ handler for core '%s'\n", description));
		kfree(irq_object);
		return NULL;
	}

	return irq_object;
}

void _mali_osk_irq_term(_mali_osk_irq_t *irq)
{
	mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)irq;

	free_irq(irq_object->irqnum, irq_object);
	kfree(irq_object);
}


/** This function is called directly in interrupt context from the OS just after
 * the CPU get the hw-irq from mali, or other devices on the same IRQ-channel.
 * It is registered one of these function for each mali core. When an interrupt
 * arrives this function will be called equal times as registered mali cores.
 * That means that we only check one mali core in one function call, and the
 * core we check for each turn is given by the \a dev_id variable.
 * If we detect an pending interrupt on the given core, we mask the interrupt
 * out by settging the core's IRQ_MASK register to zero.
 * Then we schedule the mali_core_irq_handler_bottom_half to run as high priority
 * work queue job.
 */
static irqreturn_t irq_handler_upper_half(int port_name, void *dev_id)   /* , struct pt_regs *regs*/
{
	irqreturn_t ret = IRQ_NONE;
	mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)dev_id;

	if (irq_object->uhandler(irq_object->data) == _MALI_OSK_ERR_OK) {
		ret = IRQ_HANDLED;
	}

	return ret;
}
