//==========================================================================
//
//      vpb926ejs_misc.c
//
//      HAL misc board support code for ARM9/VPB926EJS
//
//==========================================================================
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
// -------------------------------------------                              
// This file is part of eCos, the Embedded Configurable Operating System.   
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
// Copyright (C) 2003, 2004, 2006 eCosCentric Limited                       
//
// eCos is free software; you can redistribute it and/or modify it under    
// the terms of the GNU General Public License as published by the Free     
// Software Foundation; either version 2 or (at your option) any later      
// version.                                                                 
//
// eCos is distributed in the hope that it will be useful, but WITHOUT      
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
// for more details.                                                        
//
// You should have received a copy of the GNU General Public License        
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
//
// As a special exception, if other files instantiate templates or use      
// macros or inline functions from this file, or you compile this file      
// and link it with other works to produce a work based on this file,       
// this file does not by itself cause the resulting work to be covered by   
// the GNU General Public License. However the source code for this file    
// must still be made available in accordance with section (3) of the GNU   
// General Public License v2.                                               
//
// This exception does not invalidate any other reasons why a work based    
// on this file might be covered by the GNU General Public License.         
// -------------------------------------------                              
// ####ECOSGPLCOPYRIGHTEND####                                              
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s):    eCosCentric
// Contributors: hmt, Travis C. Furrer <furrer@mit.edu>, jskov
// Date:         2000-05-21
// Purpose:      HAL board support
// Description:  Implementations of HAL board interfaces
//
//####DESCRIPTIONEND####
//
//========================================================================*/

#include <pkgconf/hal.h>
#include <pkgconf/system.h>
#include CYGBLD_HAL_PLATFORM_H

#include <cyg/infra/cyg_type.h>         // base types
#include <cyg/infra/cyg_trac.h>         // tracing macros
#include <cyg/infra/cyg_ass.h>          // assertion macros

#include <cyg/hal/hal_io.h>             // IO macros
#include <cyg/hal/hal_arch.h>           // Register state info
#include <cyg/hal/hal_diag.h>
#include <cyg/hal/hal_intr.h>           // Interrupt names
#include <cyg/hal/hal_cache.h>
#include <cyg/hal/vpb926ejs.h>             // Platform specifics

#include <cyg/infra/diag.h>             // diag_printf

#include <string.h> // memset


// -------------------------------------------------------------------------
// MMU initialization:
// 
// These structures are laid down in memory to define the translation
// table.
// 

/*
 * ARM Translation Table Base Bit Masks */
#define ARM_TRANSLATION_TABLE_MASK               0xFFFFC000

/*
 * ARM Domain Access Control Bit Masks
 */
#define ARM_ACCESS_TYPE_NO_ACCESS(domain_num)    (0x0 << (domain_num)*2)
#define ARM_ACCESS_TYPE_CLIENT(domain_num)       (0x1 << (domain_num)*2)
#define ARM_ACCESS_TYPE_MANAGER(domain_num)      (0x3 << (domain_num)*2)

struct ARM_MMU_FIRST_LEVEL_FAULT {
    int id : 2;
    int sbz : 30;
};
#define ARM_MMU_FIRST_LEVEL_FAULT_ID 0x0

struct ARM_MMU_FIRST_LEVEL_PAGE_TABLE {
    int id : 2;
    int imp : 2;
    int domain : 4;
    int sbz : 1;
    int base_address : 23;
};
#define ARM_MMU_FIRST_LEVEL_PAGE_TABLE_ID 0x1

struct ARM_MMU_FIRST_LEVEL_SECTION {
    int id : 2;
    int b : 1;
    int c : 1;
    int imp : 1;
    int domain : 4;
    int sbz0 : 1;
    int ap : 2;
    int sbz1 : 8;
    int base_address : 12;
};
#define ARM_MMU_FIRST_LEVEL_SECTION_ID 0x2

struct ARM_MMU_FIRST_LEVEL_RESERVED {
    int id : 2;
    int sbz : 30;
};
#define ARM_MMU_FIRST_LEVEL_RESERVED_ID 0x3

#define ARM_MMU_FIRST_LEVEL_DESCRIPTOR_ADDRESS(ttb_base, table_index) \
   (unsigned long *)((unsigned long)(ttb_base) + ((table_index) << 2))

#define ARM_FIRST_LEVEL_PAGE_TABLE_SIZE 0x4000

#define ARM_MMU_SECTION(ttb_base, actual_base, virtual_base,              \
                        cacheable, bufferable, perm)                      \
    CYG_MACRO_START                                                       \
        register union ARM_MMU_FIRST_LEVEL_DESCRIPTOR desc;               \
                                                                          \
        desc.word = 0;                                                    \
        desc.section.id = ARM_MMU_FIRST_LEVEL_SECTION_ID;                 \
        desc.section.imp = 1;                                             \
        desc.section.domain = 0;                                          \
        desc.section.c = (cacheable);                                     \
        desc.section.b = (bufferable);                                    \
        desc.section.ap = (perm);                                         \
        desc.section.base_address = (actual_base);                        \
        *ARM_MMU_FIRST_LEVEL_DESCRIPTOR_ADDRESS(ttb_base, (virtual_base)) \
                            = desc.word;                                  \
    CYG_MACRO_END

#define X_ARM_MMU_SECTION(abase,vbase,size,cache,buff,access)      \
    { int i; int j = abase; int k = vbase;                         \
      for (i = size; i > 0 ; i--,j++,k++)                          \
      {                                                            \
        ARM_MMU_SECTION(ttb_base, j, k, cache, buff, access);      \
      }                                                            \
    }

union ARM_MMU_FIRST_LEVEL_DESCRIPTOR {
    unsigned long word;
    struct ARM_MMU_FIRST_LEVEL_FAULT fault;
    struct ARM_MMU_FIRST_LEVEL_PAGE_TABLE page_table;
    struct ARM_MMU_FIRST_LEVEL_SECTION section;
    struct ARM_MMU_FIRST_LEVEL_RESERVED reserved;
};

#define _UNCACHEABLE                  0
#define _CACHEABLE                    1
#define _UNBUFFERABLE                 0
#define _BUFFERABLE                   1

#define _PERM_NONE_NONE               0
#define _PERM_RO_NONE                 0
#define _PERM_RO_RO                   0
#define _PERM_RW_NONE                 1
#define _PERM_RW_RO                   2
#define _PERM_RW_RW                   3

#define _MMU X_ARM_MMU_SECTION

__externC void cyg_hal_arm9_set_mmuregs( unsigned long tt_base,
                                         unsigned long dacr );
void
hal_mmu_init(void)
{
    unsigned long ttb_base = VPB926EJS_SDRAM_PHYS_BASE + 0x4000;
    unsigned long i;

    /*
     * Set the Domain Access Control Register
     */
    i = ARM_ACCESS_TYPE_MANAGER(0)    | 
        ARM_ACCESS_TYPE_NO_ACCESS(1)  |
        ARM_ACCESS_TYPE_NO_ACCESS(2)  |
        ARM_ACCESS_TYPE_NO_ACCESS(3)  |
        ARM_ACCESS_TYPE_NO_ACCESS(4)  |
        ARM_ACCESS_TYPE_NO_ACCESS(5)  |
        ARM_ACCESS_TYPE_NO_ACCESS(6)  |
        ARM_ACCESS_TYPE_NO_ACCESS(7)  |
        ARM_ACCESS_TYPE_NO_ACCESS(8)  |
        ARM_ACCESS_TYPE_NO_ACCESS(9)  |
        ARM_ACCESS_TYPE_NO_ACCESS(10) |
        ARM_ACCESS_TYPE_NO_ACCESS(11) |
        ARM_ACCESS_TYPE_NO_ACCESS(12) |
        ARM_ACCESS_TYPE_NO_ACCESS(13) |
        ARM_ACCESS_TYPE_NO_ACCESS(14) |
        ARM_ACCESS_TYPE_NO_ACCESS(15);

    /*
     * Set the TTB register and the DACR
     */
    cyg_hal_arm9_set_mmuregs( ttb_base, i );
    
    /*
     * First clear all TT entries - ie Set them to Faulting
     */
    memset((void *)ttb_base, 0, ARM_FIRST_LEVEL_PAGE_TABLE_SIZE);
    

    /*     Physical   Virtual  Size   Attributes                                  Function  */
    /*     Base       Base     MB      cached?    buffered?      access perms               */
    /*     xxx00000   xxx00000                                                              */
    _MMU(0x000,     0x000,     64,  _CACHEABLE,   _BUFFERABLE,   _PERM_RW_RW); /* SDRAM CS0 */
    _MMU(0x080,     0x040,     64,  _CACHEABLE,   _BUFFERABLE,   _PERM_RW_RW); /* SDRAM CS1 */
    _MMU(0x100,     0x100,    256,  _UNCACHEABLE, _UNBUFFERABLE, _PERM_RW_RW); /* On-chip devices */
    _MMU(0x300,     0x300,     64,  _UNCACHEABLE, _UNBUFFERABLE, _PERM_RW_RW); /* DOC static CS0 */
    _MMU(0x340,     0x340,     64,  _CACHEABLE,   _BUFFERABLE,   _PERM_RW_RW); /* FLASH static CS1 */
    _MMU(0x380,     0x380,      2,  _CACHEABLE,   _BUFFERABLE,   _PERM_RW_RW); /* SRAM static CS2 */

    _MMU(0x000,     0x700,     64,  _UNCACHEABLE, _UNBUFFERABLE, _PERM_RW_RW); /* Uncached SDRAM CS0 */
    _MMU(0x080,     0x740,     64,  _UNCACHEABLE, _UNBUFFERABLE, _PERM_RW_RW); /* Uncached SDRAM CS1 */
    _MMU(0x380,     0x780,      2,  _UNCACHEABLE, _UNBUFFERABLE, _PERM_RW_RW); /* Uncached SRAM static CS2 */    
    _MMU(0x340,     0x7C0,     64,  _UNCACHEABLE, _UNBUFFERABLE, _PERM_RW_RW); /* Uncached SRAM FLASH static CS1 */    
}

// -------------------------------------------------------------------------

static void _led_set( int led )
{
    HAL_WRITE_UINT32( VPB926EJS_SYS+_SYS_LED, led );
}

static void _led_toggle( int bits )
{
    int led;
    HAL_READ_UINT32( VPB926EJS_SYS+_SYS_LED, led );
    led ^= bits;
    HAL_WRITE_UINT32( VPB926EJS_SYS+_SYS_LED, led );
}

// -------------------------------------------------------------------------

static cyg_uint32 period;

void hal_clock_initialize(cyg_uint32 _period)
{
    period = _period;
    HAL_WRITE_UINT32(VPB926EJS_TIMER0+_TIMER_CR, 0 );    
    HAL_WRITE_UINT32(VPB926EJS_TIMER0+_TIMER_LOAD, period);
    HAL_WRITE_UINT32(VPB926EJS_TIMER0+_TIMER_ICR, 0);
    
    HAL_WRITE_UINT32(VPB926EJS_TIMER0+_TIMER_CR, _TIMER_CR_ENABLED     |
                                                 _TIMER_CR_INT_ENABLED |
                                                 _TIMER_CR_SIZE        |
                                                 _TIMER_CR_PERIODIC);
}

// This routine is called during a clock interrupt.
void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
{
    HAL_WRITE_UINT32(VPB926EJS_TIMER0+_TIMER_ICR, 0);    
}

// Read the current value of the clock, returning the number of hardware
// "ticks" that have occurred (i.e. how far away the current value is from
// the start)

// Note: The "contract" for this function is that the value is the number
// of hardware clocks that have happened since the last interrupt (i.e.
// when it was reset).

void hal_clock_read(cyg_uint32 *pvalue)
{
    cyg_uint32 val;

    HAL_READ_UINT32(VPB926EJS_TIMER0+_TIMER_VALUE, val);
    *pvalue = period - val;
}

void 
hal_delay_us(int us)
{
    while( us > 0 )
    {
        cyg_uint32 us1 = us;
        cyg_int32 ticks;
        cyg_uint32 cval1, cval2;

        // Wait in bursts of 1s to avoid overflow problems with the
        // multiply by 1000 below.
        
        if( us1 > 1000000 )
            us1 = 1000000;

        us -= us1;
        
        // The timer ticks at 1000ns per tick. So we convert the us
        // value we were given to clock ticks and wait for that many
        // to pass.

        ticks = (us1 * 1000UL) / 1000UL; // 1MHz clock

        HAL_CLOCK_READ( &cval1 );

        // We just loop, waiting for clock ticks to happen,
        // and subtracting them from ticks when they do.
        
        while( ticks > 0 )
        {
            cyg_int32 diff;
            HAL_CLOCK_READ( &cval2 );

            diff = cval2 - cval1;

            // Cope with counter wrap-around.
            if( diff < 0 )
                diff += period;

            ticks -= diff;
            cval1 = cval2;

        }
    }
}

// -------------------------------------------------------------------------

// This routine is called to respond to a hardware interrupt (IRQ).  It
// should interrogate the hardware and return the IRQ vector number.
int hal_IRQ_handler(void)
{
    cyg_uint32 mask, vec;

    HAL_READ_UINT32(VPB926EJS_VIC+_VIC_ISR, mask);
    HAL_LSBIT_INDEX( vec, mask );

    if( vec == CYGNUM_HAL_INTERRUPT_FPGA )
    {
        HAL_READ_UINT32(VPB926EJS_SIC+_SIC_ISR, mask);
        HAL_LSBIT_INDEX( vec, mask );

        vec += CYGNUM_HAL_INTERRUPT_FPGA_BASE;
    }
    
    return vec;
}

//
// Interrupt control
//

void hal_interrupt_mask(int vector)
{
    CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
               vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");

    if( vector > CYGNUM_HAL_INTERRUPT_FPGA )
        HAL_WRITE_UINT32(VPB926EJS_SIC+_SIC_ICR, (1 << (vector-CYGNUM_HAL_INTERRUPT_FPGA_BASE)));
    else
    {
        if( vector >= CYGNUM_HAL_INTERRUPT_DOC &&
            vector <= CYGNUM_HAL_INTERRUPT_PCI3 )
            HAL_WRITE_UINT32(VPB926EJS_SIC+_SIC_PICCLR, (1 << vector));
        
        HAL_WRITE_UINT32(VPB926EJS_VIC+_VIC_ICR, (1 << vector));
    }
}

void hal_interrupt_unmask(int vector)
{
    CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
               vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");

    if( vector > CYGNUM_HAL_INTERRUPT_FPGA )
        HAL_WRITE_UINT32(VPB926EJS_SIC+_SIC_IER, (1 << (vector-CYGNUM_HAL_INTERRUPT_FPGA_BASE)));
    else
    {
        if( vector >= CYGNUM_HAL_INTERRUPT_DOC &&
            vector <= CYGNUM_HAL_INTERRUPT_PCI3 )
            HAL_WRITE_UINT32(VPB926EJS_SIC+_SIC_PICSET, (1 << vector));
        
        HAL_WRITE_UINT32(VPB926EJS_VIC+_VIC_IER, (1 << vector));
    }
}

void hal_interrupt_acknowledge(int vector)
{
    CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
               vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");

    // No acknowledge needed
}

void hal_interrupt_configure(int vector, int level, int up)
{
    cyg_uint32 smr;
    CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
               vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
}

void hal_interrupt_set_level(int vector, int level)
{
    cyg_uint32 smr;
    CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
               vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
    CYG_ASSERT(level <= 7 &&
               level >= 0, "Invalid interrupt priority level");
}

//
// Reset the processor/board
//
void cyg_hal_vpb926ejs_reset(void)
{
    CYG_INTERRUPT_STATE state;
    HAL_DISABLE_INTERRUPTS(state);

    // Use the watchdog to force a reset
    HAL_WRITE_UINT32( VPB926EJS_WDOG+_WDOG_LOCK, _WDOG_LOCK_ACCESS );
    HAL_WRITE_UINT32( VPB926EJS_WDOG+_WDOG_LOAD, 2 );
    HAL_WRITE_UINT32( VPB926EJS_WDOG+_WDOG_CTRL, _WDOG_CTRL_RESEN|_WDOG_CTRL_INTEN );

    // Now just spin until we get zapped
    for(;;);
}

//--------------------------------------------------------------------------
// I2C support

#define _I2C_SET_ALL() HAL_WRITE_UINT32( VPB926EJS_I2C+_I2C_SET, _I2C_BOTH )
#define _I2C_SET_SDA() HAL_WRITE_UINT32( VPB926EJS_I2C+_I2C_SET, _I2C_SDA )
#define _I2C_CLR_SDA() HAL_WRITE_UINT32( VPB926EJS_I2C+_I2C_CLR, _I2C_SDA )
#define _I2C_SET_SCL() HAL_WRITE_UINT32( VPB926EJS_I2C+_I2C_SET, _I2C_SCL )
#define _I2C_CLR_SCL() HAL_WRITE_UINT32( VPB926EJS_I2C+_I2C_CLR, _I2C_SCL )

#define _I2C_GET_SDA()                                  \
({                                                      \
    int val;                                            \
    HAL_READ_UINT32( VPB926EJS_I2C+_I2C_READ, val );    \
    (val>>1) & 1;                                       \
})

static void
_vpb926ejs_i2c_init(void)
{
    _I2C_SET_ALL();   // SDA=1, SCL=1
}

static void
_vpb926ejs_i2c_delay(void)
{
    HAL_DELAY_US(100);
}

// Issue start sequence which is SDA(1->0) with SCL(1)
static void
_vpb926ejs_i2c_start(void)
{
    _I2C_SET_SDA();   // SDA=1, SCL=?
    _vpb926ejs_i2c_delay();
    _I2C_SET_SCL();   // SDA=1, SCL=1
    _vpb926ejs_i2c_delay();
    _I2C_CLR_SDA();   // SDA=0, SCL=1
    _vpb926ejs_i2c_delay();
    _I2C_CLR_SCL();   // SDA=0, SCL=0
    _vpb926ejs_i2c_delay();
    _I2C_SET_SDA();   // SDA=1, SCL=1
    _vpb926ejs_i2c_delay();
}

// Issue stop sequence which is SDA(0->1) with SCL(1)
static void
_vpb926ejs_i2c_stop(void)
{
    _I2C_CLR_SDA();   // SDA=0, SCL=?
    _vpb926ejs_i2c_delay();
    _I2C_SET_SCL();   // SDA=1, SCL=1
    _vpb926ejs_i2c_delay();
    _I2C_SET_SDA();   // SDA=1, SCL=1
    _vpb926ejs_i2c_delay();
    _I2C_CLR_SCL();   // SDA=0, SCL=0
    _vpb926ejs_i2c_delay();
}

// Send an 8-bit value, MSB first, SCL(1->0) clocks the data
static int
_vpb926ejs_i2c_put(unsigned char val)
{
    int bit;

    for (bit = 7;  bit >= 0;  bit--) {
        if ((val & (1 << bit))) {
            _I2C_SET_SDA();   // SDA=1, SCL=?
        } else {
            _I2C_CLR_SDA();   // SDA=0, SCL=?
        }
        _vpb926ejs_i2c_delay();
        _I2C_SET_SCL();   // SDA=?, SCL=1
        _vpb926ejs_i2c_delay();
        _I2C_CLR_SCL();   // SDA=?, SCL=0
    }
    // Now wait for ACK
    _I2C_SET_SDA();   // SDA=1, SCL=0
    _vpb926ejs_i2c_delay();
    _I2C_SET_SCL();   // SDA=1, SCL=1
    _vpb926ejs_i2c_delay();

    if (_I2C_GET_SDA()) {
        // No ACK!
        return -1;
    }
    _I2C_CLR_SCL();   // SDA=?, SCL=0
    _vpb926ejs_i2c_delay();
    return 0;
}

static unsigned char
_vpb926ejs_i2c_get(void)
{
    unsigned char val = 0;
    int bit;

    for (bit = 7;  bit >= 0;  bit--) {
        _I2C_SET_SCL();   // SDA=?, SCL=1
        _vpb926ejs_i2c_delay();
        if( _I2C_GET_SDA() ) {
            val |= (1 << bit);
        }
        _I2C_CLR_SCL();   // SDA=?, SCL=0
        _vpb926ejs_i2c_delay();
    }
    // Need extra transition (for ACK time slot)
    _I2C_SET_SCL();   // SDA=?, SCL=0
    _vpb926ejs_i2c_delay();
    _I2C_CLR_SCL();   // SDA=?, SCL=0
    _vpb926ejs_i2c_delay();
    return val;
}

int
_vpb926ejs_i2c_write_reg(int addr, int reg, unsigned char val)
{
    _vpb926ejs_i2c_start();
    if (_vpb926ejs_i2c_put(addr << 1) < 0) {
        return -1;
    }
    if (_vpb926ejs_i2c_put(reg) < 0) {
        return -1;
    }
    if (_vpb926ejs_i2c_put(val) < 0) {
        return -1;
    }
    _vpb926ejs_i2c_stop();
    return 0;
}

int
_vpb926ejs_i2c_read_reg(int addr, int reg)
{
    unsigned char val;
    _vpb926ejs_i2c_start();
    if (_vpb926ejs_i2c_put(addr << 1) < 0) {
        return -1;
    }
    if (_vpb926ejs_i2c_put(reg) < 0) {
        return -1;
    }
    _vpb926ejs_i2c_start();
    if (_vpb926ejs_i2c_put((addr << 1) | 0x01) < 0) {
        return -1;
    }
    val = _vpb926ejs_i2c_get();
    _vpb926ejs_i2c_stop();
    return val;
}

// -------------------------------------------------------------------------

static void _vpb926ejs_clcd_wait(void)
{
    cyg_uint32 reg;

    HAL_WRITE_UINT32( VPB926EJS_CLCD+_CLCD_RAW, 0 );        
    
    do
    {
        HAL_READ_UINT32( VPB926EJS_CLCD+_CLCD_COM, reg );

        do
        {
            HAL_READ_UINT32( VPB926EJS_CLCD+_CLCD_RAW, reg );
        } while( reg == 0 );

        HAL_WRITE_UINT32( VPB926EJS_CLCD+_CLCD_RAW, 0 );

        HAL_READ_UINT32( VPB926EJS_CLCD+_CLCD_RD, reg );
    } while( reg & _CLCD_BUSY );
}

static void _vpb926ejs_clcd_write_com( unsigned char val )
{
    _vpb926ejs_clcd_wait();

    HAL_WRITE_UINT32( VPB926EJS_CLCD+_CLCD_COM, val );
}

static void _vpb926ejs_clcd_write_dat( unsigned char val )
{
    _vpb926ejs_clcd_wait();

    HAL_WRITE_UINT32( VPB926EJS_CLCD+_CLCD_DAT, val );
}

static void _vpb926ejs_clcd_pos( int x, int y )
{
    _vpb926ejs_clcd_write_com( _CLCD_DDRAM_ADDR | ((y * 64) + x) );
}

static void _vpb926ejs_clcd_write_char( char c )
{
    if( c != '\n' )
        _vpb926ejs_clcd_write_dat( c );
    else
        _vpb926ejs_clcd_pos( 0, 1 );
}

static void _vpb926ejs_clcd_write_string( char *s )
{
    while( *s != 0 )
    {
        _vpb926ejs_clcd_write_char( *s );
        s++;
    }
}

static void _vpb926ejs_clcd_init(void)
{
    _vpb926ejs_clcd_write_com( _CLCD_CLR_DISPLAY );
    _vpb926ejs_clcd_write_com( _CLCD_HOME );
    _vpb926ejs_clcd_write_com( _CLCD_ENTRY_MODE_SET | _CLCD_INC );
    _vpb926ejs_clcd_write_com( _CLCD_DISP_CTRL      | _CLCD_DISP_ON | _CLCD_CURS_OFF  | _CLCD_BLINK_OFF );
    _vpb926ejs_clcd_write_com( _CLCD_FUNC_SET       | _CLCD_IF8BIT  | _CLCD_NUMLINES2 | _CLCD_FONT5X8);
}

// -------------------------------------------------------------------------
//
// Platform specific initialization
//
void
plf_hardware_init(void)
{
#ifndef CYGFUN_HAL_COMMON_KERNEL_SUPPORT    
    hal_clock_initialize( CYGNUM_HAL_RTC_PERIOD );
#endif
    
    _vpb926ejs_i2c_init();

#ifdef CYGPKG_REDBOOT
    _vpb926ejs_clcd_init();
    _vpb926ejs_clcd_write_string("RedBoot\n" __DATE__);
#endif
    
}

// -------------------------------------------------------------------------
// End of vpb926ejs_misc.c


