TX53 Release 2011-12-20
[karo-tx-redboot.git] / packages / hal / arm / mx53 / karo / v1_0 / src / redboot_cmds.c
1 //==========================================================================
2 //
3 //      redboot_cmds.c
4 //
5 //      Board [platform] specific RedBoot commands
6 //
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 //
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 #include <redboot.h>
42 #include <cyg/hal/hal_intr.h>
43 #include <cyg/hal/hal_cache.h>
44 #include <cyg/hal/plf_mmap.h>
45 #include CYGBLD_HAL_PLF_DEFS_H          // Platform specific hardware definitions
46
47 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
48 #include <flash_config.h>
49
50 #if (REDBOOT_IMAGE_SIZE != CYGBLD_REDBOOT_MIN_IMAGE_SIZE)
51 #error REDBOOT_IMAGE_SIZE != CYGBLD_REDBOOT_MIN_IMAGE_SIZE
52 #endif
53
54 #endif  //CYGSEM_REDBOOT_FLASH_CONFIG
55
56 #ifdef CYGPKG_IO_FLASH
57 #include <cyg/io/flash.h>
58 #endif
59
60 char HAL_PLATFORM_EXTRA[40] = "PASS x.x [x32 DDR]";
61
62 static void runImg(int argc, char *argv[]);
63 static void do_mem(int argc, char *argv[]);
64
65 RedBoot_cmd("mem",
66                         "Set a memory location",
67                         "[-h|-b] [-n] [-a <address>] <data>",
68                         do_mem
69         );
70
71 RedBoot_cmd("run",
72                         "Run an image at a location with MMU off",
73                         "[<virtual addr>]",
74                         runImg
75         );
76
77 static void do_mem(int argc, char *argv[])
78 {
79         struct option_info opts[4];
80         bool mem_half_word, mem_byte;
81         bool no_verify;
82         bool addr_set;
83         unsigned long address;
84         unsigned int value;
85         int ret;
86         init_opts(&opts[0], 'b', false, OPTION_ARG_TYPE_FLG,
87                         &mem_byte, NULL, "write a byte");
88         init_opts(&opts[1], 'h', false, OPTION_ARG_TYPE_FLG,
89                         &mem_half_word, NULL, "write a half-word");
90         init_opts(&opts[2], 'a', true, OPTION_ARG_TYPE_NUM,
91                         &address, &addr_set, "address to write to");
92         init_opts(&opts[3], 'n', false, OPTION_ARG_TYPE_FLG,
93                         &no_verify, NULL, "noverify");
94
95         ret = scan_opts(argc, argv, 1, opts, sizeof(opts) / sizeof(opts[0]),
96                                         &value, OPTION_ARG_TYPE_NUM, "value to be written");
97         if (ret == 0) {
98                 return;
99         }
100         if (!addr_set) {
101                 diag_printf("** Error: '-a <address>' must be specified\n");
102                 return;
103         }
104         if (ret == argc + 1) {
105                 diag_printf("** Error: non-option argument '<value>' must be specified\n");
106                 return;
107         }
108         if (mem_byte && mem_half_word) {
109                 diag_printf("** Error: Should not specify both byte and half-word access\n");
110         } else if (mem_byte) {
111                 value &= 0xff;
112                 *(volatile cyg_uint8*)address = (cyg_uint8)value;
113                 if (no_verify) {
114                         diag_printf("  Set 0x%08lX to 0x%02X\n", address, value);
115                 } else {
116                         diag_printf("  Set 0x%08lX to 0x%02X (result 0x%02X)\n",
117                                                 address, value, (int)*(cyg_uint8*)address );
118                 }
119         } else if (mem_half_word) {
120                 if (address & 1) {
121                         diag_printf("** Error: address for half-word access must be half-word aligned\n");
122                 } else {
123                         value &= 0xffff;
124                         *(volatile cyg_uint16*)address = (cyg_uint16)value;
125                         if (no_verify) {
126                                 diag_printf("  Set 0x%08lX to 0x%04X\n", address, value);
127                         } else {
128                                 diag_printf("  Set 0x%08lX to 0x%04X (result 0x%04X)\n",
129                                                         address, value, (int)*(cyg_uint16*)address);
130                         }
131                 }
132         } else {
133                 if (address & 3) {
134                         diag_printf("** Error: address for word access must be word aligned\n");
135                 } else {
136                         *(volatile cyg_uint32*)address = (cyg_uint32)value;
137                         if (no_verify) {
138                                 diag_printf("  Set 0x%08lX to 0x%08X\n", address, value);
139                         } else {
140                                 diag_printf("  Set 0x%08lX to 0x%08X (result 0x%08X)\n",
141                                                         address, value, (int)*(cyg_uint32*)address);
142                         }
143                 }
144         }
145 }
146
147 void launchRunImg(unsigned long addr)
148 {
149         asm volatile ("mov r1, r0;");
150         HAL_MMU_OFF();
151         asm volatile (
152                 "mov r11, #0;"
153                 "mov r12, #0;"
154                 "mrs r10, cpsr;"
155                 "bic r10, r10, #0xF0000000;"
156                 "msr cpsr_f, r10;"
157                 "mov pc, r1"
158                 );
159 }
160
161 static void runImg(int argc,char *argv[])
162 {
163         unsigned int virt_addr, phys_addr;
164
165         // Default physical entry point for Symbian
166         if (entry_address == 0xFFFFFFFF)
167                 virt_addr = 0x800000;
168         else
169                 virt_addr = entry_address;
170
171         if (!scan_opts(argc, argv, 1, 0, 0, &virt_addr,
172                                         OPTION_ARG_TYPE_NUM, "virtual address"))
173                 return;
174
175         if (entry_address != 0xFFFFFFFF)
176                 diag_printf("load entry_address=0x%lx\n", entry_address);
177         HAL_VIRT_TO_PHYS_ADDRESS(virt_addr, phys_addr);
178
179         diag_printf("virt_addr=0x%x\n",virt_addr);
180         diag_printf("phys_addr=0x%x\n",phys_addr);
181
182         launchRunImg(phys_addr);
183 }
184
185 #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYG_HAL_STARTUP_ROMRAM)
186
187 RedBoot_cmd("romupdate",
188                         "Update Redboot with currently running image",
189                         "",
190                         romupdate
191         );
192
193 #ifdef CYGPKG_IO_FLASH
194 void romupdate(int argc, char *argv[])
195 {
196         void *err_addr, *base_addr;
197         int stat;
198
199         base_addr = (void*)(MXC_NAND_BASE_DUMMY + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET);
200         diag_printf("Updating RedBoot in NAND flash\n");
201
202         // Erase area to be programmed
203         if ((stat = flash_erase(base_addr, CYGBLD_REDBOOT_MIN_IMAGE_SIZE, &err_addr)) != 0) {
204                 diag_printf("Can't erase region at %p: %s\n",
205                                         err_addr, flash_errmsg(stat));
206                 return;
207         }
208         // Now program it
209         if ((stat = flash_program(base_addr, ram_end,
210                                                                         CYGBLD_REDBOOT_MIN_IMAGE_SIZE, &err_addr)) != 0) {
211                 diag_printf("Can't program region at %p: %s\n",
212                                         err_addr, flash_errmsg(stat));
213         }
214 }
215 #endif //CYGPKG_IO_FLASH
216 #endif /* CYG_HAL_STARTUP_ROMRAM */