<p>Arthur Heymans has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/22994">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">nb/intel/x4x: Add DDR3 JEDEC init<br><br>Add DDR3 JEDEC init (Power up and Initialization by setting emrs regs)<br><br>the ddr3_emrs1_config array is placed externally since it is needed<br>for write leveling.<br><br>Change-Id: I510b8669aaa48ba99fb4dcf1ece716aef26741bb<br>Signed-off-by: Arthur Heymans <arthur@aheymans.xyz><br>---<br>M src/northbridge/intel/x4x/raminit_ddr23.c<br>M src/northbridge/intel/x4x/raminit_tables.c<br>M src/northbridge/intel/x4x/spd_ddr3_decode.c<br>M src/northbridge/intel/x4x/x4x.h<br>4 files changed, 100 insertions(+), 7 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/94/22994/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/northbridge/intel/x4x/raminit_ddr23.c b/src/northbridge/intel/x4x/raminit_ddr23.c</span><br><span>index ddb1e01..2835890 100644</span><br><span>--- a/src/northbridge/intel/x4x/raminit_ddr23.c</span><br><span>+++ b/src/northbridge/intel/x4x/raminit_ddr23.c</span><br><span>@@ -1360,14 +1360,34 @@</span><br><span>   return channel * 512 * MiB + rank * 128 * MiB;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void dojedec_ddr2(u8 r, u8 ch, u8 cmd, u16 val)</span><br><span style="color: hsl(120, 100%, 40%);">+static void send_jedec_cmd(const struct sysinfo *s, u8 r,</span><br><span style="color: hsl(120, 100%, 40%);">+                      u8 ch, u8 cmd, u32 val)</span><br><span> {</span><br><span>         u32 addr = test_address(ch, r);</span><br><span>      volatile u32 rubbish;</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 data8 = cmd;</span><br><span style="color: hsl(120, 100%, 40%);">+       u32 data32;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0x3e) | cmd;</span><br><span style="color: hsl(0, 100%, 40%);">-    MCHBAR8(0x671) = (MCHBAR8(0x671) & ~0x3e) | cmd;</span><br><span style="color: hsl(0, 100%, 40%);">-    rubbish = read32((void *)((val<<3) | addr));</span><br><span style="color: hsl(120, 100%, 40%);">+    if (s->spd_type == DDR3 && (r & 1)</span><br><span style="color: hsl(120, 100%, 40%);">+                     && s->dimms[ch * 2 + (r >> 1)].mirrorred) {</span><br><span style="color: hsl(120, 100%, 40%);">+          data8 &= ~(1 << 4);</span><br><span style="color: hsl(120, 100%, 40%);">+         data8 |= ((1 << 4) & (cmd >> 1));</span><br><span style="color: hsl(120, 100%, 40%);">+             data8 &= ~(1 << 5);</span><br><span style="color: hsl(120, 100%, 40%);">+         data8 |= ((1 << 5) & (cmd << 1));</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0x3e) | data8;</span><br><span style="color: hsl(120, 100%, 40%);">+        MCHBAR8(0x671) = (MCHBAR8(0x671) & ~0x3e) | data8;</span><br><span style="color: hsl(120, 100%, 40%);">+        data32 = val;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (s->spd_type == DDR3 && (r & 1)</span><br><span style="color: hsl(120, 100%, 40%);">+                     && s->dimms[ch * 2 + (r >> 1)].mirrorred) {</span><br><span style="color: hsl(120, 100%, 40%);">+          data32 &= ~(0x1f8);</span><br><span style="color: hsl(120, 100%, 40%);">+               data32 |= (val & 0xa0) << 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                data32 |= (val & 0x160) >> 1;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+     data32 <<= 3;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rubbish = read32((void *)((data32 | addr)));</span><br><span>         udelay(10);</span><br><span>  MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0x3e) | NORMALOP_CMD;</span><br><span>        MCHBAR8(0x671) = (MCHBAR8(0x671) & ~0x3e) | NORMALOP_CMD;</span><br><span>@@ -1432,7 +1452,7 @@</span><br><span>                        default:</span><br><span>                             break;</span><br><span>                       }</span><br><span style="color: hsl(0, 100%, 40%);">-                       dojedec_ddr2(r, ch, jedec[i][0], v);</span><br><span style="color: hsl(120, 100%, 40%);">+                  send_jedec_cmd(s, r, ch, jedec[i][0], v);</span><br><span>                    udelay(1);</span><br><span>                   printk(RAM_SPEW, "Jedec step %d\n", i);</span><br><span>            }</span><br><span>@@ -1440,6 +1460,52 @@</span><br><span>   printk(BIOS_DEBUG, "MRS done\n");</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void jedec_ddr3(struct sysinfo *s)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    int ch, r, dimmconfig, cmd, ddr3_freq;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      u8 ddr3_emrs2_config[16][4] = { /* [config][Rank] */</span><br><span style="color: hsl(120, 100%, 40%);">+          {0, 0, 0, 0},   /* NC_NC */</span><br><span style="color: hsl(120, 100%, 40%);">+           {0, 0, 0, 0},   /* x8ss_NC */</span><br><span style="color: hsl(120, 100%, 40%);">+         {0, 0, 0, 0},   /* x8ds_NC */</span><br><span style="color: hsl(120, 100%, 40%);">+         {0, 0, 0, 0},   /* x16ss_NC */</span><br><span style="color: hsl(120, 100%, 40%);">+                {0, 0, 0, 0},   /* NC_x8ss */</span><br><span style="color: hsl(120, 100%, 40%);">+         {2, 0, 2, 0},   /* x8ss_x8ss */</span><br><span style="color: hsl(120, 100%, 40%);">+               {2, 2, 2, 0},   /* x8ds_x8ss */</span><br><span style="color: hsl(120, 100%, 40%);">+               {2, 0, 2, 0},   /* x16ss_x8ss */</span><br><span style="color: hsl(120, 100%, 40%);">+              {0, 0, 0, 0},   /* NC_x8ss */</span><br><span style="color: hsl(120, 100%, 40%);">+         {2, 0, 2, 2},   /* x8ss_x8ds */</span><br><span style="color: hsl(120, 100%, 40%);">+               {2, 2, 2, 2},   /* x8ds_x8ds */</span><br><span style="color: hsl(120, 100%, 40%);">+               {2, 0, 2, 2},   /* x16ss_x8ds */</span><br><span style="color: hsl(120, 100%, 40%);">+              {0, 0, 0, 0},   /* NC_x16ss */</span><br><span style="color: hsl(120, 100%, 40%);">+                {2, 0, 2, 0},   /* x8ss_x16ss */</span><br><span style="color: hsl(120, 100%, 40%);">+              {2, 2, 2, 0},   /* x8ds_x16ss */</span><br><span style="color: hsl(120, 100%, 40%);">+              {2, 0, 2, 0},   /* x16ss_x16ss */</span><br><span style="color: hsl(120, 100%, 40%);">+     };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  printk(BIOS_DEBUG, "MRS...\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ddr3_freq = s->selected_timings.mem_clk - MEM_CLOCK_800MHz;</span><br><span style="color: hsl(120, 100%, 40%);">+        FOR_EACH_POPULATED_RANK(s->dimms, ch, r) {</span><br><span style="color: hsl(120, 100%, 40%);">+         printk(BIOS_DEBUG, "CH%d: Found Rank %d\n", ch, r);</span><br><span style="color: hsl(120, 100%, 40%);">+         send_jedec_cmd(s, r, ch, NOP_CMD, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+         udelay(200);</span><br><span style="color: hsl(120, 100%, 40%);">+          dimmconfig = s->dimm_config[ch];</span><br><span style="color: hsl(120, 100%, 40%);">+           cmd = ddr3_freq << 3; /* actually twl - 5 which is same */</span><br><span style="color: hsl(120, 100%, 40%);">+              cmd |= ddr3_emrs2_config[dimmconfig][r] << 9;</span><br><span style="color: hsl(120, 100%, 40%);">+           send_jedec_cmd(s, r, ch, EMRS2_CMD, cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+             send_jedec_cmd(s, r, ch, EMRS3_CMD, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+               cmd = ddr3_emrs1_config[dimmconfig][r] << 2;</span><br><span style="color: hsl(120, 100%, 40%);">+            cmd |= (1 << 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                send_jedec_cmd(s, r, ch, EMRS1_CMD, cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+             send_jedec_cmd(s, r, ch, MRS_CMD, (1 << 3) | (1 << 8)</span><br><span style="color: hsl(120, 100%, 40%);">+                     | (1 << 12) | ((s->selected_timings.CAS - 4) << 4)</span><br><span style="color: hsl(120, 100%, 40%);">+                     | ((s->selected_timings.tWR - 4) << 9));</span><br><span style="color: hsl(120, 100%, 40%);">+             send_jedec_cmd(s, r, ch, ZQCAL_CMD, (1 << 10));</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+     printk(BIOS_DEBUG, "MRS done\n");</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static void sdram_recover_receive_enable(const struct sysinfo *s)</span><br><span> {</span><br><span>   u32 reg32;</span><br><span>@@ -1956,8 +2022,12 @@</span><br><span>  printk(BIOS_DEBUG, "Done pre-jedec\n");</span><br><span> </span><br><span>        // JEDEC reset</span><br><span style="color: hsl(0, 100%, 40%);">-  if (s->boot_path != BOOT_PATH_RESUME)</span><br><span style="color: hsl(0, 100%, 40%);">-                jedec_ddr2(s);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (s->boot_path != BOOT_PATH_RESUME) {</span><br><span style="color: hsl(120, 100%, 40%);">+            if (s->spd_type == DDR2)</span><br><span style="color: hsl(120, 100%, 40%);">+                   jedec_ddr2(s);</span><br><span style="color: hsl(120, 100%, 40%);">+                else /* DDR3 */</span><br><span style="color: hsl(120, 100%, 40%);">+                       jedec_ddr3(s);</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span> </span><br><span>        printk(BIOS_DEBUG, "Done jedec steps\n");</span><br><span> </span><br><span>diff --git a/src/northbridge/intel/x4x/raminit_tables.c b/src/northbridge/intel/x4x/raminit_tables.c</span><br><span>index f386b6b..ee64967 100644</span><br><span>--- a/src/northbridge/intel/x4x/raminit_tables.c</span><br><span>+++ b/src/northbridge/intel/x4x/raminit_tables.c</span><br><span>@@ -269,3 +269,22 @@</span><br><span>          {13, 6, 1, 0, 1, 0},</span><br><span>                 {0, 3, 1, 1, 0, 1}, }</span><br><span> };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const u8 ddr3_emrs1_config[16][4] = {  /* [Config][Rank] */</span><br><span style="color: hsl(120, 100%, 40%);">+    {0x00, 0x00, 0x00, 0x00},       /* NC_NC */</span><br><span style="color: hsl(120, 100%, 40%);">+   {0x11, 0x00, 0x00, 0x00},       /* 8S_NC */</span><br><span style="color: hsl(120, 100%, 40%);">+   {0x11, 0x11, 0x00, 0x00},       /* 8D_NC */</span><br><span style="color: hsl(120, 100%, 40%);">+   {0x11, 0x00, 0x00, 0x00},       /* 16S_NC */</span><br><span style="color: hsl(120, 100%, 40%);">+  {0x00, 0x00, 0x11, 0x00},       /* NC_8S */</span><br><span style="color: hsl(120, 100%, 40%);">+   {0x81, 0x00, 0x81, 0x00},       /* 8S_8S */</span><br><span style="color: hsl(120, 100%, 40%);">+   {0x81, 0x81, 0x81, 0x00},       /* 8D_8S */</span><br><span style="color: hsl(120, 100%, 40%);">+   {0x81, 0x00, 0x81, 0x00},       /* 16S_8S */</span><br><span style="color: hsl(120, 100%, 40%);">+  {0x00, 0x00, 0x11, 0x11},       /* NC_8D */</span><br><span style="color: hsl(120, 100%, 40%);">+   {0x81, 0x00, 0x81, 0x81},       /* 8S_8D */</span><br><span style="color: hsl(120, 100%, 40%);">+   {0x81, 0x81, 0x81, 0x81},       /* 8D_8D */</span><br><span style="color: hsl(120, 100%, 40%);">+   {0x81, 0x00, 0x81, 0x81},       /* 16S_8D */</span><br><span style="color: hsl(120, 100%, 40%);">+  {0x00, 0x00, 0x11, 0x00},       /* NC_16S */</span><br><span style="color: hsl(120, 100%, 40%);">+  {0x81, 0x00, 0x81, 0x00},       /* 8S_16S */</span><br><span style="color: hsl(120, 100%, 40%);">+  {0x81, 0x81, 0x81, 0x00},       /* 8D_16S */</span><br><span style="color: hsl(120, 100%, 40%);">+  {0x81, 0x00, 0x81, 0x00},       /* 16S_16S */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span>diff --git a/src/northbridge/intel/x4x/spd_ddr3_decode.c b/src/northbridge/intel/x4x/spd_ddr3_decode.c</span><br><span>index b1ac3ea..a57b14c 100644</span><br><span>--- a/src/northbridge/intel/x4x/spd_ddr3_decode.c</span><br><span>+++ b/src/northbridge/intel/x4x/spd_ddr3_decode.c</span><br><span>@@ -160,6 +160,8 @@</span><br><span>     s->dimms[dimm_idx].rows = decoded_dimm.row_bits;</span><br><span>  s->dimms[dimm_idx].cols = decoded_dimm.col_bits;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+       s->dimms[dimm_idx].mirrorred = decoded_dimm.flags.pins_mirrored;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>        saved_timings->min_tRAS =</span><br><span>                 MAX(saved_timings->min_tRAS, decoded_dimm.tRAS);</span><br><span>  saved_timings->min_tRP =</span><br><span>diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h</span><br><span>index f374725..37215b1 100644</span><br><span>--- a/src/northbridge/intel/x4x/x4x.h</span><br><span>+++ b/src/northbridge/intel/x4x/x4x.h</span><br><span>@@ -308,6 +308,7 @@</span><br><span>   unsigned int    ranks;</span><br><span>       unsigned int    rows;</span><br><span>        unsigned int    cols;</span><br><span style="color: hsl(120, 100%, 40%);">+ u8              mirrorred;</span><br><span>   u16             checksum;</span><br><span> };</span><br><span> </span><br><span>@@ -412,6 +413,7 @@</span><br><span> extern const struct dll_setting default_ddr3_800_dq[2][8];</span><br><span> extern const struct dll_setting default_ddr3_1067_dq[2][8];</span><br><span> extern const struct dll_setting default_ddr3_1333_dq[2][8];</span><br><span style="color: hsl(120, 100%, 40%);">+extern const u8 ddr3_emrs1_config[16][4];</span><br><span> </span><br><span> struct acpi_rsdp;</span><br><span> #ifndef __SIMPLE_DEVICE__</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/22994">change 22994</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/22994"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I510b8669aaa48ba99fb4dcf1ece716aef26741bb </div>
<div style="display:none"> Gerrit-Change-Number: 22994 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Arthur Heymans <arthur@aheymans.xyz> </div>