/* bootHwInit.c - hardware initialize and SPI boot for TI OMAP-L138 */
/*
* Copyright (c) 2012 Wind River Systems, Inc.
*
* The right to copy, distribute, modify or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River license agreement.
*/
/*
modification history
--------------------
01a,17oct12,c_l written.
*/
/*
DESCRIPTION
This module contains the hardware initialization code. The entry point,
sysBootHwInit(), is the first code executed in this file. It performs the
minimal hardware setup and copy the boot code from SPI flash to SDRAM,
then jumps to the routine romInit() for the second stage boot.
SEE ALSO:
\tb "OMAP-L138 DSP+ARM Processor Technical Reference Manual",
\tb "sprab41d.pdf"
*/
/* defines */
#include <vxWorks.h>
#include "config.h"
/* typedefs */
/* globals */
/* locals */
/* forward declarations */
LOCAL void ti138PinmuxInit (unsigned regOffset, unsigned mask, unsigned value);
LOCAL void ti138PLL0Init (void);
LOCAL void ti138PLL1Init (void);
LOCAL void ti138HwUartInit (void);
LOCAL void ti138HwSpiInit (void);
LOCAL void ti138HwMddrInit (void);
LOCAL void ti138HwPscInit (void);
LOCAL void ti138HwClocksInit (void);
LOCAL void ti138HwI2cInit (void);
LOCAL void ti138HwEmacInit (void);
LOCAL int sysLoadVxWorks (unsigned long, unsigned long, unsigned long);
void sysLoopDelay (int delay);
#include "omapL138SpiFlash.c"
/*******************************************************************************
*
* sysLoopDelay - simple loop delay
*
* Delay for a while, no accurate.
*
* RETURNS: N/A
*/
void sysLoopDelay
(
int delay
)
{
volatile int i;
for (i = 0; i < delay ; i++);
}
/******************************************************************************
*
* ti138PinmuxInit - pin multiplexing control
*
* This routine control ti138 pin multiplexing
*
* RETURNS: N/A
*
* ERRNO: N/A
*/
LOCAL void ti138PinmuxInit
(
unsigned int pinMux,
unsigned int mask,
unsigned int value
)
{
volatile int regVal;
OMAP_REG_INT_WRITE (BOOT_CONFIG_BASE + KICK0R, KICK0R_KEY);
OMAP_REG_INT_WRITE (BOOT_CONFIG_BASE + KICK1R, KICK1R_KEY);
/* configure pin */
regVal = OMAP_REG_INT_READ (BOOT_CONFIG_BASE + pinMux);
regVal &= ~mask;
regVal |= (mask & value);
OMAP_REG_INT_WRITE (BOOT_CONFIG_BASE + pinMux, regVal);
OMAP_REG_INT_WRITE (BOOT_CONFIG_BASE + KICK0R, 0);
OMAP_REG_INT_WRITE (BOOT_CONFIG_BASE + KICK1R, 0);
}
/******************************************************************************
*
* ti138PscCtrl - psc state transition control
*
* This routine control ti138 psc state transition
*
* RETURNS: N/A
*
* ERRNO: N/A
*/
LOCAL void ti138PscCtrl
(
unsigned int pscBaseReg,
unsigned char pscModule,
unsigned char pscDomain,
unsigned char pscState
)
{
volatile unsigned int regVal;
/* wait for any outstanding psc control command to complete */
while (((OMAP_REG_INT_READ (pscBaseReg + PTSTAT)) & PSC_STATE_BUSY) != 0)
{
};
/* executing psc state transition */
regVal = OMAP_REG_INT_READ (pscBaseReg + MDSTAT (pscModule));
regVal &= PSC_STATE_MASK;
if (regVal == pscState)
{
return; /* if we are already in that state, do nothing */
}
else
{
/* clear the bits before setting the next state */
regVal = OMAP_REG_INT_READ (pscBaseReg + MDCTL (pscModule));
regVal &= ~PSC_CTRL_NEXT;
/* executing transition */
OMAP_REG_INT_WRITE (pscBaseReg + MDCTL (pscModule), regVal);
regVal |= pscState;
OMAP_REG_INT_WRITE (pscBaseReg + MDCTL (pscModule), regVal);
regVal = OMAP_REG_INT_READ (pscBaseReg + PTCMD);
regVal |= pscDomain;
OMAP_REG_INT_WRITE (pscBaseReg + PTCMD, regVal);
/* wait for any outstanding psc control command to complete */
while (((OMAP_REG_INT_READ (pscBaseReg + PTSTAT)) & PSC_STATE_BUSY) != 0)
{
};
/* wait and verify the module state */
while (((OMAP_REG_INT_READ (pscBaseReg + MDSTAT (pscModule))) &
PSC_STATE_MASK) != pscState)
{
};
}
}
/******************************************************************************
*
* ti138HwUartInit - initialize uart
*
* This routine initializes ti138 uart
*
* RETURNS: N/A
*
* ERRNO: N/A
*/
LOCAL void ti138HwUartInit (void)
{
unsigned short divisor = 0 ;
volatile unsigned int val;
/* config pinmux for uart2 */
ti138PinmuxInit (PINMUX0, PINMUX_UART2_MASK_0, PINMUX_UART2_VALUE_0);
ti138PinmuxInit (PINMUX4, PINMUX_UART2_MASK_1, PINMUX_UART2_VALUE_1);
/* calculate baud rate */
divisor = ((SYS_CLK_FREQ / 2) / (UART_DEFAULT_BAUD * 16));
val = UART_VALUE_INIT;
OMAP_REG_INT_WRITE (UART2_REG_BASE + UART_PWREMU_MGM, val);
/* disable interrupts, flow control, and loop back */
OMAP_REG_INT_WRITE (UART2_REG_BASE + UART_IER, val);
OMAP_REG_INT_WRITE (UART2_REG_BASE + UART_MCR, val);
OMAP_REG_INT_WRITE (UART2_REG_BASE + UART_MDR, val);
/* set the DLL and DLH */
val = (divisor & UART_DLH_MASK) >> 8;
OMAP_REG_INT_WRITE (UART2_REG_BASE + UART_DLH, val);
val = divisor & UART_DLL_MASK;
OMAP_REG_INT_WRITE (UART2_REG_BASE + UART_DLL, val);
/* set the FIFO */
val = UART_FCR_INIT;
OMAP_REG_INT_WRITE (UART2_REG_BASE + UART_FCR, val);
/* choose the desired protocol settings */
val = UART_LCR_INIT;
OMAP_REG_INT_WRITE (UART2_REG_BASE + UART_LCR, val);
val = UART_UTRST | UART_URRST | UART_FREE;
OMAP_REG_INT_WRITE (UART2_REG_BASE + UART_PWREMU_MGM, val);
}
/******************************************************************************
*
* ti138HwSpiInit - initialize spi
*
* This routine initializes ti138 spi
*
* RETURNS: N/A
*
* ERRNO: N/A
*/
LOCAL void ti138HwSpiInit (void)
{
/* config pinmux for spi */
ti138PinmuxInit (PINMUX5, PINMUX_SPI1_MASK, PINMUX_SPI1_VALUE);
}
/******************************************************************************
*
* ti138HwI2cInit - initialize i2c
*
* This routine initializes ti138 i2c
*
* RETURNS: N/A
*
* ERRNO: N/A
*/
LOCAL void ti138HwI2cInit (void)
{
/* config pinmux for spi */
ti138PinmuxInit (PINMUX4, PINMUX_I2C0_MASK, PINMUX_I2C0_VAL);
}
/******************************************************************************
*
* ti138HwEmacInit - initialize emac
*
* This routine initializes ti138 emac
*
* RETURNS: N/A
*
* ERRNO: N/A
*/
LOCAL void ti138HwEmacInit (void)
{
volatile unsigned int val;
/* config pinmux for emac */
ti138PinmuxInit (PINMUX4, PINMUX_MDIO_MASK, PINMUX_MDIO_VAL);
ti138PinmuxInit (PINMUX6, PINMUX_MDIO_EN_MASK, PINMUX_MDIO_EN_VAL);
ti138PinmuxInit (PINMUX2, PINMUX_MII_MASK_0, PINMUX_MII_VAL_0);
ti138PinmuxInit (PINMUX3, PINMUX_MII_MASK_1, PINMUX_MII_VAL_1);
OMAP_REG_INT_WRITE (BOOT_CONFIG_BASE + KICK0R, KICK0R_KEY);
OMAP_REG_INT_WRITE (BOOT_CONFIG_BASE + KICK1R, KICK1R_KEY);
val = OMAP_REG_INT_READ (BOOT_CONFIG_BASE + CFGCHIP3);
val &= ~EMAC_MODE;
OMAP_REG_INT_WRITE (BOOT_CONFIG_BASE + CFGCHIP3, val);
OMAP_REG_INT_WRITE (BOOT_CONFIG_BASE + KICK0R, 0);
OMAP_REG_INT_WRITE (BOOT_CONFIG_BASE + KICK1R, 0);
}
/******************************************************************************
*
* ti138HwMddrInit - initialize mDDR on ti138
*
* This routine initializes mDDR on ti138
*
* RETURNS: N/A
*
* ERRNO: N/A
*/
LOCAL void ti138HwMddrInit (void)
{
volatile unsigned int regVal = 0;
OMAP_REG_INT_WRITE (BOOT_CONFIG_BASE + KICK0R, KICK0R_KEY);
OMAP_REG_INT_WRITE (BOOT_CONFIG_BASE + KICK1R, KICK1R_KEY);
/* enable EMIF3A clock */
ti138PscCtrl (PSC1_REG_BASE, PSC_EMIF3A, PSC_DOMAIN0, PSC_ENABLE);
/* check if VTP calibration is enabled */
regVal = OMAP_REG_INT_READ (BOOT_CONFIG_BASE_1