diff --git a/src/main/iblmain.c b/src/main/iblmain.c
--- a/src/main/iblmain.c
+++ b/src/main/iblmain.c
+/*
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of Texas Instruments Incorporated nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+*/
+
+
+
/*****************************************************************************************
* FILE PURPOSE: Perform the top level boot
*****************************************************************************************
#include "iblcfg.h"
#include "device.h"
#include "ethboot.h"
+#include "nandboot.h"
+#include "norboot.h"
#include "bis.h"
#include "coffwrap.h"
#include "iblbtbl.h"
#include "iblblob.h"
#include "timer.h"
#include "i2c.h"
+#include "spi_api.h"
#include "ibl_elf.h"
#include <string.h>
+#include "uart.h"
+extern cregister unsigned int IER;
-/**
- * @brief The ibl table is declared.
- *
- * @details
- * The ibl table is declared uninitialized by this ibl program. An external
- * initialization can be performed if the default operation of the ibl is
- * not desired.
- */
-#pragma DATA_SECTION(ibl, ".ibl_config_table")
-ibl_t ibl;
-
+uint32 iblEndianIdx = 0;
+uint32 iblImageIdx = 0;
/**
- * @brief The ibl status table is declared.
- *
- * @details
- * The ibl status table is declared. It is initialized at run time
- * in function main.
+ * @brief
+ * Data structures shared between the 1st and 2nd stage IBL load
+ * are declared in a single header file, included in both stages
*/
-#pragma DATA_SECTION(iblStatus, ".ibl_status_table")
-iblStatus_t iblStatus;
+#include "iblStage.h"
+
/* Eat printfs */
}
+/**
+ * @b Description
+ * @n
+ *
+ * For NAND and NOR boots, configure the specified peripheral or memory interface
+ */
+void iblPmemCfg (int32 interface, int32 port, bool enableNand)
+{
+ int32 ret;
+
+ switch (interface) {
+
+ #if (!defined(EXCLUDE_NAND_GPIO))
+
+ case ibl_PMEM_IF_GPIO:
+ ret = devicePowerPeriph (TARGET_PWR_GPIO);
+ break;
+ #endif
+
+ #if (!defined(EXCLUDE_NOR_SPI) && !defined(EXCLUDE_NAND_SPI))
+
+ case ibl_PMEM_IF_SPI: {
+
+ Uint32 v;
+ spiConfig_t cfg;
+
+ ret = devicePowerPeriph (TARGET_PWR_SPI);
+ if (ret != 0)
+ break;
+
+ cfg.port = port;
+ cfg.mode = ibl.spiConfig.mode;
+ cfg.addrWidth = ibl.spiConfig.addrWidth;
+ cfg.npin = ibl.spiConfig.nPins;
+ cfg.csel = ibl.spiConfig.csel;
+ cfg.c2tdelay = ibl.spiConfig.c2tdelay;
+
+ /* On c66x devices the PLL module has a built in divide by 6, and the SPI
+ * has a maximum clock divider value of 0xff */
+ v = ibl.pllConfig[ibl_MAIN_PLL].pllOutFreqMhz / (DEVICE_SPI_MOD_DIVIDER * ibl.spiConfig.busFreqMHz);
+ if (v > 0xff)
+ v = 0xff;
+
+ cfg.clkdiv = (UINT16) v;
+
+ ret = hwSpiConfig (&cfg);
+ if (ret != 0) {
+ iblStatus.iblFail = ibl_FAIL_CODE_SPI_PARAMS;
+ return;
+ }
+
+ }
+ break;
+ #endif
+
+ #if (!defined(EXCLUDE_NOR_EMIF) || !defined(EXCLUDE_NAND_EMIF))
+
+ case ibl_PMEM_IF_CHIPSEL_2:
+ case ibl_PMEM_IF_CHIPSEL_3:
+ case ibl_PMEM_IF_CHIPSEL_4:
+ case ibl_PMEM_IF_CHIPSEL_5: {
+
+ int i;
+
+ /* Locate the configuration corresponding to this chip select space */
+ for (i = 0; i < ibl_MAX_EMIF_PMEM; i++)
+ if (ibl.emifConfig[i].csSpace == interface)
+ break;
+
+ if (i == ibl_MAX_EMIF_PMEM) {
+ iblStatus.iblFail = ibl_FAIL_CODE_NO_EMIF_CFG;
+ return;
+ }
+#ifdef C665x
+ ret = devicePowerPeriph (TARGET_PWR_EMIF_C6657);
+#else
+ ret = devicePowerPeriph (TARGET_PWR_EMIF);
+#endif
+ if (ret != 0)
+ break;
+
+ if (hwEmif25Init (interface, ibl.emifConfig[i].busWidth, ibl.emifConfig[i].waitEnable, enableNand) != 0)
+ iblStatus.iblFail = ibl_FAIL_CODE_EMIF_CFG_FAIL;
+
+ }
+ break;
+
+ #endif
+
+ default:
+
+
+
+ iblStatus.iblFail = ibl_FAIL_CODE_INVALID_NAND_PERIPH;
+ return;
+ }
+
+ if (ret != 0) {
+ iblStatus.iblFail = ibl_FAIL_CODE_PERIPH_POWER_UP;
+ return;
+ }
+
+}
+
+
/**
* @b Description
void main (void)
{
int32 i, j;
+ UINT32 v, boot_mode_idx, boot_para_idx;
+ unsigned int dip_setting;
/* Initialize the status structure */
- memset (&iblStatus, 0, sizeof(iblStatus_t));
- iblStatus.iblMagic = ibl_MAGIC_VALUE;
+ iblMemset (&iblStatus, 0, sizeof(iblStatus_t));
+ iblStatus.iblMagic = ibl_MAGIC_VALUE;
+ iblStatus.iblVersion = ibl_VERSION;
- /* Initialize the system timer (software tracking of the hardware timer state */
- timer_init ();
+ /* Init UART */
+ uart_init();
+ uart_write_string("", 0);
+ uart_write_string("IBL version: "ibl_VERSION_STR, 0);
-#if 0
- /* If there is no magic value in the ibl configuration structure then a default
- * table is used. */
- if (ibl.iblMagic != ibl_MAGIC_VALUE) {
- deviceLoadDefaultIblTable();
- iblStatus.noMagic = 1;
- ibl.iblMagic = ibl_MAGIC_VALUE;
- }
-#endif
+ /* Power up the timer */
+ devicePowerPeriph (TARGET_PWR_TIMER_0);
- /* Load the default configuration table from the i2c. The actual speed of the device
- * isn't really known here, since it is part of the table, so a compile time
- * value is used (the pll may have been configured during the initial load) */
- hwI2Cinit (IBL_I2C_DEV_FREQ_MHZ, /* The CPU frequency during I2C data load */
- DEVICE_I2C_MODULE_DIVISOR, /* The divide down of CPU that drives the i2c */
- IBL_I2C_CLK_FREQ_KHZ, /* The I2C data rate used during table load */
- IBL_I2C_OWN_ADDR); /* The address used by this device on the i2c bus */
-
- if (hwI2cMasterRead (IBL_I2C_CFG_TABLE_DATA_ADDR, /* The address on the eeprom of the table */
- sizeof(ibl_t), /* The number of bytes to read */
- (UINT8 *)&ibl, /* Where to store the bytes */
- IBL_I2C_CFG_EEPROM_BUS_ADDR, /* The bus address of the eeprom */
- IBL_I2C_CFG_ADDR_DELAY) /* The delay between sending the address and reading data */
-
- != I2C_RET_OK) {
-
- /* There is no recovery if the load of the configuration table failed */
- iblStatus.tableLoadFail = 0x11111111;
- for (;;);
- }
+ /* Initialize the system timer (software tracking of the hardware timer state) */
+ timer_init ();
/* Load default mac addresses for ethernet boot if requested */
- for (i = 0; i < ibl_N_ETH_PORTS; i++) {
+ for (i = 0; i < ibl_N_BOOT_MODES; i++) {
- if ( (iblPriorityIsValid (ibl.ethConfig[i].ethPriority) ) &&
- (iblMacAddrIsZero (ibl.ethConfig[i].ethInfo.hwAddress) ) )
+ if (ibl.bootModes[i].bootMode == ibl_BOOT_MODE_TFTP) {
- deviceLoadDefaultEthAddress (ibl.ethConfig[i].ethInfo.hwAddress);
+ if (iblMacAddrIsZero (ibl.bootModes[i].u.ethBoot.ethInfo.hwAddress))
+ deviceLoadDefaultEthAddress (ibl.bootModes[i].u.ethBoot.ethInfo.hwAddress);
+ }
}
- /* Pll configuration is device specific */
- devicePllConfig ();
-
/* DDR configuration is device specific */
deviceDdrConfig ();
/* Try booting forever */
for (;;) {
- /* Start looping through the boot modes to find the one with the lowest priority
- * value, and try to boot it */
- for (i = ibl_HIGHEST_PRIORITY; i < ibl_LOWEST_PRIORITY; i++) {
-
- for (j = 0; j < ibl_N_ETH_PORTS; j++) {
- if (ibl.ethConfig[j].ethPriority == i)
- iblEthBoot (j);
+#ifndef EXCLUDE_MULTI_BOOT
+ v = DEVICE_REG32_R(DEVICE_JTAG_ID_REG);
+ v &= DEVICE_JTAG_ID_MASK;
+ if (
+ (v == DEVICE_C6678_JTAG_ID_VAL) ||
+ (v == DEVICE_C6670_JTAG_ID_VAL) ||
+ (v == DEVICE_C6657_JTAG_ID_VAL)
+ )
+ {
+ IER = 0;
+
+ /* For C66x devices, check the DEVSTAT register to find which image on which device to boot. */
+ v = DEVICE_REG32_R(DEVICE_REG_DEVSTAT);
+
+ /* Get the Endianness */
+ if (ibl_N_ENDIANS == 1)
+ {
+ iblEndianIdx = 0;
+ }
+ else
+ {
+ if (v & ibl_ENDIAN_LITTLE)
+ {
+ iblEndianIdx = 0;
+ }
+ else
+ {
+ iblEndianIdx = 1;
+ }
}
- if (ibl.nandConfig.nandPriority == i)
- iblNandBoot ();
+ /* Get the boot mode index */
+ boot_para_idx = BOOT_READ_BITFIELD(v,8,4);
+ /* Only 1 image supported for TFTP boot */
+ if (boot_para_idx > (ibl_N_IMAGES*(ibl_N_BOOT_MODES-1)))
+ {
+ /* boot parameter index not supported */
+ continue;
+ }
+ boot_mode_idx = boot_para_idx/ibl_N_IMAGES;
+ /* Get the boot image index */
+ iblImageIdx = boot_para_idx & (ibl_N_IMAGES - 1);
+
+ iblStatus.activeBoot = ibl.bootModes[boot_mode_idx].bootMode;
+
+ switch (ibl.bootModes[boot_mode_idx].bootMode)
+ {
+#ifndef EXCLUDE_ETH
+ case ibl_BOOT_MODE_TFTP:
+ iblStatus.activeDevice = ibl_ACTIVE_DEVICE_ETH;
+ /*Print something to UART, max len=80, if len is pased as 0 UART prints entire string upto '\n' or max len */
+ uart_write_string("IBL: Booting from ethernet",0);
+ iblMemcpy (&iblStatus.ethParams, &ibl.bootModes[boot_mode_idx].u.ethBoot.ethInfo, sizeof(iblEthBootInfo_t));
+ iblEthBoot (boot_mode_idx);
+ break;
+#endif
+
+#if ((!defined(EXCLUDE_NAND_EMIF)) || (!defined(EXCLUDE_NAND_GPIO)))
+ case ibl_BOOT_MODE_NAND:
+ iblPmemCfg (ibl.bootModes[boot_mode_idx].u.nandBoot.interface, ibl.bootModes[boot_mode_idx].port, TRUE);
+ memset ((void *)0x80000000, 0, 0x20000000);
+ /*Print something to UART, max len=80, if len is pased as 0 UART prints entire string upto '\n' or max len */
+ uart_write_string("IBL: Booting from NAND",0);
+ iblNandBoot (boot_mode_idx);
+ break;
+#endif
+
+#if (!defined(EXCLUDE_NOR_EMIF) && !defined(EXCLUDE_NOR_SPI))
+ case ibl_BOOT_MODE_NOR:
+ iblPmemCfg (ibl.bootModes[boot_mode_idx].u.norBoot.interface, ibl.bootModes[boot_mode_idx].port, TRUE);
+ /*Print something to UART, max len=80, if len is pased as 0 UART prints entire string upto '\n' or max len */
+ uart_write_string("IBL: Booting from NOR",0);
+ iblNorBoot (boot_mode_idx);
+ break;
+#endif
+ }
iblStatus.heartBeat += 1;
}
+#else
+
+ dip_setting = get_device_switch_setting();
+
+ if (dip_setting == 0)
+ boot_mode_idx = 0;
+ else if (dip_setting == 1)
+ boot_mode_idx = 1;
+
+ iblStatus.activeBoot = ibl.bootModes[boot_mode_idx].bootMode;
+
+ switch (ibl.bootModes[boot_mode_idx].bootMode) {
+#ifndef EXCLUDE_ETH
+ case ibl_BOOT_MODE_TFTP:
+ iblStatus.activeDevice = ibl_ACTIVE_DEVICE_ETH;
+ iblMemcpy (&iblStatus.ethParams, &ibl.bootModes[boot_mode_idx].u.ethBoot.ethInfo, sizeof(iblEthBootInfo_t));
+ /*Print something to UART, max len=80, if len is pased as 0 UART prints entire string upto '\n' or max len */
+ uart_write_string("IBL: Booting from Ethernet",0);
+ iblEthBoot (boot_mode_idx);
+ break;
+#endif
+
+#if ((!defined(EXCLUDE_NAND_EMIF)) || (!defined(EXCLUDE_NAND_GPIO)))
+ case ibl_BOOT_MODE_NAND:
+ iblPmemCfg (ibl.bootModes[boot_mode_idx].u.nandBoot.interface, ibl.bootModes[boot_mode_idx].port, TRUE);
+ /*Print something to UART, max len=80, if len is pased as 0 UART prints entire string upto '\n' or max len */
+ uart_write_string("IBL: Booting from NAND",0);
+ iblNandBoot (boot_mode_idx);
+ break;
+#endif
+ }
+ iblStatus.heartBeat += 1;
+#endif
}
-
-
} /* main */
*/
Uint32 iblBoot (BOOT_MODULE_FXN_TABLE *bootFxn, Int32 dataFormat, void *formatParams)
{
- Uint32 entry = 0;
-
- union {
-
- Uint8 dataBuf[4]; /* Place holder */
- Uint32 bisValue;
- Uint16 coffVer;
-
- } fid;
-
+ Uint32 entry = 0;
+ Uint32 value32;
+ Uint8 dataBuf[4];
+ Uint16 value16;
/* Determine the data format if required */
if (dataFormat == ibl_BOOT_FORMAT_AUTO) {
- (*bootFxn->peek)((Uint8 *)&fid, sizeof(fid));
+ (*bootFxn->peek)(dataBuf, sizeof(dataBuf));
+ value32 = (dataBuf[0] << 24) | (dataBuf[1] << 16) | (dataBuf[2] << 8) | (dataBuf[3] << 0);
+ value16 = (dataBuf[0] << 8) | (dataBuf[1] << 0);
/* BIS */
- if (fid.bisValue == BIS_MAGIC_NUMBER)
+#ifndef EXCLUDE_BIS
+ if (value32 == BIS_MAGIC_NUMBER)
dataFormat = ibl_BOOT_FORMAT_BIS;
+#endif
- if (iblIsCoff (fid.coffVer))
+#ifndef EXCLUDE_COFF
+ if (iblIsCoff (value16))
dataFormat = ibl_BOOT_FORMAT_COFF;
+#endif
+
+#ifndef EXCLUDE_ELF
+ if (iblIsElf (dataBuf))
+ dataFormat = ibl_BOOT_FORMAT_ELF;
+#endif
- else {
+ if (dataFormat == ibl_BOOT_FORMAT_AUTO) {
iblStatus.autoDetectFailCnt += 1;
return (0);
}
}
+ iblStatus.activeFileFormat = dataFormat;
+
+
/* Invoke the parser */
switch (dataFormat) {
+#ifndef EXCLUDE_BIS
case ibl_BOOT_FORMAT_BIS:
iblBootBis (bootFxn, &entry);
break;
+#endif
+#ifndef EXCLUDE_COFF
case ibl_BOOT_FORMAT_COFF:
iblBootCoff (bootFxn, &entry);
break;
+#endif
case ibl_BOOT_FORMAT_BTBL:
iblBootBtbl (bootFxn, &entry);
break;
+#ifndef EXCLUDE_BLOB
case ibl_BOOT_FORMAT_BBLOB:
iblBootBlob (bootFxn, &entry, formatParams);
break;
+#endif
-#if 0
+#ifndef EXCLUDE_ELF
case ibl_BOOT_FORMAT_ELF:
iblBootElf (bootFxn, &entry);
break;