You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
288 lines
7.5 KiB
288 lines
7.5 KiB
/*
|
|
* uartboot.c - UART boot mode
|
|
*
|
|
* Copyright (C) 2008 Hugo Villeneuve <hugo@hugovil.com>
|
|
*
|
|
* Based on TI DaVinci Flash and Boot Utilities, original copyright follows:
|
|
* Copyright 2008 Texas Instruments, Inc. <www.ti.com>
|
|
*
|
|
* This program 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 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "common.h"
|
|
#include "davinci.h"
|
|
#include "uart.h"
|
|
#include "util.h"
|
|
#include "crc.h"
|
|
#if defined(FLASH_TYPE_NOR)
|
|
#include "nor.h"
|
|
#elif defined(FLASH_TYPE_NAND)
|
|
#include "nand.h"
|
|
#endif
|
|
|
|
/* Symbols from linker script */
|
|
extern uint32_t __DDR_START;
|
|
extern uint32_t DDR_SIZE;
|
|
|
|
static int
|
|
ddr_memory_test(void)
|
|
{
|
|
int k;
|
|
volatile uint32_t *ddr_start = &__DDR_START;
|
|
uint32_t read32;
|
|
|
|
log_info("DDR tests");
|
|
|
|
log_info("1. RAMP test:");
|
|
for (k = 0; k < DDR_SIZE/4; k++)
|
|
ddr_start[k] = k; /* Write */
|
|
|
|
for (k = 0; k < DDR_SIZE/4; k++) {
|
|
read32 = ddr_start[k]; /* Read */
|
|
if (read32 != k)
|
|
goto error;
|
|
}
|
|
log_info(" Success");
|
|
|
|
log_info("2. PATTERN test:");
|
|
for (k = 0; k < DDR_SIZE/4; k++)
|
|
ddr_start[k] = DDR_TEST_PATTERN; /* Write */
|
|
|
|
for (k = 0; k < DDR_SIZE/4; k++) {
|
|
read32 = ddr_start[k]; /* Read */
|
|
if (read32 != DDR_TEST_PATTERN)
|
|
goto error;
|
|
}
|
|
log_info(" Success");
|
|
|
|
host_msg("DDRTEST_SUCCESS");
|
|
return 0;
|
|
|
|
error:
|
|
uart_send_str("Failed at address: ");
|
|
uart_send_hexnum(k * 4, 8);
|
|
uart_send_str(", Expected: ");
|
|
uart_send_hexnum(k, 8);
|
|
uart_send_str(", Read: ");
|
|
uart_send_hexnum(read32, 8);
|
|
uart_send_lf();
|
|
host_msg("DDRTEST_FAILURE");
|
|
return -1;
|
|
}
|
|
|
|
void
|
|
uart_boot(uint32_t *jump_entry_point, int need_nwp_nand)
|
|
{
|
|
#if defined(FLASH_TYPE_NAND)
|
|
int wrote_copies = 0;
|
|
int prog_ok = 0;
|
|
int block_num;
|
|
struct nand_image_descriptor_t im_desc;
|
|
#elif defined(FLASH_TYPE_NOR)
|
|
struct nor_boot_t norBoot;
|
|
uint32_t blkAddress, blkSize, baseAddress;
|
|
#endif
|
|
struct uart_ack_header_t uart_ack_header;
|
|
uint32_t boot_cmd;
|
|
|
|
crc32_dv_build_table();
|
|
log_info("Starting UART Boot");
|
|
host_msg("BOOTPSP");
|
|
|
|
/* Get the BOOT command */
|
|
if (uart_get_cmd(&boot_cmd) != E_PASS)
|
|
goto uartboot_error;
|
|
|
|
/* Set the entry point to reset by default */
|
|
*jump_entry_point = 0x0;
|
|
|
|
switch (boot_cmd) {
|
|
case UBL_CMD_DDR_TEST:
|
|
/* Perform DDR memory testing. */
|
|
ddr_memory_test();
|
|
break;
|
|
|
|
/* Download via UART UBL and APP and burn to flash. */
|
|
case UBL_CMD_FLASH_UBL_APP:
|
|
host_msg("SENDUBL");
|
|
|
|
/* Download UBL */
|
|
if (uart_get_prog(&uart_ack_header) != E_PASS)
|
|
goto uartboot_error;
|
|
|
|
log_info("Writing UBL");
|
|
|
|
#if defined(FLASH_TYPE_NOR)
|
|
NOR_Erase(nor_get_flashbase(), uart_ack_header.size);
|
|
|
|
/* Write binary UBL to NOR flash. */
|
|
NOR_WriteBytes(nor_get_flashbase(), uart_ack_header.size,
|
|
(uint32_t) uart_ack_header.recv_buffer);
|
|
#elif defined(FLASH_TYPE_NAND)
|
|
nand_remove_nwp(need_nwp_nand);
|
|
wrote_copies = 0;
|
|
for (block_num = START_UBL_BLOCK_NUM; block_num <= END_UBL_BLOCK_NUM; block_num++) {
|
|
im_desc.magic = uart_ack_header.magic;
|
|
im_desc.block_num = block_num;
|
|
im_desc.entry_point = uart_ack_header.entry_point;
|
|
im_desc.load_address = 0; /* Load address not used by RBL */
|
|
|
|
if (nand_write_prog(&im_desc, uart_ack_header.recv_buffer, uart_ack_header.size) == E_PASS) {
|
|
wrote_copies += 1;
|
|
prog_ok = 1;
|
|
}
|
|
}
|
|
if (!prog_ok)
|
|
goto uartboot_error;
|
|
#endif
|
|
|
|
/* Indicate that UBL flashing was successfull. */
|
|
uart_send_str("INFO: UBLs written: ");
|
|
uart_send_hexnum(wrote_copies, 1);
|
|
uart_send_lf();
|
|
host_msg("DONE");
|
|
|
|
host_msg("SENDAPP");
|
|
|
|
/* Get the application header and data */
|
|
if (uart_get_prog(&uart_ack_header) != E_PASS)
|
|
goto uartboot_error;
|
|
|
|
log_info("Writing APP");
|
|
|
|
#if defined(FLASH_TYPE_NOR)
|
|
/* Erase the NOR flash where header and data will go */
|
|
DiscoverBlockInfo((nor_get_flashbase() + UBL_IMAGE_SIZE),
|
|
&blkSize, &blkAddress);
|
|
baseAddress = blkAddress + blkSize;
|
|
NOR_Erase(baseAddress, uart_ack_header.size + sizeof(norBoot));
|
|
|
|
/* MagicFlag for Application (binary or safe) */
|
|
norBoot.magicNum = uart_ack_header.magic;
|
|
|
|
/* Bytes of application (either srec or binary) */
|
|
norBoot.appSize = uart_ack_header.size;
|
|
|
|
/* Value from ACK header */
|
|
norBoot.entryPoint = uart_ack_header.entry_point;
|
|
|
|
/* Semi-hardcoded load address to entry point. FIXME */
|
|
norBoot.ldAddress = uart_ack_header.entry_point;
|
|
|
|
/* Write the struct nor_boot_t header to the flash */
|
|
NOR_WriteBytes(baseAddress, sizeof(norBoot),
|
|
(uint32_t) &norBoot);
|
|
|
|
/* Write the application data to the flash */
|
|
NOR_WriteBytes((baseAddress + sizeof(norBoot)),
|
|
uart_ack_header.size,
|
|
(uint32_t) uart_ack_header.recv_buffer);
|
|
|
|
/* Semi-hardcoded load address to entry point. FIXME */
|
|
if (nor_write_prog(&nor_boot, uart_ack_header.recv_buffer,
|
|
uart_ack_header.size,
|
|
baseAddress + sizeof(norBoot),
|
|
uart_ack_header.magic,
|
|
uart_ack_header.entry_point,
|
|
uart_ack_header.entry_point) != E_PASS)
|
|
goto uartboot_error;
|
|
#elif defined(FLASH_TYPE_NAND)
|
|
/* Write multiple copy of U-Boot (depending on the defines in NAND.h) */
|
|
nand_remove_nwp(need_nwp_nand);
|
|
prog_ok = 0;
|
|
wrote_copies = 0;
|
|
for (block_num = START_UBOOT_BLOCK_NUM; (block_num+MAX_BLOCK_PER_UBOOT-1) <= END_UBOOT_BLOCK_NUM; block_num += MAX_BLOCK_PER_UBOOT) {
|
|
im_desc.magic = uart_ack_header.magic;
|
|
im_desc.block_num = block_num;
|
|
im_desc.entry_point = uart_ack_header.entry_point;
|
|
|
|
/* Assuming load address is identical to entry point. */
|
|
im_desc.load_address = uart_ack_header.entry_point;
|
|
|
|
if (nand_write_prog(&im_desc, uart_ack_header.recv_buffer, uart_ack_header.size) == E_PASS) {
|
|
wrote_copies += 1;
|
|
prog_ok = 1;
|
|
}
|
|
}
|
|
if (!prog_ok)
|
|
goto uartboot_error;
|
|
#endif
|
|
|
|
/* Indicate that APP flashing was successfull. */
|
|
uart_send_str("INFO: APPs written: ");
|
|
uart_send_hexnum(wrote_copies, 1);
|
|
uart_send_lf();
|
|
host_msg("DONE");
|
|
|
|
break;
|
|
|
|
case UBL_CMD_FLASH_DATA:
|
|
host_msg("SENDDATA");
|
|
|
|
/* Get the data block infos and actual bytes */
|
|
if (uart_get_prog(&uart_ack_header) != E_PASS)
|
|
goto uartboot_error;
|
|
|
|
log_info("Writing DATA");
|
|
|
|
im_desc.magic = uart_ack_header.magic;
|
|
im_desc.block_num = uart_ack_header.entry_point; /* Block in flash */
|
|
|
|
if (nand_write_prog(&im_desc, uart_ack_header.recv_buffer,
|
|
uart_ack_header.size) != E_PASS)
|
|
goto uartboot_error;
|
|
|
|
/* Indicate that APP flashing was successfull. */
|
|
host_msg("DONE");
|
|
|
|
break;
|
|
|
|
case UBL_CMD_FLASH_ERASE:
|
|
log_info("Erasing whole flash");
|
|
|
|
#if defined(FLASH_TYPE_NOR)
|
|
if (NOR_GlobalErase() != E_PASS) {
|
|
log_info("Erase failed");
|
|
goto uartboot_error;
|
|
}
|
|
#elif defined(FLASH_TYPE_NAND)
|
|
nand_remove_nwp(need_nwp_nand);
|
|
if (nand_erase_all() != E_PASS) {
|
|
log_info("Erase failed");
|
|
goto uartboot_error;
|
|
}
|
|
#endif
|
|
|
|
log_info("Erase successfull");
|
|
|
|
break;
|
|
default:
|
|
/* Load and run application */
|
|
host_msg("SENDAPP");
|
|
|
|
if (uart_get_prog(&uart_ack_header) != E_PASS)
|
|
goto uartboot_error;
|
|
|
|
*jump_entry_point = uart_ack_header.entry_point;
|
|
break;
|
|
} /* end switch statement */
|
|
|
|
return;
|
|
|
|
uartboot_error:
|
|
/* Set the entry point to reset. */
|
|
*jump_entry_point = 0x0;
|
|
}
|