]> git.kernelconcepts.de Git - karo-tx-redboot.git/blobdiff - packages/hal/arm/xscale/triton/v2_0/src/redboot_cmds.c
Initial revision
[karo-tx-redboot.git] / packages / hal / arm / xscale / triton / v2_0 / src / redboot_cmds.c
diff --git a/packages/hal/arm/xscale/triton/v2_0/src/redboot_cmds.c b/packages/hal/arm/xscale/triton/v2_0/src/redboot_cmds.c
new file mode 100755 (executable)
index 0000000..f9f73f3
--- /dev/null
@@ -0,0 +1,334 @@
+//==========================================================================
+//
+//      redboot_cmds.c
+//
+//      TRITON [platform] specific RedBoot commands
+//
+//==========================================================================
+//#####ECOSGPLCOPYRIGHTBEGIN####
+//## -------------------------------------------
+//## This file is part of eCos, the Embedded Configurable Operating System.
+//## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//##
+//## eCos 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 or (at your option) any later version.
+//##
+//## eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
+//## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//##
+//## As a special exception, if other files instantiate templates or use macros
+//## or inline functions from this file, or you compile this file and link it
+//## with other works to produce a work based on this file, this file does not
+//## by itself cause the resulting work to be covered by the GNU General Public
+//## License. However the source code for this file must still be made available
+//## in accordance with section (3) of the GNU General Public License.
+//##
+//## This exception does not invalidate any other reasons why a work based on
+//## this file might be covered by the GNU General Public License.
+//##
+//## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+//## at http://sources.redhat.com/ecos/ecos-license/
+//## -------------------------------------------
+//#####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    gthomas
+// Contributors: gthomas
+//               Richard Panton <richard.panton@3glab.com>
+// Date:         2001-02-24
+// Purpose:      
+// Description:  
+//              
+// This code is part of RedBoot (tm).
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include <redboot.h>
+
+#include <cyg/hal/hal_triton.h>
+#include <cyg/hal/hal_intr.h>
+#include <cyg/hal/hal_cache.h>
+
+// Exported CLI function(s)
+
+
+
+#define CCCR_MEMCLK_99         0x00000001
+#define CCCR_MEMCLK_117                0x00000002
+#define CCCR_MEMCLK_132                0x00000003
+#define CCCR_MEMCLK_147        0x00000004
+#define CCCR_MEMCLK_165        0x00000005
+
+#define CCCR_RUN_EQ_MEM                0x00000020
+#define CCCR_RUN_2T_MEM                0x00000040
+
+#define CCCR_TURBO_10          0x00000100
+#define CCCR_TURBO_15          0x00000180
+#define CCCR_TURBO_20          0x00000200
+#define CCCR_TURBO_30          0x00000300
+
+
+
+RedBoot_cmd("mem",
+           "Set a memory location",
+           "[-h|-b] [-a <address>] <data>",
+           do_mem
+           );
+
+void do_mem(int argc, char *argv[])
+{
+       struct option_info opts[3];
+       bool mem_half_word, mem_byte;
+       volatile cyg_uint32 *address = NULL;
+       cyg_uint32 value;
+
+       init_opts(&opts[0], 'b', false, OPTION_ARG_TYPE_FLG,
+                 (void *)&mem_byte, 0, "write a byte");
+       init_opts(&opts[1], 'h', false, OPTION_ARG_TYPE_FLG,
+                 (void *)&mem_half_word, 0, "write a half-word");
+       init_opts(&opts[2], 'a', true, OPTION_ARG_TYPE_NUM,
+                 (void *)&address, NULL, "address to write at");
+       if (!scan_opts(argc, argv, 1, opts, 3, (void *)&value, OPTION_ARG_TYPE_NUM, "address to set"))
+               return;
+       if (mem_byte && mem_half_word) {
+               diag_printf("*ERR: Should not specify both byte and half-word access\n");
+       } else if (mem_byte) {
+               *(cyg_uint8*)address = (cyg_uint8)(value & 255);
+               diag_printf("  Set 0x%08X to 0x%02X (result 0x%02X)\n", address, value & 255, (int)*(cyg_uint8*)address);
+       } else if (mem_half_word) {
+               if ((unsigned long)address & 1) {
+                       diag_printf("*ERR: Badly aligned address 0x%08X for half-word store\n", address);
+               } else {
+                       *(cyg_uint16*)address = (cyg_uint16)(value & 0xffff);
+                       diag_printf("  Set 0x%08X to 0x%04X (result 0x%04X)\n", address, value & 0xffff, (int)*(cyg_uint16*)address);
+               }
+       } else {
+               if ((unsigned long)address & 3) {
+                       diag_printf("*ERR: Badly aligned address 0x%08X for word store\n", address);
+               } else {
+                       *address = value;
+                       diag_printf("  Set 0x%08X to 0x%08X (result 0x%08X)\n", address, value,
+                                   *address);
+               }
+       }
+}
+
+RedBoot_cmd("clock", 
+            "Set/Query the system clock speed", 
+            "[-s <clock>]",
+            do_clock
+           );
+
+int get_clock_rate(void) {
+       
+       unsigned long CCCR_reg, CCLKCFG_reg;
+       
+       
+       asm volatile (
+                     "ldr r1, =0x41300000;"            // Core Clock Config Reg
+                     "ldr %0, [r1];"
+                     "mrc p14, 0, %1, c6, c0, 0;"      // read CCLKCFG register
+                     : "=r"(CCCR_reg), "=r"(CCLKCFG_reg)
+                     :  
+                     : "r1"
+                     );
+
+       CCCR_reg &= 0x3ff;                      // blank reserved bits
+
+       if (!(CCLKCFG_reg & 1)) {               // we do not stay in turbo mode
+               CCCR_reg &= 0x7f;               // delete turbo information
+               switch (CCCR_reg) {
+               case (CCCR_MEMCLK_99 | CCCR_RUN_EQ_MEM):
+                       return 100;
+                       break;
+               case (CCCR_MEMCLK_99 | CCCR_RUN_2T_MEM):
+                       return 200;
+                       break;
+               default:
+                       return 0;
+               }
+       } else {                                // we stay in turbo mode
+               switch (CCCR_reg) {
+               case (CCCR_MEMCLK_99 | CCCR_RUN_2T_MEM | CCCR_TURBO_15):
+                       return 300;
+                       break;
+               case (CCCR_MEMCLK_99 | CCCR_RUN_2T_MEM | CCCR_TURBO_20):
+                       return 400;
+                       break;
+               default:
+                       return 0;
+               }
+       }
+}
+void do_clock(int argc, char *argv[])
+{
+       int new_clock, ret;
+       bool new_clock_set, clock_ok;
+       struct option_info opts[1];
+//#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
+//    struct config_option opt;
+//#endif
+       unsigned long reg;
+
+       init_opts(&opts[0], 's', true, OPTION_ARG_TYPE_NUM,
+                 (void *)&new_clock, (bool *)&new_clock_set, "new clock speed");
+       if (!scan_opts(argc, argv, 1, opts, 1, 0, 0, "")) {
+               return;
+       }
+
+       if (new_clock_set) {
+               diag_printf("Clock speed will be changed to %d MHz\n", new_clock);
+        
+               clock_ok = 1;    
+        
+               switch (new_clock) {
+               case 100:
+                       reg =   CCCR_MEMCLK_99  | CCCR_RUN_EQ_MEM | CCCR_TURBO_10;
+                       asm volatile (
+                                     "mov      r1,     %0;"
+                                     "ldr    r2, =0x41300000;"                 // Core Clock Config Reg
+                                     "str    r1, [r2];"                                // set speed
+                                     "mov      r1, #0x2;"                                      // no turbo mode
+                                     "mcr      p14, 0, r1, c6, c0, 0;"         // frequency change  sequence
+                                     :  
+                                     : "r"(reg)  
+                                     : "r1", "r2"
+                                     );        
+                       break;
+               case 200:
+                       reg =   CCCR_MEMCLK_99 | CCCR_RUN_2T_MEM | CCCR_TURBO_10;
+                       asm volatile (
+                                     "mov      r1,     %0;"
+                                     "ldr    r2, =0x41300000;"                 // Core Clock Config Reg
+                                     "str    r1, [r2];"                                // set speed
+                                     "mov      r1, #0x2;"                                      // no turbo mode
+                                     "mcr      p14, 0, r1, c6, c0, 0;"         // frequency change  sequence
+                                     :  
+                                     : "r"(reg)  
+                                     : "r1", "r2"
+                                     );        
+                       break;
+               case 300:       
+                       reg =   CCCR_MEMCLK_99 | CCCR_RUN_2T_MEM | CCCR_TURBO_15;
+                       asm volatile (
+                                     "mov      r1,     %0;"
+                                     "ldr    r2, =0x41300000;"                 // Core Clock Config Reg
+                                     "str    r1, [r2];"                                // set speed
+                                     "mov      r1, #0x3;"                                      // set turbo mode
+                                     "mcr      p14, 0, r1, c6, c0, 0;"         // frequency change  sequence
+                                     :  
+                                     : "r"(reg)  
+                                     : "r1", "r2"
+                                     );        
+                       break;
+               case 400:
+                       reg =   CCCR_MEMCLK_99 | CCCR_RUN_2T_MEM | CCCR_TURBO_20;
+                       asm volatile (
+                                     "mov      r1,     %0;"
+                                     "ldr    r2, =0x41300000;"                 // Core Clock Config Reg
+                                     "str    r1, [r2];"                                // set speed
+                                     "mov      r1, #0x3;"                                      // set turbo mode
+                                     "mcr      p14, 0, r1, c6, c0, 0;"         // frequency change  sequence
+                                     :  
+                                     : "r"(reg)  
+                                     : "r1", "r2"
+                                     );        
+                       break;
+               default:
+                       clock_ok = 0;
+                       diag_printf("\ndon't know how to install %d MHz, keeping clock speed at %d MHz\n\n", new_clock, get_clock_rate());
+               }       
+               if (clock_ok) {    
+                       diag_printf("\nclock speed set to %d MHz ...\n", new_clock);
+               }
+
+//#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
+//        opt.type = CONFIG_INT;
+//        opt.enable = (char *)0;
+//        opt.enable_sense = 1;
+//        opt.key = "console_baud_rate";
+//        opt.dflt = new_rate;
+//        flash_add_config(&opt, true);
+//#endif
+       } else {
+               ret = get_clock_rate();
+               diag_printf("Clock = ");
+               if (ret == 0) {
+                       diag_printf("unknown\n");
+               } else {
+                       diag_printf("%d\n", ret);
+               }
+       }
+}
+
+RedBoot_cmd("run",
+            "Execute code at a location",
+            "[-w <timeout>] [entry]",
+            do_run
+           );
+
+void do_run(int argc, char *argv[])
+{
+       typedef void code_fun(void);
+       unsigned long entry;
+       unsigned long oldints;
+       code_fun *fun;
+       bool wait_time_set;
+       int  wait_time, res;
+       struct option_info opts[1];
+       char line[8];
+
+       entry = entry_address;  // Default from last 'load' operation
+       init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM,
+                 (void *)&wait_time, (bool *)&wait_time_set, "wait timeout");
+       if (!scan_opts(argc, argv, 1, opts, 1, (void *)&entry, OPTION_ARG_TYPE_NUM,
+                      "starting address")) {
+               entry = 0xa0100000;
+               diag_printf("starting run at address 0x%08X ...\n", entry);
+       }
+       if (wait_time_set) {
+               int script_timeout_ms = wait_time * 1000;
+#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
+               unsigned char *hold_script = script;
+               script = (unsigned char *)0;
+#endif
+               diag_printf("About to start execution at %p - abort with ^C within %d seconds\n",
+                           (void *)entry, wait_time);
+               while (script_timeout_ms >= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) {
+                       res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT);
+                       if (res == _GETS_CTRLC) {
+#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
+                               script = hold_script;  // Re-enable script
+#endif
+                               return;
+                       }
+                       script_timeout_ms -= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT;
+               }
+       }
+       fun = (code_fun *)entry;
+       HAL_DISABLE_INTERRUPTS(oldints);
+       HAL_DCACHE_SYNC();
+       HAL_ICACHE_DISABLE();
+       HAL_DCACHE_DISABLE();
+       HAL_DCACHE_SYNC();
+       HAL_ICACHE_INVALIDATE_ALL();
+       HAL_DCACHE_INVALIDATE_ALL();
+#ifdef HAL_ARCH_PROGRAM_NEW_STACK
+       HAL_ARCH_PROGRAM_NEW_STACK(fun);
+#else
+       (*fun)();
+#endif
+       HAL_ICACHE_ENABLE();
+       HAL_DCACHE_ENABLE();
+       HAL_RESTORE_INTERRUPTS(oldints);
+}