]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/xscale/triton270/v2_0/src/redboot_cmds.c
RedBoot TX53 Release 2012-02-15
[karo-tx-redboot.git] / packages / hal / arm / xscale / triton270 / v2_0 / src / redboot_cmds.c
1 //==========================================================================
2 //
3 //      redboot_cmds.c
4 //
5 //      KaRo TRITON270 [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 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):    gthomas
44 // Contributors: gthomas
45 //               Richard Panton <richard.panton@3glab.com>
46 // Date:         2001-02-24
47 // Purpose:      
48 // Description:  
49 //              
50 // This code is part of RedBoot (tm).
51 //
52 //####DESCRIPTIONEND####
53 //
54 //==========================================================================
55
56 #include <redboot.h>
57
58 #include <cyg/hal/hal_triton270.h>
59 #include <cyg/hal/hal_intr.h>
60 #include <cyg/hal/hal_cache.h>
61
62 #include <cyg/hal/hal_io.h>             // IO macros
63
64 RedBoot_cmd("mem",
65             "Set a memory location",
66             "[-h|-b] [-a <address>] <data>",
67             do_mem
68             );
69
70 void do_mem(int argc, char *argv[])
71 {
72         struct option_info opts[3];
73         bool mem_half_word, mem_byte;
74         volatile cyg_uint32 *address = NULL;
75         cyg_uint32 value;
76
77         init_opts(&opts[0], 'b', false, OPTION_ARG_TYPE_FLG,
78                   (void *)&mem_byte, 0, "write a byte");
79         init_opts(&opts[1], 'h', false, OPTION_ARG_TYPE_FLG,
80                   (void *)&mem_half_word, 0, "write a half-word");
81         init_opts(&opts[2], 'a', true, OPTION_ARG_TYPE_NUM,
82                   (void *)&address, NULL, "address to write at");
83         if (!scan_opts(argc, argv, 1, opts, 3, (void*)&value, OPTION_ARG_TYPE_NUM, "address to set"))
84                 return;
85         if (mem_byte && mem_half_word) {
86                 diag_printf("*ERR: Should not specify both byte and half-word access\n");
87         } else if (mem_byte) {
88                 *(cyg_uint8*)address = (cyg_uint8)(value & 255);
89                 diag_printf("  Set 0x%08X to 0x%02X (result 0x%02X)\n", address, value & 255, (int)*(cyg_uint8*)address);
90         } else if (mem_half_word) {
91                 if ((unsigned long)address & 1) {
92                         diag_printf("*ERR: Badly aligned address 0x%08X for half-word store\n", address);
93                 } else {
94                         *(cyg_uint16*)address = (cyg_uint16)(value & 0xffff);
95                         diag_printf("  Set 0x%08X to 0x%04X (result 0x%04X)\n", address, value & 0xffff, (int)*(cyg_uint16*)address);
96                 }
97         } else {
98                 if ((unsigned long)address & 3) {
99                         diag_printf("*ERR: Badly aligned address 0x%08X for word store\n", address);
100                 } else {
101                         *address = value;
102                         diag_printf("  Set 0x%08X to 0x%08X (result 0x%08X)\n", address, value,
103                                     *address);
104                 }
105         }
106 }
107
108 RedBoot_cmd("clock",
109             "Set/Query the system clock speed",
110             "[-s <clock> (200/300/400/500/600)]",
111             do_clock
112             );
113
114 clock_param_t pclktab[] = {
115         {91,   45,  91,  45,  91, 0,  7, 2, 0, 0, 0,  950, 0x02, 1, 1},
116         {104, 104, 104, 104,  52, 1,  8, 2, 1, 0, 1,  950, 0x02, 0, 1},
117         {156, 104, 104, 104,  52, 1,  8, 6, 1, 1, 1, 1150, 0x06, 0, 1},
118         {208, 208, 208, 104, 104, 1, 16, 2, 1, 0, 1, 1150, 0x06, 1, 1},
119         {312, 208, 208, 104, 104, 1, 16, 3, 1, 0, 1, 1250, 0x08, 1, 1},
120         {416, 208, 208, 104, 104, 1, 16, 4, 1, 0, 1, 1350, 0x0a, 1, 1},
121         {520, 208, 208, 104, 104, 1, 16, 5, 1, 0, 1, 1450, 0x0c, 1, 1},
122         {624, 208, 208, 104, 104, 1, 16, 6, 1, 0, 1, 1550, 0x0e, 1, 1},
123 };
124 clock_param_t *get_clock_rate(void);
125
126 int get_clock_table_index(int clock)
127 {
128         int i = 0;
129         int deltan;
130         int deltap;
131         int rindex = 1;
132         int maxindex;
133
134         maxindex = sizeof(pclktab) / sizeof(clock_param_t) - 1;
135         if (clock < pclktab[0].t_clock) {
136                 clock = 91;
137                 rindex = 0;
138         } else if (clock > pclktab[maxindex].t_clock) {
139                 clock = 624;
140                 rindex = maxindex;
141         } else {
142                 while (i <= maxindex) {
143                         if (pclktab[i].t_clock < clock) {
144                                 i++;
145                         } else {
146                                 if (i == maxindex){
147                                         rindex = maxindex;
148                                 } else {
149                                         deltan = pclktab[i].t_clock - clock;
150                                         deltap = pclktab[i + 1].t_clock - clock;
151                                         if (deltan < deltap) {
152                                                 rindex = i;
153                                         } else {
154                                                 rindex = i + 1;
155                                         }
156                                 }
157                                 break;
158                         }
159                 }
160         }
161
162         return rindex;
163 }
164
165 void change_core_voltage(unsigned char ind)
166 {
167         unsigned long   value;
168
169         // enable Power I2C
170         HAL_READ_UINT32(PCFR, value);
171         value |= 0x40;
172         HAL_WRITE_UINT32(PCFR, value);
173
174         diag_printf("Core voltage will be set to %d.%d Volts",
175                     pclktab[ind].VOLTAGE_VAL / 1000, pclktab[ind].VOLTAGE_VAL % 1000);
176         write_i2c_pwr(0x18,  pclktab[ind].DAC_VAL | 0x20);
177         diag_printf(".\n");
178
179         // disable Power I2C
180         HAL_READ_UINT32(PCFR, value);
181         value &= (~0x40);
182         HAL_WRITE_UINT32(PCFR, value);
183 }
184
185 clock_param_t *get_clock_rate(void)
186 {
187         unsigned long CCCR_reg, CLKCFG_reg;
188         unsigned char clkcfg_t, clkcfg_ht, clkcfg_b;
189         unsigned char cccr_l, cccr_2n, cccr_a;
190         int i;
191         clock_param_t *match = NULL;
192
193         asm volatile (
194                       "ldr r1, =0x41300000;"                    // Core Clock Config Reg
195                       "ldr %0, [r1];"
196                       "mrc p14, 0, %1, c6, c0, 0;"      // read CCLKCFG register
197                       : "=r"(CCCR_reg), "=r"(CLKCFG_reg)
198                       :
199                       : "r1"
200                       );
201
202         clkcfg_t        =       CLKCFG_reg & 0x01;
203         clkcfg_ht       =       (CLKCFG_reg & 0x04) >> 2;
204         clkcfg_b        =       (CLKCFG_reg & 0x08) >> 3;
205
206         cccr_l          =       (CCCR_reg & 0x0000001f) >> 0;
207         cccr_2n         =       (CCCR_reg & 0x00000780) >> 7;
208         cccr_a          =       (CCCR_reg & 0x02000000) >> 25;
209 #if 0
210         diag_printf("clkcfg_t   = %d \n", clkcfg_t);
211         diag_printf("clkcfg_ht  = %d \n", clkcfg_ht);
212         diag_printf("clkcfg_b   = %d \n", clkcfg_b);
213         diag_printf("cccr_l     = %d \n", cccr_l);
214         diag_printf("cccr_2n    = %d \n", cccr_2n);
215         diag_printf("cccr_a     = %d \n", cccr_a);
216 #endif
217         for (i = 0; i < sizeof(pclktab) / sizeof(clock_param_t); i++) {
218                 if (clkcfg_t  == pclktab[i].CLKCFG_T &&
219                     clkcfg_ht == pclktab[i].CLKCFG_HT &&
220                     clkcfg_b  == pclktab[i].CLKCFG_B &&
221                     cccr_l    == pclktab[i].CCCR_L &&
222                     cccr_2n   == pclktab[i].CCCR_2N &&
223                     cccr_a    == pclktab[i].CCCR_A) {
224                         match = &pclktab[i];
225                         break;
226                 }
227         }
228
229         if (match == NULL) {
230                 //diag_printf("error, unknown clock configuration\n");
231         }
232         return match;
233 }
234
235 void change_clock(unsigned char ind)
236 {
237         clock_param_t   *cpara;
238         unsigned long CCCR_reg, CLKCFG_reg;
239
240         diag_printf("Clock speed will be changed to %d MHz", pclktab[ind].t_clock);
241         CCCR_reg = pclktab[ind].CCCR_L |
242                 ((pclktab[ind].CCCR_2N) << 7) |
243                 ((pclktab[ind].CCCR_A) << 25);
244         CLKCFG_reg = pclktab[ind].CLKCFG_T |
245                 ((pclktab[ind].CLKCFG_HT) << 2) |
246                 ((pclktab[ind].CLKCFG_B) << 3);
247         asm volatile (
248                       "mov      r1,     %0;"
249                       "ldr      r2, =0x41300000;"                       // Core Clock Config Reg
250                       "ldr      r3, [r2];"                                      // read the register
251                       "ldr      r4, =0xcc000000;"                       // mask bits to preserve
252                       "and      r3, r3, r4;"
253                       "orr      r3, r3, r1;"                            // write speed values
254                       "str      r3, [r2];"                              // set speed
255                       "mov      r1, %1;"                                        // set turbo mode, set fast bus
256                       "orr      r1, r1, #0x2;"                          // set change frequency
257                       "mov      r3, r1;"                                        // save value
258                       "mcr      p14, 0, r1, c6, c0, 0;"         // frequency change  sequence
259                       "ldr      r1, [r2];"                                      // dummy read from CCCR
260                       "100:;"
261                       "mrc      p14, 0, r1, c6, c0, 0;"         // read CLKCFG
262                       "cmp r3, r1;"                                             // compare it with value written
263                       "bne 100b;"
264                       :
265                       : "r"(CCCR_reg),  "r"(CLKCFG_reg)
266                       : "r1", "r2", "r3", "r4"
267                       );
268         cpara = get_clock_rate();
269         diag_printf("\nclock speed set to %d MHz ...\n", cpara->t_clock);
270 }
271
272 void do_clock(int argc, char *argv[])
273 {
274         int new_clock, ind;
275         bool new_clock_set, clock_ok;
276         struct option_info opts[1];
277 //#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
278 //    struct config_option opt;
279 //#endif
280         unsigned long value;
281         clock_param_t *cpara, *old_clock;
282
283         init_opts(&opts[0], 's', true, OPTION_ARG_TYPE_NUM,
284                   (void *)&new_clock, (bool *)&new_clock_set, "new clock speed");
285         if (!scan_opts(argc, argv, 1, opts, 1, 0, 0, "")) {
286                 return;
287         }
288
289         get_clock_table_index(new_clock);
290
291         if (new_clock_set) {
292                 clock_ok = 1;
293
294                 old_clock = get_clock_rate();
295                 if (old_clock == 0) {
296                         diag_printf("error decoding clock settings, clock unknown\n");
297                         return;
298                 }
299                 ind = get_clock_table_index(new_clock);
300
301                 HAL_READ_UINT32(MDREFR, value);
302                 value |= 0x20000000;                            // set K0DB4
303                 HAL_WRITE_UINT32(MDREFR, value);
304
305                 if (pclktab[ind].t_clock > old_clock->t_clock) {
306                         change_core_voltage(ind);
307                         change_clock(ind);
308                 } else {
309                         change_clock(ind);
310                         change_core_voltage(ind);
311                 }
312
313                 if (pclktab[ind].MDREFR_K0DB2) {
314                         HAL_READ_UINT32(MDREFR, value);         // set K0DB2
315                         value |= 0x00004000;
316                 } else {
317                         HAL_READ_UINT32(MDREFR, value);         // reset K0DB0
318                         value &= (~0x00004000);
319                 }
320                 HAL_WRITE_UINT32(MDREFR, value);
321
322                 if (pclktab[ind].MDREFR_K0DB4) {
323                         HAL_READ_UINT32(MDREFR, value);         // set K0DB2
324                         value |= 0x20000000;
325                 } else {
326                         HAL_READ_UINT32(MDREFR, value);         // reset K0DB2
327                         value &= (~0x20000000);
328                 }
329                 HAL_WRITE_UINT32(MDREFR, value);
330         } else {
331                 cpara = get_clock_rate();
332                 if (cpara == 0) {
333                         diag_printf("error decoding clock settings, clock unknown\n");
334                 } else {
335                         diag_printf("Actual Processor Clock: %d MHz   System Bus Clock %d MHz    MEM Clock %d MHz   SDRAM Clock %d MHz   LCD Clock %d MHz\n",
336                                     cpara->t_clock, cpara->sys_clock, cpara->mem_clock, cpara->SDRAM_clock, cpara->LCD_clock);
337                 }
338         }
339 }
340
341 RedBoot_cmd("run",
342             "Execute code at a location",
343             "[-w <timeout>] [entry]",
344             do_run
345             );
346
347 void do_run(int argc, char *argv[])
348 {
349         typedef void code_fun(void);
350         unsigned long entry;
351         unsigned long oldints;
352         code_fun *fun;
353         bool wait_time_set;
354         int  wait_time, res;
355         struct option_info opts[1];
356         char line[8];
357
358         entry = entry_address;  // Default from last 'load' operation
359         init_opts(&opts[0], 'w', true, OPTION_ARG_TYPE_NUM,
360                   (void *)&wait_time, (bool *)&wait_time_set, "wait timeout");
361         if (!scan_opts(argc, argv, 1, opts, 1, (void *)&entry, OPTION_ARG_TYPE_NUM,
362                        "starting address")) {
363                 entry = 0xa0100000;
364                 diag_printf("starting run at address 0x%08X ...\n", entry);
365         }
366         if (wait_time_set) {
367                 int script_timeout_ms = wait_time * 1000;
368 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
369                 unsigned char *hold_script = script;
370                 script = (unsigned char *)0;
371 #endif
372                 diag_printf("About to start execution at %p - abort with ^C within %d seconds\n",
373                             (void *)entry, wait_time);
374                 while (script_timeout_ms >= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT) {
375                         res = _rb_gets(line, sizeof(line), CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT);
376                         if (res == _GETS_CTRLC) {
377 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
378                                 script = hold_script;  // Re-enable script
379 #endif
380                                 return;
381                         }
382                         script_timeout_ms -= CYGNUM_REDBOOT_CLI_IDLE_TIMEOUT;
383                 }
384         }
385         fun = (code_fun *)entry;
386         HAL_DISABLE_INTERRUPTS(oldints);
387         HAL_DCACHE_SYNC();
388         HAL_ICACHE_DISABLE();
389         HAL_DCACHE_DISABLE();
390         HAL_DCACHE_SYNC();
391         HAL_ICACHE_INVALIDATE_ALL();
392         HAL_DCACHE_INVALIDATE_ALL();
393 #ifdef HAL_ARCH_PROGRAM_NEW_STACK
394         HAL_ARCH_PROGRAM_NEW_STACK(fun);
395 #else
396         (*fun)();
397 #endif
398         HAL_ICACHE_ENABLE();
399         HAL_DCACHE_ENABLE();
400         HAL_RESTORE_INTERRUPTS(oldints);
401 }
402
403 cyg_int32 write_i2c_pwr(cyg_uint8 device_adr,  cyg_uint8 dat_value)
404 {
405         cyg_uint32      value;
406         unsigned int    retries;
407
408         // write device address now
409
410         HAL_WRITE_UINT32(PWRIDBR, (device_adr & 0xfe));
411         HAL_READ_UINT32(PWRICR, value);
412         value = value & ~(ICR_STOP | ICR_ALDIE);
413         HAL_WRITE_UINT32(PWRICR, value | ICR_START | ICR_TB);
414
415         HAL_READ_UINT32(PWRISR, value);
416         retries = 1000000;
417         while (!(value & ISR_ITE) && retries--) {       // wait for Transmit Empty
418                 HAL_READ_UINT32(PWRISR, value);
419         }
420         if (!(value & ISR_ITE)) {
421                 diag_printf("I2C: timeout waiting for ITE\n");
422                 return -1;
423         }
424
425         HAL_READ_UINT32(PWRISR, value);
426         if (value & ISR_BED) {
427                 //diag_printf("I2C: bus error, status after write device address is: %06X\n", value);
428                 HAL_READ_UINT32(PWRICR, value);
429                 HAL_WRITE_UINT32(PWRICR, value | ICR_MA);               // send master abort
430                 HAL_DELAY_US(10000);
431                 HAL_WRITE_UINT32(PWRICR, value & ~ICR_MA);
432                 return -1;
433         }
434         HAL_WRITE_UINT32(PWRISR, ISR_ITE);      // clear ITE status
435
436         // write data now
437         HAL_WRITE_UINT32(PWRIDBR, dat_value & 0xff);
438         HAL_READ_UINT32(PWRICR, value);
439         value &= ~ICR_START;
440         HAL_WRITE_UINT32(PWRICR, value | (ICR_TB | ICR_STOP));
441
442         HAL_READ_UINT32(PWRISR, value);
443         retries = 1000000;
444         while (!(value & ISR_ITE) && retries--) {       // wait for Transmit Empty
445                 HAL_READ_UINT32(PWRISR, value);
446         }
447         if (!(value & ISR_ITE)) {
448                 diag_printf("I2C: timeout waiting for ITE\n");
449                 return -1;
450         }
451         HAL_READ_UINT32(PWRISR, value);
452         if (value & ISR_BED) {
453                 //diag_printf("I2C: bus error, status after write device address is: %06X\n", value);
454                 HAL_READ_UINT32(PWRICR, value);
455                 HAL_WRITE_UINT32(PWRICR, value | ICR_MA);               // send master abort
456                 HAL_DELAY_US(10000);
457                 HAL_WRITE_UINT32(PWRICR, value & ~ICR_MA);
458                 return -1;
459         }
460         HAL_WRITE_UINT32(PWRISR, ISR_ITE);      // clear ITE status
461
462         HAL_READ_UINT32(PWRICR, value);
463         value = value & ~(ICR_STOP | ICR_START | ICR_TB);
464         HAL_WRITE_UINT32(PWRICR, value);
465
466         return 0;
467 }