1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  Board device initialization		File: bcm95836cpci_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    *********************************************************************
11    *
12    *  Copyright 2000,2001,2002,2003,2004
13    *  Broadcom Corporation. All rights reserved.
14    *
15    *  This software is furnished under license and may be used and
16    *  copied only in accordance with the following terms and
17    *  conditions.  Subject to these conditions, you may download,
18    *  copy, install, use, modify and distribute modified or unmodified
19    *  copies of this software in source and/or binary form.  No title
20    *  or ownership is transferred hereby.
21    *
22    *  1) Any source code used, modified or distributed must reproduce
23    *     and retain this copyright notice and list of conditions
24    *     as they appear in the source file.
25    *
26    *  2) No right is granted to use any trade name, trademark, or
27    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
28    *     name may not be used to endorse or promote products derived
29    *     from this software without the prior written permission of
30    *     Broadcom Corporation.
31    *
32    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44    *     THE POSSIBILITY OF SUCH DAMAGE.
45    ********************************************************************* */
46
47
48#include "cfe.h"
49#include "env_subr.h"
50#include "bcmnvram.h"
51
52#include "sbmips32.h"
53#include "sb_bp.h"
54
55#include "dev_newflash.h"
56#include "sb_utils.h"
57
58
59/*  *********************************************************************
60    *  Devices we're importing
61    ********************************************************************* */
62
63extern cfe_driver_t ns16550_uart;
64extern cfe_driver_t sb_mac;
65extern cfe_driver_t newflashdrv;
66
67#if CFG_PCI
68extern void cpci_add_devices(int init_pci);
69#endif
70
71extern cfe_driver_t ds1743_nvram;
72extern cfe_driver_t ds1743_clock;
73
74extern void ui_init_bcm95836cpcicmds(void);
75extern int ui_init_toyclockcmds(void);
76extern void ui_init_flashtestcmds(void);
77
78#if CFG_USB
79static void board_usb_init(void);
80extern int usb_init(uint32_t addr);
81extern cfe_driver_t usb_disk;
82extern int ui_init_usbcmds(void);
83#endif
84
85extern void board_setleds(uint32_t);
86void board_led_msg(char *msg);
87
88/*  *********************************************************************
89    *  Some board-specific parameters
90    ********************************************************************* */
91
92typedef struct initenv_s {
93    const char *name;
94    const char *value;
95    const char *def;
96} initenv_t;
97
98/* Note: et1 MAC port is not brought out on current revs */
99const initenv_t bcm95836cpci_envvars[] = {
100    {"et0macaddr","$$NVRAM","02-10-18-58-36-10"},
101    {"et1macaddr","$$NVRAM","02-10-18-58-36-11"},
102    {"et0phyaddr","2",NULL},
103    {"et1phyaddr","1",NULL},
104    {"et0mdcport","0",NULL},
105    {"et1mdcport","1",NULL},
106    {"boardtype","bcm95836cpci",NULL},
107    {NULL,NULL}};
108
109
110/*  *********************************************************************
111    *  board_led_msg()
112    *
113    *   Write characters to OSRAM 4-char LED display.
114    *
115    *  Input parameters:
116    *  	  String of 1 character or more in length
117    *
118    *  Return value:
119    *  	   nothing
120    ******************************************************************** */
121void board_led_msg(char * msg)
122{
123    int len = strlen(msg);
124    uint32_t a0;
125    int i;
126
127    for (a0 = 0,i = 0; i < 4; i++) {
128	a0 <<= 8;
129	a0 |= (i < len) ? msg[i] : ' ';
130	}
131    board_setleds(a0);
132}
133
134
135/*  *********************************************************************
136    *  bcm95836cpci_initenv()
137    *
138    *  Initialize default environment variables.
139    *
140    *  Input parameters:
141    *  	   nothing
142    *
143    *  Return value:
144    *  	   nothing
145    ********************************************************************* */
146static void bcm95836cpci_initenv(void)
147{
148    const initenv_t *ini;
149    char *txt;
150
151    ini = bcm95836cpci_envvars;
152
153    /* Assign either the forced value, or the value
154       of another environment variable if the name starts
155       with a dollar sign.  If that name is not defined
156       either, then use the default from the table. */
157
158    while (ini->name) {
159	if (strcmp(ini->value, "$$NVRAM") == 0) {
160	    txt = (char *)nvram_get(ini->name);
161	    if (!txt) txt = (char *) ini->def;
162	    }
163	else if (ini->value[0] == '$') {
164	    txt = env_getenv(&(ini->value[1]));
165	    if (!txt) txt = (char *) ini->def;
166	    }
167	else {
168	    txt = (char *) ini->value;
169	    }
170	if (txt) {
171	    if (!env_getenv(ini->name)) {
172		env_setenv(ini->name,txt,ENV_FLG_BUILTIN);
173		}
174	    }
175	ini++;
176	}
177
178}
179
180
181/*  *********************************************************************
182    *  bcm95836cpci_probeflash()
183    *
184    *  Probe the flash and initialize as required.
185    *
186    *  Input parameters:
187    *  	   nothing
188    *
189    *  Return value:
190    *  	   nothing
191    *
192    * Note: BCM95836CPCI has a 512K PLCC boot rom and a 16M (8M x 16)
193    *       Intel 28F128J3A flash chip.  However, accesses to flash
194    *       using CS4, required for the nvram partition, are limited
195    *       to 8M and other operating systems using that partition
196    *       are currently limited to 4M.  We therefore size each
197    *       partition of the Intel flash to reside in the low 4M.
198    ********************************************************************* */
199
200#define BOOT_SPACE   (512*KB)
201#define TRX_SPACE    (1*KB)     /* Must hold a trx_hdr structure */
202#define OS_SPACE     ((4*MB) - BOOT_SPACE - TRX_SPACE - NVRAM_SPACE)
203#define NVRAM_OFFSET (BOOT_SPACE + TRX_SPACE + OS_SPACE)
204
205static void bcm95836cpci_probeflash(void)
206{
207#ifdef INCLUDE_FLASH_DRIVERS
208    newflash_probe_t fprobe;
209
210    /*
211     * JP1001 BCM95836CPCI
212     * 1 2
213     * o o (open)   = Boot from PLCC (512K AM29LV040B)
214     * o-o (closed) = Boot from Intel 28F128J3A-110 (16MB)
215     *
216     * To put CFE on the Intel flash, burn cfe.srec into PLCC,
217     * move jumper JP1001 from pins 2-3 to jump pins 1-2, and
218     * then flash cfe.flash into it.
219     *
220     * We configure 4 flash devices on the BCM95836CPCI:
221     *
222     *	flash0:	boot flash (PLCC or Intel flash, per jumper above), 512kB.
223     *	flash1:	Intel flash, 8MB (boot/trx/os/nvram partitions).
224     *	flash2:	Intel flash, 8MB (boot/trx/nvram partitions).
225     *	flash3:	Intel flash, 8MB (single partition).
226     */
227
228    memset(&fprobe,0,sizeof(fprobe));
229
230    /* We configure flash0 w/o partitions so that the "flash" UI command
231     * will find it correctly by default.  Ugh.
232     */
233    fprobe.flash_phys = 0x1FC00000;	/* boot flash.  */
234    fprobe.flash_size = 512 * KB;   /*REAL_BOOTROM_SIZE;*/
235    fprobe.flash_flags = FLASH_FLG_BUS8 | FLASH_FLG_DEV8;
236    fprobe.flash_nparts = 0;
237    cfe_add_device(&newflashdrv, 0, 0, &fprobe);	/* flash0 */
238
239    memset(&fprobe,0,sizeof(fprobe));
240
241    /* following bcm947xx_devs.c as modified by the switch group */
242    fprobe.flash_phys = 0x1B000000;    /* shadow (Intel) flash at CS4 */
243    fprobe.flash_size = 16 * MB;
244    fprobe.flash_flags = FLASH_FLG_BUS8 | FLASH_FLG_DEV16;
245
246    /* Because CFE can only boot from the beginning of a partition */
247    fprobe.flash_nparts = 4;
248    fprobe.flash_parts[0].fp_size = BOOT_SPACE;
249    fprobe.flash_parts[0].fp_name = "boot";
250    fprobe.flash_parts[1].fp_size = TRX_SPACE;   /* currently 7 words used */
251    fprobe.flash_parts[1].fp_name = "trx";
252    fprobe.flash_parts[2].fp_size = OS_SPACE;
253    fprobe.flash_parts[2].fp_name = "os";
254    fprobe.flash_parts[3].fp_size = NVRAM_SPACE;
255    fprobe.flash_parts[3].fp_name = "nvram";
256    cfe_add_device(&newflashdrv, 0, 0, &fprobe);	/* flash1 */
257
258    /* Because CFE can only flash an entire partition */
259    fprobe.flash_nparts = 3;
260    fprobe.flash_parts[0].fp_size = BOOT_SPACE;
261    fprobe.flash_parts[0].fp_name = "boot";
262    fprobe.flash_parts[1].fp_size = TRX_SPACE + OS_SPACE;
263    fprobe.flash_parts[1].fp_name = "trx";
264    fprobe.flash_parts[2].fp_size = NVRAM_SPACE;
265    fprobe.flash_parts[2].fp_name = "nvram";
266    cfe_add_device(&newflashdrv, 0, 0, &fprobe);	/* flash2 */
267
268    /* Because sometimes we want to program the entire device */
269    fprobe.flash_nparts = 0;
270    cfe_add_device(&newflashdrv, 0, 0, &fprobe);	/* flash3 */
271
272    board_led_msg("FLASH");
273
274#endif /* INCLUDE_FLASH_DRIVERS */
275}
276
277
278/*  *********************************************************************
279    *  board_console_init()
280    *
281    *  Add the console device and set it to be the primary
282    *  console.
283    *
284    *  Input parameters:
285    *  	   nothing
286    *
287    *  Return value:
288    *  	   nothing
289    ********************************************************************* */
290
291void board_console_init(void)
292{
293    uint32_t uart_clock;
294
295    uart_clock = sb_uart_clock();
296
297    /* This hack prevents a divider value of 0 in the UART registers.  It's
298       not obviously the right thing to do here. */
299    if (uart_clock < (CFG_SERIAL_BAUD_RATE*16))
300	uart_clock = 16*CFG_SERIAL_BAUD_RATE;
301
302    /* Console on BCM95836cpci is COM1, note: no HW Flow control */
303    cfe_add_device(&ns16550_uart, BCM95836_COM1, uart_clock, 0);
304    cfe_set_console("uart0");
305
306    /* Auxiliary UART */
307    cfe_add_device(&ns16550_uart,BCM95836_COM2,uart_clock,0);
308
309    /* Make nvram variables available early.  These are located in
310     * the flash1/flash2 "nvram" partition.
311     */
312    nvram_init((uint8_t *)PHYS_TO_K1(0x1B000000 + NVRAM_OFFSET), NVRAM_SPACE);
313
314#if CFG_PCI
315    cfe_startflags |= CFE_INIT_PCI;
316#endif
317}
318
319
320/*  *********************************************************************
321    *  board_device_init()
322    *
323    *  Initialize and add other devices.  Add everything you need
324    *  for bootstrap here, like disk drives, flash memory, UARTs,
325    *  network controllers, etc.
326    *
327    *  Input parameters:
328    *  	   nothing
329    *
330    *  Return value:
331    *  	   nothing
332    ********************************************************************* */
333
334void board_device_init(void)
335{
336    /* NVRAM is DS1743 TOD/NVRAM (Battery backed SRAM) */
337    cfe_add_device(&ds1743_nvram,
338		   BCM95836_CPCI_NVRAM_ADDR,
339		   BCM95836_CPCI_NVRAM_SIZE,0);
340    cfe_set_envdevice("nvram0");
341    cfe_add_device(&ds1743_clock, BCM95836_CPCI_NVRAM_ADDR, 0, 0);
342
343    /* We would like the environment variables to be set up early.
344     * For compatibility with HND conventions, some of the device
345     * attach routines, e.g, for the MACs, may interrogate the
346     * environment.
347     */
348
349    bcm95836cpci_probeflash();
350    bcm95836cpci_initenv();
351
352    cfe_add_device(&sb_mac, 0, 2, env_getenv("et0macaddr"));
353#if 0   /* MAC 1 is not brought out */
354    cfe_add_device(&sb_mac, 1, 1, env_getenv("et1macaddr"));
355#endif
356
357#if CFG_USB
358    board_usb_init();
359    usb_init(SB_USB_BASE);
360    cfe_add_device(&usb_disk,0,0,0);
361#endif
362
363#if CFG_PCI
364    /* We are a PCI host in a CPCI system.  Most of the supported PCI
365       devices are not currently available for CPCI; we link only
366       a subset. */
367    cpci_add_devices(1);
368#endif
369}
370
371
372
373/*  *********************************************************************
374    *  board_device_reset()
375    *
376    *  Reset devices.  This call is done when the firmware is restarted,
377    *  as might happen when an operating system exits, just before the
378    *  "reset" command is applied to the installed devices.   You can
379    *  do whatever board-specific things are here to keep the system
380    *  stable, like stopping DMA sources, interrupts, etc.
381    *
382    *  Input parameters:
383    *  	   nothing
384    *
385    *  Return value:
386    *  	   nothing
387    ********************************************************************* */
388
389void board_device_reset(void)
390{
391}
392
393#if CFG_USB
394/*  *********************************************************************
395    *  board_usb_init()
396    *
397    *  Turn on the OHCI controller at the core.
398    *
399    *  Input parameters:
400    *  	   nothing
401    *
402    *  Return value:
403    *  	   nothing
404    ********************************************************************* */
405static void board_usb_init(void)
406{
407    volatile uint32_t *reg;
408
409    /* host mode (M_SBTS_UH=1) sequence taken from the BCM4710 UM */
410
411    reg = (volatile uint32_t *) PHYS_TO_K1(SB_USB_BASE + R_SBTMSTATELOW);
412
413    *reg = M_SBTS_RS | M_SBTS_CE | M_SBTS_FC | M_SBTS_UH;
414    cfe_usleep(100);
415    *reg = M_SBTS_CE | M_SBTS_FC | M_SBTS_UH;
416    cfe_usleep(100);
417    *reg = M_SBTS_CE | M_SBTS_UH;
418    cfe_usleep(100);
419}
420#endif
421
422
423/*  *********************************************************************
424    *  board_final_init()
425    *
426    *  Do any final initialization, such as adding commands to the
427    *  user interface.
428    *
429    *  If you don't want a user interface, put the startup code here.
430    *  This routine is called just before CFE starts its user interface.
431    *
432    *  Input parameters:
433    *  	   nothing
434    *
435    *  Return value:
436    *  	   nothing
437    ********************************************************************* */
438
439void board_final_init(void)
440{
441    ui_init_bcm95836cpcicmds();
442    ui_init_toyclockcmds();
443    ui_init_flashtestcmds();
444
445#if CFG_USB
446    ui_init_usbcmds();
447#endif
448    board_led_msg("CFE ");
449}
450