BCM WL 6.30.102.9 (r366174)
[tomato.git] / release / src-rt / cfe / patch / ui_bcm947xx.c
blobf6c4635ddb5a25eea0be255d7aee14586b8368e7
1 /*
2 * Broadcom Common Firmware Environment (CFE)
3 * Board device initialization, File: ui_bcm947xx.c
5 * Copyright (C) 2011, Broadcom Corporation
6 * All Rights Reserved.
7 *
8 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
9 * the contents of this file may not be disclosed to third parties, copied
10 * or duplicated in any form, in whole or in part, without the prior
11 * written permission of Broadcom Corporation.
13 * $Id: ui_bcm947xx.c 323091 2012-03-22 23:32:36Z $
16 #include "lib_types.h"
17 #include "lib_string.h"
18 #include "lib_queue.h"
19 #include "lib_malloc.h"
20 #include "lib_printf.h"
21 #include "cfe.h"
22 #include "cfe_iocb.h"
23 #include "cfe_devfuncs.h"
24 #include "cfe_ioctl.h"
25 #include "cfe_error.h"
26 #include "cfe_fileops.h"
27 #include "cfe_loader.h"
28 #include "ui_command.h"
29 #include "bsp_config.h"
31 #include <typedefs.h>
32 #include <osl.h>
33 #include <bcmdevs.h>
34 #include <bcmutils.h>
35 #include <hndsoc.h>
36 #include <siutils.h>
37 #include <sbchipc.h>
38 #include <sbmemc.h>
39 #include <dmemc_core.h>
40 #include <bcmendian.h>
41 #include <bcmnvram.h>
42 #include <hndcpu.h>
43 #include <trxhdr.h>
44 #include "addrspace.h"
45 #include "initdata.h"
47 #include "bsp_priv.h"
49 static int
50 ui_cmd_reboot(ui_cmdline_t *cmd, int argc, char *argv[])
52 hnd_cpu_reset(sih);
53 return 0;
57 static int
58 ui_cmd_nvram(ui_cmdline_t *cmd, int argc, char *argv[])
60 char *command, *name, *value;
61 char *buf;
62 size_t size;
63 int ret;
65 if (!(command = cmd_getarg(cmd, 0)))
66 return CFE_ERR_INV_PARAM;
68 if (!strcmp(command, "get")) {
69 if ((name = cmd_getarg(cmd, 1)))
70 if ((value = nvram_get(name)))
71 printf("%s\n", value);
72 } else if (!strcmp(command, "set")) {
73 if ((name = cmd_getarg(cmd, 1))) {
74 if ((value = strchr(name, '=')))
75 *value++ = '\0';
76 else if ((value = cmd_getarg(cmd, 2))) {
77 if (*value == '=')
78 value = cmd_getarg(cmd, 3);
80 if (value)
81 nvram_set(name, value);
83 } else if (!strcmp(command, "unset")) {
84 if ((name = cmd_getarg(cmd, 1)))
85 nvram_unset(name);
86 } else if (!strcmp(command, "commit")) {
87 nvram_commit();
88 } else if (!strcmp(command, "erase")) {
89 extern char *flashdrv_nvram;
90 if ((ret = cfe_open(flashdrv_nvram)) < 0)
91 return ret;
92 if (!(buf = KMALLOC(NVRAM_SPACE, 0)))
93 return CFE_ERR_NOMEM;
94 memset(buf, 0xff, NVRAM_SPACE);
95 cfe_writeblk(ret, 0, (unsigned char *)buf, NVRAM_SPACE);
96 cfe_close(ret);
97 KFREE(buf);
98 } else if (!strcmp(command, "show") || !strcmp(command, "getall")) {
99 if (!(buf = KMALLOC(NVRAM_SPACE, 0)))
100 return CFE_ERR_NOMEM;
101 nvram_getall(buf, NVRAM_SPACE);
102 for (name = buf; *name; name += strlen(name) + 1)
103 printf("%s\n", name);
104 size = sizeof(struct nvram_header) + ((uintptr)name - (uintptr)buf);
105 printf("size: %d bytes (%d left)\n", size, NVRAM_SPACE - size);
106 KFREE(buf);
109 return 0;
112 static int
113 check_trx(char *trx_name)
115 int ret;
116 fileio_ctx_t *fsctx;
117 void *ref;
118 struct trx_header trx;
119 #ifdef CFG_NFLASH
120 uint32 crc;
121 static uint32 buf[16*1024];
122 #else
123 uint32 crc, buf[512];
124 #endif /* CFG_NFLASH */
125 int first_read = 1;
126 unsigned int len, count;
128 /* Open header */
129 ret = fs_init("raw", &fsctx, trx_name);
130 if (ret)
131 return ret;
133 ret = fs_open(fsctx, &ref, "", FILE_MODE_READ);
134 if (ret) {
135 fs_uninit(fsctx);
136 return ret;
139 /* Read header */
140 ret = fs_read(fsctx, ref, (unsigned char *) &trx, sizeof(struct trx_header));
141 if (ret != sizeof(struct trx_header)) {
142 ret = CFE_ERR_IOERR;
143 goto done;
146 /* Verify magic number */
147 if (ltoh32(trx.magic) != TRX_MAGIC) {
148 ret = CFE_ERR_INVBOOTBLOCK;
149 goto done;
152 /* Checksum over header */
153 crc = hndcrc32((uint8 *) &trx.flag_version,
154 sizeof(struct trx_header) - OFFSETOF(struct trx_header, flag_version),
155 CRC32_INIT_VALUE);
157 for (len = ltoh32(trx.len) - sizeof(struct trx_header); len; len -= count) {
158 if (first_read) {
159 count = MIN(len, sizeof(buf) - sizeof(struct trx_header));
160 first_read = 0;
161 } else
162 count = MIN(len, sizeof(buf));
164 /* Read data */
165 ret = fs_read(fsctx, ref, (unsigned char *) &buf, count);
166 if (ret != count) {
167 ret = CFE_ERR_IOERR;
168 goto done;
171 /* Checksum over data */
172 crc = hndcrc32((uint8 *) &buf, count, crc);
175 /* Verify checksum */
176 if (ltoh32(trx.crc32) != crc) {
177 ret = CFE_ERR_BOOTPROGCHKSUM;
178 goto done;
181 ret = 0;
183 done:
184 fs_close(fsctx, ref);
185 fs_uninit(fsctx);
186 if (ret)
187 xprintf("%s\n", cfe_errortext(ret));
188 return ret;
192 * ui_get_loadbuf(bufptr, bufsize)
194 * Figure out the location and size of the staging buffer.
196 * Input parameters:
197 * bufptr - address to return buffer location
198 * bufsize - address to return buffer size
200 static void ui_get_loadbuf(uint8_t **bufptr, int *bufsize)
202 int size = CFG_FLASH_STAGING_BUFFER_SIZE;
205 * Get the address of the staging buffer. We can't
206 * allocate the space from the heap to store the
207 * new flash image, because the heap may not be big
208 * enough. So, if FLASH_STAGING_BUFFER_SIZE is non-zero
209 * then just use it and FLASH_STAGING_BUFFER; else
210 * use the larger of (mem_bottomofmem - FLASH_STAGING_BUFFER)
211 * and (mem_totalsize - mem_topofmem).
214 if (size > 0) {
215 *bufptr = (uint8_t *) KERNADDR(CFG_FLASH_STAGING_BUFFER_ADDR);
216 *bufsize = size;
217 } else {
218 int below, above;
219 int reserved = CFG_FLASH_STAGING_BUFFER_ADDR;
221 /* For small memory size (8MB), we tend to use the below region.
222 * The buffer address may conflict with the os running address,
223 * so we reserve 3MB for the os.
225 if ((mem_totalsize == (8*1024)) && (PHYSADDR(mem_bottomofmem) > 0x300000))
226 reserved = 0x300000;
228 below = PHYSADDR(mem_bottomofmem) - reserved;
229 above = (mem_totalsize << 10) - PHYSADDR(mem_topofmem);
231 if (below > above) {
232 *bufptr = (uint8_t *) KERNADDR(reserved);
233 *bufsize = below;
234 } else {
235 *bufptr = (uint8_t *) KERNADDR(mem_topofmem);
236 *bufsize = above;
241 #if defined(DUAL_IMAGE) || defined(FAILSAFE_UPGRADE)
242 static
243 int check_image_prepare_cmd(int the_image, char *buf, uint32 osaddr, int bufsize)
245 int ret = -1;
246 char trx_name[16], os_name[16];
247 char trx2_name[16], os2_name[16];
249 #ifdef CFG_NFLASH
250 ui_get_trx_flashdev(trx_name);
251 ui_get_os_flashdev(os_name);
252 #else
253 strcpy(trx_name, "flash1.trx");
254 strcpy(os_name, "flash0.os");
255 #endif
257 strncpy (trx2_name,trx_name,sizeof(trx2_name));
258 strncpy (os2_name,os_name,sizeof(os2_name));
259 strcat (trx2_name, "2");
260 strcat (os2_name, "2");
262 if (the_image == 0) {
263 if ((ret = check_trx(trx_name)) == 0) {
264 sprintf(buf, "boot -raw -z -addr=0x%x -max=0x%x %s:", osaddr, bufsize,
265 os_name);
266 } else {
267 printf("%s CRC check failed!\n", trx_name);
269 } else if (the_image == 1) {
270 if ((ret = check_trx(trx2_name)) == 0) {
271 sprintf(buf, "boot -raw -z -addr=0x%x -max=0x%x %s:", osaddr, bufsize,
272 os2_name);
273 } else {
274 printf("%s CRC check failed!\n", trx2_name);
276 } else {
277 printf("Image partition %d does not exist\n", the_image);
279 return ret;
281 #endif /* DUAL_IMAGE || FAILSAFE_UPGRADE */
283 #ifdef CFG_NFLASH
284 static int ui_get_bootflags(void)
286 int bootflags = 0;
287 char *val;
289 /* Only support chipcommon revision == 38 and BCM4706 for now */
290 if (((CHIPID(sih->chip) == BCM4706_CHIP_ID) || sih->ccrev == 38) &&
291 (sih->cccaps & CC_CAP_NFLASH)) {
292 if ((val = nvram_get("bootflags")))
293 bootflags = atoi(val);
294 else if ((sih->chipst & (1 << 4)) != 0) {
295 /* This is NANDBOOT */
296 bootflags = FLASH_KERNEL_NFLASH | FLASH_BOOT_NFLASH;
299 return bootflags;
302 void ui_get_boot_flashdev(char *flashdev)
304 if (!flashdev)
305 return;
306 if ((ui_get_bootflags() & FLASH_BOOT_NFLASH) == FLASH_BOOT_NFLASH)
307 strcpy(flashdev, "nflash1.boot");
308 else
309 strcpy(flashdev, "flash1.boot");
311 return;
314 void ui_get_os_flashdev(char *flashdev)
316 if (!flashdev)
317 return;
318 if ((ui_get_bootflags() & FLASH_KERNEL_NFLASH) == FLASH_KERNEL_NFLASH)
319 strcpy(flashdev, "nflash0.os");
320 else
321 strcpy(flashdev, "flash0.os");
323 return;
326 void ui_get_trx_flashdev(char *flashdev)
328 if (!flashdev)
329 return;
330 if ((ui_get_bootflags() & FLASH_KERNEL_NFLASH) == FLASH_KERNEL_NFLASH)
331 strcpy(flashdev, "nflash1.trx");
332 else
333 strcpy(flashdev, "flash1.trx");
334 return;
336 #endif /* CFG_NFLASH */
338 static int
339 ui_cmd_go(ui_cmdline_t *cmd, int argc, char *argv[])
341 int ret = 0;
342 char buf[512];
343 struct trx_header *file_buf;
344 uint8_t *ptr;
345 char *val;
346 uint32 osaddr;
347 int bufsize = 0;
348 int retry = 0;
349 int trx_failed;
350 #ifdef FAILSAFE_UPGRADE
351 char *bootpartition = nvram_get(BOOTPARTITION);
352 char *partialboots = nvram_get(PARTIALBOOTS);
353 char *maxpartialboots = nvram_get(MAXPARTIALBOOTS);
354 #endif
355 #ifdef DUAL_IMAGE
356 char *bootpartition = nvram_get(IMAGE_BOOT);
357 #endif
358 #ifdef CFG_NFLASH
359 char trx_name[16], os_name[16];
360 #else
361 char *trx_name = "flash1.trx";
362 char *os_name = "flash0.os";
363 #endif /* CFG_NFLASH */
365 val = nvram_get("os_ram_addr");
366 if (val)
367 osaddr = bcm_strtoul(val, NULL, 16);
368 else
369 osaddr = 0x80001000;
371 #if defined(FAILSAFE_UPGRADE) || defined(DUAL_IMAGE)
372 if (bootpartition != NULL) {
373 #ifdef CFG_NFLASH
374 ui_get_trx_flashdev(trx_name);
375 #endif
376 trx_failed = check_trx(trx_name);
377 #ifdef CFG_NFLASH
378 strcat(trx_name,"2");
379 #endif
380 trx_failed &= check_trx(trx_name);
381 } else
382 #endif /* FAILSAFE_UPGRADE || DUAL_IMAGE*/
384 #ifdef CFG_NFLASH
385 ui_get_trx_flashdev(trx_name);
386 ui_get_os_flashdev(os_name);
387 #endif
388 trx_failed = check_trx(trx_name);
391 if (trx_failed) {
392 /* Wait for CFE_ERR_TIMEOUT_LIMIT for an image */
393 while (1) {
394 sprintf(buf, "flash -noheader :%s", trx_name);
395 if ((ret = ui_docommand(buf)) != CFE_ERR_TIMEOUT)
396 break;
397 if (++retry == CFE_ERR_TIMEOUT_LIMIT) {
398 ret = CFE_ERR_INTR;
399 break;
402 } else if (!nvram_invmatch("boot_wait", "on")) {
403 ui_get_loadbuf(&ptr, &bufsize);
404 /* Load the image */
405 sprintf(buf, "load -raw -addr=0x%p -max=0x%x :", ptr, bufsize);
406 ret = ui_docommand(buf);
408 /* Load was successful. Check for the TRX magic.
409 * If it's a TRX image, then proceed to flash it, else try to boot
410 * Note: To boot a TRX image directly from the memory, address will need to be
411 * load address + trx header length.
413 if (ret == 0) {
414 file_buf = (struct trx_header *)ptr;
415 /* If it's a TRX, then proceed to writing to flash else,
416 * try to boot from memory
418 if (file_buf->magic != TRX_MAGIC) {
419 sprintf(buf, "boot -raw -z -addr=0x%x -max=0x%x -fs=memory :0x%p",
420 osaddr, bufsize, ptr);
421 return ui_docommand(buf);
423 /* Flash the image from memory directly */
424 sprintf(buf, "flash -noheader -mem -size=0x%x 0x%p %s",
425 file_buf->len, ptr, trx_name);
426 ret = ui_docommand(buf);
430 if (ret == CFE_ERR_INTR)
431 return ret;
432 /* Boot the image */
433 bufsize = PHYSADDR(mem_bottomofmem) - PHYSADDR(osaddr);
435 #if defined(FAILSAFE_UPGRADE) || defined(DUAL_IMAGE)
436 /* Get linux_boot variable to see what is current image */
437 if (bootpartition != NULL) {
438 char temp[20];
439 int i = atoi(bootpartition);
440 #ifdef FAILSAFE_UPGRADE
441 if (maxpartialboots && (atoi(maxpartialboots) > 0)) {
442 if (partialboots && (atoi(partialboots) > atoi(maxpartialboots))) {
443 i = 1-i;
444 printf("Changed to the other image %d (maxpartialboots exceeded)\n", i);
445 /* reset to new image */
446 sprintf(temp, "%d", i);
447 nvram_set(PARTIALBOOTS, "1");
448 nvram_set(BOOTPARTITION, temp);
449 nvram_commit();
450 } else {
451 /* Increment the counter */
452 sprintf(temp,"%d",partialboots ? atoi(partialboots)+1:1);
453 nvram_set(PARTIALBOOTS, temp);
454 nvram_commit();
457 #endif
458 if (i > 1)
459 i = 0;
461 /* We try the specified one, if it is failed, we try the other one */
462 if (check_image_prepare_cmd(i, buf, osaddr, bufsize) == 0) {
463 printf("Booting(%d): %s\n",i,buf);
464 } else if (check_image_prepare_cmd(1-i, buf, osaddr, bufsize) == 0) {
465 printf("Changed to the other image %d\n", 1 - i);
466 sprintf(temp, "%d", 1-i);
467 nvram_set(BOOTPARTITION, temp);
468 #ifdef FAILSAFE_UPGRADE
469 nvram_set(PARTIALBOOTS, "1");
470 #endif
471 nvram_commit();
472 } else {
473 printf ("Both images bad!!!\n");
474 buf[0] = 0;
477 else
478 #endif /* FAILSAFE_UPGRADE || DUAL_IMAGE */
479 sprintf(buf, "boot -raw -z -addr=0x%x -max=0x%x %s:", osaddr, bufsize, os_name);
481 return ui_docommand(buf);
484 static int
485 ui_cmd_clocks(ui_cmdline_t *cmd, int argc, char *argv[])
487 chipcregs_t *cc = (chipcregs_t *)si_setcoreidx(sih, SI_CC_IDX);
488 uint32 ccc = R_REG(NULL, &cc->capabilities);
489 uint32 pll = ccc & CC_CAP_PLL_MASK;
491 if (pll != PLL_NONE) {
492 uint32 n = R_REG(NULL, &cc->clockcontrol_n);
493 printf("Current clocks for pll=0x%x:\n", pll);
494 printf(" mips: %d\n", si_clock_rate(pll, n, R_REG(NULL, &cc->clockcontrol_m3)));
495 printf(" sb: %d\n", si_clock_rate(pll, n, R_REG(NULL, &cc->clockcontrol_sb)));
496 printf(" pci: %d\n", si_clock_rate(pll, n, R_REG(NULL, &cc->clockcontrol_pci)));
497 printf(" mipsref: %d\n", si_clock_rate(pll, n,
498 R_REG(NULL, &cc->clockcontrol_m2)));
499 } else {
500 printf("Current clocks: %d/%d/%d/%d Mhz.\n",
501 si_cpu_clock(sih) / 1000000,
502 si_mem_clock(sih) / 1000000,
503 si_clock(sih) / 1000000,
504 si_alp_clock(sih) / 1000000);
506 return 0;
510 extern int ui_init_devcmds(void); // J++
512 ui_init_bcm947xxcmds(void)
514 cmd_addcmd("reboot",
515 ui_cmd_reboot,
516 NULL,
517 "Reboot.",
518 "reboot\n\n"
519 "Reboots.",
520 "");
521 cmd_addcmd("nvram",
522 ui_cmd_nvram,
523 NULL,
524 "NVRAM utility.",
525 "nvram [command] [args..]\n\n"
526 "Access NVRAM.",
527 "get [name];Gets the value of the specified variable|"
528 "set [name=value];Sets the value of the specified variable|"
529 "unset [name];Deletes the specified variable|"
530 "commit;Commit variables to flash|"
531 "erase;Erase all nvram|"
532 "show;Shows all variables|");
533 cmd_addcmd("go",
534 ui_cmd_go,
535 NULL,
536 "Verify and boot OS image.",
537 "go\n\n"
538 "Boots OS image if valid. Waits for a new OS image if image is invalid\n"
539 "or boot_wait is unset or not on.",
540 "");
541 cmd_addcmd("show clocks",
542 ui_cmd_clocks,
543 NULL,
544 "Show current values of the clocks.",
545 "show clocks\n\n"
546 "Shows the current values of the clocks.",
547 "");
548 ui_init_devcmds(); // J++
549 #if CFG_WLU
550 wl_addcmd();
551 #endif
553 return 0;