FreeCalypso > hg > freecalypso-reveng
diff frbl/reconst/boot.c @ 315:bc3391aa3d35
frbl/reconst/boot.c: import from TI's FLUID package
with defenestrated line endings
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 04 Mar 2020 23:17:27 +0000 |
parents | |
children | 2ceb1f263e19 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/frbl/reconst/boot.c Wed Mar 04 23:17:27 2020 +0000 @@ -0,0 +1,357 @@ +/****************************************************************************** + * FLUID (Flash Loader Utility Independent of Device) + * + * (C) Delta Technologies 2001. + * Cleanup, modifications and extensions by Mads Meisner-Jensen, mmj@ti.com. + * + * Target Bootloader + * + * $Id: boot.c 1.18 Mon, 28 Apr 2003 08:49:16 +0200 tsj $ + * + ******************************************************************************/ + +#include "chipset.cfg" +#include "target.h" + + +#define DEBUG_TRACE 0 + + +// Protocol version of this bootloader + +// Version 0: Original, unmodified Delta Technology Bootloader. + +// Version 1: First Fluid Bootloader. 'B'audrate command and 'V'ersion +// command. Backward compatibly with version 0. + +// Version 2: 'H'ardware chipset query command. Debug/Trace +// functionality. Backward compatibly with version 0, 1. Fixed bug where +// IND$CALL was used to start command interpreter instead of private jump() +// function + +// Version 3: Generic 'Q'uery command. Discontinued 'H'ardware query command +// from version 2. + +#define BOOTLOADER_VERSION '3' + + +/****************************************************************************** + * Bootstrap/Init + ******************************************************************************/ + +// Initialize stackpointer according to chipset. Note that we ALWAYS do +// this, no matter if we were laoded with JTAG or if we were compiled-in. + +#if (CHIPSET == 3) +asm("STACK_INIT .equ 03000000h"); +asm("STACK_ADD .equ 00020000h ; 128kB"); +#elif (CHIPSET == 7) +asm("STACK_INIT .equ 00800000h"); +asm("STACK_ADD .equ 00020000h ; 128kB"); +#elif (CHIPSET == 12) +asm("STACK_INIT .equ 08000000h"); +asm("STACK_ADD .equ 00020000h ; 128kB"); +#else +#error Unknown target hardware selected +#endif + +#ifdef FLUID_BOOT_STAND_ALONE +asm(" .def _c_int00 "); +asm("_c_int00:"); +#endif + +asm(" .state32 "); +asm(" mov sp,#STACK_INIT"); +asm(" add sp,sp,#STACK_ADD"); +asm(" adr lr,start_end + 1 ; module end address with lsb set"); +asm(" bx lr ; branch to start"); +asm(" nop"); +asm("start_end:"); + + + +/****************************************************************************** + * Main + ******************************************************************************/ + +uint32 uart; + +void jump(uint32, uint32); + +void putchar(uint8 ch); +uint8 getchar(void); +void uart_init(UBYTE dlh, UBYTE dll); +void hardware_init(uint16 *code); + +void fluid_bootloader(void) +{ + uint8 ch; + uint16 *mem; + union32_t addr; + union16_t size; + union16_t data; + uint8 uart_dlh, uart_dll; + uint16 chip_id_code; + + hardware_init(&chip_id_code); + + uart = UART_MODEM; + uart_init(0, 0x07); // baudrate = 115200kbps + uart = UART_IRDA; + uart_init(0, 0x07); // baudrate = 115200kbps + +#ifdef TESTBOOT + while (1) { + uart = UART_MODEM; + if ((REGISTER_8_READ(uart + UART_LSR) & STAT_RXRDY)) + break; + uart = UART_IRDA; + if ((REGISTER_8_READ(uart + UART_LSR) & STAT_RXRDY)) + break; + } + while (getchar() != 0xAA) + ; + while (getchar() != 0x01) + ; + while (getchar() != 0xDD) + ; +#endif + + while (1) { + uart = UART_MODEM; + putchar(PROTO_HELLO); + if ((REGISTER_8_READ(uart + UART_LSR) & STAT_RXRDY)) + break; + uart = UART_IRDA; + putchar(PROTO_HELLO); + if ((REGISTER_8_READ(uart + UART_LSR) & STAT_RXRDY)) + break; + } + while (1) { + ch = getchar(); + switch (ch) { + case PROTO_VERSION: + putchar(BOOTLOADER_VERSION); + break; + case PROTO_QUERY: + ch = getchar(); + if (ch == PROTO_QUERY_CHIP) { + data.i = chip_id_code; + putchar(data.b[0]); + putchar(data.b[1]); + putchar(0); + putchar(0); + } + else { + putchar(PROTO_ERROR); + } + break; + case PROTO_BAUDRATE: + ch = getchar(); // Get DLH + case 0: + uart_init(ch, getchar()); + break; + case PROTO_DOWNLOAD: + addr.b[0] = getchar(); + addr.b[1] = getchar(); + addr.b[2] = getchar(); + addr.b[3] = getchar(); + size.b[0] = getchar(); + size.b[1] = getchar(); + putchar(PROTO_READY); + mem = (uint16 *) addr.i; + while (size.i--) { + // Data bytes arrive in reverse order due to little endian mode + data.b[1] = getchar(); + data.b[0] = getchar(); + *mem++ = data.i; + } + +#if DEBUG_TRACE + // Insert convenient tracing here... +#endif + // Start the program we loaded. + jump(uart, addr.i); + break; + default: + putchar(PROTO_ERROR); + } + } +} + +// Little assembly function that makes a jump to the address/argument, +// similar to the compiler's IND$CALL. We do not use the compiler's IND$CALL +// because when we compile for non-standalone, IND$CALL is already +// defined. We expect that the base address of the UART is in R0, so it can +// be properly passed on to the command interpreter. +asm("$jump:"); +asm(" bx r1"); + +void putchar(uint8 ch) +{ + PUTCHAR_FUNCTION_CODE(uart) +} + +uint8 getchar(void) +{ + GETCHAR_FUNCTION_CODE(uart) +} + + +/****************************************************************************** + * Initialization + ******************************************************************************/ +#if (CHIPSET == 3) + #define IQ_MASK (0xFFFFFA02) /* Mask Interrupt Register */ +#elif (CHIPSET == 7) || (CHIPSET == 12) + #define IQ_MASK1 (0xFFFFFA08) /* Mask Interrupt Register 1 */ + #define IQ_MASK2 (0xFFFFFA0A) /* Mask Interrupt Register 2 */ +#else + #error Unknown target hardware selected +#endif + + +void hardware_init(uint16 *chip_id_code) +{ + uint16 clk; + char chip_set = 0; + + // We read the chipset version directly from the hardware because + // otherwise the stand-alone bootloader (to be downloaded with JTAG) is + // obviously not target independent! + *chip_id_code = *((volatile uint16 *) CHIP_ID_CODE); + + + // We should only intialize the hardware if we were downloaded with JTAG + +#ifdef FLUID_BOOT_STAND_ALONE + + // FIXME: we should perhaps have different init depending on chipset + // detected? + + // Mask all interrupts +#if (CHIPSET == 3) + *((volatile uint16 *) IQ_MASK) = 0xFFFF; +#elif (CHIPSET == 7) + *((volatile uint16 *) IQ_MASK1) = 0xFFFF; + *((volatile uint16 *) IQ_MASK2) = 0x001F; +#elif (CHIPSET == 12) + *((volatile uint16 *) IQ_MASK1) = 0xFFFF; + *((volatile uint16 *) IQ_MASK2) = 0xFFFF; //BJO Check IRQ_29_MSK - should it be 0 ? +#endif + + // Disable watchdog timer + *((volatile uint16 *) WATCHDOG_TIM_MODE) = 0xF5; + *((volatile uint16 *) WATCHDOG_TIM_MODE) = 0xA0; +#if (CHIPSET == 12) //BJO Check this (documented?) + *((volatile uint16 *) WATCHDOG_TIM_MODE+80) = 0xF5; // Secure watchdog CALPLUS + *((volatile uint16 *) WATCHDOG_TIM_MODE+80) = 0xA0; // Secure watchdog CALPLUS +#endif + + +#if (CHIPSET == 3) || (CHIPSET == 7) + // FIXME: Describe exactly how the CSs are initialized + *((volatile uint16 *) CS0_MEM_REG) = 0x2A1; + *((volatile uint16 *) CS1_MEM_REG) = 0x2A1; + *((volatile uint16 *) CS2_MEM_REG) = 0x2A1; + *((volatile uint16 *) CS3_MEM_REG) = 0x283; + *((volatile uint16 *) CS4_MEM_REG) = 0x283; + *((volatile uint16 *) CS6_MEM_REG) = 0x2C0; +#elif (CHIPSET == 12) + *((volatile uint16 *) CS0_MEM_REG) = 0x2A3; //*BJO Check these settings + *((volatile uint16 *) CS1_MEM_REG) = 0x2A3; + *((volatile uint16 *) CS2_MEM_REG) = 0x2A3; + *((volatile uint16 *) CS3_MEM_REG) = 0x2A3; + *((volatile uint16 *) CS4_MEM_REG) = 0x2A3; + *((volatile uint16 *) CS5_MEM_REG) = 0x2A3; +#endif + + +#if (CHIPSET == 3) + clk = *(volatile uint16 *) CLKM_CNTL_ARM_CLK; + clk &= ~(0x0C | 0x30); + clk |= (2 << 4); + *(volatile uint16 *) CLKM_CNTL_ARM_CLK = clk; + +#elif (CHIPSET == 7) + + // Reset DPLL register + * (volatile uint16 *) MEM_DPLL_ADDR = DPLL_RESET_VALUE; + + // Wait that DPLL is in BYPASS mode + while (((* (volatile uint16 *) MEM_DPLL_ADDR) & 1) != 1) + ; + + // Reset CLKM register + *(volatile uint16 *) MEM_CLKM_ADDR = CLKM_CNTL_ARM_CLK_RST; + +#elif (CHIPSET == 12) + + *((volatile uint8*)CTNL_CLK) = 0x91; // Make sure we are set to 26MHz mode (div 2) // CALPLUS + *((volatile uint16 *) MEM_DPLL_ADDR) = 0x6012 | (8<<7) | (1<<5); // multiplyer=8, divider=2 (-1) 52MHz!!! // CALPLUS + // Wait that DPLL is locked + while (((* (volatile unsigned short *) MEM_DPLL_ADDR) & 1) != 1) ; // CALPLUS + +#endif + + +#endif // ifdef FLUID_BOOT_STAND_ALONE +} + +void uart_init(uint8 my_dlh, uint8 my_dll) +{ + uint8 ch; + + /* + * Transition from the DSP Rhea bus to the MCU Rhea bus. + */ + BIT_SET (UART_UIR, UART_MASK_IT); + BIT_CLR (UART_UIR, UART_ACCESS); + BIT_CLR (UART_UIR, UART_MASK_IT); + + /* + * Set the UART in reset mode. + */ + REGISTER_8_WRITE(uart + UART_MDR1, CMD_UART_RESET); + + /* + * FIFO configuration + */ + REGISTER_8_WRITE(uart + UART_LCR, CMD_EFR_EN); + BIT_SET (uart + UART_EFR, ENHANCED_EN); + REGISTER_8_WRITE(uart + UART_LCR, CMD_FCR_MCR_EN); + REGISTER_8_WRITE(uart + UART_FCR, CMD_FIFO_EN); + + /* + * Speed configuration + */ + REGISTER_8_WRITE(uart + UART_LCR, CMD_EFR_EN); + REGISTER_8_WRITE(uart + UART_DLL, my_dll); + REGISTER_8_WRITE(uart + UART_DLH, my_dlh); + + /* + * Character format configuration + */ + REGISTER_8_WRITE(uart + UART_LCR, CMD_CHAR8_STOP1_NOPAR); + + /* + * Modem configuration + */ + REGISTER_8_WRITE(uart + UART_MDR1, CMD_UART_MODE); + + /* + * Flush Rx buffer + */ + while ((REGISTER_8_READ(uart + UART_LSR) & STAT_RXRDY)) + ch = (REGISTER_8_READ(uart + UART_RHR)); +} + + +/****************************************************************************** + * Debug + ******************************************************************************/ + +#if (DEBUG_TRACE == 1) +#include "debug.c" +#endif +