/*
 *  TOPPERS/JSP Kernel
 *      Toyohashi Open Platform for Embedded Real-Time Systems/
 *      Just Standard Profile Kernel
 * 
 *  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
 *                              Toyohashi Univ. of Technology, JAPAN
 *  Copyright (C) 2003      by Advanced Data Controls, Corp
 *  Copyright (C) 2004 by Embedded and Real-Time Systems Laboratory
 *              Graduate School of Information Science, Nagoya Univ., JAPAN  
 * 
 *  上記著作権者は，以下の (1)〜(4) の条件か，Free Software Foundation 
 *  によって公表されている GNU General Public License の Version 2 に記
 *  述されている条件を満たす場合に限り，本ソフトウェア（本ソフトウェア
 *  を改変したものを含む．以下同じ）を使用・複製・改変・再配布（以下，
 *  利用と呼ぶ）することを無償で許諾する．
 *  (1) 本ソフトウェアをソースコードの形で利用する場合には，上記の著作
 *      権表示，この利用条件および下記の無保証規定が，そのままの形でソー
 *      スコード中に含まれていること．
 *  (2) 本ソフトウェアを，ライブラリ形式など，他のソフトウェア開発に使
 *      用できる形で再配布する場合には，再配布に伴うドキュメント（利用
 *      者マニュアルなど）に，上記の著作権表示，この利用条件および下記
 *      の無保証規定を掲載すること．
 *  (3) 本ソフトウェアを，機器に組み込むなど，他のソフトウェア開発に使
 *      用できない形で再配布する場合には，次のいずれかの条件を満たすこ
 *      と．
 *    (a) 再配布に伴うドキュメント（利用者マニュアルなど）に，上記の著
 *        作権表示，この利用条件および下記の無保証規定を掲載すること．
 *    (b) 再配布の形態を，別に定める方法によって，TOPPERSプロジェクトに
 *        報告すること．
 *  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
 *      害からも，上記著作権者およびTOPPERSプロジェクトを免責すること．
 * 
 *  本ソフトウェアは，無保証で提供されているものである．上記著作権者お
 *  よびTOPPERSプロジェクトは，本ソフトウェアに関して，その適用可能性も
 *  含めて，いかなる保証も行わない．また，本ソフトウェアの利用により直
 *  接的または間接的に生じたいかなる損害に関しても，その責任を負わない．
 * 
 *  @(#) $Id: sys_config.c,v 1.1 2004/05/23 12:18:56 honda Exp $
 */

/*
 *    ターゲットシステム依存モジュール（MMsam7s用）
 */

#include "jsp_kernel.h"
#include <cqnxparm.h>
#include <hw_timer.h>
#include <lpc2388def.h>

#define	USE_USB

void
init_clock()
{
    UW MValue, NValue;

    if (PLLSTAT & (1<<25)) {
	PLLCON = 1;
	PLLFEED = 0xaa;
	PLLFEED = 0x55;
    }
    PLLCON = 0;
    PLLFEED = 0xaa;
    PLLFEED = 0x55;

    SCS |= 0x20;	/* Enable main OSC */
    while (!(SCS & 0x40))
	;		/* Wait until main OSC is stable */
    CLKSRCSEL = 0x01;	/* Select main OSC, 12MHz as the PLL clock source */

    PLLCFG = PLL_MVAL | (PLL_NVAL << 16);
    PLLFEED = 0xaa;
    PLLFEED = 0x55;
    PLLCON = 1;		/* Enable PLL */
    PLLFEED = 0xaa;
    PLLFEED = 0x55;

    CCLKCFG = CCLKDIV;	/* Set clock divisor */
#ifdef USE_USB
    USBCLKCFG = USBCLKDIV;
#endif
    while ((PLLSTAT & (1<<26)) == 0)
	;		/* Check lock bit status */
    MValue = PLLSTAT & 0x00007FFF;
    NValue = (PLLSTAT & 0x00FF0000) >> 16;
    while ((MValue != PLL_MVAL) && (NValue != PLL_NVAL))
	;
    PLLCON = 3;		/* Enable PLL and connect */
    PLLFEED = 0xaa;
    PLLFEED = 0x55;
    while ((PLLSTAT & (1<<25)) == 0)
	;		/* Check conect bit status */

    PCLKSEL0 = PCLKSEL1 = 0;	/* PCLK is Fcclk/4 = 18MHz */
}

init_MAM(void)
{
    MAMCR = 0;
    MAMTIM = 3;
    MAMCR = 2;
}

/*
 *  未定義の割込みが入った場合の処理
 */
void
undef_interrupt(){
    syslog(LOG_EMERG, "Unregistered Interrupt occurs.");
    while(1);
}

/*
 *  割込み関連の初期化
 */
void
init_IRQ(){
    int i;
    volatile unsigned long *pvect, *pprio;

    /* Select IRQ for all vectors */
    VICIntSelect = 0;
    /* Disable all IRQs */
    VICIntEnClr = 0xffffffff;
    
#define	VICVectTable	((volatile FP *)(VIC_BASE_ADDR + 0x100))
#define	VICPrioTable	((volatile int *)(VIC_BASE_ADDR + 0x200))
    /*
     *  割込みテーブルの初期化
     */
    for(i = 0; i < MAX_INT_NUM; i++){
	VICVectTable[i] = (volatile FP)undef_interrupt;
        VICPrioTable[i] = 15;			/* lowest priority */
    }
}

void
init_pio(void)
{
    PINSEL0 = 0x50;	/* RXD0, TXD0 */

    /* Enable LED on P1[18] */
    SCS = SCS | 0x01;
    FIO1MASK = ~LEDMASK;
    FIO1DIR = LEDMASK;
}

/*
 *  ターゲットシステム依存の初期化
 */
void
sys_initialize()
{
    int i;

    init_clock();

    MEMMAP = 0x01;

    init_MAM();

    init_pio();

    init_IRQ();

    /*
     *  sys_putc が可能になるようにUARTを初期化
     */
    init_uart();
}


/*
 *  ターゲットシステムの終了
 */
void
sys_exit(void)
{
    syslog(LOG_EMERG, "End Kernel.....!");
    while(1);
}


/*
 *  ターゲットシステムの文字出力
 */

void
sys_putc(char c)
{
    if (c == '\n') {
        uart_putc('\r');
    }
    uart_putc(c);
}

/*
 *  割込みハンドラの設定
 *
 *  割込み番号 inhno の割込みハンドラの起動番地を inthdr に設定する．
 */
void
define_inh(INHNO inhno, FP inthdr)
{
    assert(inhno <= MAX_INT_NUM);
    VICVectTable[inhno] = (volatile FP) inthdr;
}

/* Change Interrupt Priority */
void chg_ipr(INTNO intno, int pri)
{
    assert(intno <= MAX_INT_NUM);
    VICPrioTable[intno] = pri;
}

ER dis_int(int intno)
{
    if (intno > MAX_INT_NUM)
        return E_PAR;
    VICIntEnClr = (1<<intno);
    return 0;
}

ER ena_int(int intno)
{
    if (intno > MAX_INT_NUM)
        return E_PAR;
    VICIntEnable = (1<<intno);
    return 0;
}
