1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * Board device initialization File: bcm94710_devs.c 5 * 6 * This is the "C" part of the board support package. The 7 * routines to create and initialize the console, wire up 8 * device drivers, and do other customization live here. 9 * 10 * Author: Mitch Lichtenberg (mpl@broadcom.com) 11 * 12 ********************************************************************* 13 * 14 * XX Copyright 2000,2001 15 * Broadcom Corporation. All rights reserved. 16 * 17 * BROADCOM PROPRIETARY AND CONFIDENTIAL 18 * 19 * This software is furnished under license and may be used and 20 * copied only in accordance with the license. 21 ********************************************************************* */ 22 23 24 25#include "sbmips.h" 26#include "lib_types.h" 27#include "lib_printf.h" 28#include "lib_physio.h" 29#include "cfe_iocb.h" 30#include "cfe_device.h" 31#include "cfe_timer.h" 32#include "cfe.h" 33#include "ui_command.h" 34#include "bsp_config.h" 35#include "dev_newflash.h" 36#include "env_subr.h" 37#include "pcivar.h" 38#include "pcireg.h" 39#include "../../../../../dev/ns16550.h" 40#include "net_ebuf.h" 41#include "net_ether.h" 42#include "net_api.h" 43 44#include <typedefs.h> 45#include <osl.h> 46#include <bcmutils.h> 47#include <sbutils.h> 48#include <sbconfig.h> 49#include <sbchipc.h> 50#include <sbextif.h> 51#include <hndpci.h> 52#include "bsp_priv.h" 53#include <trxhdr.h> 54#include <bcmdevs.h> 55#include <bcmnvram.h> 56#include <hndcpu.h> 57#include <hndchipc.h> 58#include <epivers.h> 59 60#define MAX_WAIT_TIME 20 /* seconds to wait for boot image */ 61#define MIN_WAIT_TIME 3 /* seconds to wait for boot image */ 62 63#define RESET_DEBOUNCE_TIME (500*1000) /* 500 ms */ 64 65/* Defined as sbh by bsp_config.h for convenience */ 66sb_t *bcm947xx_sbh = NULL; 67 68/* Configured devices */ 69#if (CFG_FLASH || CFG_SFLASH) && CFG_XIP 70#error "XIP and Flash cannot be defined at the same time" 71#endif 72 73extern cfe_driver_t ns16550_uart; 74#if CFG_FLASH 75extern cfe_driver_t newflashdrv; 76#endif 77#if CFG_SFLASH 78extern cfe_driver_t sflashdrv; 79#endif 80#if CFG_ET 81extern cfe_driver_t bcmet; 82#endif 83#if CFG_WL 84extern cfe_driver_t bcmwl; 85#endif 86#if CFG_BCM57XX 87extern cfe_driver_t bcm5700drv; 88#endif 89 90/* Reset NVRAM */ 91static int restore_defaults = 0; 92 93static void 94board_console_add(void *regs, uint irq, uint baud_base, uint reg_shift) 95{ 96 physaddr_t base; 97 98 /* The CFE NS16550 driver expects a physical address */ 99 base = PHYSADDR((physaddr_t) regs); 100 cfe_add_device(&ns16550_uart, base, baud_base, ®_shift); 101} 102 103#if CFG_FLASH || CFG_SFLASH 104static void 105reset_release_wait (void) 106{ 107 int gpio; 108 109 if ((gpio = nvram_resetgpio_init ((void *)sbh)) < 0) 110 return; 111 112 while (1) { 113 /* Reset button is active low */ 114 if (sb_gpioin(sbh) & ((uint32)1 << gpio)) { 115 OSL_DELAY(RESET_DEBOUNCE_TIME); 116 117 if (sb_gpioin(sbh) & ((uint32)1 << gpio)) 118 break; 119 } 120 } 121} 122#endif 123 124/* ********************************************************************* 125 * board_console_init() 126 * 127 * Add the console device and set it to be the primary 128 * console. 129 * 130 * Input parameters: 131 * nothing 132 * 133 * Return value: 134 * nothing 135 ********************************************************************* */ 136#if CFG_BUFLOG 137extern int logbuf_write(const char *str); 138extern int logbuf_dump(void); 139#endif 140 141void 142board_console_init(void) 143{ 144 unsigned int boardtype; 145 unsigned long mipsclock = 0, sbclock = 0, pciclock = 0; 146 char *clkfreq; 147 148#if CFG_BUFLOG 149 xprinthook = logbuf_write; 150#endif 151 /* Initialize SB access */ 152 sbh = sb_kattach(SB_OSH); 153 ASSERT(sbh); 154 155#if !CFG_SIM 156 /* Figure out current MIPS clock speed */ 157 if ((cfe_cpu_speed = sb_cpu_clock(sbh)) == 0) 158 cfe_cpu_speed = 100000000; 159 160 /* Initialize NVRAM access */ 161 if (nvram_init((void *)sbh) > 0) 162 restore_defaults = 1; 163 164 if (!restore_defaults) { 165 char *end; 166 167 /* MIPS clock speed override */ 168 if ((clkfreq = nvram_get("clkfreq"))) { 169 mipsclock = bcm_strtoul(clkfreq, &end, 0) * 1000000; 170 if (*end == ',') 171 sbclock = bcm_strtoul(++end, NULL, 0) * 1000000; 172 } else if (sb_chip(sbh) == BCM4710_DEVICE_ID) { 173 mipsclock = 124800000; 174 175 /* Use a 25 MHz PCI clock on bcm94710r* boards to drive the RoboSwitch */ 176 boardtype = sb_boardtype(sbh); 177 if ((boardtype == BCM94710R1_BOARD) || (boardtype == BCM94710R4_BOARD)) 178 pciclock = 25000000; 179 } 180 181 if (mipsclock) { 182 /* Set current MIPS clock speed */ 183 sb_mips_setclock(sbh, mipsclock, sbclock, pciclock); 184 } 185 } 186#endif 187 188 189 /* Initialize clocks and interrupts */ 190 sb_mips_init(sbh, 0); 191 192 /* Initialize UARTs */ 193 sb_serial_init(sbh, board_console_add); 194 195 if (cfe_finddev("uart0")) { 196 cfe_set_console("uart0"); 197#if CFG_BUFLOG 198 logbuf_dump(); 199#endif 200 } 201} 202 203#if CFG_FLASH || CFG_SFLASH 204static void 205flash_init(void) 206{ 207 newflash_probe_t fprobe; 208 chipcregs_t *cc = NULL; 209 extifregs_t *extif = NULL; 210 uint32 fltype, bootsz, *bisz; 211 cfe_driver_t *drv; 212 213 memset(&fprobe, 0, sizeof(fprobe)); 214 215 fprobe.flash_phys = SB_FLASH1; 216 if ((cc = (chipcregs_t *) sb_setcore(sbh, SB_CC, 0))) { 217 fltype = R_REG(NULL, &cc->capabilities) & CC_CAP_FLASH_MASK; 218 fprobe.flash_phys = SB_FLASH2; 219 } else if ((extif = sb_setcore(sbh, SB_EXTIF, 0))) 220 fltype = PFLASH; 221 else 222 fltype = FLASH_NONE; 223 224 switch (fltype) { 225#if CFG_FLASH 226 case PFLASH: 227 drv = &newflashdrv; 228 fprobe.flash_flags = FLASH_FLG_BUS16 | FLASH_FLG_DEV16; 229 if ((cc && !(R_REG(NULL, &cc->flash_config) & CC_CFG_DS)) || 230 (extif && !(R_REG(NULL, &extif->flash_config) & CF_DS))) 231 fprobe.flash_flags = FLASH_FLG_BUS8 | FLASH_FLG_DEV16; 232 break; 233#endif 234#if CFG_SFLASH 235 case SFLASH_ST: 236 case SFLASH_AT: 237 ASSERT(cc); 238 drv = &sflashdrv; 239 /* Overload cmdset field */ 240 fprobe.flash_cmdset = (int)cc; 241 break; 242#endif 243 default: 244 /* No flash or unsupported flash */ 245 return; 246 } 247 248 /* Default is 256K boot partition */ 249 bootsz = 256 * 1024; 250 /* Do we have a self-describing binary image? */ 251 bisz = (uint32 *)PHYS_TO_K1(fprobe.flash_phys + BISZ_OFFSET); 252 if (bisz[BISZ_MAGIC_IDX] == BISZ_MAGIC) { 253 if ((bisz[BISZ_DATAEND_IDX] - bisz[BISZ_TXTST_IDX]) < (128 * 1024)) 254 bootsz = 128 * 1024; 255 printf("Boot partition size = %d(0x%x)\n", bootsz, bootsz); 256 } 257 258 /* Because CFE can only boot from the beginning of a partition */ 259 fprobe.flash_nparts = 4; 260 fprobe.flash_parts[0].fp_size = bootsz; 261 fprobe.flash_parts[0].fp_name = "boot"; 262 fprobe.flash_parts[1].fp_size = sizeof(struct trx_header); 263 fprobe.flash_parts[1].fp_name = "trx"; 264 fprobe.flash_parts[2].fp_size = 0; 265 fprobe.flash_parts[2].fp_name = "os"; 266 fprobe.flash_parts[3].fp_size = NVRAM_SPACE; 267 fprobe.flash_parts[3].fp_name = "nvram"; 268 cfe_add_device(drv, 0, 0, &fprobe); 269 270 /* Because CFE can only flash an entire partition */ 271 fprobe.flash_nparts = 3; 272 fprobe.flash_parts[0].fp_size = bootsz; 273 fprobe.flash_parts[0].fp_name = "boot"; 274 fprobe.flash_parts[1].fp_size = 0; 275 fprobe.flash_parts[1].fp_name = "trx"; 276 fprobe.flash_parts[2].fp_size = NVRAM_SPACE; 277 fprobe.flash_parts[2].fp_name = "nvram"; 278 cfe_add_device(drv, 0, 0, &fprobe); 279 280 /* Because sometimes we want to program the entire device */ 281 fprobe.flash_nparts = 0; 282 cfe_add_device(drv, 0, 0, &fprobe); 283} 284#endif 285 286/* ********************************************************************* 287 * board_device_init() 288 * 289 * Initialize and add other devices. Add everything you need 290 * for bootstrap here, like disk drives, flash memory, UARTs, 291 * network controllers, etc. 292 * 293 * Input parameters: 294 * nothing 295 * 296 * Return value: 297 * nothing 298 ********************************************************************* */ 299 300void 301board_device_init(void) 302{ 303 unsigned int unit; 304#if CFG_ET || CFG_WL || CFG_BCM57XX 305 void *regs; 306#endif 307 308 /* Set by board_console_init() */ 309 ASSERT(sbh); 310 311#ifdef BCM4710 312 if (sb_chip(sbh) == BCM4710_DEVICE_ID) { 313 pcireg_t cr; 314 315 /* Initialize PCI access */ 316 sbpci_init(sbh); 317 318 /* Check PCI revision ID through external PCI config access */ 319 if (sbpci_read_config(sbh, 1, 0, 0, PCI_CLASS_REG, &cr, sizeof(cr)) == 0 && 320 PCI_REVISION(cr) == 0) 321 sbpci_check(sbh); 322 } 323#endif 324 325#if CFG_FLASH || CFG_SFLASH 326 flash_init(); 327#endif 328 329 for (unit = 0; unit < SB_MAXCORES; unit++) { 330#if CFG_ET 331 if ((regs = sb_setcore(sbh, SB_ENET, unit))) 332 cfe_add_device(&bcmet, BCM47XX_ENET_ID, unit, regs); 333#endif 334#if CFG_WL 335 if ((regs = sb_setcore(sbh, SB_D11, unit))) 336 cfe_add_device(&bcmwl, BCM4306_D11G_ID, unit, regs); 337#endif 338#if CFG_BCM57XX 339 if((regs = sb_setcore(sbh, SB_GIGETH, unit))) 340 cfe_add_device(&bcm5700drv, BCM47XX_GIGETH_ID, unit, regs); 341#endif 342 } 343} 344 345/* ********************************************************************* 346 * board_device_reset() 347 * 348 * Reset devices. This call is done when the firmware is restarted, 349 * as might happen when an operating system exits, just before the 350 * "reset" command is applied to the installed devices. You can 351 * do whatever board-specific things are here to keep the system 352 * stable, like stopping DMA sources, interrupts, etc. 353 * 354 * Input parameters: 355 * nothing 356 * 357 * Return value: 358 * nothing 359 ********************************************************************* */ 360 361void 362board_device_reset(void) 363{ 364} 365 366/* ********************************************************************* 367 * board_final_init() 368 * 369 * Do any final initialization, such as adding commands to the 370 * user interface. 371 * 372 * If you don't want a user interface, put the startup code here. 373 * This routine is called just before CFE starts its user interface. 374 * 375 * Input parameters: 376 * nothing 377 * 378 * Return value: 379 * nothing 380 ********************************************************************* */ 381 382void 383board_final_init(void) 384{ 385 char *addr, *mask, *wait_time; 386 char buf[512], *cur = buf; 387 int commit; 388 uint32 ncdl; 389#if CFG_WL && CFG_WLU && CFG_SIM 390 char *ssid; 391#endif 392 393 ui_init_bcm947xxcmds(); 394 395 /* Force commit of embedded NVRAM */ 396 commit = restore_defaults; 397 398 /* Set the SDRAM NCDL value into NVRAM if not already done */ 399 if ((getintvar(NULL, "sdram_ncdl") == 0) && 400 ((ncdl = sb_memc_get_ncdl(sbh)) != 0)) { 401 sprintf(buf, "0x%x", ncdl); 402 nvram_set("sdram_ncdl", buf); 403 commit = 1; 404 } 405 406 /* Set the bootloader version string if not already done */ 407 sprintf(buf, "CFE %s", EPI_ROUTER_VERSION_STR); 408 if (strcmp(nvram_safe_get("pmon_ver"), buf) != 0) { 409 nvram_set("pmon_ver", buf); 410 commit = 1; 411 } 412 413#if CFG_FLASH || CFG_SFLASH 414#if !CFG_SIM 415 /* Commit NVRAM */ 416 if (commit) { 417 printf("Committing NVRAM..."); 418 nvram_commit(); 419 printf("done\n"); 420 if (restore_defaults) { 421 printf ("Waiting for reset button release..."); 422 reset_release_wait (); 423 printf("done\n"); 424 } 425 } 426#endif 427 428#if !CFG_SIM 429 /* Reboot after restoring defaults */ 430 if (restore_defaults) 431 sb_watchdog(sbh, 1); 432#endif /* !CFG_SIM */ 433#else 434 if (commit) 435 printf("Flash not configured, not commiting NVRAM...\n"); 436#endif 437 438 /* 439 * Read the wait_time NVRAM variable and set the tftp max retries. 440 * Assumption: tftp_rrq_timeout & tftp_recv_timeout are set to 1sec. 441 */ 442 if ((wait_time = nvram_get("wait_time")) != NULL) { 443 tftp_max_retries = atoi(wait_time); 444 if (tftp_max_retries > MAX_WAIT_TIME) 445 tftp_max_retries = MAX_WAIT_TIME; 446 else if (tftp_max_retries < MIN_WAIT_TIME) 447 tftp_max_retries = MIN_WAIT_TIME; 448 } 449 450 /* Configure network */ 451 if (cfe_finddev("eth0") && 452 (addr = nvram_get("lan_ipaddr")) && 453 (mask = nvram_get("lan_netmask"))) { 454 sprintf(buf, "ifconfig eth0 -addr=%s -mask=%s", addr, mask); 455 ui_docommand(buf); 456#if CFG_WL && CFG_WLU && CFG_SIM 457 if ((ssid = nvram_get("wl0_ssid"))) { 458 sprintf(buf, "wl join %s", ssid); 459 ui_docommand(buf); 460 } 461#endif 462 } 463 464#if !CFG_SIM 465 /* Boot image */ 466 cur += sprintf(cur, "go;"); 467#endif /* !CFG_SIM */ 468 469 /* Startup */ 470 if (cur > buf) 471 env_setenv("STARTUP", buf, ENV_FLG_NORMAL); 472} 473 474