#include "archinc.h"
#include "eventq.h"
#include "watchdog.h"
#include "cli.h"

#define WDEN    0x01
#define WDRESET 0x02
#define WDTOF   0x04
#define WDINT   0x08

// TODO: implement real watchdog functionality by using timer or eventq

static void handleEvent(void);

/* ISR declaration */
DECLARE_ISR(watchdogIsr);

#ifdef CONFIG_TOOLCHAIN_IAR
#pragma inline
#endif
static INLINE_KEYWORD void feedWatchdog(void)
{
  // do watchdog feed sequence with interrupts disabled
  IRQ_DISABLE();
  WDFEED = (unsigned long)0xAA;
  WDFEED = (unsigned long)0x55;
  IRQ_ENABLE();
}

void watchdogFeed(void)
{
  eventqPut(WATCHDOG_FEED);
}

ISR_FUNCTION(watchdogIsr)
{
}

static int resetHandler(int argc, char * argv[], int flags)
{
  feedWatchdog();
  while(1); // wait for reset
  return 0; // should never get here
}

static void handleEvent(void)
{
  feedWatchdog();
}

int watchdogInit(void) 
{
  cliRegisterCommand("reset", resetHandler, "reset - resets the processor via watchdog");

  // enable us to feed the 'dog
  eventqRegisterHandler(WATCHDOG_FEED, handleEvent);

  // initialize watchdog counter to 1/2 max value
  WDTC  = (unsigned long)0x80000000;

  // set mode to reset
  WDMOD = (unsigned long)(WDEN | WDRESET);

  // enable watchdog timer!
  feedWatchdog();

  return 0;
}
