<p>Arthur Heymans has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/26563">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">nb/intel/x4x: Add the option for stacked channel map settings<br><br>There seems to be a hardware bug where the combination of non-stacked<br>channel settings, both channels populated and 533MHz dram speed cause<br>the display to be unusable.<br><br>The code to actually select stacked mode based on hardware<br>configuration will be add in a followup patch.<br><br>This patch does the following:<br>* Add option to the sysinfo struct for stacked mode<br>* Fix programming channel 1 DRB which needs special care for the last<br>  populated rank in stacked mode<br><br>TESTED on Intel dg41wv (with stacked mode hardcoded and dram at 533MHz)<br><br>Change-Id: I95965bfea129b37f64163159fefa1c8f16331b62<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/x4x.h<br>2 files changed, 37 insertions(+), 13 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/63/26563/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 4dbee32..6bf356f 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>@@ -1320,10 +1320,8 @@</span><br><span>     MCHBAR16(C1DRB0) = 0x0002;</span><br><span>   MCHBAR16(C1DRB1) = 0x0004;</span><br><span>   MCHBAR16(C1DRB2) = 0x0006;</span><br><span style="color: hsl(0, 100%, 40%);">-      /*</span><br><span style="color: hsl(0, 100%, 40%);">-       * For some reason the boundary needs to be 0x10 instead of 0x8 here.</span><br><span style="color: hsl(0, 100%, 40%);">-    * Vendor does this too...</span><br><span style="color: hsl(0, 100%, 40%);">-       */</span><br><span style="color: hsl(120, 100%, 40%);">+   /* In stacked mode the last present rank on ch1 needs to have its</span><br><span style="color: hsl(120, 100%, 40%);">+      * size doubled in c1drbx */</span><br><span>         MCHBAR16(C1DRB3) = 0x0010;</span><br><span>   MCHBAR8(0x111) = MCHBAR8(0x111) | STACKED_MEM;</span><br><span>       MCHBAR32(0x104) = 0;</span><br><span>@@ -1550,7 +1548,7 @@</span><br><span> </span><br><span> static void set_dradrb(struct sysinfo *s)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-      u8 map, i, ch, r, rankpop0, rankpop1;</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 map, i, ch, r, rankpop0, rankpop1, lastrank_ch1;</span><br><span>  u32 c0dra = 0;</span><br><span>       u32 c1dra = 0;</span><br><span>       u32 c0drb = 0;</span><br><span>@@ -1632,6 +1630,7 @@</span><br><span>               MCHBAR8(0x660) = MCHBAR8(0x660) | 1;</span><br><span> </span><br><span>     // DRB</span><br><span style="color: hsl(120, 100%, 40%);">+        lastrank_ch1 = 0;</span><br><span>    FOR_EACH_RANK(ch, r) {</span><br><span>               if (ch == 0) {</span><br><span>                       if (RANK_IS_POPULATED(s->dimms, ch, r)) {</span><br><span>@@ -1641,6 +1640,7 @@</span><br><span>                         MCHBAR16(0x200 + 2*r) = c0drb;</span><br><span>               } else {</span><br><span>                     if (RANK_IS_POPULATED(s->dimms, ch, r)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                          lastrank_ch1 = r;</span><br><span>                            dra1 = (c1dra >> (8*r)) & 0x7f;</span><br><span>                            c1drb = (u16)(c1drb + drbtab[dra1]);</span><br><span>                         }</span><br><span>@@ -1650,6 +1650,14 @@</span><br><span> </span><br><span>       s->channel_capacity[0] = c0drb << 6;</span><br><span>        s->channel_capacity[1] = c1drb << 6;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* In stacked mode the last present rank on ch1 needs to have its</span><br><span style="color: hsl(120, 100%, 40%);">+      * size doubled in c1drbx */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (s->stacked_mode) {</span><br><span style="color: hsl(120, 100%, 40%);">+             for (r = lastrank_ch1; r < 4; r++)</span><br><span style="color: hsl(120, 100%, 40%);">+                 MCHBAR16(0x600 + 2*r) = 2 * c1drb;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  totalmemorymb = s->channel_capacity[0] + s->channel_capacity[1];</span><br><span>       printk(BIOS_DEBUG, "Total memory: %d + %d = %dMiB\n",</span><br><span>              s->channel_capacity[0], s->channel_capacity[1], totalmemorymb);</span><br><span>@@ -1659,8 +1667,12 @@</span><br><span>       size_ch1 = s->channel_capacity[1];</span><br><span>        size_me = ME_UMA_SIZEMB;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    MCHBAR8(0x111) = MCHBAR8(0x111) & ~0x2;</span><br><span style="color: hsl(0, 100%, 40%);">-     MCHBAR8(0x111) = MCHBAR8(0x111) | (1 << 4);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (s->stacked_mode) {</span><br><span style="color: hsl(120, 100%, 40%);">+             MCHBAR8(0x111) = MCHBAR8(0x111) | STACKED_MEM;</span><br><span style="color: hsl(120, 100%, 40%);">+        } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              MCHBAR8(0x111) = MCHBAR8(0x111) & ~STACKED_MEM;</span><br><span style="color: hsl(120, 100%, 40%);">+           MCHBAR8(0x111) = MCHBAR8(0x111) | (1 << 4);</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span> </span><br><span>        if (size_me == 0) {</span><br><span>          dual_channel_size = MIN(size_ch0, size_ch1) * 2;</span><br><span>@@ -1677,6 +1689,9 @@</span><br><span>             }</span><br><span>            dual_channel_size = MIN(size_ch0 - size_me, size_ch1) * 2;</span><br><span>   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (s->stacked_mode)</span><br><span style="color: hsl(120, 100%, 40%);">+               dual_channel_size = 0;</span><br><span>       MCHBAR16(0x104) = dual_channel_size;</span><br><span>         single_channel_size = size_ch0 + size_ch1 - dual_channel_size;</span><br><span>       MCHBAR16(0x102) = single_channel_size;</span><br><span>@@ -1693,11 +1708,13 @@</span><br><span>             map |= 0x18;</span><br><span>         /* Enable flex mode, we hardcode this everywhere */</span><br><span>  if (size_me == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-             map |= 0x04;</span><br><span style="color: hsl(0, 100%, 40%);">-            if (size_ch0 <= size_ch1)</span><br><span style="color: hsl(0, 100%, 40%);">-                    map |= 0x01;</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!(s->stacked_mode && size_ch0 != 0 && size_ch1 != 0)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        map |= 0x04;</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (size_ch0 <= size_ch1)</span><br><span style="color: hsl(120, 100%, 40%);">+                          map |= 0x01;</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span>    } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                if (size_ch0 - size_me < size_ch1)</span><br><span style="color: hsl(120, 100%, 40%);">+         if (s->stacked_mode == 0 && size_ch0 - size_me < size_ch1)</span><br><span>                     map |= 0x04;</span><br><span>         }</span><br><span> </span><br><span>@@ -1712,13 +1729,17 @@</span><br><span>       * channel size on ch0.</span><br><span>       */</span><br><span>  if (size_me == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-             if (size_ch0 > size_ch1)</span><br><span style="color: hsl(120, 100%, 40%);">+           if (s->stacked_mode && size_ch1 != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                      single_channel_offset = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+            else if (size_ch0 > size_ch1)</span><br><span>                     single_channel_offset = dual_channel_size / 2</span><br><span>                                + single_channel_size;</span><br><span>               else</span><br><span>                         single_channel_offset = dual_channel_size / 2;</span><br><span>       } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                if ((size_ch0 > size_ch1) && ((map & 0x7) == 4))</span><br><span style="color: hsl(120, 100%, 40%);">+               if (s->stacked_mode && size_ch1 != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                      single_channel_offset = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+            else if ((size_ch0 > size_ch1) && ((map & 0x7) == 4))</span><br><span>                         single_channel_offset = dual_channel_size / 2</span><br><span>                                + single_channel_size;</span><br><span>               else</span><br><span>diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h</span><br><span>index 95f618d..ffbed2e 100644</span><br><span>--- a/src/northbridge/intel/x4x/x4x.h</span><br><span>+++ b/src/northbridge/intel/x4x/x4x.h</span><br><span>@@ -340,6 +340,9 @@</span><br><span>  struct dll_setting dqs_settings[TOTAL_CHANNELS][TOTAL_BYTELANES];</span><br><span>    struct dll_setting dq_settings[TOTAL_CHANNELS][TOTAL_BYTELANES];</span><br><span>     u8              nmode;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* at 533MHz memfreq the gfx device only works if channels</span><br><span style="color: hsl(120, 100%, 40%);">+     * are put in stacked mode */</span><br><span style="color: hsl(120, 100%, 40%);">+ u8              stacked_mode;</span><br><span> };</span><br><span> #define BOOT_PATH_NORMAL 0</span><br><span> #define BOOT_PATH_WARM_RESET       1</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/26563">change 26563</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/26563"/><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: I95965bfea129b37f64163159fefa1c8f16331b62 </div>
<div style="display:none"> Gerrit-Change-Number: 26563 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Arthur Heymans <arthur@aheymans.xyz> </div>