//==========================================================================
//
//      gx059_misc.c
//
//      Cortex-M3 Honeywell GX059 HAL functions
//
//==========================================================================
// ####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 2008, 2011 Free Software Foundation, Inc.
//
// 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):   Original for STM3210E EVAL: nickg
//              Updated for EK-LM3S811: ccoutand
//              Updated for EK-LM3S9B90: stuartw
//              Updated for GX059: stuartw
// Date:        2011-07-12
// Description:
//
//####DESCRIPTIONEND####
//
//==========================================================================

#include <pkgconf/hal.h>

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

#include <cyg/hal/hal_arch.h>
#include <cyg/hal/hal_intr.h>
#include <cyg/hal/rom_api.h>
#include <cyg/hal/var_io.h>

//==========================================================================
//
// Define used to convert a textual pin, for example A1, to the values needed
// for the array of EPIPinInfo structures.

#define SET_EPI_PIN_INFO( pin ) CYGHWR_HAL_LM3S_EPI0_P ## pin,         \
                                CYGHWR_HAL_LM3S_EPI0_FUNC_P ## pin

//==========================================================================
//
// Structure used to define the pins needed to be configured for the EPI
// interface.

typedef struct
{
    cyg_uint32  pin;
    cyg_uint32  function;
} EPIPinInfo;

//==========================================================================
//
// Array of structures used to define the pins needed to be configured for
// the EPI interface.

const EPIPinInfo epi0_pin_info[] =
{
    { SET_EPI_PIN_INFO( B4 ) },
    { SET_EPI_PIN_INFO( B5 ) },
    { SET_EPI_PIN_INFO( C4 ) },
    { SET_EPI_PIN_INFO( C5 ) },
    { SET_EPI_PIN_INFO( C6 ) },
    { SET_EPI_PIN_INFO( C7 ) },
    { SET_EPI_PIN_INFO( D2 ) },
    { SET_EPI_PIN_INFO( D3 ) },
    { SET_EPI_PIN_INFO( D4 ) },
    { SET_EPI_PIN_INFO( D5 ) },
    { SET_EPI_PIN_INFO( D6 ) },
    { SET_EPI_PIN_INFO( D7 ) },
    { SET_EPI_PIN_INFO( E0 ) },
    { SET_EPI_PIN_INFO( E1 ) },
    { SET_EPI_PIN_INFO( E2 ) },
    { SET_EPI_PIN_INFO( E3 ) },
    { SET_EPI_PIN_INFO( F4 ) },
    { SET_EPI_PIN_INFO( F5 ) },
    { SET_EPI_PIN_INFO( G0 ) },
    { SET_EPI_PIN_INFO( G1 ) },
    { SET_EPI_PIN_INFO( H0 ) },
    { SET_EPI_PIN_INFO( H1 ) },
    { SET_EPI_PIN_INFO( H2 ) },
    { SET_EPI_PIN_INFO( H3 ) },
    { SET_EPI_PIN_INFO( H4 ) },
    { SET_EPI_PIN_INFO( H5 ) },
    { SET_EPI_PIN_INFO( H6 ) },
    { SET_EPI_PIN_INFO( H7 ) },
    { SET_EPI_PIN_INFO( J0 ) },
    { SET_EPI_PIN_INFO( J1 ) },
    { SET_EPI_PIN_INFO( J2 ) },
    { 0, 0 }
};

//==========================================================================
//
// Provide the setup required for external memory, both SRAM and Flash.

void
hal_setup_external_memory( void )
{
    int        i;
    cyg_uint32 reg;

    /*
     * First enable the EPI module.
     * We need to do this explicitly because the existing eCos code can't
     * cope with register bits > 28!
     */
    HAL_READ_UINT32(( CYGHWR_HAL_LM3S_SC + CYGHWR_HAL_LM3S_SC_RCGC1 ), reg);
    reg |= CYGHWR_HAL_LM3S_SC_RCGC1_EPI0;
    HAL_WRITE_UINT32(( CYGHWR_HAL_LM3S_SC + CYGHWR_HAL_LM3S_SC_RCGC1 ), reg);

    /* Now enable all the required GPIO modules */
    CYGHWR_HAL_LM3S_PERIPH_SET( CYGHWR_HAL_LM3S_P_GPIOB, 1 );
    CYGHWR_HAL_LM3S_PERIPH_SET( CYGHWR_HAL_LM3S_P_GPIOC, 1 );
    CYGHWR_HAL_LM3S_PERIPH_SET( CYGHWR_HAL_LM3S_P_GPIOD, 1 );
    CYGHWR_HAL_LM3S_PERIPH_SET( CYGHWR_HAL_LM3S_P_GPIOE, 1 );
    CYGHWR_HAL_LM3S_PERIPH_SET( CYGHWR_HAL_LM3S_P_GPIOF, 1 );
    CYGHWR_HAL_LM3S_PERIPH_SET( CYGHWR_HAL_LM3S_P_GPIOG, 1 );
    CYGHWR_HAL_LM3S_PERIPH_SET( CYGHWR_HAL_LM3S_P_GPIOH, 1 );
    CYGHWR_HAL_LM3S_PERIPH_SET( CYGHWR_HAL_LM3S_P_GPIOJ, 1 );

    /*
     * Configure the pins and functions.
     */
    i = 0;
    while( epi0_pin_info[i].pin ) {
        CYGHWR_HAL_LM3S_GPIO_SET( epi0_pin_info[i].pin );
        CYGHWR_HAL_LM3S_GPIO_PCTL_SET( epi0_pin_info[i].function );
        i++;
    }

    /*
     * GPIO Should be all set so program the EPI0 registers
     *
     * First set the EPI Configuration to HB8 mode
     */
    reg = CYGHWR_HAL_LM3S_EPI0_CFG_MODE_HB8 |
          CYGHWR_HAL_LM3S_EPI0_CFG_BLKEN;
    HAL_WRITE_UINT32(( CYGHWR_HAL_LM3S_EPI0 + CYGHWR_HAL_LM3S_EPI0_EPICFG ),
                       reg);

    /*
     * Set the baud rate to SYSCLK/2
     */
    reg = 0x00000001;
    HAL_WRITE_UINT32(( CYGHWR_HAL_LM3S_EPI0 + CYGHWR_HAL_LM3S_EPI0_EPIBAUD ),
                       reg);

    /*
     * Set the HB8 mode to address & data multiplexed
     */
    reg = CYGHWR_HAL_LM3S_EPI0_HB8CFG_ADMUX;
    HAL_WRITE_UINT32(( CYGHWR_HAL_LM3S_EPI0 + CYGHWR_HAL_LM3S_EPI0_EPIHB8CFG ),
                       reg );

    /*
     * Set the HB8 Chip Select mode to ALE with dual CSn configuration with
     * Word access enabled
     */
    reg = ( CYGHWR_HAL_LM3S_EPI0_HB8CFG2_ALE_CSN |
            CYGHWR_HAL_LM3S_EPI0_HB8CFG2_WORD );
    HAL_WRITE_UINT32(( CYGHWR_HAL_LM3S_EPI0 + CYGHWR_HAL_LM3S_EPI0_EPIHB8CFG2 ),                       reg);

    /*
     * Set the EPI address map to have SRAM at 0x60000000, size 16MB, flash at
     * 0xA0000000, size 16MB
     */
    reg = ( CYGHWR_HAL_LM3S_EPI0_ADDR_RAM60     |
            CYGHWR_HAL_LM3S_EPI0_ADDR_RAM16M   |
            CYGHWR_HAL_LM3S_EPI0_ADDR_FLASHA0   |
            CYGHWR_HAL_LM3S_EPI0_ADDR_FLASH16M );
    HAL_WRITE_UINT32(( CYGHWR_HAL_LM3S_EPI0 + CYGHWR_HAL_LM3S_EPI0_EPIADDRMAP ),                       reg);
}

//==========================================================================
// System init
//
// This code runs before the DATA is copied from ROM and the BSS cleared,
// hence it cannot make use of static variables or data tables.

__externC void
hal_system_init( void )
{
    /*
     * Setup access to the external memory. Once this is done the data can be
     * copied from ROM.
     */
    hal_setup_external_memory();
}

//==========================================================================
// Setup platform

__externC void
hal_platform_init( void )
{
    /*
     * These can both be used as debug/diag ports so we need to set
     * them up early.
     */
    /*
     * Initialise UART0
     */
    ROM_SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOA );

    ROM_GPIOPinTypeUART( CYGHWR_HAL_LM3S_GPIOA,
                         ( GPIO_PIN_0 | GPIO_PIN_1 ));

    /*
     * Initialise UART1
     */
    ROM_SysCtlPeripheralEnable( SYSCTL_PERIPH_GPIOD );
    CYGHWR_HAL_LM3S_GPIO_PCTL_SET( CYGHWR_HAL_LM3S_UART1_RX_FUNC );
    CYGHWR_HAL_LM3S_GPIO_PCTL_SET( CYGHWR_HAL_LM3S_UART1_TX_FUNC );
#ifdef UART1_USE_PD2_3
    ROM_GPIOPinTypeUART( CYGHWR_HAL_LM3S_GPIOD,
                         ( GPIO_PIN_2 | GPIO_PIN_3 ));
#else
    ROM_GPIOPinTypeUART( CYGHWR_HAL_LM3S_GPIOD,
                         ( GPIO_PIN_0 | GPIO_PIN_1 ));
#endif
}


//==========================================================================

#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS

#include CYGHWR_MEMORY_LAYOUT_H

//--------------------------------------------------------------------------
// Accesses to areas not backed by real devices or memory can cause
// the CPU to hang.
//
// The following table defines the memory areas that GDB is allowed to
// touch. All others are disallowed.
// This table needs to be kept up to date with the set of memory areas
// that are available on the board.

static struct {
    CYG_ADDRESS     start;             // Region start address
    CYG_ADDRESS     end;               // End address (last byte)
} hal_data_access[] = {
#ifdef CYGMEM_REGION_ram               // On-chip SRAM
    {
    CYGMEM_REGION_ram, CYGMEM_REGION_ram + CYGMEM_REGION_ram_SIZE - 1},
#endif
#ifdef CYGMEM_REGION_sram              // External SRAM
    {
    CYGMEM_REGION_sram, CYGMEM_REGION_sram + CYGMEM_REGION_sram_SIZE - 1},
#endif
#ifdef CYGMEM_REGION_flash             // On-chip flash
    {
    CYGMEM_REGION_flash,
            CYGMEM_REGION_flash + CYGMEM_REGION_flash_SIZE - 1},
#endif
#ifdef CYGMEM_REGION_extflash          // External
    {
    CYGMEM_REGION_extflash,
            CYGMEM_REGION_extflash + CYGMEM_REGION_extflash_SIZE - 1},
#endif
    {
    0xE0000000, 0x00000000 - 1},       // Cortex-M peripherals
    {
    0x40000000, 0x50000000 - 1},       // Stellaris peripherals
};

__externC int
cyg_hal_stub_permit_data_access( CYG_ADDRESS addr, cyg_uint32 count )
{
    int             i;
    for( i = 0; i < sizeof( hal_data_access ) / sizeof( hal_data_access[0] );
         i++ ) {
        if( ( addr >= hal_data_access[i].start )
            && ( addr + count ) <= hal_data_access[i].end )
            return true;
    }
    return false;
}

#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS


//==========================================================================
// EOF ek_lm3s9b90_misc.c
