summaryrefslogtreecommitdiffstats
path: root/src/northbridge/intel/x4x/raminit_ddr2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/northbridge/intel/x4x/raminit_ddr2.c')
-rw-r--r--src/northbridge/intel/x4x/raminit_ddr2.c86
1 files changed, 59 insertions, 27 deletions
diff --git a/src/northbridge/intel/x4x/raminit_ddr2.c b/src/northbridge/intel/x4x/raminit_ddr2.c
index ddbcd5b7009b..6ee34adfc7a3 100644
--- a/src/northbridge/intel/x4x/raminit_ddr2.c
+++ b/src/northbridge/intel/x4x/raminit_ddr2.c
@@ -1157,8 +1157,8 @@ static void dradrb_ddr2(struct sysinfo *s)
u32 dra0;
u32 dra1;
u16 totalmemorymb;
- u32 size, offset;
- u32 size0, size1;
+ u32 dual_channel_size, single_channel_size, single_channel_offset;
+ u32 size_ch0, size_ch1, size_me;
u8 dratab[2][2][2][4] = {
{
{
@@ -1245,47 +1245,79 @@ static void dradrb_ddr2(struct sysinfo *s)
s->channel_capacity[0], s->channel_capacity[1], totalmemorymb);
/* Populated channel sizes in MiB */
- size0 = s->channel_capacity[0];
- size1 = s->channel_capacity[1];
+ size_ch0 = s->channel_capacity[0];
+ size_ch1 = s->channel_capacity[1];
+ size_me = ME_UMA_SIZEMB;
MCHBAR8(0x111) = MCHBAR8(0x111) & ~0x2;
MCHBAR8(0x111) = MCHBAR8(0x111) | (1 << 4);
- /* Set ME UMA size in MiB */
- MCHBAR16(0x100) = ME_UMA_SIZEMB;
-
- /* Set ME UMA Present bit */
- MCHBAR32(0x111) = MCHBAR32(0x111) | 1;
-
- size = MIN(size0 - ME_UMA_SIZEMB, size1) * 2;
-
- MCHBAR16(0x104) = size;
- MCHBAR16(0x102) = size0 + size1 - size;
+ if (size_me == 0) {
+ dual_channel_size = MIN(size_ch0, size_ch1) * 2;
+ } else {
+ if (size_ch0 == 0) {
+ /* ME needs ram on CH0 */
+ size_me = 0;
+ /* TOTEST: bailout? */
+ } else {
+ /* Set ME UMA size in MiB */
+ MCHBAR16(0x100) = size_me;
+ /* Set ME UMA Present bit */
+ MCHBAR32(0x111) = MCHBAR32(0x111) | 1;
+ }
+ dual_channel_size = MIN(size_ch0 - size_me, size_ch1) * 2;
+ }
+ MCHBAR16(0x104) = dual_channel_size;
+ single_channel_size = size_ch0 + size_ch1 - dual_channel_size;
+ MCHBAR16(0x102) = single_channel_size;
map = 0;
- if (size0 == 0)
+ if (size_ch0 == 0)
map = 0;
- else if (size1 == 0)
+ else if (size_ch1 == 0)
map |= 0x20;
else
map |= 0x40;
- if (size == 0)
+ if (dual_channel_size == 0)
map |= 0x18;
+ /* Enable flex mode, we hardcode this everywhere */
+ if (size_me == 0) {
+ map |= 0x04;
+ if (size_ch0 <= size_ch1)
+ map |= 0x01;
+ } else {
+ if (size_ch0 - size_me < size_ch1)
+ map |= 0x04;
+ }
- if (size0 - ME_UMA_SIZEMB >= size1)
- map |= 0x4;
MCHBAR8(0x110) = map;
MCHBAR16(0x10e) = 0;
- if (size1 != 0)
- offset = 0;
- else if ((size0 > size1) && ((map & 0x7) == 0x4))
- offset = size/2 + (size0 + size1 - size);
- else
- offset = size/2 + ME_UMA_SIZEMB;
- MCHBAR16(0x108) = offset;
- MCHBAR16(0x10a) = size/2;
+ /*
+ * "108h[15:0] Single Channel Offset for Ch0"
+ * This is the 'limit' of the part on CH0 that cannot be matched
+ * with memory on CH1. MCHBAR16(0x10a) is where the dual channel
+ * memory on ch0s end and MCHBAR16(0x108) is the limit of the single
+ * channel size on ch0.
+ */
+ if (size_me == 0) {
+ if (size_ch0 > size_ch1)
+ single_channel_offset = dual_channel_size / 2
+ + single_channel_size;
+ else
+ single_channel_offset = dual_channel_size / 2;
+ } else {
+ if ((size_ch0 > size_ch1) && ((map & 0x7) == 4))
+ single_channel_offset = dual_channel_size / 2
+ + single_channel_size;
+ else
+ single_channel_offset = dual_channel_size / 2
+ + size_me;
+ }
+
+ MCHBAR16(0x108) = single_channel_offset;
+ MCHBAR16(0x10a) = dual_channel_size / 2;
}
static void mmap_ddr2(struct sysinfo *s)