ML410 with linux 2.6 TEMAC IIC DDR2 SPD

From RCSWiki

Jump to: navigation, search

This tutorial builds on the previous two tutorials for Linux 2.6 on the ML410. Specifically this tutorial explains the steps to get DDR2's SPD (Serial Presence Detection) to work. The idea is to use the EEPROM on the DDR2 DIMM which holds the information about the module and setup Linux accordingly.

Some important information regarding DDR2's SPD EEPROM. It does NOT contain the actual size of the DDR2 module, instead it gives details regarding the number of physical banks and the size of each bank. Using these two together (# Banks * Size / Bank) will result in the size of the DIMM.

This tutorial will explain the steps to add this functionality to the previous tutorial. All of the following modifications are to the embedded_config.c file located under linux-2.6\arch\ppc\boot\simple

  • Add two Global Variables:
    • #define DDR2_SPD_ADDR 0xA8
      • The location of DDR2's EEPROM on the I2C Bus
    • #define DDR2_SPD_SIZE 128
      • Number of Bytes to Read from DDR2's EEPROM
  • Add the following function:
unsigned int get_DDR2_size() {
  /* Declare Temporary Variables */
  char addr = 0;
  char numBanks = 0;
  char sizeBank = 0;
  char data[DDR2_SPD_SIZE];
  unsigned int size = 0;

  /* Read DDR2 SPD Data from DDR2's EEPROM */
  /* Start Reading at byte 0 and read until byte 128 */
  XIic_Send(XPAR_IIC_BUS_BASEADDR, DDR2_SPD_ADDR>>1, &addr, 1, XIIC_STOP);
  XIic_Recv(XPAR_IIC_BUS_BASEADDR, DDR2_SPD_ADDR>>1, &data, DDR2_SPD_SIZE, XIIC_STOP);

  // Byte 5 lower 4 bits:                                                                     
  //    0 = 1 bank                                                                            
  //    1 = 2 banks                                                                           
  //    2 = 3 banks                                                                           
  //    3 = 4 banks                                                                           
  numBanks = (data[5] & 0x0F) + 1;

  // Byte 31                                                                                  
  //   0x20 = 128 MB / Bank                                                                   
  //   0x40 = 256 MB / Bank                                                                   
  //   0x80 = 512 MB / Bank                                                                   
  //   0x01 = 1 GB / Bank                                                                     
  //   0x02 = 2 GB / Bank                                                                     
  //   0x03 = 4 GB / Bank                                                                     
  sizeBank = data[31];

  // Size = # Banks * (Size / Bank)                                                           
  switch (sizeBank) {
  case 0x20:
    size = (0x08000000 / numBanks);
    break;
  case 0x40:
    size = (0x10000000 / numBanks);
    break;
  case 0x80:
    size = (0x20000000 / numBanks);
    break;
  case 0x01:
    size = (0x40000000 / numBanks);
    break;
  case 0x02:
    size = (0x80000000 / numBanks);
    break;
  case 0x03:
    size = (0xFFFFFFFF / numBanks);
    break;
  default:
    size = (0x04000000);
    break;
  }
  return size;
}
  • In the function embed_config change the line from:
    • bd->bi_memsize = XPAR_DDR_0_SIZE;
  • To:
    • bd->bi_memsize = get_DDR2_size();


Or you can download my modified embed_config.c file

Personal tools