]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Init DDR2 controller
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 1 Mar 2010 17:53:34 +0000 (18:53 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Mon, 1 Mar 2010 17:53:34 +0000 (18:53 +0100)
include/grub/mips/yeeloong/boot.h
include/grub/smbus.h
kern/mips/yeeloong/fwstart.S
util/grub-mkrawimage.c

index 205c557fe47827f5e7daec5bb9d80aacbf6e1e1e..6a4189ede3df750f8c88b778e6f4b9f15b4a4c5b 100644 (file)
@@ -24,4 +24,7 @@
 #define GRUB_MACHINE_FLASH_CACHE_ERROR      0xbfc00300
 #define GRUB_MACHINE_FLASH_OTHER_EXCEPTION  0xbfc00380
 
+#define GRUB_MACHINE_DDR2_BASE              0xaffffe00
+#define GRUB_MACHINE_DDR2_REG1_HI_8BANKS    0x00000001
+
 #endif
index b9cc6ab9e4cd4b8d4f2c1c8303a628a2c41b5789..0b8e6718ff16a2e285c8a4230357141886335d03 100644 (file)
 #define GRUB_SMB_RAM_START_ADDR 0x50
 #define GRUB_SMB_RAM_NUM_MAX 0x08
 
+#define GRUB_SMBUS_SPD_MEMORY_TYPE_ADDR 2
+#define GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2 8
+#define GRUB_SMBUS_SPD_MEMORY_NUM_BANKS_ADDR 17
+#define GRUB_SMBUS_SPD_MEMORY_NUM_ROWS_ADDR 3
+#define GRUB_SMBUS_SPD_MEMORY_NUM_COLUMNS_ADDR 4
+#define GRUB_SMBUS_SPD_MEMORY_NUM_OF_RANKS_ADDR 5
+#define GRUB_SMBUS_SPD_MEMORY_NUM_OF_RANKS_MASK 0x7
+#define GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_ADDR 18
+#define GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_MIN_VALUE 5
+#define GRUB_SMBUS_SPD_MEMORY_TRAS_ADDR 30
+#define GRUB_SMBUS_SPD_MEMORY_TRTP_ADDR 38
+
+#ifndef ASM_FILE
+
 struct grub_smbus_spd
 {
   grub_uint8_t written_size;
   grub_uint8_t log_total_flash_size;
-#define GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2 8
   grub_uint8_t memory_type;
   union
   {
     grub_uint8_t unknown[253];
     struct {
-      grub_uint8_t unused1[70];
+      grub_uint8_t num_rows;
+      grub_uint8_t num_columns;
+      grub_uint8_t num_of_ranks;
+      grub_uint8_t unused1[12];
+      grub_uint8_t num_of_banks;
+      grub_uint8_t unused2[2];
+      grub_uint8_t cas_latency;
+      grub_uint8_t unused3[9];
+      grub_uint8_t rank_capacity;
+      grub_uint8_t unused4[1];
+      grub_uint8_t tras;
+      grub_uint8_t unused5[7];
+      grub_uint8_t trtp;
+      grub_uint8_t unused6[31];
       grub_uint8_t part_number[18];
-      grub_uint8_t unused2[165];
+      grub_uint8_t unused7[165];
     } ddr2;
   };
 };
 
 #endif
+
+#endif
index 59fe4d3e6d4023210ec7518ce0a5d9caf117db96..3dccb65fd143fe4b14c651dd91f2be0d6db0b91f 100644 (file)
@@ -22,6 +22,7 @@
 #include <grub/pci.h>
 #include <grub/serial.h>
 #include <grub/cs5536.h>
+#include <grub/smbus.h>
 
        .set noreorder
        .set noat
@@ -103,21 +104,102 @@ __start:
        sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL3) ($t0)
        sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0)
 
-       ori $a0, $zero, 0x50
+       /* Yeeloong has only one memory slot.  */
+       /* Output first byte on serial for debugging.  */
+       ori $a1, $zero, GRUB_SMB_RAM_START_ADDR
        bal read_spd
-        move $a1, $zero
+        move $a0, $zero
        bal printhex
         move $a0, $v0
 
-       ori $a0, $zero, 0x50
        bal read_spd
-        ori $a1, $zero, 2
+        ori $a0, $zero, 2
+       ori $t0, $zero, GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2
+       lui $a0, %hi(unimplemented_memory_type)
+       bne $t0, $v0, fatal
+        addiu $a0, $a0, %hi(unimplemented_memory_type)
+
+       /* And here is our goal: DDR2 controller initialisation.  */
+        lui    $t0, 0xbfe0
+        ld     $t1, 0x0180($t0)
+       andi    $t1, $t1, 0x4ff
+        sd     $t1, 0x0180($t0)
+
+       b continue
+
+       . = start + GRUB_MACHINE_FLASH_TLB_REFILL - GRUB_MACHINE_FLASH_START
+tlb_refill:    
+       mfc0 $s1, $14
+       mfc0 $s2, $8
+       move $s3, $ra
+       lui $a0, %hi(epc)
+       bal message
+        addiu $a0, $a0, %lo(epc)
+
        bal printhex
-        move $a0, $v0
+        move $a0, $s1
+
+       lui $a0, %hi(badvaddr)
+       bal message
+        addiu $a0, $a0, %lo(badvaddr)
+
+       bal printhex
+        move $a0, $s2
+
+       lui $a0, %hi(return_msg)
+       bal message
+        addiu $a0, $a0, %lo(return_msg)
+
+       bal printhex
+        move $a0, $s3
        
-       lui $a0, %hi(not_implemented)
+       lui $a0, %hi(newline)
+       bal message
+        addiu $a0, $a0, %lo(newline)
+
+       lui $a0, %hi(unhandled_tlb_refill)
+       b fatal
+        addiu $a0, $a0, %lo(unhandled_tlb_refill)
+
+       . = start + GRUB_MACHINE_FLASH_CACHE_ERROR - GRUB_MACHINE_FLASH_START
+cache_error:
+       lui $a0, %hi(unhandled_cache_error)
+       b fatal
+        addiu $a0, $a0, %lo(unhandled_cache_error)
+
+       . = start + GRUB_MACHINE_FLASH_OTHER_EXCEPTION - GRUB_MACHINE_FLASH_START
+other_exception:
+       mfc0 $s0, $13
+       mfc0 $s1, $14
+       mfc0 $s2, $8
+       lui $a0, %hi(cause)
+       bal message
+        addiu $a0, $a0, %lo(cause)
+
+       bal printhex
+        move $a0, $s0
+
+       lui $a0, %hi(epc)
+       bal message
+        addiu $a0, $a0, %lo(epc)
+
+       bal printhex
+        move $a0, $s1
+
+       lui $a0, %hi(badvaddr)
+       bal message
+        addiu $a0, $a0, %lo(badvaddr)
+
+       bal printhex
+        move $a0, $s2
+       
+       lui $a0, %hi(newline)
+       bal message
+        addiu $a0, $a0, %lo(newline)
+       
+       lui $a0, %hi(unhandled_exception)
        b fatal
-        addiu $a0, $a0, %lo(not_implemented)
+        addiu $a0, $a0, %lo(unhandled_exception)
 
        /* Same as similarly named C function but in asm since
           we need it early.  */
@@ -171,7 +253,7 @@ message:
         addiu $a0, $a0, 1
        jr  $ra
         nop
-
+       
        /* Print 32-bit hexadecimal on serial.
            In: $a0. Out: None. Clobbered: $a0, $t0, $t1, $t2
        */
@@ -202,25 +284,7 @@ fatal:
 self:
        b self
         nop
-
-       . = start + GRUB_MACHINE_FLASH_TLB_REFILL - GRUB_MACHINE_FLASH_START
-tlb_refill:    
-       lui $a0, %hi(unhandled_tlb_refill)
-       b fatal
-        addiu $a0, $a0, %lo(unhandled_tlb_refill)
-
-       . = start + GRUB_MACHINE_FLASH_CACHE_ERROR - GRUB_MACHINE_FLASH_START
-cache_error:
-       lui $a0, %hi(unhandled_cache_error)
-       b fatal
-        addiu $a0, $a0, %lo(unhandled_cache_error)
-
-       . = start + GRUB_MACHINE_FLASH_OTHER_EXCEPTION - GRUB_MACHINE_FLASH_START
-other_exception:
-       lui $a0, %hi(unhandled_exception)
-       b fatal
-        addiu $a0, $a0, %lo(unhandled_exception)
-
+       
        /* Write CS5536 MSR.
            In:   $a0 address, $a1 lower word, $a2 upper word.
            Out:         None
@@ -251,7 +315,7 @@ return:
        jr $ra
         nop
        
-       /* Read SPD byte. In: $a0 device, $a1 byte. Out: $v0 read byte (0x100 on failure).
+       /* Read SPD byte. In: $a0 byte, $a1 device. Out: $v0 read byte (0x100 on failure).
            Clobbered: $t0, $t1, $t2, $t3, $a0. */
 read_spd:
        move $t2, $a0
@@ -268,7 +332,7 @@ read_spd:
        
        /* Send device address.  */
        lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
-       sll $t1, $t2, 1
+       sll $t1, $a1, 1
        bal smbus_wait
         sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
 
@@ -281,7 +345,7 @@ read_spd:
        /* Send byte address.  */
        lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
        bal smbus_wait
-        sb $a1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
+        sb $t2, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
 
        /* Send START.  */
        lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE)
@@ -292,7 +356,7 @@ read_spd:
 
        /* Send device address.  */
        lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
-       sll $t1, $t2, 1
+       sll $t1, $a1, 1
        ori $t1, $t1, 1
        bal smbus_wait
         sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
@@ -321,3 +385,156 @@ unhandled_tlb_refill:     .asciz "Unhandled TLB refill.\n\r"
 unhandled_cache_error: .asciz "Unhandled cache error.\n\r"
 unhandled_exception:   .asciz "Unhandled exception.\n\r"
 smbus_enabled: .asciz "SMBus controller enabled.\n\r"
+unimplemented_memory_type:     .asciz "non-DDR2 memory isn't supported.\n\r"
+no_cas_latency:                .asciz "Couldn't determine CAS latency.\n\r"
+cause:  .asciz "Cause: "
+epc:   .asciz "\n\rEPC: "
+badvaddr:      .asciz "\n\rBadVaddr: "
+newline:       .asciz "\n\r"
+return_msg:      .asciz "\n\rReturn address: "
+
+       .p2align 3
+
+regdump:
+       .quad 0x0100010000000101 /* 0 */
+       .quad 0x0100010100000000 /* 2 */
+       .quad 0x0101000001000000 /* 3 */
+       .quad 0x0100020200010101 /* 4 */
+       .quad 0x0a04030603050203 /* 6 */
+       .quad 0x0f0e040000010a0b /* 7 */
+       .quad 0x0000010200000102 /* 8 */
+       .quad 0x0000060c00000000 /* 9 */
+       .quad 0x2323233f3f1f0200 /* a */
+       .quad 0x5f7f232323232323 /* b */
+       .quad 0x002a3c0615000000 /* c */
+       .quad 0x002a002a002a002a /* d */
+       .quad 0x002a002a002a002a /* e */
+       .quad 0x00b40020006d0004 /* f */
+       .quad 0x070007ff00000087 /* 10 */
+       .quad 0x000000000016101f /* 11 */
+       .quad 0x001c000000000000 /* 12 */
+       .quad 0x28e1000200c8006b /* 13 */
+       .quad 0x0000204200c8002f /* 14 */
+       .quad 0x0000000000030d40 /* 15 */
+       .quad 0 /* 16 */
+       .quad 0 /* 17 */
+       .quad 0 /* 18 */
+       .quad 0 /* 19 */
+       .quad 0 /* 1a */
+       .quad 0 /* 1b */
+       .quad 0 /* 1c */
+
+       .p2align
+
+write_dumpreg: 
+       ld $t2, 0($t6)
+       sd $t2, 0($t4)
+       addiu $t4, $t4, 0x10
+       jr $ra
+        addiu $t6, $t6, 0x8
+
+continue:
+       lui $t4, %hi(GRUB_MACHINE_DDR2_BASE)
+       addiu $t4, $t4, %lo(GRUB_MACHINE_DDR2_BASE)
+       lui $t6, %hi(regdump)
+
+       /* 0 */
+       bal write_dumpreg
+        addiu $t6, $t6, %lo(regdump)
+
+       /* 1 */
+       ori $a1, $a1, 0x50
+       move $t8, $zero
+       lui  $t5, 0x0001
+       bal read_spd
+        ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_BANKS_ADDR
+       ori $t7, $zero, 8
+       bne $v0, $t7, 1f
+        ori $t5, $t5, 0x0001
+       ori $t8, $t8, GRUB_MACHINE_DDR2_REG1_HI_8BANKS
+1:
+       dsll $t8, $t8, 32
+       or $t5, $t5, $t8
+       sd  $t5, 0 ($t4)
+       addiu $t4, $t4, 0x10
+
+       /* 2 */
+       bal write_dumpreg
+        nop
+
+       /* 3 */
+       bal write_dumpreg
+        nop
+
+       /* 4 */
+       bal write_dumpreg
+        nop
+
+       /* 5 */
+       /* FIXME: figure termination resistance.  */
+       ori $t5, $zero, 0x2
+       bal read_spd
+        ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_ROWS_ADDR
+       /* $v0 = 15 - $v0.  */
+       xori $v0, $v0, 0xf
+       andi $v0, $v0, 0x7
+       sll $v0, $v0, 8
+       or $t5, $t5, $v0
+
+       /* Find the fastest supported CAS latency.  */
+       bal read_spd
+        ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_ADDR
+       ori $t0, $zero, GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_MIN_VALUE
+       ori $t1, $zero, (1 << GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_MIN_VALUE)
+2:     
+       and $t2, $t1, $v0
+       bne $t2, $zero, 1f
+        ori $t3, $zero, 8
+       lui $a0, %hi(no_cas_latency)
+       beq $t0, $t3, fatal
+        addiu $a0, $a0, %lo(no_cas_latency)
+       addiu $t0, $t0, 1
+       b 2b
+        sll $t1, $t1, 1
+1:
+       sll $t0, $t0, 16
+       or $t5, $t5, $t0
+       
+       bal read_spd
+        ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_COLUMNS_ADDR
+       /* $v0 = 15 - ($v0 + 1) = 14 - $v0.  */
+       addiu $v0, $v0, 1
+       xori $v0, $v0, 0xf
+       andi $v0, $v0, 0x7
+       sll $v0, 24
+       or $t5, $t5, $v0
+       sd  $t5, 0 ($t4)
+
+       addiu $t4, $t4, 0x10
+       
+       ori $t7, $zero, 0x16
+
+1:     
+       ld $t2, 0($t6)
+       sd $t2, 0($t4)
+       addiu $t4, $t4, 0x10
+       addiu $t7, $t7, -1
+       bne $t7, $zero, 1b
+        addiu $t6, $t6, 0x8
+       
+       lui $t4, %hi(GRUB_MACHINE_DDR2_BASE)
+       ld  $t5, (%lo(GRUB_MACHINE_DDR2_BASE) + 0x30) ($t4)
+       ori $t0, $zero, 1
+       dsll $t0, $t0, 40
+       or $t5, $t5, $t0
+       sd  $t5, (%lo(GRUB_MACHINE_DDR2_BASE) + 0x30) ($t4)
+
+       /* Desactivate DDR2 registers.  */
+        lui    $t0, 0xbfe0
+        ld     $t1, 0x0180($t0)
+       ori     $t1, $t1, 0x100
+        sd     $t1, 0x0180($t0)
+
+       addiu $a0, $zero, -1
+       addiu $a1, $zero, -1
+       addiu $a2, $zero, -1
index 83bb51c02f7491fcf2d7974c21430722c6f0ab91..2f721f6ed6d097afc8d2f3ec7838fc44f7cb4142 100644 (file)
@@ -391,7 +391,31 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[],
       free (core_img);
       core_img = elf_img;
       core_size = program_size  + sizeof (*ehdr) + sizeof (*phdr);
-  }
+    }
+  else
+    {
+      char *rom_img;
+      size_t rom_size;
+      char *boot_path, *boot_img;
+      size_t boot_size;
+      
+      boot_path = grub_util_get_path (dir, "fwstart.img");
+      boot_size = grub_util_get_image_size (boot_path);
+      boot_img = grub_util_read_image (boot_path);
+
+      rom_size = core_size + boot_size;
+
+      rom_img = xmalloc (rom_size);
+      memset (rom_img, 0, rom_size); 
+
+      memcpy (rom_img, boot_img, boot_size);
+
+      memcpy (rom_img + boot_size, core_img, core_size);      
+
+      free (core_img);
+      core_img = rom_img;
+      core_size = rom_size;
+    }
 #endif
 
   grub_util_write_image (core_img, core_size, out);