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, &reg_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