/*
|
/*
|
* SD/MMC card bootloader for OR1k SoC
|
* SD/MMC card bootloader for OR1k SoC
|
*
|
*
|
* Copyright (c) 2008 by:
|
* Copyright (c) 2008 by:
|
* Xianfeng Zeng <xianfeng.zeng@gmail.com, Xianfeng.zeng@SierraAtlantic.com>
|
* Xianfeng Zeng <xianfeng.zeng@gmail.com, Xianfeng.zeng@SierraAtlantic.com>
|
*
|
*
|
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
* it under the terms of the BSD Licence, GNU General Public License
|
* it under the terms of the BSD Licence, GNU General Public License
|
* as published by the Free Software Foundation; either version 2 of the
|
* as published by the Free Software Foundation; either version 2 of the
|
* License, or (at your option) any later version
|
* License, or (at your option) any later version
|
*
|
*
|
* ChangeLog:
|
* ChangeLog:
|
* 2009-10-05 12:56:55 xzeng
|
* 2009-10-05 12:56:55 xzeng
|
* Init.
|
* Init.
|
*
|
*
|
*/
|
*/
|
|
|
|
|
#define INCLUDED_FROM_C_FILE
|
#define INCLUDED_FROM_C_FILE
|
|
|
#include "orsocdef.h"
|
#include "orsocdef.h"
|
#include "board.h"
|
#include "board.h"
|
|
|
|
|
#define DEBUG 1
|
#define DEBUG 1
|
|
|
#define barrier() __asm__ __volatile__("": : :"memory")
|
#define barrier() __asm__ __volatile__("": : :"memory")
|
|
|
#ifdef DEBUG
|
#ifdef DEBUG
|
void putc(int c)
|
void or1k_putc(int c)
|
{
|
{
|
while ( 0x20 != (REG8(UART_BASE_ADD+5) & 0x20) )
|
while ( 0x20 != (REG8(UART_BASE_ADD+5) & 0x20) )
|
;
|
;
|
|
|
REG8(UART_BASE_ADD) = c;
|
REG8(UART_BASE_ADD) = c;
|
}
|
}
|
|
|
void print(unsigned char *c)
|
void print(unsigned char *c)
|
{
|
{
|
uint32 i;
|
uint32 i;
|
|
|
if (c == NULL)
|
if (c == NULL)
|
return;
|
return;
|
|
|
for (i = 0; c[i] != 0; i++) {
|
for (i = 0; c[i] != 0; i++) {
|
putc(c[i]);
|
or1k_putc(c[i]);
|
}
|
}
|
}
|
}
|
|
|
void print32bit (long unsigned int val)
|
void print32bit (long unsigned int val)
|
{
|
{
|
int i;
|
int i;
|
unsigned long int myNibble;
|
unsigned long int myNibble;
|
char myChar;
|
char myChar;
|
|
|
for (i=0;i<8;i++) {
|
for (i=0;i<8;i++) {
|
myNibble = (val >> 28) & 0xfUL;
|
myNibble = (val >> 28) & 0xfUL;
|
if (myNibble <= 0x9)
|
if (myNibble <= 0x9)
|
myChar = (char) myNibble + 0x30;
|
myChar = (char) myNibble + 0x30;
|
else
|
else
|
myChar = (char) myNibble + 0x37;
|
myChar = (char) myNibble + 0x37;
|
putc (myChar);
|
or1k_putc (myChar);
|
val = val << 4;
|
val = val << 4;
|
}
|
}
|
putc ('\n');
|
or1k_putc ('\n');
|
putc ('\r');
|
or1k_putc ('\r');
|
}
|
}
|
|
|
|
|
#else
|
#else
|
#define putc(a)
|
#define or1k_putc(a)
|
#define print(a)
|
#define print(a)
|
#endif
|
#endif
|
|
|
|
|
void do_sleep()
|
void do_sleep()
|
{
|
{
|
uint32 i;
|
uint32 i;
|
for (i = 0; i < 200000; i++)
|
for (i = 0; i < 200000; i++)
|
;
|
;
|
}
|
}
|
|
|
void do_sleep2()
|
void do_sleep2()
|
{
|
{
|
uint32 i;
|
uint32 i;
|
for (i = 0; i < 1000; i++)
|
for (i = 0; i < 1000; i++)
|
;
|
;
|
}
|
}
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/* G P I O W R I T E */
|
/* G P I O W R I T E */
|
/******************************************************************************/
|
/******************************************************************************/
|
|
|
// Write to the GPIO (32 bits)
|
// Write to the GPIO (32 bits)
|
|
|
void GPIO_Write(uint32 GPIO_data)
|
void GPIO_Write(uint32 GPIO_data)
|
{
|
{
|
REG32(GPIO_BASE + RGPIO_OUT) = GPIO_data;
|
REG32(GPIO_BASE + RGPIO_OUT) = GPIO_data;
|
}
|
}
|
|
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/* F O R s p i M A S T E R */
|
/* F O R s p i M A S T E R */
|
/******************************************************************************/
|
/******************************************************************************/
|
|
|
//Initialize
|
//Initialize
|
int spiMaster_init()
|
int spiMaster_init()
|
{
|
{
|
uint8 data;
|
uint8 data;
|
int i;
|
int i;
|
|
|
REG8(SD_BASE_ADD + SD_CLK_DEL_REG) = 0x1;
|
REG8(SD_BASE_ADD + SD_CLK_DEL_REG) = 0x1;
|
|
|
for (i = 0; i < 5; i++) {
|
for (i = 0; i < 5; i++) {
|
REG8(SD_BASE_ADD + SD_TRANS_TYPE_REG) = SD_INIT_SD;
|
REG8(SD_BASE_ADD + SD_TRANS_TYPE_REG) = SD_INIT_SD;
|
REG8(SD_BASE_ADD + SD_TRANS_CTRL_REG) = 1; // TRANS_START;
|
REG8(SD_BASE_ADD + SD_TRANS_CTRL_REG) = 1; // TRANS_START;
|
|
|
do_sleep();
|
do_sleep();
|
|
|
while (REG8(SD_BASE_ADD + SD_TRANS_STS_REG) & 0x1) { // exit while !TRABS_BUSY
|
while (REG8(SD_BASE_ADD + SD_TRANS_STS_REG) & 0x1) { // exit while !TRABS_BUSY
|
;
|
;
|
}
|
}
|
|
|
data = REG8(SD_BASE_ADD + SD_TRANS_ERROR_REG) & 0x3;
|
data = REG8(SD_BASE_ADD + SD_TRANS_ERROR_REG) & 0x3;
|
|
|
if (data == 0) {
|
if (data == 0) {
|
return 0;
|
return 0;
|
}
|
}
|
}
|
}
|
return data;
|
return data;
|
}
|
}
|
|
|
unsigned char data[512];
|
unsigned char data[512];
|
|
|
int copy_sd2ddr(void)
|
int copy_sd2ddr(void)
|
{
|
{
|
|
|
int i, j;
|
int i, j;
|
uint8 data;
|
uint8 data;
|
unsigned char transError;
|
unsigned char transError;
|
|
|
uint32 blockCnt;
|
uint32 blockCnt;
|
uint32 numBlocks = 2 * 1024 * 10; // How mang blocks will be copied
|
uint32 numBlocks = 2 * 1024 * 10; // How mang blocks will be copied
|
|
|
uint32 ddr_offset = 0;
|
uint32 ddr_offset = 0;
|
|
|
print("Start copying SD image to DDR SDRAM...\n\r");
|
print("\n\r");
|
|
print("Copying SD image to DDR SDRAM...\n\r");
|
print("Blocks:");
|
print("Blocks:");
|
print32bit((long unsigned int)numBlocks);
|
print32bit((long unsigned int)numBlocks);
|
|
|
for (blockCnt = 0; blockCnt < numBlocks; blockCnt++) {
|
for (blockCnt = 0; blockCnt < numBlocks; blockCnt++) {
|
REG8(SD_BASE_ADD + SD_ADDR_7_0_REG) = 0;
|
REG8(SD_BASE_ADD + SD_ADDR_7_0_REG) = 0;
|
REG8(SD_BASE_ADD + SD_ADDR_15_8_REG) = (unsigned char) ((ddr_offset >> 8) & 0xff);
|
REG8(SD_BASE_ADD + SD_ADDR_15_8_REG) = (unsigned char) ((ddr_offset >> 8) & 0xff);
|
REG8(SD_BASE_ADD + SD_ADDR_23_16_REG) = (unsigned char) ((ddr_offset >> 16) & 0xff);
|
REG8(SD_BASE_ADD + SD_ADDR_23_16_REG) = (unsigned char) ((ddr_offset >> 16) & 0xff);
|
REG8(SD_BASE_ADD + SD_ADDR_31_24_REG) = (unsigned char) ((ddr_offset >> 24) & 0xff);
|
REG8(SD_BASE_ADD + SD_ADDR_31_24_REG) = (unsigned char) ((ddr_offset >> 24) & 0xff);
|
|
|
|
|
REG8(SD_BASE_ADD + SD_TRANS_TYPE_REG) = SD_RW_READ_SD_BLOCK;
|
REG8(SD_BASE_ADD + SD_TRANS_TYPE_REG) = SD_RW_READ_SD_BLOCK;
|
REG8(SD_BASE_ADD + SD_RX_FIFO_CONTROL_REG) = 0x1; // Clean the RX FIFO
|
REG8(SD_BASE_ADD + SD_RX_FIFO_CONTROL_REG) = 0x1; // Clean the RX FIFO
|
REG8(SD_BASE_ADD + SD_TRANS_CTRL_REG) = 0x1; //TRANS_START
|
REG8(SD_BASE_ADD + SD_TRANS_CTRL_REG) = 0x1; //TRANS_START
|
while (REG8(SD_BASE_ADD + SD_TRANS_STS_REG) & 0x1) { // exit while !TRABS_BUSY
|
while (REG8(SD_BASE_ADD + SD_TRANS_STS_REG) & 0x1) { // exit while !TRABS_BUSY
|
;
|
;
|
}
|
}
|
|
|
transError = REG8(SD_BASE_ADD + SD_TRANS_ERROR_REG) & 0xc;
|
transError = REG8(SD_BASE_ADD + SD_TRANS_ERROR_REG) & 0xc;
|
if ( transError == SD_READ_NO_ERROR) {
|
if ( transError == SD_READ_NO_ERROR) {
|
for (i = 0; i < 512; i++) {
|
for (i = 0; i < 512; i++) {
|
data = REG8(SD_BASE_ADD + SD_RX_FIFO_DATA_REG) ;
|
data = REG8(SD_BASE_ADD + SD_RX_FIFO_DATA_REG) ;
|
REG8(DDR_SDRAM_BASE_ADDR + ddr_offset + i) = data ;
|
REG8(DDR_SDRAM_BASE_ADDR + ddr_offset + i) = data ;
|
// print32bit((long unsigned int)data);
|
// print32bit((long unsigned int)data);
|
}
|
}
|
if ((blockCnt % 0x40) == 0) {
|
if ((blockCnt % 0x40) == 0) {
|
putc('.');
|
or1k_putc('.');
|
j++;
|
j++;
|
}
|
}
|
if (j == 20) {
|
if (j == 20) {
|
j = 0;
|
j = 0;
|
print("\n\r");
|
print("\n\r");
|
}
|
}
|
|
|
ddr_offset += 512;
|
ddr_offset += 512;
|
} else {
|
} else {
|
putc('R');
|
or1k_putc('R');
|
j++;
|
j++;
|
if (j == 20) {
|
if (j == 20) {
|
j = 0;
|
j = 0;
|
print("\n\r");
|
print("\n\r");
|
}
|
}
|
spiMaster_init(); // Init again and retry
|
spiMaster_init(); // Init again and retry
|
blockCnt--; // read the same block again
|
blockCnt--; // read the same block again
|
}
|
}
|
}
|
}
|
|
|
print("\r\nSD Copy Done!\n\r");
|
print("\r\nSD Copy Done!\n\r");
|
}
|
}
|
|
|
|
|
/******************************************************************************/
|
/******************************************************************************/
|
/* TEST EXTERNAL DDR SDRAM */
|
/* TEST EXTERNAL DDR SDRAM */
|
/******************************************************************************/
|
/******************************************************************************/
|
|
|
void ddr_sdram_sample_test()
|
void ddr_sdram_sample_test()
|
{
|
{
|
uint32 int32;
|
uint32 int32;
|
uint16 int16;
|
uint16 int16;
|
uint8 int8;
|
uint8 int8;
|
int i;
|
int i;
|
|
|
REG32(DDR_SDRAM_BASE_ADDR) = 0x12345678;
|
REG32(DDR_SDRAM_BASE_ADDR) = 0x12345678;
|
int32 = REG32(DDR_SDRAM_BASE_ADDR);
|
int32 = REG32(DDR_SDRAM_BASE_ADDR);
|
|
|
REG16(DDR_SDRAM_BASE_ADDR + 10) = 0x55aa;
|
REG16(DDR_SDRAM_BASE_ADDR + 10) = 0x55aa;
|
int16 = REG16(DDR_SDRAM_BASE_ADDR + 10);
|
int16 = REG16(DDR_SDRAM_BASE_ADDR + 10);
|
|
|
REG8(DDR_SDRAM_BASE_ADDR + 20) = 0x5a;
|
REG8(DDR_SDRAM_BASE_ADDR + 20) = 0x5a;
|
int8 = REG8(DDR_SDRAM_BASE_ADDR + 20);
|
int8 = REG8(DDR_SDRAM_BASE_ADDR + 20);
|
|
|
if (REG8(DDR_SDRAM_BASE_ADDR + 20) != 0x5a)
|
if (REG8(DDR_SDRAM_BASE_ADDR + 20) != 0x5a)
|
print ("DDR SDRAM accesses short type Error:20!\n\r");
|
print ("DDR SDRAM accesses short type Error:20!\n\r");
|
|
|
REG8(DDR_SDRAM_BASE_ADDR + 100) = 0x12;
|
REG8(DDR_SDRAM_BASE_ADDR + 100) = 0x12;
|
REG8(DDR_SDRAM_BASE_ADDR + 101) = 0x34;
|
REG8(DDR_SDRAM_BASE_ADDR + 101) = 0x34;
|
REG8(DDR_SDRAM_BASE_ADDR + 102) = 0x56;
|
REG8(DDR_SDRAM_BASE_ADDR + 102) = 0x56;
|
REG8(DDR_SDRAM_BASE_ADDR + 103) = 0x78;
|
REG8(DDR_SDRAM_BASE_ADDR + 103) = 0x78;
|
|
|
int32 = REG32(DDR_SDRAM_BASE_ADDR + 100);
|
int32 = REG32(DDR_SDRAM_BASE_ADDR + 100);
|
|
|
if (REG8(DDR_SDRAM_BASE_ADDR + 100) != 0x12)
|
if (REG8(DDR_SDRAM_BASE_ADDR + 100) != 0x12)
|
print ("DDR SDRAM accesses char type Error:100!\n\r");
|
print ("DDR SDRAM accesses char type Error:100!\n\r");
|
if (REG8(DDR_SDRAM_BASE_ADDR + 101) != 0x34)
|
if (REG8(DDR_SDRAM_BASE_ADDR + 101) != 0x34)
|
print ("DDR SDRAM accesses char type Error:101!\n\r");
|
print ("DDR SDRAM accesses char type Error:101!\n\r");
|
if (REG8(DDR_SDRAM_BASE_ADDR + 102) != 0x56)
|
if (REG8(DDR_SDRAM_BASE_ADDR + 102) != 0x56)
|
print ("DDR SDRAM accesses char type Error:102!\n\r");
|
print ("DDR SDRAM accesses char type Error:102!\n\r");
|
if (REG8(DDR_SDRAM_BASE_ADDR + 103) != 0x78)
|
if (REG8(DDR_SDRAM_BASE_ADDR + 103) != 0x78)
|
print ("DDR SDRAM accesses char type Error:103!\n\r");
|
print ("DDR SDRAM accesses char type Error:103!\n\r");
|
|
|
for (i=0;i<64;i++) {
|
for (i=0;i<64;i++) {
|
REG8(DDR_SDRAM_BASE_ADDR + i) = i;
|
REG8(DDR_SDRAM_BASE_ADDR + i) = i;
|
}
|
}
|
|
|
for (i=0;i<64;i++) {
|
for (i=0;i<64;i++) {
|
REG8(0x3900+i) = REG8(DDR_SDRAM_BASE_ADDR + i);
|
REG8(0x3900+i) = REG8(DDR_SDRAM_BASE_ADDR + i);
|
}
|
}
|
|
|
print ("DDR SDRAM sample test done.\n\r");
|
print ("DDR SDRAM sample test done.\n\r");
|
}
|
}
|
|
|
|
|
/*$$EXTERNAL EXEPTIONS*/
|
/*$$EXTERNAL EXEPTIONS*/
|
/******************************************************************************/
|
/******************************************************************************/
|
/* E X T E R N A L E X E P T I O N S */
|
/* E X T E R N A L E X E P T I O N S */
|
/******************************************************************************/
|
/******************************************************************************/
|
|
|
void external_exeption()
|
void external_exeption()
|
{
|
{
|
REG uint8 i;
|
REG uint8 i;
|
REG uint32 PicSr,sr;
|
REG uint32 PicSr,sr;
|
}
|
}
|
|
|
|
|
/*$$MAIN*/
|
/*$$MAIN*/
|
/******************************************************************************/
|
/******************************************************************************/
|
/* */
|
/* */
|
/* M A I N P R O G R A M */
|
/* M A I N P R O G R A M */
|
/* */
|
/* */
|
/******************************************************************************/
|
/******************************************************************************/
|
|
|
void Start()
|
void Start()
|
{
|
{
|
uint32 i;
|
uint32 i;
|
uint8 str[9];
|
uint8 str[9];
|
|
|
// Configure GPIO
|
// Configure GPIO
|
REG32(GPIO_BASE + RGPIO_OE) = 0xff; // bit0-7 = outputs, bit8-31 = inputs
|
REG32(GPIO_BASE + RGPIO_OE) = 0xff; // bit0-7 = outputs, bit8-31 = inputs
|
REG32(GPIO_BASE + RGPIO_INTE) = 0x0; // Disable interrupts from GPIO
|
REG32(GPIO_BASE + RGPIO_INTE) = 0x0; // Disable interrupts from GPIO
|
|
|
print("\n\r\n\t");
|
print("\n\r\n\t");
|
print("==OpenRisc 1200 SOC==\n\r\n");
|
print("==OpenRisc 1200 SOC==\n\r\n");
|
GPIO_Write(~0x0);
|
GPIO_Write(~0x0);
|
|
|
print("\n\r");
|
print("\n\r");
|
|
|
print("SD Card Bootloader, v0.2\n\r");
|
print("SD Card Bootloader, v0.2\n\r");
|
print("Xianfeng Zeng, 2009 SA\n\r");
|
print("Xianfeng Zeng, 2009 SA\n\r");
|
print("Xianfeng@opencores.org\n\r");
|
print("Xianfeng@opencores.org\n\r");
|
print("http://www.opencores.org/project,or1k_soc_on_altera_embedded_dev_kit\n\r");
|
print("http://www.opencores.org/project,or1k_soc_on_altera_embedded_dev_kit\n\r");
|
|
|
print("\n\r");
|
print("\n\r");
|
|
|
print("System Clock: 30MHz\n\r\n");
|
print("System Clock: 30MHz\n\r\n");
|
|
|
print("DDR SDRAM Base Address: 0x00000000 - 32MB\n\r");
|
print("DDR SDRAM Base Address: 0x00000000 - 32MB\n\r");
|
print("Ethernet Base Address: 0x20000000 IRQ 4\n\r");
|
print("Ethernet Base Address: 0x20000000 IRQ 4\n\r");
|
print("UART Base Address: 0x30000000 IRQ 2\n\r");
|
print("UART Base Address: 0x30000000 IRQ 2\n\r");
|
print("GPIO Base Address: 0x40000000 IRQ 3\n\r");
|
print("GPIO Base Address: 0x40000000 IRQ 3\n\r");
|
print("SD Card Base Address: 0x50000000\n\r");
|
print("SD Card Base Address: 0x50000000\n\r");
|
print("SRAM Base Address: 0xF0000000 - 16KB\n\r");
|
print("SRAM Base Address: 0xF0000000 - 16KB\n\r");
|
print("\r\n\n");
|
print("\r\n\n");
|
|
|
|
|
print("Init SD Card:");
|
print("Init SD Card:");
|
REG8(SD_BASE_ADD + SD_TRANS_CTRL_REG) = 0x1; /* reset spiMaster */
|
REG8(SD_BASE_ADD + SD_TRANS_CTRL_REG) = 0x1; /* reset spiMaster */
|
do_sleep();
|
do_sleep();
|
REG8(SD_BASE_ADD + SD_TRANS_CTRL_REG) = 0x0;
|
REG8(SD_BASE_ADD + SD_TRANS_CTRL_REG) = 0x0;
|
if (spiMaster_init() == 0) {
|
if (spiMaster_init() == 0) {
|
print("Passed!\n\r");
|
print("Passed!\n\r");
|
} else {
|
} else {
|
print("Failed!\n\r");
|
print("Failed!\n\r");
|
}
|
}
|
|
|
ddr_sdram_sample_test();
|
ddr_sdram_sample_test();
|
copy_sd2ddr();
|
copy_sd2ddr();
|
|
|
GPIO_Write(~0x1);
|
GPIO_Write(~0x1);
|
|
|
print("\n\r");
|
print("\n\r");
|
|
|
print("Jump to DDR SDRAM: 0x100\n\r");
|
print("Jump to DDR SDRAM: 0x100\n\r");
|
jumpToRAM();
|
jumpToRAM();
|
|
|
print("Should not get here!!:\n\r");
|
print("Should not get here!!:\n\r");
|
while(TRUE) {
|
while(TRUE) {
|
do_sleep();
|
do_sleep();
|
putc('.');
|
or1k_putc('.');
|
GPIO_Write(~0x0); // Test finished
|
GPIO_Write(~0x0); // Test finished
|
do_sleep();
|
do_sleep();
|
GPIO_Write(~0x1);
|
GPIO_Write(~0x1);
|
do_sleep();
|
do_sleep();
|
GPIO_Write(~0x2);
|
GPIO_Write(~0x2);
|
do_sleep();
|
do_sleep();
|
GPIO_Write(~0x4);
|
GPIO_Write(~0x4);
|
do_sleep();
|
do_sleep();
|
GPIO_Write(~0x8);
|
GPIO_Write(~0x8);
|
|
|
if (i == 39) {
|
if (i == 39) {
|
print("\n\r");
|
print("\n\r");
|
i = 0;
|
i = 0;
|
} else
|
} else
|
i++;
|
i++;
|
}
|
}
|
}
|
}
|
|
|
|
|