Basic SDRAM runtime lib, software working without SRAM
authorlekernel <sebastien.bourdeauducq@lekernel.net>
Mon, 17 May 2010 15:54:05 +0000 (17:54 +0200)
committerlekernel <sebastien.bourdeauducq@lekernel.net>
Mon, 17 May 2010 15:54:05 +0000 (17:54 +0200)
20 files changed:
build_bios.sh
software/bios/Makefile
software/bios/boot.c
software/bios/crt0.S
software/bios/linker.ld
software/bios/main.c
software/bios/splash.c
software/bios/splash.h
software/include/base/irq.h
software/include/hal/time.h
software/include/hw/interrupts.h
software/include/hw/sram.h [deleted file]
software/include/net/microudp.h
software/libbase/irq.S
software/libhal/Makefile
software/libhal/mem.c
software/libhpdmc/libhpdmc.S
software/libhpdmc/test.S
software/libnet/Makefile
software/libnet/microudp.c

index 5767c1d..d4ff941 100755 (executable)
@@ -25,6 +25,16 @@ else
 fi
 
 echo "Building embedded software :"
+echo -n "  HPDMC runtime..."
+echo >> $LOGFILE
+date >> $LOGFILE
+cd $BASEDIR/software/libhpdmc && make >> $LOGFILE 2>&1
+if [ "$?" != 0 ] ; then
+        echo "FAILED"
+       exit 1
+else
+        echo "OK"
+fi
 echo -n "  Base library..."
 echo >> $LOGFILE
 date >> $LOGFILE
index fcf855f..238016e 100644 (file)
@@ -11,8 +11,8 @@ all: bios_splash.bin
        chmod -x $@
        $(MMDIR)/tools/crc32 $@ write
 
-bios.elf: linker.ld $(OBJECTS) $(MMDIR)/software/libbase/libbase-light.a $(MMDIR)/software/libnet/libnet.a
-       $(LD) $(LDFLAGS) -T linker.ld -N -o $@ $(OBJECTS) -L$(MMDIR)/software/libbase -L$(MMDIR)/software/libnet -lbase-light -lnet
+bios.elf: linker.ld $(OBJECTS) $(MMDIR)/software/libhpdmc/libhpdmc.a $(MMDIR)/software/libbase/libbase-light.a $(MMDIR)/software/libnet/libnet.a
+       $(LD) $(LDFLAGS) -T linker.ld -N -o $@ $(OBJECTS) -L$(MMDIR)/software/libhpdmc -L$(MMDIR)/software/libbase -L$(MMDIR)/software/libnet -lhpdmc -lbase-light -lnet
        chmod -x $@
 
 splash.raw: splash.png
@@ -53,12 +53,12 @@ main.o: ../../software/include/base/cffat.h ../../software/include/base/crc.h
 main.o: ../../software/include/base/system.h
 main.o: ../../software/include/base/board.h
 main.o: ../../software/include/base/version.h
-main.o: ../../software/include/net/mdio.h ../../software/include/hw/hpdmc.h
-main.o: ../../software/include/hw/common.h ../../software/include/hw/vga.h
-main.o: ../../software/include/hw/fmlbrg.h ../../software/include/hw/sysctl.h
+main.o: ../../software/include/net/mdio.h ../../software/include/hw/vga.h
+main.o: ../../software/include/hw/common.h ../../software/include/hw/fmlbrg.h
+main.o: ../../software/include/hw/sysctl.h
 main.o: ../../software/include/hw/capabilities.h
 main.o: ../../software/include/hw/gpio.h ../../software/include/hw/uart.h
-main.o: boot.h splash.h
+main.o: ../../software/include/hw/hpdmc.h boot.h splash.h
 splash.o: ../../software/include/base/stdio.h
 splash.o: ../../software/include/base/stdlib.h
 splash.o: ../../software/include/hw/vga.h ../../software/include/hw/common.h
index f4c40e6..0007c42 100644 (file)
@@ -215,6 +215,8 @@ static int tftp_get_v(unsigned int ip, const char *filename, char *buffer)
        return r;
 }
 
+static char microudp_buf[MICROUDP_BUFSIZE];
+
 void netboot()
 {
        int size;
@@ -228,7 +230,7 @@ void netboot()
 
        ip = IPTOINT(REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4);
        
-       microudp_start(macadr, IPTOINT(LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4), (void *)(SDRAM_BASE+1024*1024*(brd_desc->sdram_size-2)));
+       microudp_start(macadr, IPTOINT(LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4), microudp_buf);
        
        if(tftp_get_v(ip, "boot.bin", (void *)SDRAM_BASE) <= 0) {
                printf("E: Network boot failed\n");
index 470336e..e3ca93b 100644 (file)
 .global     _start
 _start:
 _reset_handler:
-       xor     r0, r0, r0
-       wcsr    IE, r0
-       mvhi    r1, hi(_reset_handler)
-       ori     r1, r1, lo(_reset_handler)
-       wcsr    EBA, r1
+       xor     r0, r0, r0
+       wcsr    IE, r0
+       mvhi    r1, hi(_reset_handler)
+       ori     r1, r1, lo(_reset_handler)
+       wcsr    EBA, r1
+       calli   _sdram_init
        xor     r2, r2, r2
-       calli   _crt0
-       nop
+       calli   _crt0
 
 _breakpoint_handler:
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
+       nop; nop; nop; nop
+       nop; nop; nop; nop
 
 _instruction_bus_error_handler:
        nop; nop; nop; nop
@@ -88,7 +82,7 @@ _crt0:
        sw      (r1+0), r0
        addi    r1, r1, 4
        bi      .clearBSS
-       
+
 .callMain:
        mv      r1, r2
        mvi     r2, 0
index 50f8ff4..d2345d5 100644 (file)
@@ -5,8 +5,7 @@ __DYNAMIC = 0;
 
 MEMORY {
        flash : ORIGIN = 0x00000000, LENGTH = 0x800000   /* 8M */
-       sram  : ORIGIN = 0x20000000, LENGTH = 0x1000     /* 4k */
-       sdram : ORIGIN = 0x40000000, LENGTH = 0x4000000  /* 64M */
+       sdram : ORIGIN = 0x42000000, LENGTH = 0x2000000  /* use the upper 32M of the SDRAM */
 }
 
 SECTIONS
@@ -27,6 +26,7 @@ SECTIONS
                _erodata = .;
        } > flash
 
+       /* We shouldn't have a .data section, however the GNU crapchain whines if we don't */
        .data :
        {
                . = ALIGN(4);
@@ -50,8 +50,8 @@ SECTIONS
                *(COMMON)
                _ebss = .;
                _end = .;
-       } > sram
+       } > sdram
 }
 
-PROVIDE(_fstack = ORIGIN(sram) + LENGTH(sram) - 4);
+PROVIDE(_fstack = ORIGIN(sdram) + LENGTH(sdram) - 4);
 
index 71aadb6..75a301b 100644 (file)
 #include <board.h>
 #include <version.h>
 #include <net/mdio.h>
-#include <hw/hpdmc.h>
 #include <hw/vga.h>
 #include <hw/fmlbrg.h>
 #include <hw/sysctl.h>
 #include <hw/capabilities.h>
 #include <hw/gpio.h>
 #include <hw/uart.h>
+#include <hw/hpdmc.h>
 
 #include "boot.h"
 #include "splash.h"
 
 const struct board_desc *brd_desc;
 
-/* SDRAM functions */
-
-static int dqs_ps;
-
-static void ddrinit()
-{
-       volatile unsigned int i;
-
-       putsnonl("I: Initializing SDRAM [DDR200 CL=2 BL=8]...");
-       /* Bring CKE high */
-       CSR_HPDMC_SYSTEM = HPDMC_SYSTEM_BYPASS|HPDMC_SYSTEM_RESET|HPDMC_SYSTEM_CKE;
-       for(i=0;i<2;i++);
-       CSR_HPDMC_BYPASS = 0x400B;      /* Precharge All */
-       for(i=0;i<2;i++);
-       CSR_HPDMC_BYPASS = 0x2000F;     /* Load Extended Mode Register */
-       for(i=0;i<2;i++);
-       CSR_HPDMC_BYPASS = 0x123F;      /* Load Mode Register */
-       for(i=0;i<200;i++);
-       CSR_HPDMC_BYPASS = 0x400B;      /* Precharge All */
-       for(i=0;i<2;i++);
-       CSR_HPDMC_BYPASS = 0xD;         /* Auto Refresh */
-       for(i=0;i<8;i++);
-       CSR_HPDMC_BYPASS = 0xD;         /* Auto Refresh */
-       for(i=0;i<8;i++);
-       CSR_HPDMC_BYPASS = 0x23F;       /* Load Mode Register, Enable DLL */
-       for(i=0;i<200;i++);
-       /* Leave Bypass mode and bring up hardware controller */
-       CSR_HPDMC_SYSTEM = HPDMC_SYSTEM_CKE;
-       
-       /* Set up pre-programmed data bus timings */
-       CSR_HPDMC_IODELAY = HPDMC_IDELAY_RST;
-       for(i=0;i<brd_desc->ddr_idelay;i++)
-               CSR_HPDMC_IODELAY = HPDMC_IDELAY_CE|HPDMC_IDELAY_INC;
-       
-       dqs_ps = brd_desc->ddr_dqsdelay;
-       for(i=0;i<brd_desc->ddr_dqsdelay;i++) {
-               CSR_HPDMC_IODELAY = HPDMC_DQSDELAY_CE|HPDMC_DQSDELAY_INC;
-               while(!(CSR_HPDMC_IODELAY & HPDMC_DQSDELAY_RDY));
-       }
-       
-       printf("OK\n");
-}
-
-static int plltest()
-{
-       int ok1, ok2;
-
-       printf("I: Checking if SDRAM clocking is functional:\n");
-       ok1 = CSR_HPDMC_IODELAY & HPDMC_PLL1_LOCKED;
-       ok2 = CSR_HPDMC_IODELAY & HPDMC_PLL2_LOCKED;
-       printf("I:   PLL#1: %s\n", ok1 ? "Locked" : "Error");
-       printf("I:   PLL#2: %s\n", ok2 ? "Locked" : "Error");
-       return(ok1 && ok2);
-}
-
-static int memtest(unsigned int div)
-{
-       unsigned int *testbuf = (unsigned int *)SDRAM_BASE;
-       unsigned int expected;
-       unsigned int i;
-       unsigned int size;
-
-       putsnonl("I: SDRAM test...");
-
-       size = brd_desc->sdram_size*1024*1024/(4*div);
-       for(i=0;i<size;i++)
-               testbuf[i] = i;
-
-       /* NB. The Mico32 cache (Level-1) is write-through,
-        * therefore there is no order to flush the cache hierarchy.
-        */
-       asm volatile( /* Invalidate Level-1 data cache */
-               "wcsr DCC, r0\n"
-               "nop\n"
-       );
-       flush_bridge_cache(); /* Invalidate Level-2 cache */
-
-       for(i=0;i<size;i++) {
-               expected = i;
-               if(testbuf[i] != expected) {
-                       printf("\nE: Failed offset 0x%08x (got 0x%08x, expected 0x%08x)\n", i, testbuf[i], expected);
-                       return 0;
-               }
-       }
-
-       printf("%u/%uMB tested OK\n", brd_desc->sdram_size/div, brd_desc->sdram_size);
-       return 1;
-}
-
-static void calibrate()
-{
-       int taps;
-       int quit;
-       char c;
-
-       printf("================================\n");
-       printf("DDR SDRAM calibration tool\n");
-       printf("================================\n");
-       printf("Memo:\n");
-       printf("[> Input Delay\n");
-       printf(" r = reset to 0 taps\n");
-       printf(" u = add 1 tap\n");
-       printf(" d = remove 1 tap\n");
-       printf("[> DQS output phase\n");
-       printf(" U = increase phase\n");
-       printf(" D = decrease phase\n");
-       printf("[> Misc\n");
-       printf(" t = load image to framebuffer\n");
-       printf(" q = quit\n");
-       
-       CSR_VGA_RESET = 0;
-       
-       CSR_HPDMC_IODELAY = HPDMC_IDELAY_RST;
-       
-       taps = 0;
-       quit = 0;
-       while(!quit) {
-               printf("Taps: %02d (78ps each) - DQS phase: %04d/255\r", taps, dqs_ps);
-               c = readchar();
-               switch(c) {
-                       case 'q':
-                               quit = 1;
-                               break;
-                       case 'r':
-                               taps = 0;
-                               CSR_HPDMC_IODELAY = HPDMC_IDELAY_RST;
-                               break;
-                       case 'u':
-                               if(taps < 63) {
-                                       taps++;
-                                       CSR_HPDMC_IODELAY = HPDMC_IDELAY_CE|HPDMC_IDELAY_INC;
-                               }
-                               break;
-                       case 'd':
-                               if(taps > 0) {
-                                       taps--;
-                                       CSR_HPDMC_IODELAY = HPDMC_IDELAY_CE;
-                               }
-                               break;
-                       case 'U':
-                               if(dqs_ps < 255) {
-                                       dqs_ps++;
-                                       CSR_HPDMC_IODELAY = HPDMC_DQSDELAY_CE|HPDMC_DQSDELAY_INC;
-                                       while(!(CSR_HPDMC_IODELAY & HPDMC_DQSDELAY_RDY));
-                               }
-                               break;
-                       case 'D':
-                               if(dqs_ps > 0) {
-                                       dqs_ps--;
-                                       CSR_HPDMC_IODELAY = HPDMC_DQSDELAY_CE;
-                                       while(!(CSR_HPDMC_IODELAY & HPDMC_DQSDELAY_RDY));
-                               }
-                               break;
-                       case 't':
-                               splash_display((void *)SDRAM_BASE);
-                               break;
-               }
-       }
-
-       CSR_VGA_RESET = VGA_RESET;
-
-       printf("\n");
-}
-
-static void scandqs(char *endp)
-{
-       int end;
-       char *c;
-
-       if(*endp == 0)
-               end = 255;
-       else {
-               end = (unsigned *)strtoul(endp, &c, 0);
-               if(*c != 0) {
-                       printf("incorrect end phase\n");
-                       return;
-               }
-       }
-       while(dqs_ps < end) {
-               dqs_ps++;
-               printf("DQS phase: %d\n", dqs_ps);
-               CSR_HPDMC_IODELAY = HPDMC_DQSDELAY_CE|HPDMC_DQSDELAY_INC;
-               while(!(CSR_HPDMC_IODELAY & HPDMC_DQSDELAY_RDY));
-               memtest(1);
-       }
-}
-
 /* General address space functions */
 
 #define NUMBER_OF_BYTES_ON_A_LINE 16
@@ -479,9 +292,6 @@ static void help()
        puts("It is used for system development and maintainance, and not");
        puts("for regular operation.\n");
        puts("Available commands:");
-       puts("plltest    - print status of the SDRAM clocking PLLs");
-       puts("memtest    - extended SDRAM test");
-       puts("calibrate  - run DDR SDRAM calibration tool");
        puts("flush      - flush FML bridge cache");
        puts("mr         - read address space");
        puts("mw         - write address space");
@@ -519,11 +329,7 @@ static void do_command(char *c)
 
        token = get_token(&c);
 
-       if(strcmp(token, "plltest") == 0) plltest();
-       else if(strcmp(token, "memtest") == 0) memtest(1);
-       else if(strcmp(token, "calibrate") == 0) calibrate();
-       else if(strcmp(token, "scandqs") == 0) scandqs(get_token(&c));
-       else if(strcmp(token, "flush") == 0) flush_bridge_cache();
+       if(strcmp(token, "flush") == 0) flush_bridge_cache();
 
        else if(strcmp(token, "mr") == 0) mr(get_token(&c), get_token(&c));
        else if(strcmp(token, "mw") == 0) mw(get_token(&c), get_token(&c), get_token(&c));
@@ -619,14 +425,14 @@ static void display_capabilities()
 
 static const char banner[] =
        "\nMILKYMIST(tm) v"VERSION" BIOS\thttp://www.milkymist.org\n"
-       "(c) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq\n\n"
+       "(c) Copyright 2007, 2008, 2009, 2010 Sebastien Bourdeauducq\n\n"
        "This program is free software: you can redistribute it and/or modify\n"
        "it under the terms of the GNU General Public License as published by\n"
        "the Free Software Foundation, version 3 of the License.\n\n";
 
 static void boot_sequence()
 {
-       splash_display((void *)(SDRAM_BASE+1024*1024*(brd_desc->sdram_size-1)));
+       splash_display();
        if(test_user_abort()) {
                serialboot(1);
                netboot();
@@ -659,16 +465,7 @@ int main(int i, char **c)
        display_board();
        display_capabilities();
        
-       if(plltest()) {
-               ddrinit();
-               flush_bridge_cache();
-
-               if(memtest(8))
-                       boot_sequence();
-               else
-                       printf("E: Aborted boot on memory error\n");
-       } else
-               printf("E: Faulty SDRAM clocking\n");
+       boot_sequence();
 
        splash_showerr();
        while(1) {
index 0742eb2..cea2153 100644 (file)
 
 static int splash_hres;
 static int splash_vres;
-static unsigned short *splash_fb = NULL;
+static unsigned short splash_fb[640*480] __attribute__((aligned(32)));;
 
-void splash_display(void *fbadr)
+void splash_display()
 {
        int i;
        unsigned short *splash_src = (unsigned short *)65536;
        
        printf("I: Displaying splash screen...");
 
-       splash_fb = (unsigned short *)fbadr;
        splash_hres = 640;
        splash_vres = 480;
 
@@ -49,7 +48,7 @@ void splash_showerr()
        int x, y;
        unsigned short color = 0xF800;
 
-       if(splash_fb == NULL) return;
+       if(splash_hres == 0) return;
        for(y=0;y<5;y++)
                for(x=0;x<splash_hres;x++)
                        splash_fb[splash_hres*y+x] = color;
index bc0b15e..ba6d984 100644 (file)
@@ -1,16 +1,16 @@
 /*
  * Milkymist VJ SoC (Software)
  * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
- * 
+ *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, version 3 of the License.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
@@ -18,7 +18,7 @@
 #ifndef __SPLASH_H
 #define __SPLASH_H
 
-void splash_display(void *fbadr);
+void splash_display();
 void splash_showerr();
 
 #endif /* __SPLASH_H */
index 30ecf22..ca8b766 100644 (file)
@@ -1,16 +1,16 @@
 /*
  * Milkymist VJ SoC (Software)
  * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
- * 
+ *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, version 3 of the License.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
index c7492f7..b0bd9c5 100644 (file)
@@ -1,16 +1,16 @@
 /*
  * Milkymist VJ SoC (Software)
  * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
- * 
+ *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, version 3 of the License.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
index 1c82375..f8cc5d7 100644 (file)
@@ -31,5 +31,7 @@
 #define IRQ_TMU                        (0x00000400) /* 10 */
 #define IRQ_PS2KEYBOARD                (0x00000800) /* 11 */
 #define IRQ_PS2MOUSE           (0x00001000) /* 12 */
+#define IRQ_ETHRX              (0x00002000) /* 13 */
+#define IRQ_ETHTX              (0x00004000) /* 14 */
 
 #endif /* __INTERRUPTS_H */
diff --git a/software/include/hw/sram.h b/software/include/hw/sram.h
deleted file mode 100644 (file)
index 4a33b17..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Milkymist VJ SoC (Software)
- * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
- * 
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3 of the License.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __HW_SRAM_H
-#define __HW_SRAM_H
-
-#define SRAM_BASE      (0x20000000)
-#define SRAM_SIZE      (0x1000)
-
-#endif /* __HW_SRAM_H */
index f75fb0b..7f13719 100644 (file)
@@ -20,6 +20,8 @@
 
 #define IPTOINT(a, b, c, d) ((a << 24)|(b << 16)|(c << 8)|d)
 
+#define MICROUDP_BUFSIZE (3*1532)
+
 typedef void (*udp_callback)(unsigned int src_ip, unsigned short src_port, unsigned short dst_port, void *data, unsigned int length);
 
 void microudp_start(unsigned char *macaddr, unsigned int ip, void *buffers);
index d9f118d..28a8693 100644 (file)
@@ -1,16 +1,16 @@
 /*
  * Milkymist VJ SoC (Software)
  * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
- * 
+ *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, version 3 of the License.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
index 92ed346..6e4d34c 100644 (file)
@@ -33,8 +33,7 @@ hdlcd.o: ../../software/include/hal/slowout.h
 hdlcd.o: ../../software/include/hal/hdlcd.h
 mem.o: ../../software/include/base/stdio.h
 mem.o: ../../software/include/base/stdlib.h
-mem.o: ../../software/include/base/malloc.h ../../software/include/hw/sram.h
-mem.o: ../../software/include/hal/mem.h
+mem.o: ../../software/include/base/malloc.h ../../software/include/hal/mem.h
 pfpu.o: ../../software/include/base/stdio.h
 pfpu.o: ../../software/include/base/stdlib.h
 pfpu.o: ../../software/include/base/irq.h
index b23034b..fed7338 100644 (file)
@@ -17,7 +17,6 @@
 
 #include <stdio.h>
 #include <malloc.h>
-#include <hw/sram.h>
 
 #include <hal/mem.h>
 
@@ -27,10 +26,6 @@ struct malloc_bank banks[2] = {
        {
                .addr_start = (unsigned int)&heap,
                .addr_end = (unsigned int)&heap + sizeof(heap)
-       },
-       {
-               .addr_start = SRAM_BASE,
-               .addr_end = SRAM_BASE + SRAM_SIZE
        }
 };
 
index e6cf7ca..0e7d305 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * libHPDMC - SDRAM initialization runtime for Milkymist bootloaders
  * Copyright (C) 2010 Sebastien Bourdeauducq
  *
@@ -11,7 +11,7 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses>.
  */
@@ -20,6 +20,9 @@
 #include <hw/hpdmc.h>
 #include <hw/vga.h>
 #include <hw/interrupts.h>
+#include <hw/sysctl.h>
+#include <hw/gpio.h>
+#include <version.h>
 
 /*
  * GLOBAL VARIABLES
  * r23: return address
  */
 
-.section .text, "ax", @progbits 
+.section .text, "ax", @progbits
 .global _sdram_init
 _sdram_init:
        mv      r23, ra
        mvhi    r1, hi(banner)
        ori     r1, r1, lo(banner)
        calli   print
+       mvhi    r1, hi(version)
+       ori     r1, r1, lo(version)
+       calli   print
+       mvhi    r1, hi(nl)
+       ori     r1, r1, lo(nl)
+       calli   print
+       mvhi    r1, hi(nl)
+       ori     r1, r1, lo(nl)
+       calli   print
        
        bi send_init
 send_init_return:
        mvhi    r1, hi(seqcomplete)
        ori     r1, r1, lo(seqcomplete)
        calli   print
-       
+
+       /* set IDELAY=0 */
+       mvhi    r1, hi(CSR_HPDMC_IODELAY)
+       ori     r1, r1, lo(CSR_HPDMC_IODELAY)
+       mvu     r2, (HPDMC_IDELAY_RST)
+       sw      (r1+0), r2
        xor     r25, r25, r25
        xor     r24, r24, r24
+
+       mvhi    r1, hi(CSR_GPIO_IN)
+       ori     r1, r1, lo(CSR_GPIO_IN)
+       lw      r2, (r1+0)
+       andi    r2, r2, (GPIO_PBC)
+       bne     r2, r0, mancal
+
        bi      autocalibrate
 autocalibrate_fail_return:
        mvhi    r1, hi(autocalfail)
@@ -55,8 +79,8 @@ autocalibrate_success_return:
        ori     r1, r1, lo(autocalok)
        calli   print
        
-       /* big memory test */
-       mvi     r1, 1
+       /* small memory test */
+       mvi     r1, 0
        xor     r2, r2, r2
        calli   memtest
        be      r1, r0, memtest_fail
@@ -136,9 +160,29 @@ send_init:
 
        bi      send_init_return
 
-/* clobbers: */
+/*
+ * TODO: proper dynamic autocalibration:
+ * scan IDELAY/DQS and memtest,
+ * then place in the middle of the working zone.
+ */
+/* clobbers: r1, r2, r3, r4 */
 autocalibrate:
-       bi      autocalibrate_fail_return
+       mvu     r24, 244 /* DQS phase, change this number for your board */
+       mvhi    r1, hi(CSR_HPDMC_IODELAY)
+       ori     r1, r1, lo(CSR_HPDMC_IODELAY)
+       xor     r2, r2, r2
+       mvu     r3, (HPDMC_DQSDELAY_CE|HPDMC_DQSDELAY_INC)
+       be      r2, r24, dqs_loop_end
+dqs_loop:
+       sw      (r1+0), r3
+dqs_loop_wait:
+       lw      r4, (r1+0)
+       andi    r4, r4, HPDMC_DQSDELAY_RDY
+       be      r4, r0, dqs_loop_wait
+       addi    r2, r2, 1
+       bne     r2, r24, dqs_loop
+dqs_loop_end:
+       bi      autocalibrate_success_return
 
 /* does not return */
 mancal:
@@ -272,7 +316,7 @@ boot:
 
 /* memtest - tests memory
  *
- * inputs:     r1 - 64MB/1MB
+ * inputs:     r1 - big/small
  *              r2 - PRNG seed
  * outputs:    r1 - pass/fail
  * clobbers:   r1, r3, r4, r5, r6, r7
@@ -286,7 +330,7 @@ memtest:
        mvhi    r7, hi(22695477)
        ori     r7, r7, lo(22695477)
        bne     r1, r0, patloop
-       mvhi    r3, 0x4
+       mvhi    r3, 0x10
        mv      r4, r3
 patloop:
        sw      (r5+0), r6
@@ -406,14 +450,15 @@ delay:
        ret
 
 .section .rodata, "a"
-banner: .string "libHPDMC SDRAM initialization runtime\n(c) Copyright 2010 Sebastien Bourdeauducq, released under GNU LGPL version 3.\n\n\0"
-seqcomplete: .string "Initialization sequence completed.\n\0"
-autocalfail: .string "Autocalibration failed, entering manual mode.\n\0"
-autocalok: .string "Autocalibration OK, testing memory...\n\0"
-continueboot: .string "All SDRAM initialization completed, boot continuing.\n\0"
-testfailmsg: .string "Memory test failed, entering manual mode.\n\0"
-manualkeys: .string "\nu: inc. input delay // d: dec. input delay\nU: inc. DQS phase   // D: dec. DQS phase\nt: test 1MB         // T: test 64MB\np: display pattern\nb: boot\n\0"
-memtestfailed: .string "Memory test failed.\n\0"
-memtestpassed: .string "Memory test passed.\n\0"
-spacer: .string " -- \0"
-nl: .string "\n\0"
\ No newline at end of file
+banner: .string "libHPDMC SDRAM initialization runtime\n(c) Copyright 2010 Sebastien Bourdeauducq, released under GNU LGPL version 3.\nVersion "
+version: .string VERSION
+seqcomplete: .string "Initialization sequence completed.\n"
+autocalfail: .string "Autocalibration failed, entering manual mode.\n"
+autocalok: .string "Autocalibration OK, testing memory...\n"
+continueboot: .string "All SDRAM initialization completed, boot continuing.\n\n"
+testfailmsg: .string "Memory test failed, entering manual mode.\n"
+manualkeys: .string "\nu: inc. input delay // d: dec. input delay\nU: inc. DQS phase   // D: dec. DQS phase\nt: test (small)     // T: test (large)\np: display pattern\nb: boot\n"
+memtestfailed: .string "Memory test failed.\n"
+memtestpassed: .string "Memory test passed.\n"
+spacer: .string " -- "
+nl: .string "\n"
index 7ec2ae1..891c08c 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * libHPDMC - SDRAM initialization runtime for Milkymist bootloaders
  * Copyright (C) 2010 Sebastien Bourdeauducq
  *
@@ -11,7 +11,7 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, see <http://www.gnu.org/licenses>.
  */
index 786e8fd..a90dd1e 100644 (file)
@@ -21,10 +21,14 @@ clean:
 
 mdio.o: ../../software/include/hw/minimac.h
 mdio.o: ../../software/include/hw/common.h ../../software/include/net/mdio.h
+microudp.o: ../../software/include/base/stdio.h
+microudp.o: ../../software/include/base/stdlib.h
 microudp.o: ../../software/include/base/crc.h
+microudp.o: ../../software/include/base/irq.h
 microudp.o: ../../software/include/hw/minimac.h
 microudp.o: ../../software/include/hw/common.h
 microudp.o: ../../software/include/hw/sysctl.h
+microudp.o: ../../software/include/hw/interrupts.h
 microudp.o: ../../software/include/net/microudp.h
 tftp.o: ../../software/include/base/string.h
 tftp.o: ../../software/include/base/stdlib.h
index baea5d7..c73dbe3 100644 (file)
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <stdio.h>
 #include <crc.h>
+#include <irq.h>
 #include <hw/minimac.h>
 #include <hw/sysctl.h>
+#include <hw/interrupts.h>
 
 #include <net/microudp.h>
 
@@ -127,7 +130,8 @@ static void send_packet()
        txlen += 4;
        CSR_MINIMAC_TXADR = (unsigned int)txbuffer;
        CSR_MINIMAC_TXREMAINING = txlen;
-       while(CSR_MINIMAC_TXREMAINING != 0);
+       while((irq_pending() & IRQ_ETHTX) == 0);
+       irq_ack(IRQ_ETHTX);
 }
 
 static unsigned char my_mac[6];
@@ -362,6 +366,8 @@ void microudp_start(unsigned char *macaddr, unsigned int ip, void *buffers)
        int i;
        char *_buffers = (char *)buffers;
 
+       irq_ack(IRQ_ETHRX|IRQ_ETHTX);
+
        rxbuffer = (ethernet_buffer *)_buffers;
        rxbuffer_back = (ethernet_buffer *)(_buffers + sizeof(ethernet_buffer));;
        txbuffer = (ethernet_buffer *)(_buffers + 2*sizeof(ethernet_buffer));
@@ -384,24 +390,36 @@ void microudp_start(unsigned char *macaddr, unsigned int ip, void *buffers)
 void microudp_service()
 {
        ethernet_buffer *buf;
-       
-       if(CSR_MINIMAC_STATE0 == MINIMAC_STATE_PENDING) {
-               asm volatile( /* Invalidate Level-1 data cache */
-                       "wcsr DCC, r0\n"
-                       "nop\n"
-               );
-               rxlen = CSR_MINIMAC_COUNT0;
-               /* Switch RX buffers */
-               buf = rxbuffer;
-               rxbuffer = rxbuffer_back;
-               rxbuffer_back = buf;
-               /* Re-arm DMA engine ASAP */
-               CSR_MINIMAC_ADDR0 = (unsigned int)rxbuffer_back;
-               CSR_MINIMAC_STATE0 = MINIMAC_STATE_LOADED;
-               /* Now we have time to do the processing */
-               process_frame();
+
+       if(irq_pending() & IRQ_ETHRX) {
+               if(CSR_MINIMAC_SETUP & MINIMAC_SETUP_RXRST) {
+                       printf("Minimac RX FIFO overflow!\n");
+                       CSR_MINIMAC_SETUP = 0;
+                       irq_ack(IRQ_ETHRX);
+               }
+               if(CSR_MINIMAC_STATE0 == MINIMAC_STATE_PENDING) {
+                       asm volatile( /* Invalidate Level-1 data cache */
+                               "wcsr DCC, r0\n"
+                               "nop\n"
+                       );
+                       rxlen = CSR_MINIMAC_COUNT0;
+                       /*
+                        * Ack interrupt.
+                        * We must empty the slot before so Minimac deasserts its IRQ line.
+                        */
+                       CSR_MINIMAC_STATE0 = MINIMAC_STATE_EMPTY;
+                       irq_ack(IRQ_ETHRX);
+                       /* Switch RX buffers */
+                       buf = rxbuffer;
+                       rxbuffer = rxbuffer_back;
+                       rxbuffer_back = buf;
+                       /* Re-arm DMA engine ASAP */
+                       CSR_MINIMAC_ADDR0 = (unsigned int)rxbuffer_back;
+                       CSR_MINIMAC_STATE0 = MINIMAC_STATE_LOADED;
+                       /* Now we have time to do the processing */
+                       process_frame();
+               }
        }
-       CSR_MINIMAC_SETUP = 0;
 }
 
 void microudp_shutdown()