1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * Board device initialization File: carmel_devs.c
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.
10 * Author: Mitch Lichtenberg (mpl@broadcom.com)
12 *********************************************************************
14 * Copyright 2000,2001,2002,2003
15 * Broadcom Corporation. All rights reserved.
17 * This software is furnished under license and may be used and
18 * copied only in accordance with the following terms and
19 * conditions. Subject to these conditions, you may download,
20 * copy, install, use, modify and distribute modified or unmodified
21 * copies of this software in source and/or binary form. No title
22 * or ownership is transferred hereby.
24 * 1) Any source code used, modified or distributed must reproduce
25 * and retain this copyright notice and list of conditions
26 * as they appear in the source file.
28 * 2) No right is granted to use any trade name, trademark, or
29 * logo of Broadcom Corporation. The "Broadcom Corporation"
30 * name may not be used to endorse or promote products derived
31 * from this software without the prior written permission of
32 * Broadcom Corporation.
34 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
35 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
36 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
37 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
38 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
39 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
40 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
41 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
42 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
44 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
45 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
46 * THE POSSIBILITY OF SUCH DAMAGE.
47 ********************************************************************* */
52 #include "lib_types.h"
53 #include "lib_queue.h"
55 #include "lib_malloc.h"
56 #include "lib_string.h"
58 #include "lib_printf.h"
60 #include "cfe_device.h"
61 #include "cfe_timer.h"
64 #include "cfe_devfuncs.h"
66 #include "sb1250_defs.h"
67 #include "sb1250_regs.h"
68 #include "sb1250_pci.h"
69 #include "sb1250_ldt.h"
70 #include "sb1250_scd.h"
71 #include "sb1250_smbus.h"
72 #include "sb1250_draminit.h"
74 #include "bsp_config.h"
77 #include "carmel_env.h"
80 #include "dev_newflash.h"
82 #include "cfe_loader.h"
83 #include "cfe_autoboot.h"
85 #include "ui_command.h"
88 static int program_spd_eeprom(void);
90 /* *********************************************************************
91 * Devices we're importing
92 ********************************************************************* */
94 extern cfe_driver_t sb1250_uart
; /* SB1250 serial ports */
95 extern cfe_driver_t ns16550_uart
; /* NS16550 UART */
96 extern cfe_driver_t sb1250_ether
; /* SB1250 MACs */
97 extern cfe_driver_t newflashdrv
; /* flash */
98 extern cfe_driver_t idedrv
; /* IDE disk */
100 extern cfe_driver_t sb1250_24lc128eeprom
; /* Microchip EEPROM */
101 extern cfe_driver_t sb1250_at24c02eeprom
; /* Atmel SPD EEPROM */
103 /* *********************************************************************
104 * Commands we're importing
105 ********************************************************************* */
107 extern int ui_init_carmelcmds(void);
108 extern int ui_init_corecmds(void);
109 extern int ui_init_soccmds(void);
110 extern int ui_init_testcmds(void);
111 extern int ui_init_resetcmds(void);
112 extern int ui_init_phycmds(void);
113 extern int ui_init_memtestcmds(void);
114 extern int ui_init_ethertestcmds(void);
115 extern int ui_init_flashtestcmds(void);
116 extern int ui_init_disktestcmds(void);
117 extern int ui_init_spdcmds(void);
118 extern int ui_init_uarttestcmds(void);
119 extern int ui_init_xpgmcmds(void);
121 /* To use the 7-seg display */
122 extern void board_setdisplay(unsigned int val
);
124 /* *********************************************************************
125 * Some other stuff we use
126 ********************************************************************* */
128 extern void sb1250_show_cpu_type(void);
129 int carmel_startup(void);
131 /* *********************************************************************
132 * Some board-specific parameters
133 ********************************************************************* */
136 /* *********************************************************************
137 * SysConfig switch settings and related parameters
138 ********************************************************************* */
143 #define UART_CONSOLE 0x00000000
144 #define IDE_SUPPORT 0x00000001
145 #define IDE_BOOT 0x00000020
146 #define AUTOSTART 0x00000002
147 #define NO_AUTOSTART 0x00000004
148 #define PROGRAM_SPD 0x00000008
149 #define NO_READ_IDEEPROM 0x00000010
150 #define AUTOBOOT 0x00000040
152 const unsigned int board_startflags
[16] = {
153 UART_CONSOLE
| AUTOSTART
, /* 0 : UART console */
154 UART_CONSOLE
| AUTOSTART
| IDE_SUPPORT
, /* 1 : IDE support */
155 UART_CONSOLE
| AUTOSTART
| IDE_SUPPORT
| IDE_BOOT
, /* 2 : IDE support */
156 UART_CONSOLE
| AUTOSTART
| AUTOBOOT
, /* 3 : AUTOBOOT */
167 PROGRAM_SPD
| UART_CONSOLE
, /* 14 : UART, program SPD EEPROM */
168 NO_AUTOSTART
| NO_READ_IDEEPROM
| CFE_INIT_SAFE
, /* 15 : Safe mode */
171 /* *********************************************************************
172 * board_console_init()
174 * Add the console device and set it to be the primary
182 ********************************************************************* */
184 void board_console_init(void)
189 syscfg
= SBREADCSR(A_SCD_SYSTEM_CFG
);
192 cfe_add_device(&sb1250_uart
,A_DUART
,0,0);
195 * Read the config switch and decide how we are going to set up
196 * the console. This is actually board revision dependent.
198 board_rev
= G_SYS_CONFIG(syscfg
) & 0x3;
199 config_switch
= (G_SYS_CONFIG(syscfg
) >> 2) & 0x0F;
201 cfe_startflags
= board_startflags
[config_switch
];
203 cfe_set_console("uart0");
206 * Set variable that contains CPU speed, spit out config register
209 plldiv
= G_SYS_PLL_DIV(syscfg
);
215 cfe_cpu_speed
= 500000; /* wire func sim at 500KHz */
217 cfe_cpu_speed
= 50000000 * plldiv
; /* use PLL divisor */
221 * NVRAM (environment variables)
224 cfe_add_device(&sb1250_24lc128eeprom
,ENVEEPROM_SMBUS_CHAN
,ENVEEPROM_SMBUS_DEV
,0);
225 cfe_set_envdevice("eeprom0"); /* Connect NVRAM to 24lc128 */
229 /* *********************************************************************
230 * board_smbus_waitready(chan)
232 * Wait until the SMBus channel is ready. We simply poll
233 * the busy bit until it clears.
236 * chan - channel (0 or 1)
240 ********************************************************************* */
241 static int board_smbus_waitready(int chan
)
246 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_STATUS
));
249 status
= SBREADCSR(reg
);
250 if (status
& M_SMB_BUSY
) continue;
254 if (status
& M_SMB_ERROR
) {
256 SBWRITECSR(reg
,(status
& M_SMB_ERROR
));
262 /* *********************************************************************
263 * board_probe_ideeprom(chan,dev)
265 * Probe for an ID EEPROM at the specified device and channel.
267 * Actually, we just probe for anything at this address, and
268 * assume it's an ID EEPROM
271 * chan - SMBus channel
275 * TRUE - device is present
276 * FALSE - not present
277 ********************************************************************* */
279 static int board_probe_ideeprom(int chan
,int slaveaddr
)
286 * Initialize the SMBus channel
289 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_FREQ
));
291 SBWRITECSR(reg
,K_SMB_FREQ_100KHZ
);
293 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_CONTROL
));
295 SBWRITECSR(reg
,0); /* not in direct mode, no interrupts, will poll */
298 * Make sure the bus is idle (probably should
302 if (board_smbus_waitready(chan
) < 0) return FALSE
;
305 * Write the device address to the controller. There are two
306 * parts, the high part goes in the "CMD" field, and the
307 * low part is the data field.
310 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_CMD
));
311 SBWRITECSR(reg
,((devaddr
>> 8) & 0x7));
314 * Write the data to the controller
317 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_DATA
));
318 SBWRITECSR(reg
,((devaddr
& 0xFF) & 0xFF));
324 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_START
));
325 SBWRITECSR(reg
,V_SMB_TT(K_SMB_TT_WR2BYTE
) | slaveaddr
);
331 err
= board_smbus_waitready(chan
);
332 if (err
< 0) return FALSE
;
338 SBWRITECSR(reg
,V_SMB_TT(K_SMB_TT_RD1BYTE
) | slaveaddr
);
340 err
= board_smbus_waitready(chan
);
341 if (err
< 0) return err
;
344 * Probably don't need to read the data, but we'll do it anyway.
347 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_DATA
));
348 err
= SBREADCSR(reg
);
354 /* *********************************************************************
355 * board_device_init()
357 * Initialize and add other devices. Add everything you need
358 * for bootstrap here, like disk drives, flash memory, UARTs,
359 * network controllers, etc.
366 ********************************************************************* */
368 void board_device_init(void)
370 newflash_probe_t fprobe
;
373 * Print out the board version number.
375 printf("%s board revision %d\n", CFG_BOARDNAME
,board_rev
+ 1);
378 * Boot ROM (16MB), using "new" flash driver. Partition the flash.
380 * Partitions are as follows:
383 * 1MB - "fpga" FPGA images
384 * 14MB - "os" Linux boot area
387 memset(&fprobe
,0,sizeof(fprobe
));
388 fprobe
.flash_phys
= BOOTROM_PHYS
;
389 fprobe
.flash_size
= BOOTROM_SIZE
*K64
;
390 fprobe
.flash_flags
= FLASH_FLG_BUS8
| FLASH_FLG_DEV16
;
391 fprobe
.flash_nparts
= 3;
392 fprobe
.flash_parts
[0].fp_size
= 1*1024*1024;
393 fprobe
.flash_parts
[0].fp_name
= "boot";
394 fprobe
.flash_parts
[1].fp_size
= 1*1024*1024;
395 fprobe
.flash_parts
[1].fp_name
= "fpga";
396 fprobe
.flash_parts
[2].fp_size
= 0;
397 fprobe
.flash_parts
[2].fp_name
= "os";
399 cfe_add_device(&newflashdrv
,0,0,&fprobe
);
402 * SPD EEPROM on the Carmel. This is used to store the type of memory
403 * soldered onto the board. [eeprom1]
406 cfe_add_device(&sb1250_at24c02eeprom
,SPDEEPROM_SMBUS_CHAN
,SPDEEPROM_SMBUS_DEV
,0);
409 * EEPROM on the monterey. This is used to identify the host that
410 * the Carmel is plugged into. [eeprom2]
413 if (board_probe_ideeprom(IDEEPROM_SMBUS_CHAN_ALT
,IDEEPROM_SMBUS_DEV
)) {
414 printf("ID EEPROM found at SMBus channel %d device 0x%02x\n",
415 IDEEPROM_SMBUS_CHAN_ALT
,IDEEPROM_SMBUS_DEV
);
416 cfe_add_device(&sb1250_24lc128eeprom
,IDEEPROM_SMBUS_CHAN_ALT
,IDEEPROM_SMBUS_DEV
,0);
417 carmel_envdev
= "eeprom2";
419 else if (board_probe_ideeprom(IDEEPROM_SMBUS_CHAN
,IDEEPROM_SMBUS_DEV
)) {
420 printf("ID EEPROM found at SMBus channel %d device 0x%02x\n",
421 IDEEPROM_SMBUS_CHAN
,IDEEPROM_SMBUS_DEV
);
422 cfe_add_device(&sb1250_24lc128eeprom
,IDEEPROM_SMBUS_CHAN
,IDEEPROM_SMBUS_DEV
,0);
423 carmel_envdev
= "eeprom2";
426 printf("ID EEPROM not found.\n");
427 cfe_startflags
|= NO_READ_IDEEPROM
;
430 if (!(cfe_startflags
& NO_READ_IDEEPROM
)) {
435 * MACs - must init after environment, since the hw address is stored there
437 cfe_add_device(&sb1250_ether
,A_MAC_BASE_0
,0,env_getenv("ETH0_HWADDR"));
443 cfe_add_device(&ns16550_uart
,UART_PHYS
+0,0,NULL
); /* Quad UART channel 0 */
444 cfe_add_device(&ns16550_uart
,UART_PHYS
+8,0,NULL
); /* Quad UART channel 1 */
445 cfe_add_device(&ns16550_uart
,UART_PHYS
+16,0,NULL
); /* Quad UART channel 2 */
446 cfe_add_device(&ns16550_uart
,UART_PHYS
+24,0,NULL
); /* Quad UART channel 3 */
449 * Set variable that contains CPU speed, spit out config register
452 printf("Config switch: %d\n", config_switch
);
458 if (board_startflags
[config_switch
] & IDE_SUPPORT
) {
459 cfe_add_device(&idedrv
,IDE_PHYS
+(0x1F0<<5),
460 IDE_PROBE_MASTER_TYPE(IDE_DEVTYPE_DISK
) |
461 IDE_PROBE_SLAVE_TYPE(IDE_DEVTYPE_NOPROBE
),
466 sb1250_show_cpu_type();
469 * Reset the MAC address for MAC 1, since it's not hooked
472 SBWRITECSR(A_MAC_REGISTER(1,R_MAC_ETHERNET_ADDR
),0);
477 /* *********************************************************************
478 * board_device_reset()
480 * Reset devices. This call is done when the firmware is restarted,
481 * as might happen when an operating system exits, just before the
482 * "reset" command is applied to the installed devices. You can
483 * do whatever board-specific things are here to keep the system
484 * stable, like stopping DMA sources, interrupts, etc.
491 ********************************************************************* */
493 void board_device_reset(void)
496 * Reset the MAC address for MAC 1, since it's not hooked
499 SBWRITECSR(A_MAC_REGISTER(1,R_MAC_ETHERNET_ADDR
),0);
502 /* *********************************************************************
503 * program_spd_eeprom()
505 * Program the Atmel eeprom with SPD definitions
513 ********************************************************************* */
515 static int program_spd_eeprom(void)
517 unsigned char spd
[JEDEC_SPD_MAX
];
521 memset(spd
,0,JEDEC_SPD_MAX
);
524 * 128MB (STAKTEK: 256MB) on MC 1 (JEDEC SDRAM)
525 * Samsung K4H561638B - 16Mx16 chips
527 * Minimum tMEMCLK: 8.0ns (125Mhz max freq)
529 * CS0 Geometry: 13 rows, 9 columns, 2 bankbits
531 * 64khz refresh, CAS Latency 2.5
532 * Timing (ns): tCK=7.50 tRAS=45 tRP=20.00 tRRD=15.0 tRCD=20.0 tRFC=auto tRC=auto
534 * Clock Config: Default
537 spd
[JEDEC_SPD_MEMTYPE
] = JEDEC_MEMTYPE_DDRSDRAM2
;
538 spd
[JEDEC_SPD_ROWS
] = 0x0D;
539 spd
[JEDEC_SPD_COLS
] = 0x09;
540 spd
[JEDEC_SPD_BANKS
] = 0x04;
542 #if !defined(_CARMEL_STAKTEK_)
543 spd
[JEDEC_SPD_SIDES
] = 0x01;
545 spd
[JEDEC_SPD_SIDES
] = 0x02;
548 spd
[JEDEC_SPD_WIDTH
] = 0x48;
550 spd
[JEDEC_SPD_tCK25
] = 0x75;
551 spd
[JEDEC_SPD_tCK20
] = 0x00;
552 spd
[JEDEC_SPD_tCK10
] = 0x00;
553 spd
[JEDEC_SPD_RFSH
] = 0x82;
554 spd
[JEDEC_SPD_CASLATENCIES
] = 0x08;
555 spd
[JEDEC_SPD_ATTRIBUTES
] = 0x00;
556 spd
[JEDEC_SPD_tRAS
] = 0x2D;
557 spd
[JEDEC_SPD_tRP
] = 0x50;
558 spd
[JEDEC_SPD_tRRD
] = 0x3C;
559 spd
[JEDEC_SPD_tRCD
] = 0x50;
560 spd
[JEDEC_SPD_tRFC
] = 0x00;
561 spd
[JEDEC_SPD_tRC
] = 0x00;
563 fh
= cfe_open("eeprom1");
565 xprintf("Could not open device: %s\n",cfe_errortext(fh
));
566 xprintf("SPD EEPROM IS NOT PROGRAMMED\n");
570 res
= cfe_writeblk(fh
,0,spd
,JEDEC_SPD_MAX
);
571 if (res
!= JEDEC_SPD_MAX
) {
572 xprintf("Could not write to device: %s\n",cfe_errortext(fh
));
573 xprintf("SPD EEPROM IS NOT PROGRAMMED\n");
578 xprintf("SPD EEPROM programmed at SMBus chan: %d addr: 0x%x\n\n",SPDEEPROM_SMBUS_CHAN
,
579 SPDEEPROM_SMBUS_DEV
);
586 /* *********************************************************************
587 * set_display_standalone(arg)
588 * set_display_connected(arg)
590 * Set 'C F E' on the 7-seg display.
591 * Set rotating pattern.
598 ********************************************************************* */
600 static int64_t timer
;
601 static int blinky_state
= 0;
603 #define CFE_BLINKIE_TIMER (CFE_HZ/2)
604 static uint8_t cfe_blinkies
[4] = {0x8C,0x1C,0x0C,0xFF};
606 #define BLINKIE_TIMER (CFE_HZ/4)
607 static uint8_t blinkies
[3] = {
610 ~( (1<<3) | (1<<6))};
613 #define SETDISPLAY(x) board_setdisplay(x)
614 static void set_display_standalone(void *arg
)
617 if (TIMER_EXPIRED(timer
)) {
618 SETDISPLAY(cfe_blinkies
[blinky_state
]);
619 TIMER_SET(timer
,CFE_BLINKIE_TIMER
);
621 if (blinky_state
>= 4) blinky_state
= 0;
626 static void set_display_connected(void *arg
)
629 if (TIMER_EXPIRED(timer
)) {
630 SETDISPLAY(blinkies
[blinky_state
]);
631 TIMER_SET(timer
,BLINKIE_TIMER
);
633 if (blinky_state
>= 3) blinky_state
= 0;
638 /* *********************************************************************
639 * board_setup_autoboot()
641 * Set up autoboot methods. This routine sets up the list of
642 * places to find a boot program.
649 ********************************************************************* */
650 static void board_setup_autoboot(void)
653 * Uncomment to try IDE. We leave this disabled for now due
654 * to the long timeout if you don't have an IDE disk connected.
657 if (board_startflags
[config_switch
] & IDE_BOOT
) {
658 cfe_add_autoboot(CFE_AUTOBOOT_DISK
,0,"ide0.0","raw","raw",NULL
);
662 * If you had partitioned your flash, you could boot from it like this:
665 /* cfe_add_autoboot(CFE_AUTOBOOT_RAW,0,"flash0.os","elf","raw",NULL); */
668 * Now try running a script (file containing CFE commands) from
669 * the TFTP server. Your DHCP server must set option 130
670 * to contain the name of the script. Option 130 gets stored
671 * in "BOOT_SCRIPT" when a DHCP reply is received.
674 cfe_add_autoboot(CFE_AUTOBOOT_NETWORK
,LOADFLG_BATCH
,
675 "eth0","raw","tftp","$BOOT_SERVER:$BOOT_SCRIPT");
678 * Finally, try loading whatever the DHCP server says is the boot
679 * program. Do this as an ELF file, and failing that, try a
683 cfe_add_autoboot(CFE_AUTOBOOT_NETWORK
,0,"eth0","elf","tftp",NULL
);
684 cfe_add_autoboot(CFE_AUTOBOOT_NETWORK
,0,"eth0","raw","tftp",NULL
);
689 /* *********************************************************************
692 * Do stuff we do when Carmels start up
699 ********************************************************************* */
700 int carmel_startup(void)
705 fpgaload
= carmel_getenv("M_FPGALOAD");
707 if (fpgaload
&& (strcmp(fpgaload
,"YES") == 0)) {
708 res
= ui_docommand("xload");
709 if (res
!= 0) printf("Failed to load FPGA on main board.\n");
710 else printf("FPGA loaded successfully.\n");
716 /* *********************************************************************
719 * Do any final initialization, such as adding commands to the
722 * If you don't want a user interface, put the startup code here.
723 * This routine is called just before CFE starts its user interface.
730 ********************************************************************* */
732 void board_final_init(void)
736 ui_init_carmelcmds();
741 ui_init_memtestcmds();
743 ui_init_ethertestcmds();
744 ui_init_flashtestcmds();
745 ui_init_disktestcmds();
747 ui_init_uarttestcmds();
751 * If Carmel is connected, display rotating pattern. If standalone, display CFE
753 fh
= cfe_open("eeprom2");
755 cfe_bg_add(set_display_standalone
,NULL
);
758 cfe_bg_add(set_display_connected
,NULL
);
761 TIMER_SET(timer
,CFE_HZ
);
766 if (cfe_startflags
& PROGRAM_SPD
) {
767 program_spd_eeprom();
774 board_setup_autoboot();
780 if (!(cfe_startflags
& NO_AUTOSTART
)) {
783 if(cfe_startflags
& AUTOBOOT
) {