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
+