/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 1997, 1998, 2001, 2003 by Ralf Baechle
 */
#include <linux/init.h>
#include <linux/ds1286.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/notifier.h>
#include <linux/timer.h>

#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/reboot.h>
#include <asm/sgialib.h>
#include <asm/sgi/ioc.h>
#include <asm/sgi/hpc3.h>
#include <asm/sgi/mc.h>
#include <asm/sgi/ip22.h>

/*
 * Just powerdown if init hasn't done after POWERDOWN_TIMEOUT seconds.
 * I'm not sure if this feature is a good idea, for now it's here just to
 * make the power button make behave just like under IRIX.
 */
#define POWERDOWN_TIMEOUT	120

/*
 * Blink frequency during reboot grace period and when paniced.
 */
#define POWERDOWN_FREQ		(HZ / 4)
#define PANIC_FREQ		(HZ / 8)

static struct timer_list power_timer, blink_timer, debounce_timer, volume_timer;

#define MACHINE_PANICED		1
#define MACHINE_SHUTTING_DOWN	2
static int machine_state = 0;

static void sgi_machine_restart(char *command) __attribute__((noreturn));
static void sgi_machine_halt(void) __attribute__((noreturn));
static void sgi_machine_power_off(void) __attribute__((noreturn));

static void sgi_machine_restart(char *command)
{
	if (machine_state & MACHINE_SHUTTING_DOWN)
		sgi_machine_power_off();
	sgimc->cpuctrl0 |= SGIMC_CCTRL0_SYSINIT;
	while (1);
}

static void sgi_machine_halt(void)
{
	if (machine_state & MACHINE_SHUTTING_DOWN)
		sgi_machine_power_off();
	ArcEnterInteractiveMode();
}

static void sgi_machine_power_off(void)
{
	unsigned int tmp;

	local_irq_disable();

	/* Disable watchdog */
	tmp = hpc3c0->rtcregs[RTC_CMD] & 0xff;
	hpc3c0->rtcregs[RTC_CMD] = tmp | RTC_WAM;
	hpc3c0->rtcregs[RTC_WSEC] = 0;
	hpc3c0->rtcregs[RTC_WHSEC] = 0;

	while (1) {
		sgioc->panel = ~SGIOC_PANEL_POWERON;
		/* Good bye cruel world ...  */

		/* If we're still running, we probably got sent an alarm
		   interrupt.  Read the flag to clear it.  */
		tmp = hpc3c0->rtcregs[RTC_HOURS_ALARM];
	}
}

static void power_timeout(unsigned long data)
{
	sgi_machine_power_off();
}

static void blink_timeout(unsigned long data)
{
	/* XXX fix this for fullhouse  */
	sgi_ioc_reset ^= (SGIOC_RESET_LC0OFF|SGIOC_RESET_LC1OFF);
	sgioc->reset = sgi_ioc_reset;

	mod_timer(&blink_timer, jiffies+data);
}

static void debounce(unsigned long data)
{
	del_timer(&debounce_timer);
	if (sgint->istat1 & SGINT_ISTAT1_PWR) {
		/* Interrupt still being sent. */
		debounce_timer.expires = jiffies + 5; /* 0.05s  */
		add_timer(&debounce_timer);

		sgioc->panel = SGIOC_PANEL_POWERON | SGIOC_PANEL_POWERINTR |
			       SGIOC_PANEL_VOLDNINTR | SGIOC_PANEL_VOLDNHOLD |
			       SGIOC_PANEL_VOLUPINTR | SGIOC_PANEL_VOLUPHOLD;

		return;
	}

	if (machine_state & MACHINE_PANICED)
		sgimc->cpuctrl0 |= SGIMC_CCTRL0_SYSINIT;

	enable_irq(SGI_PANEL_IRQ);
}

static inline void power_button(void)
{
	if (machine_state & MACHINE_PANICED)
		return;

	if ((machine_state & MACHINE_SHUTTING_DOWN) || kill_proc(1,SIGINT,1)) {
		/* No init process or button pressed twice.  */
		sgi_machine_power_off();
	}

	machine_state |= MACHINE_SHUTTING_DOWN;
	blink_timer.data = POWERDOWN_FREQ;
	blink_timeout(POWERDOWN_FREQ);

	init_timer(&power_timer);
	power_timer.function = power_timeout;
	power_timer.expires = jiffies + POWERDOWN_TIMEOUT * HZ;
	add_timer(&power_timer);
}

void (*indy_volume_button)(int) = NULL;

EXPORT_SYMBOL(indy_volume_button);

static inline void volume_up_button(unsigned long data)
{
	del_timer(&volume_timer);

	if (indy_volume_button)
		indy_volume_button(1);

	if (sgint->istat1 & SGINT_ISTAT1_PWR) {
		volume_timer.expires = jiffies + 1;
		add_timer(&volume_timer);
	}
}

static inline void volume_down_button(unsigned long data)
{
	del_timer(&volume_timer);

	if (indy_volume_button)
		indy_volume_button(-1);

	if (sgint->istat1 & SGINT_ISTAT1_PWR) {
		volume_timer.expires = jiffies + 1;
		add_timer(&volume_timer);
	}
}

static irqreturn_t panel_int(int irq, void *dev_id, struct pt_regs *regs)
{
	unsigned int buttons;

	buttons = sgioc->panel;
	sgioc->panel = SGIOC_PANEL_POWERON | SGIOC_PANEL_POWERINTR;

	if (sgint->istat1 & SGINT_ISTAT1_PWR) {
		/* Wait until interrupt goes away */
		disable_irq(SGI_PANEL_IRQ);
		init_timer(&debounce_timer);
		debounce_timer.function = debounce;
		debounce_timer.expires = jiffies + 5;
		add_timer(&debounce_timer);
	}

	/* Power button was pressed
	 * ioc.ps page 22: "The Panel Register is called Power Control by Full
	 * House. Only lowest 2 bits are used. Guiness uses upper four bits
	 * for volume control". This is not true, all bits are pulled high
	 * on fullhouse */
	if (ip22_is_fullhouse() || !(buttons & SGIOC_PANEL_POWERINTR)) {
		power_button();
		return IRQ_HANDLED;
	}
	/* TODO: mute/unmute */
	/* Volume up button was pressed */
	if (!(buttons & SGIOC_PANEL_VOLUPINTR)) {
		init_timer(&volume_timer);
		volume_timer.function = volume_up_button;
		volume_timer.expires = jiffies + 1;
		add_timer(&volume_timer);
	}
	/* Volume down button was pressed */
	if (!(buttons & SGIOC_PANEL_VOLDNINTR)) {
		init_timer(&volume_timer);
		volume_timer.function = volume_down_button;
		volume_timer.expires = jiffies + 1;
		add_timer(&volume_timer);
	}

	return IRQ_HANDLED;
}

static int panic_event(struct notifier_block *this, unsigned long event,
                      void *ptr)
{
	if (machine_state & MACHINE_PANICED)
		return NOTIFY_DONE;
	machine_state |= MACHINE_PANICED;

	blink_timer.data = PANIC_FREQ;
	blink_timeout(PANIC_FREQ);

	return NOTIFY_DONE;
}

static struct notifier_block panic_block = {
	.notifier_call	= panic_event,
};

static int __init reboot_setup(void)
{
	_machine_restart = sgi_machine_restart;
	_machine_halt = sgi_machine_halt;
	_machine_power_off = sgi_machine_power_off;

	request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL);
	init_timer(&blink_timer);
	blink_timer.function = blink_timeout;
	notifier_chain_register(&panic_notifier_list, &panic_block);

	return 0;
}

subsys_initcall(reboot_setup);
