--- /dev/null
+//==========================================================================
+//
+// 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);
+}