flash -> FLASH
[oweals/u-boot_mod.git] / u-boot / common / cmd_custom.c
1 /*
2  * (C) Copyright 2013
3  * Piotr Dymacz (pepe2k), Real Time Systems, piotr@realtimesystems.pl, pepe2k@gmail.com
4  * Custom commands for U-Boot 1.1.4 modification.
5  *
6  * See file CREDITS for list of people who contributed to U-Boot project.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <common.h>
23 #include <command.h>
24 #include <asm/mipsregs.h>
25 #include <asm/addrspace.h>
26 #include <ar7240_soc.h>
27 #include "../board/ar7240/common/ar7240_flash.h"
28
29 extern void ar7240_sys_frequency(u32 *cpu_freq, u32 *ddr_freq, u32 *ahb_freq);
30
31 #if defined(OFFSET_MAC_ADDRESS)
32 /*
33  * Show MAC address(es)
34  */
35 int do_print_mac(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){
36         char buffer[6];
37 #if defined(OFFSET_MAC_ADDRESS2)
38         char buffer2[6];
39 #endif
40
41 #if defined(OFFSET_MAC_ADDRESS2)
42         // get MAC1 and MAC2 addresses from flash and print them
43         memcpy(buffer,  (void *)(CFG_FLASH_BASE + OFFSET_MAC_DATA_BLOCK + OFFSET_MAC_ADDRESS),  6);
44         memcpy(buffer2, (void *)(CFG_FLASH_BASE + OFFSET_MAC_DATA_BLOCK + OFFSET_MAC_ADDRESS2), 6);
45
46         puts("Current MAC addresses stored in FLASH:\n");
47         printf("MAC1 at 0x%X: %02X:%02X:%02X:%02X:%02X:%02X\n", CFG_FLASH_BASE + OFFSET_MAC_DATA_BLOCK + OFFSET_MAC_ADDRESS,
48                                                                                                                         buffer[0] & 0xFF, buffer[1] & 0xFF, buffer[2] & 0xFF, buffer[3] & 0xFF, buffer[4] & 0xFF, buffer[5] & 0xFF);
49
50         printf("MAC2 at 0x%X: %02X:%02X:%02X:%02X:%02X:%02X\n\n", CFG_FLASH_BASE + OFFSET_MAC_DATA_BLOCK + OFFSET_MAC_ADDRESS2,
51                                                                                                                           buffer2[0] & 0xFF, buffer2[1] & 0xFF, buffer2[2] & 0xFF, buffer2[3] & 0xFF, buffer2[4] & 0xFF, buffer2[5] & 0xFF);
52 #else
53         // get MAC address from flash and print it
54         memcpy(buffer, (void *)(CFG_FLASH_BASE + OFFSET_MAC_DATA_BLOCK + OFFSET_MAC_ADDRESS), 6);
55
56         printf("Current MAC address stored in FLASH at offset 0x%X: ", CFG_FLASH_BASE + OFFSET_MAC_DATA_BLOCK + OFFSET_MAC_ADDRESS);
57         printf("%02X:%02X:%02X:%02X:%02X:%02X\n\n", buffer[0] & 0xFF, buffer[1] & 0xFF, buffer[2] & 0xFF, buffer[3] & 0xFF, buffer[4] & 0xFF, buffer[5] & 0xFF);
58 #endif
59
60         return(0);
61 }
62
63 #if defined(OFFSET_MAC_ADDRESS2)
64 U_BOOT_CMD(printmac, 1, 1, do_print_mac, "print MAC addresses stored in FLASH\n", NULL);
65 #else
66 U_BOOT_CMD(printmac, 1, 1, do_print_mac, "print MAC address stored in FLASH\n", NULL);
67 #endif
68
69 /*
70  * Change MAC address(es)
71  */
72 int do_set_mac(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){
73         unsigned char *data_pointer;
74         char buf[128];
75         int i = 0, j = 0;
76
77         // allow only 2 arg (command name + mac), second argument length should be 17 (xx:xx:xx:xx:xx:xx)
78         if(argc != 2 || strlen(argv[1]) != 17){
79 #if defined(CFG_LONGHELP)
80                 if(cmdtp->help != NULL){
81                         printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->help);
82                 } else {
83                         printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->usage);
84                 }
85 #else
86                 printf("Usage:\n%s %s\n", cmdtp->name, cmdtp->usage);
87 #endif
88                 return(1);
89         }
90
91         // count ':'
92         for(i = 0; i< 17; i++){
93                 if(argv[1][i] == ':'){
94                         j++;
95                 }
96         }
97
98         if(j != 5){
99                 puts("## Error: given MAC address has wrong format (should be: xx:xx:xx:xx:xx:xx)!\n");
100                 return(1);
101         }
102
103         // backup block with MAC address from flash in RAM
104         data_pointer = (unsigned char *)WEBFAILSAFE_UPLOAD_RAM_ADDRESS;
105
106         if(!data_pointer){
107                 puts("## Error: couldn't allocate RAM for data block backup!\n");
108                 return(1);
109         }
110
111         puts("** Notice:\n   you should always make a backup of your device\n           entire FLASH content before making any changes\n\n");
112
113         memcpy((void *)data_pointer, (void *)(CFG_FLASH_BASE + OFFSET_MAC_DATA_BLOCK), OFFSET_MAC_DATA_BLOCK_LENGTH);
114
115         // store new MAC address in RAM
116         for(i = 0; i < 6; i++){
117                 data_pointer[OFFSET_MAC_ADDRESS + i] = simple_strtoul((char *)(argv[1] + i*3), NULL, 16);
118         }
119
120         // now we can erase flash and write data from RAM
121         sprintf(buf,
122                         "erase 0x%lX +0x%lX; cp.b 0x%lX 0x%lX 0x%lX",
123                         CFG_FLASH_BASE + OFFSET_MAC_DATA_BLOCK,
124                         OFFSET_MAC_DATA_BLOCK_LENGTH,
125                         WEBFAILSAFE_UPLOAD_RAM_ADDRESS,
126                         CFG_FLASH_BASE + OFFSET_MAC_DATA_BLOCK,
127                         OFFSET_MAC_DATA_BLOCK_LENGTH);
128
129         printf("Executing: %s\n\n", buf);
130
131         return(run_command(buf, 0));
132 }
133
134 U_BOOT_CMD(setmac, 2, 0, do_set_mac, "save new MAC address in FLASH\n", "xx:xx:xx:xx:xx:xx\n\t- change MAC address stored in FLASH (xx - value in hex format)\n");
135
136 #endif /* if defined(OFFSET_MAC_ADDRESS) */
137
138 #if defined(OFFSET_ROUTER_MODEL)
139 /*
140  * Show TP-Link router model
141  */
142 int do_print_model(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){
143         unsigned char buffer[8];
144
145         // get router model from flash and print it
146         memcpy(buffer, (void *)(CFG_FLASH_BASE + OFFSET_MAC_DATA_BLOCK + OFFSET_ROUTER_MODEL), 8);
147
148         printf("Router model stored in FLASH at offset 0x%X: ", CFG_FLASH_BASE + OFFSET_MAC_DATA_BLOCK + OFFSET_ROUTER_MODEL);
149         printf("%02X%02X%02X%02X%02X%02X%02X%02X\n\n", buffer[0] & 0xFF, buffer[1] & 0xFF, buffer[2] & 0xFF, buffer[3] & 0xFF, buffer[4] & 0xFF, buffer[5] & 0xFF, buffer[6] & 0xFF, buffer[7] & 0xFF);
150
151         return(0);
152 }
153
154 U_BOOT_CMD(printmodel, 1, 1, do_print_model, "print router model stored in FLASH\n", NULL);
155
156 #endif /* if defined(OFFSET_ROUTER_MODEL) */
157
158 #if defined(OFFSET_PIN_NUMBER)
159 /*
160  * Show pin number
161  */
162 int do_print_pin(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){
163         unsigned char buffer[9];
164
165         // get pin number from flash and print it
166         memcpy(buffer, (void *)(CFG_FLASH_BASE + OFFSET_MAC_DATA_BLOCK + OFFSET_PIN_NUMBER), 8);
167         buffer[8] = 0;
168
169         printf("Router pin number stored in FLASH at offset 0x%X: ", CFG_FLASH_BASE + OFFSET_MAC_DATA_BLOCK + OFFSET_PIN_NUMBER);
170         printf("%s\n\n", buffer);
171
172         return(0);
173 }
174
175 U_BOOT_CMD(printpin, 1, 1, do_print_pin, "print WPS pin stored in FLASH\n", NULL);
176
177 #endif /* if defined(OFFSET_PIN_NUMBER) */
178
179 #if defined(CONFIG_NETCONSOLE)
180 /*
181  * Start NetConsole
182  */
183 int do_start_nc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){
184         return(run_command("setenv stdin nc;setenv stdout nc;setenv stderr nc;version;", 0));
185 }
186
187 U_BOOT_CMD(startnc, 1, 0, do_start_nc, "start net console\n", NULL);
188
189 /*
190  * Start Serial Console
191  */
192 int do_start_sc(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){
193         return(run_command("setenv stdin serial;setenv stdout serial;setenv stderr serial;version;", 0));
194 }
195
196 U_BOOT_CMD(startsc, 1, 0, do_start_sc, "start serial console\n", NULL);
197
198 #endif /* if defined(CONFIG_NETCONSOLE) */
199
200 #if defined(CONFIG_FOR_8DEVICES_CARAMBOLA2) || \
201     defined(CONFIG_FOR_DRAGINO_V2)
202 /*
203  * Erase environment sector
204  */
205 int do_default_env(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){
206         int     rc, rcode = 0;
207 #if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE)
208         unsigned char env_buffer[CFG_ENV_SECT_SIZE];
209 #endif
210
211 #if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE)
212         /* copy whole env sector to temporary buffer */
213         memcpy(env_buffer, (void *)CFG_ENV_ADDR, CFG_ENV_SECT_SIZE);
214
215         /* clear env part */
216         memset(env_buffer, 0xFF, CFG_ENV_SIZE);
217 #endif
218
219         /* erase whole env sector */
220         if(flash_sect_erase(CFG_ENV_ADDR, CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1)){
221                 rcode = 1;
222         }
223
224 #if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE)
225         /* restore data from buffer in FLASH */
226         rc = flash_write((char *)env_buffer, CFG_ENV_ADDR, CFG_ENV_SECT_SIZE);
227
228         if(rc != 0){
229                 flash_perror(rc);
230                 rcode = 1;
231         }
232 #endif
233
234         return(rcode);
235 }
236
237 U_BOOT_CMD(defenv, 1, 1, do_default_env, "reset environment variables to their default values\n", NULL);
238 #endif /* if defined(CONFIG_FOR_8DEVICES_CARAMBOLA2) || defined(CONFIG_FOR_DRAGINO_V2) */
239
240 #if defined(PLL_IN_FLASH_MAGIC_OFFSET)
241
242 typedef struct {
243         // Clocks in MHz
244         unsigned short cpu_clock;
245         unsigned short ram_clock;
246         unsigned short ahb_clock;
247         unsigned short spi_clock;
248
249         // Registers values
250         // (more info in includes/configs/ap121.h)
251         unsigned int cpu_clk_control;
252         unsigned int cpu_pll_config;
253         unsigned int spi_control;
254 } ar9331_clock_profile;
255
256 static const ar9331_clock_profile oc_profiles[] = {
257         {
258          200, 200, 100, 25,
259          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
260 #if defined(CONFIG_40MHZ_XTAL_SUPPORT)
261          MAKE_AR9331_CPU_PLL_CONFIG_VAL(20, 1, 0, 2),
262 #else
263          MAKE_AR9331_CPU_PLL_CONFIG_VAL(32, 1, 0, 2),
264 #endif
265          MAKE_AR9331_SPI_CONTROL_VAL(4)
266         },
267
268         {
269          200, 200, 200, 33,
270          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 1),
271 #if defined(CONFIG_40MHZ_XTAL_SUPPORT)
272          MAKE_AR9331_CPU_PLL_CONFIG_VAL(20, 1, 0, 2),
273 #else
274          MAKE_AR9331_CPU_PLL_CONFIG_VAL(32, 1, 0, 2),
275 #endif
276          MAKE_AR9331_SPI_CONTROL_VAL(6)
277         },
278
279 #if !defined(CONFIG_40MHZ_XTAL_SUPPORT)
280         {
281          225, 225, 112, 28,
282          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
283          MAKE_AR9331_CPU_PLL_CONFIG_VAL(36, 1, 0, 2),
284          MAKE_AR9331_SPI_CONTROL_VAL(4)
285         },
286
287         {
288          225, 225, 225, 28,
289          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 1),
290          MAKE_AR9331_CPU_PLL_CONFIG_VAL(36, 1, 0, 2),
291          MAKE_AR9331_SPI_CONTROL_VAL(8)
292         },
293 #endif
294
295         {
296          250, 250, 125, 31,
297          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
298 #if defined(CONFIG_40MHZ_XTAL_SUPPORT)
299          MAKE_AR9331_CPU_PLL_CONFIG_VAL(25, 1, 0, 2),
300 #else
301          MAKE_AR9331_CPU_PLL_CONFIG_VAL(20, 1, 0, 1),
302 #endif
303          MAKE_AR9331_SPI_CONTROL_VAL(4)
304         },
305
306         {
307          250, 250, 250, 31,
308          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 1),
309 #if defined(CONFIG_40MHZ_XTAL_SUPPORT)
310          MAKE_AR9331_CPU_PLL_CONFIG_VAL(25, 1, 0, 2),
311 #else
312          MAKE_AR9331_CPU_PLL_CONFIG_VAL(20, 1, 0, 1),
313 #endif
314          MAKE_AR9331_SPI_CONTROL_VAL(8)
315         },
316
317         {
318          300, 300, 150, 25,
319          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
320 #if defined(CONFIG_40MHZ_XTAL_SUPPORT)
321          MAKE_AR9331_CPU_PLL_CONFIG_VAL(15, 1, 0, 1),
322 #else
323          MAKE_AR9331_CPU_PLL_CONFIG_VAL(24, 1, 0, 1),
324 #endif
325          MAKE_AR9331_SPI_CONTROL_VAL(6)
326         },
327
328 #if !defined(CONFIG_40MHZ_XTAL_SUPPORT)
329         {
330          325, 325, 162, 27,
331          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
332          MAKE_AR9331_CPU_PLL_CONFIG_VAL(26, 1, 0, 1),
333          MAKE_AR9331_SPI_CONTROL_VAL(6)
334         },
335
336         {
337          350, 350, 175, 29,
338          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
339          MAKE_AR9331_CPU_PLL_CONFIG_VAL(28, 1, 0, 1),
340          MAKE_AR9331_SPI_CONTROL_VAL(6)
341         },
342 #endif
343
344         {
345          360, 360, 180, 30,
346          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
347 #if defined(CONFIG_40MHZ_XTAL_SUPPORT)
348          MAKE_AR9331_CPU_PLL_CONFIG_VAL(18, 1, 0, 1),
349 #else
350          MAKE_AR9331_CPU_PLL_CONFIG_VAL(29, 1, 0, 1),
351 #endif
352          MAKE_AR9331_SPI_CONTROL_VAL(6)
353         },
354
355 #if defined(CONFIG_40MHZ_XTAL_SUPPORT)
356         {
357          380, 380, 190, 32,
358          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
359          MAKE_AR9331_CPU_PLL_CONFIG_VAL(19, 1, 0, 1),
360          MAKE_AR9331_SPI_CONTROL_VAL(6)
361         },
362 #endif
363
364         {
365          400, 400, 200, 33,
366          CPU_CLK_CONTROL_VAL_DEFAULT,
367          CPU_PLL_CONFIG_VAL_DEFAULT,
368          AR7240_SPI_CONTROL_DEFAULT
369         },
370
371 #if !defined(CONFIG_40MHZ_XTAL_SUPPORT)
372         {
373          412, 412, 206, 34,
374          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
375          MAKE_AR9331_CPU_PLL_CONFIG_VAL(33, 1, 0, 1),
376          MAKE_AR9331_SPI_CONTROL_VAL(6)
377         },
378 #endif
379
380 #if defined(CONFIG_40MHZ_XTAL_SUPPORT)
381         {
382          420, 420, 210, 35,
383          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
384          MAKE_AR9331_CPU_PLL_CONFIG_VAL(21, 1, 0, 1),
385          MAKE_AR9331_SPI_CONTROL_VAL(6)
386         },
387 #endif
388
389 #if !defined(CONFIG_40MHZ_XTAL_SUPPORT)
390         {
391          425, 425, 212, 35,
392          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
393          MAKE_AR9331_CPU_PLL_CONFIG_VAL(34, 1, 0, 1),
394          MAKE_AR9331_SPI_CONTROL_VAL(6)
395         },
396
397         {
398          437, 437, 218, 27,
399          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
400          MAKE_AR9331_CPU_PLL_CONFIG_VAL(35, 1, 0, 1),
401          MAKE_AR9331_SPI_CONTROL_VAL(8)
402         },
403 #endif
404
405 #if defined(CONFIG_40MHZ_XTAL_SUPPORT)
406         {
407          440, 440, 220, 27,
408          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
409          MAKE_AR9331_CPU_PLL_CONFIG_VAL(22, 1, 0, 1),
410          MAKE_AR9331_SPI_CONTROL_VAL(8)
411         },
412 #endif
413
414 #if !defined(CONFIG_40MHZ_XTAL_SUPPORT)
415         {
416          450, 450, 225, 28,
417          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
418          MAKE_AR9331_CPU_PLL_CONFIG_VAL(36, 1, 0, 1),
419          MAKE_AR9331_SPI_CONTROL_VAL(8)
420         },
421 #endif
422
423         {
424          460, 460, 230, 29,
425          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
426 #if defined(CONFIG_40MHZ_XTAL_SUPPORT)
427          MAKE_AR9331_CPU_PLL_CONFIG_VAL(23, 1, 0, 1),
428 #else
429          MAKE_AR9331_CPU_PLL_CONFIG_VAL(37, 1, 0, 1),
430 #endif
431          MAKE_AR9331_SPI_CONTROL_VAL(8)
432         },
433
434 #if !defined(CONFIG_40MHZ_XTAL_SUPPORT)
435         {
436          475, 475, 237, 30,
437          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
438          MAKE_AR9331_CPU_PLL_CONFIG_VAL(38, 1, 0, 1),
439          MAKE_AR9331_SPI_CONTROL_VAL(8)
440         },
441 #endif
442
443 #if defined(CONFIG_40MHZ_XTAL_SUPPORT)
444         {
445          480, 480, 240, 30,
446          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
447          MAKE_AR9331_CPU_PLL_CONFIG_VAL(24, 1, 0, 1),
448          MAKE_AR9331_SPI_CONTROL_VAL(8)
449         },
450 #endif
451
452 #if !defined(CONFIG_40MHZ_XTAL_SUPPORT)
453         {
454          487, 487, 243, 30,
455          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
456          MAKE_AR9331_CPU_PLL_CONFIG_VAL(39, 1, 0, 1),
457          MAKE_AR9331_SPI_CONTROL_VAL(8)
458         },
459 #endif
460
461         {
462          500, 500, 250, 31,
463          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
464 #if defined(CONFIG_40MHZ_XTAL_SUPPORT)
465          MAKE_AR9331_CPU_PLL_CONFIG_VAL(25, 1, 0, 1),
466 #else
467          MAKE_AR9331_CPU_PLL_CONFIG_VAL(40, 1, 0, 1),
468 #endif
469          MAKE_AR9331_SPI_CONTROL_VAL(8)
470         },
471
472         {
473          500, 250, 250, 31,
474          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 2, 2),
475 #if defined(CONFIG_40MHZ_XTAL_SUPPORT)
476          MAKE_AR9331_CPU_PLL_CONFIG_VAL(25, 1, 0, 1),
477 #else
478          MAKE_AR9331_CPU_PLL_CONFIG_VAL(40, 1, 0, 1),
479 #endif
480          MAKE_AR9331_SPI_CONTROL_VAL(8)
481         },
482
483 #if defined(CONFIG_40MHZ_XTAL_SUPPORT)
484         {
485          520, 520, 260, 32,
486          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
487          MAKE_AR9331_CPU_PLL_CONFIG_VAL(26, 1, 0, 1),
488          MAKE_AR9331_SPI_CONTROL_VAL(8)
489         },
490 #endif
491
492 #if !defined(CONFIG_40MHZ_XTAL_SUPPORT)
493         {
494          525, 262, 131, 33,
495          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 2, 4),
496          MAKE_AR9331_CPU_PLL_CONFIG_VAL(42, 1, 0, 1),
497          MAKE_AR9331_SPI_CONTROL_VAL(4)
498         },
499 #endif
500
501         {
502          560, 280, 140, 35,
503          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 2, 4),
504 #if defined(CONFIG_40MHZ_XTAL_SUPPORT)
505          MAKE_AR9331_CPU_PLL_CONFIG_VAL(28, 1, 0, 1),
506 #else
507          MAKE_AR9331_CPU_PLL_CONFIG_VAL(45, 1, 0, 1),
508 #endif
509          MAKE_AR9331_SPI_CONTROL_VAL(4)
510         },
511
512 #if defined(CONFIG_40MHZ_XTAL_SUPPORT)
513         {
514          580, 290, 145, 36,
515          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 2, 4),
516          MAKE_AR9331_CPU_PLL_CONFIG_VAL(29, 1, 0, 1),
517          MAKE_AR9331_SPI_CONTROL_VAL(4)
518         },
519 #endif
520
521         {
522          600, 300, 200, 33,
523          MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 2, 3),
524 #if CONFIG_40MHZ_XTAL_SUPPORT
525          MAKE_AR9331_CPU_PLL_CONFIG_VAL(30, 1, 0, 1),
526 #else
527          MAKE_AR9331_CPU_PLL_CONFIG_VAL(48, 1, 0, 1),
528 #endif
529          MAKE_AR9331_SPI_CONTROL_VAL(6)
530         },
531 };
532
533 /*
534  * Set and store PLL configuration in FLASH
535  */
536 int do_set_clocks(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){
537         unsigned int cpu_pll_config_flash, cpu_clock_control_flash, spi_control_flash, reg;
538         unsigned int ahb_freq, ddr_freq, cpu_freq, spi_freq;
539         unsigned int *data_pointer;
540         int i, index, profiles_count;
541         char buf[128];
542
543         profiles_count = sizeof(oc_profiles) / sizeof(ar9331_clock_profile);
544
545         // print all available profiles and current settings
546         if(argc == 1){
547
548                 // read clocks
549                 ar7240_sys_frequency(&cpu_freq, &ddr_freq, &ahb_freq);
550
551                 // calculate SPI clock (we need to set bit 0 to 1 in SPI_FUNC_SELECT to access SPI registers)
552                 ar7240_reg_wr(AR7240_SPI_FS, 0x01);
553                 spi_freq = ahb_freq / (((ar7240_reg_rd(AR7240_SPI_CLOCK) & 0x3F) + 1) * 2);
554                 ar7240_reg_wr(AR7240_SPI_FS, 0x0);
555
556                 // make MHz from Hz
557                 cpu_freq /= 1000000;
558                 ddr_freq /= 1000000;
559                 ahb_freq /= 1000000;
560                 spi_freq /= 1000000;
561
562                 printf("Current clocks (approximated):\n- CPU: %3d MHz\n", cpu_freq);
563                 printf("- RAM: %3d MHz\n", ddr_freq);
564                 printf("- AHB: %3d MHz\n", ahb_freq);
565                 printf("- SPI: %3d MHz\n", spi_freq);
566
567                 // reference clock
568                 if(ar7240_reg_rd(HORNET_BOOTSTRAP_STATUS) & HORNET_BOOTSTRAP_SEL_25M_40M_MASK){
569                         puts("- REF:  40 MHz\n\n");
570                 } else {
571                         puts("- REF:  25 MHz\n\n");
572                 }
573
574                 // do we have PLL_MAGIC in FLASH?
575                 reg = ar7240_reg_rd(CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET + PLL_IN_FLASH_MAGIC_OFFSET);
576
577                 // read all register values stored in FLASH
578                 cpu_pll_config_flash = ar7240_reg_rd(CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET + PLL_IN_FLASH_MAGIC_OFFSET + 4);
579                 cpu_clock_control_flash = ar7240_reg_rd(CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET + PLL_IN_FLASH_MAGIC_OFFSET + 8);
580                 spi_control_flash = ar7240_reg_rd(CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET + PLL_IN_FLASH_MAGIC_OFFSET + 12);
581
582                 printf("Available PLL and clocks configurations: %d\n\n", profiles_count);
583
584                 puts("      | CPU | RAM | AHB | SPI | [ ]\n  ---------------------------------\n");
585
586                 for(i = 0; i <  profiles_count; i++){
587                         printf("%4d. |%4d |%4d |%4d |%4d | ", i + 1,
588                                                                                                   oc_profiles[i].cpu_clock,
589                                                                                                   oc_profiles[i].ram_clock,
590                                                                                                   oc_profiles[i].ahb_clock,
591                                                                                                   oc_profiles[i].spi_clock);
592
593                         if(reg == PLL_IN_FLASH_MAGIC &&
594                            oc_profiles[i].cpu_pll_config == cpu_pll_config_flash &&
595                            oc_profiles[i].cpu_clk_control == cpu_clock_control_flash &&
596                            oc_profiles[i].spi_control == spi_control_flash){
597                                 puts("[*]\n");
598                         } else {
599                                 puts("[ ]\n");
600                         }
601                 }
602
603                 puts("\n[*] = currently selected profile (stored in FLASH).\nAll clocks in MHz, run 'setclk X' to choose one.\n\n");
604                 puts("** Notice:\n   you should always make a backup of your device\n   entire FLASH content before making any changes\n\n");
605
606                 return(0);
607         } else {
608                 // selected index
609                 index = simple_strtoul(argv[1], NULL, 10);
610
611                 if(index > profiles_count || index < 1){
612                         printf("## Error: selected index should be in range 1..%d!\n", profiles_count);
613                         return(1);
614                 }
615
616                 printf("You have selected profile: %d.\n\n", index);
617
618                 // array is zero-based indexing
619                 index--;
620
621                 // backup entire block in which we store PLL/CLK settings
622                 data_pointer = (unsigned int *)WEBFAILSAFE_UPLOAD_RAM_ADDRESS;
623
624                 if(!data_pointer){
625                         puts("## Error: couldn't allocate RAM for data block backup!\n");
626                         return(1);
627                 }
628
629                 memcpy((void *)data_pointer, (void *)(CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET), PLL_IN_FLASH_DATA_BLOCK_LENGTH);
630
631                 // save PLL_IN_FLASH_MAGIC and PLL/clocks registers values
632                 data_pointer = (unsigned int *)(WEBFAILSAFE_UPLOAD_RAM_ADDRESS + PLL_IN_FLASH_MAGIC_OFFSET);
633                 *data_pointer = PLL_IN_FLASH_MAGIC;
634
635                 data_pointer++;
636                 *data_pointer = oc_profiles[index].cpu_pll_config;
637
638                 data_pointer++;
639                 *data_pointer = oc_profiles[index].cpu_clk_control;
640
641                 data_pointer++;
642                 *data_pointer = oc_profiles[index].spi_control;
643
644                 // erase FLASH, copy data from RAM
645                 sprintf(buf,
646                                 "erase 0x%lX +0x%lX; cp.b 0x%lX 0x%lX 0x%lX",
647                                 CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET,
648                                 PLL_IN_FLASH_DATA_BLOCK_LENGTH,
649                                 WEBFAILSAFE_UPLOAD_RAM_ADDRESS,
650                                 CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET,
651                                 PLL_IN_FLASH_DATA_BLOCK_LENGTH);
652
653                 printf("Executing: %s\n\n", buf);
654
655                 return(run_command(buf, 0));
656         }
657 }
658
659 U_BOOT_CMD(setclk, 2, 0, do_set_clocks, "select clocks configuration from predefined list\n",
660                 "index\n"
661                 "\t- save 'index' configuration in FLASH\n"
662                 "setclk\n"
663                 "\t- prints available clocks configurations and current settings");
664
665 /*
666  * Remove (clear) PLL and clock settings in FLASH
667  */
668 int do_clear_clocks(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){
669         unsigned char *data_pointer;
670         int i;
671         char buf[128];
672         unsigned int reg = 0;
673
674         // do we have PLL_MAGIC in FLASH?
675         reg = ar7240_reg_rd(CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET + PLL_IN_FLASH_MAGIC_OFFSET);
676
677         if(reg == PLL_IN_FLASH_MAGIC){
678                 // backup entire block in which we store PLL/CLK settings
679                 data_pointer = (unsigned char *)WEBFAILSAFE_UPLOAD_RAM_ADDRESS;
680
681                 if(!data_pointer){
682                         puts("## Error: couldn't allocate RAM for data block backup!\n");
683                         return(1);
684                 }
685
686                 memcpy((void *)data_pointer, (void *)(CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET), PLL_IN_FLASH_DATA_BLOCK_LENGTH);
687
688                 // 16 bytes (4x 32-bit values)
689                 for(i = 0; i < 16; i++){
690                         data_pointer[PLL_IN_FLASH_MAGIC_OFFSET + i] = 0xFF;
691                 }
692
693                 // erase FLASH, copy data from RAM
694                 sprintf(buf,
695                                 "erase 0x%lX +0x%lX; cp.b 0x%lX 0x%lX 0x%lX",
696                                 CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET,
697                                 PLL_IN_FLASH_DATA_BLOCK_LENGTH,
698                                 WEBFAILSAFE_UPLOAD_RAM_ADDRESS,
699                                 CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET,
700                                 PLL_IN_FLASH_DATA_BLOCK_LENGTH);
701
702                 printf("Executing: %s\n\n", buf);
703
704                 return(run_command(buf, 0));
705         } else {
706                 puts("** Warning: there is no PLL and clocks configuration in FLASH!\n");
707                 return(1);
708         }
709 }
710
711 U_BOOT_CMD(clearclk, 1, 0, do_clear_clocks, "remove PLL and clocks configuration from FLASH\n", NULL);
712 #endif /* #if defined(PLL_IN_FLASH_MAGIC_OFFSET) */