mail.coreboot.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2025
May
April
March
February
January
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
List overview
Download
coreboot-gerrit
May 2017
----- 2025 -----
May 2025
April 2025
March 2025
February 2025
January 2025
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
coreboot-gerrit@coreboot.org
1 participants
3888 discussions
Start a n
N
ew thread
Change in coreboot[master]: nb/intel/x4x: DDR3 JEDEC init
by Arthur Heymans (Code Review)
24 May '17
24 May '17
Arthur Heymans has uploaded a new change for review. (
https://review.coreboot.org/19877
) Change subject: nb/intel/x4x: DDR3 JEDEC init ...................................................................... nb/intel/x4x: DDR3 JEDEC init Change-Id: I3b5eeb0aff6764292bbcbed7274274f615066c14 Signed-off-by: Arthur Heymans <arthur(a)aheymans.xyz> --- M src/northbridge/intel/x4x/raminit_ddr23.c M src/northbridge/intel/x4x/spd_ddr3_decode.c M src/northbridge/intel/x4x/x4x.h 3 files changed, 78 insertions(+), 9 deletions(-) git pull ssh://review.coreboot.org:29418/coreboot refs/changes/77/19877/1 diff --git a/src/northbridge/intel/x4x/raminit_ddr23.c b/src/northbridge/intel/x4x/raminit_ddr23.c index 0d09c05..a289788 100644 --- a/src/northbridge/intel/x4x/raminit_ddr23.c +++ b/src/northbridge/intel/x4x/raminit_ddr23.c @@ -1269,14 +1269,31 @@ } } -static void send_jedec_cmd(u8 r, u8 ch, u8 cmd, u16 val) +void send_jedec_cmd(const struct sysinfo *s, u8 r, u8 ch, u8 cmd, u32 val) { u32 addr = (ch << 29) | (r*0x08000000); volatile u32 rubbish; + u8 data8 = cmd; + u32 data32; - MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0x3e) | cmd; - MCHBAR8(0x671) = (MCHBAR8(0x671) & ~0x3e) | cmd; - rubbish = read32((void *)((val<<3) | addr)); + if (s->spd_type == DDR3 && (r & 1) && s->dimms[r].mirrorred) { + data8 &= ~(1 << 4); + data8 |= ((1 << 4) & (cmd >> 1)); + data8 &= ~(1 << 5); + data8 |= ((1 << 5) & (cmd << 1)); + } + + MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0x3e) | data8; + MCHBAR8(0x671) = (MCHBAR8(0x671) & ~0x3e) | data8; + data32 = val; + if (s->spd_type == DDR3 && (r & 1) && s->dimms[r].mirrorred) { + data32 &= ~(0x1f8); + data32 |= (val & 0xb0) << 1; + data32 |= (val & 0x160) >> 1; + } + data32 <<= 3; + + rubbish = read32((void *)((data32 | addr))); udelay(10); MCHBAR8(0x271) = (MCHBAR8(0x271) & ~0x3e) | NORMALOP_CMD; MCHBAR8(0x671) = (MCHBAR8(0x671) & ~0x3e) | NORMALOP_CMD; @@ -1341,7 +1358,7 @@ default: break; } - send_jedec_cmd(r + ch*4, ch, jedec[i][0], v); + send_jedec_cmd(s, r + ch*4, ch, jedec[i][0], v); udelay(1); //printk(BIOS_DEBUG, "Jedec step %d\n", i); } @@ -1349,6 +1366,51 @@ printk(BIOS_DEBUG, "MRS done\n"); } +static void jedec_ddr3(struct sysinfo *s) +{ + int ch, r, dimmconfig, cmd, ddr3_freq; + + u8 ddr3_emrs2_config[16][4] = { /* [config][Rank] */ + {0, 0, 0, 0}, /* NC_NC */ + {0, 0, 0, 0}, /* x8ss_NC */ + {0, 0, 0, 0}, /* x8ds_NC */ + {0, 0, 0, 0}, /* x16ss_NC */ + {0, 0, 0, 0}, /* NC_x8ss */ + {2, 0, 2, 0}, /* x8ss_x8ss */ + {2, 2, 2, 0}, /* x8ds_x8ss */ + {2, 0, 2, 0}, /* x16ss_x8ss */ + {0, 0, 0, 0}, /* NC_x8ss */ + {2, 0, 2, 2}, /* x8ss_x8ds */ + {2, 2, 2, 2}, /* x8ds_x8ds */ + {2, 0, 2, 2}, /* x16ss_x8ds */ + {0, 0, 0, 0}, /* NC_x16ss */ + {2, 0, 2, 0}, /* x8ss_x16ss */ + {2, 2, 2, 0}, /* x8ds_x16ss */ + {2, 0, 2, 0}, /* x16ss_x16ss */ + }; + + printk(BIOS_DEBUG, "MRS...\n"); + + ddr3_freq = s->selected_timings.mem_clk - MEM_CLOCK_800MHz; + FOR_EACH_POPULATED_RANK(s->dimms, ch, r) { + printk(BIOS_DEBUG, "CH%d: Found Rank %d\n", ch, r); + send_jedec_cmd(s, r + ch * 4, ch, NOP_CMD, 0); + udelay(200); + dimmconfig = s->dimm_config[ch]; + cmd = ddr3_freq << 3; /* actually twl - 5 which is same */ + cmd |= ddr3_emrs2_config[dimmconfig][r] << 9; + send_jedec_cmd(s, r + ch * 4, ch, EMRS2_CMD, cmd); + send_jedec_cmd(s, r + ch * 4, ch, EMRS3_CMD, 0); + cmd = ddr3_emrs1_config[dimmconfig][r] << 2; + cmd |= (1 << 1); + send_jedec_cmd(s, r + ch * 4, ch, EMRS1_CMD, cmd); + send_jedec_cmd(s, r + ch * 4, ch, MRS_CMD, (1 << 3) | (1 << 8) + | (1 << 12) | ((s->selected_timings.CAS - 4) << 4) + | ((s->selected_timings.tWR - 4) << 9)); + send_jedec_cmd(s, r + ch * 4, ch, ZQCAL_CMD, (1 << 10)); + } + printk(BIOS_DEBUG, "MRS done\n"); +} static u8 sampledqs(u16 mchloc, u32 addr, u8 hilow, u8 repeat) { u8 dqsmatch = 1; @@ -2163,9 +2225,12 @@ MCHBAR16(0x212) = (MCHBAR16(0x212) & ~0xf00) | 0xf00; printk(BIOS_DEBUG, "Done pre-jedec\n"); - // JEDEC reset - if (s->boot_path != BOOT_PATH_RESUME) - jedec_ddr2(s); + if (s->boot_path != BOOT_PATH_RESUME) { + if (s->spd_type == DDR2) + jedec_ddr2(s); + else + jedec_ddr3(s); + } printk(BIOS_DEBUG, "Done jedec steps\n"); diff --git a/src/northbridge/intel/x4x/spd_ddr3_decode.c b/src/northbridge/intel/x4x/spd_ddr3_decode.c index fd69fd4..eab0548 100644 --- a/src/northbridge/intel/x4x/spd_ddr3_decode.c +++ b/src/northbridge/intel/x4x/spd_ddr3_decode.c @@ -152,6 +152,8 @@ s->dimms[dimm_idx].rows = decoded_dimm.row_bits; s->dimms[dimm_idx].cols = decoded_dimm.col_bits; + s->dimms[dimm_idx].mirrorred = decoded_dimm.flags.pins_mirrored; + saved_timings->min_tRAS = MAX(saved_timings->min_tRAS, decoded_dimm.tRAS); saved_timings->min_tRP = diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h index 9ef07b3..c2eea38 100644 --- a/src/northbridge/intel/x4x/x4x.h +++ b/src/northbridge/intel/x4x/x4x.h @@ -276,6 +276,7 @@ unsigned int ranks; unsigned int rows; unsigned int cols; + u8 mirrorred; }; /* The setup is up to two DIMMs per channel */ @@ -355,6 +356,7 @@ struct abs_timings *saved_timings); int ddr3_save_dimminfo(u8 dimm_idx, u8 *raw_spd, struct abs_timings *saved_timings, struct sysinfo *s); +void send_jedec_cmd(const struct sysinfo *s, u8 r, u8 ch, u8 cmd, u32 val); void dqsset(u8 ch, u8 lane, const struct dll_setting *setting); void dqset(u8 ch, u8 lane, const struct dll_setting *setting); @@ -364,7 +366,7 @@ extern const struct dll_setting ddr3_dll_setting_800[2][23]; extern const struct dll_setting ddr3_dll_setting_1066[2][23]; extern const struct dll_setting ddr3_dll_setting_1333[2][23]; - +extern const u8 ddr3_emrs1_config[16][4]; struct acpi_rsdp; #ifndef __SIMPLE_DEVICE__ -- To view, visit
https://review.coreboot.org/19877
To unsubscribe, visit
https://review.coreboot.org/settings
Gerrit-MessageType: newchange Gerrit-Change-Id: I3b5eeb0aff6764292bbcbed7274274f615066c14 Gerrit-PatchSet: 1 Gerrit-Project: coreboot Gerrit-Branch: master Gerrit-Owner: Arthur Heymans <arthur(a)aheymans.xyz>
1
0
0
0
Change in coreboot[master]: nb/intel/x4x: Add DDR3 rcomp
by Arthur Heymans (Code Review)
24 May '17
24 May '17
Arthur Heymans has uploaded a new change for review. (
https://review.coreboot.org/19875
) Change subject: nb/intel/x4x: Add DDR3 rcomp ...................................................................... nb/intel/x4x: Add DDR3 rcomp Change-Id: Ifef905f5115ffc826b1a355e54c4b1ca818e56fa Signed-off-by: Arthur Heymans <arthur(a)aheymans.xyz> --- M src/northbridge/intel/x4x/raminit_ddr23.c 1 file changed, 95 insertions(+), 45 deletions(-) git pull ssh://review.coreboot.org:29418/coreboot refs/changes/75/19875/1 diff --git a/src/northbridge/intel/x4x/raminit_ddr23.c b/src/northbridge/intel/x4x/raminit_ddr23.c index 673ebad..28e242c 100644 --- a/src/northbridge/intel/x4x/raminit_ddr23.c +++ b/src/northbridge/intel/x4x/raminit_ddr23.c @@ -1095,60 +1095,110 @@ static void rcomp_ddr2(struct sysinfo *s) { - u8 i, j, k; - u32 x32a[8] = { 0x04040404, 0x06050505, 0x09090807, 0x0D0C0B0A, + u8 i, j, k, reg8; + const u32 ddr2_x32a[8] = { 0x04040404, 0x06050505, 0x09090807, 0x0D0C0B0A, 0x04040404, 0x08070605, 0x0C0B0A09, 0x100F0E0D }; - u16 x378[6] = { 0, 0xAAAA, 0x7777, 0x7777, 0x7777, 0x7777 }; - u32 x382[6] = { 0, 0x02020202, 0x02020202, 0x02020202, 0x04030303, 0x04030303 }; - u32 x386[6] = { 0, 0x03020202, 0x03020202, 0x03020202, 0x05040404, 0x05040404 }; - u32 x38a[6] = { 0, 0x04040303, 0x04040303, 0x04040303, 0x07070605, 0x07070605 }; - u32 x38e[6] = { 0, 0x06060505, 0x06060505, 0x06060505, 0x09090808, 0x09090808 }; - u32 x392[6] = { 0, 0x02020202, 0x02020202, 0x02020202, 0x03030202, 0x03030202 }; - u32 x396[6] = { 0, 0x03030202, 0x03030202, 0x03030202, 0x05040303, 0x05040303 }; - u32 x39a[6] = { 0, 0x04040403, 0x04040403, 0x04040403, 0x07070605, 0x07070605 }; - u32 x39e[6] = { 0, 0x06060505, 0x06060505, 0x06060505, 0x08080808, 0x08080808 }; - u16 addr[6] = { 0x31c, 0x374, 0x3a2, 0x3d0, 0x3fe, 0x42c }; + const u16 ddr2_x378[6] = { 0, 0xAAAA, 0x7777, 0x7777, 0x7777, 0x7777 }; + const u32 ddr2_x382[6] = { 0, 0x02020202, 0x02020202, 0x02020202, 0x04030303, 0x04030303 }; + const u32 ddr2_x386[6] = { 0, 0x03020202, 0x03020202, 0x03020202, 0x05040404, 0x05040404 }; + const u32 ddr2_x38a[6] = { 0, 0x04040303, 0x04040303, 0x04040303, 0x07070605, 0x07070605 }; + const u32 ddr2_x38e[6] = { 0, 0x06060505, 0x06060505, 0x06060505, 0x09090808, 0x09090808 }; + const u32 ddr2_x392[6] = { 0, 0x02020202, 0x02020202, 0x02020202, 0x03030202, 0x03030202 }; + const u32 ddr2_x396[6] = { 0, 0x03030202, 0x03030202, 0x03030202, 0x05040303, 0x05040303 }; + const u32 ddr2_x39a[6] = { 0, 0x04040403, 0x04040403, 0x04040403, 0x07070605, 0x07070605 }; + const u32 ddr2_x39e[6] = { 0, 0x06060505, 0x06060505, 0x06060505, 0x08080808, 0x08080808 }; + + const u32 ddr3_x32a[8] = {0x06060606, 0x06060606, 0x0b090807, 0x12110f0d, + 0x06060606, 0x08070606, 0x0d0b0a09, 0x16161511}; + const u32 ddr3_x378[6] = {0x0000, 0xbbbb, 0x6666, 0x6666, 0x6666, 0x6666}; + const u32 ddr3_x382[6] = {0x00000000, 0x05050505, 0x04040404, 0x04040404, 0x34343434, 0x34343434}; + const u32 ddr3_x386[6] = {0x00000000, 0x05050505, 0x04040404, 0x04040404, 0x34343434, 0x34343434}; + const u32 ddr3_x38a[6] = {0x00000000, 0x06060605, 0x07060504, 0x07060504, 0x34343434, 0x34343434}; + const u32 ddr3_x38e[6] = {0x00000000, 0x09080707, 0x09090808, 0x09090808, 0x34343434, 0x34343434}; + const u32 ddr3_x392[6] = {0x00000000, 0x05050505, 0x04040404, 0x04040404, 0x34343434, 0x34343434}; + const u32 ddr3_x396[6] = {0x00000000, 0x05050505, 0x04040404, 0x04040404, 0x34343434, 0x34343434}; + const u32 ddr3_x39a[6] = {0x00000000, 0x07060606, 0x08070605, 0x08070605, 0x34343434, 0x34343434}; + const u32 ddr3_x39e[6] = {0x00000000, 0x09090807, 0x0b0b0a09, 0x0b0b0a09, 0x34343434, 0x34343434}; + + const u16 addr[6] = { 0x31c, 0x374, 0x3a2, 0x3d0, 0x3fe, 0x42c }; u8 bit[6] = { 0, 0, 1, 1, 0, 0 }; FOR_EACH_POPULATED_CHANNEL(s->dimms, i) { for (j = 0; j < 6; j++) { - if (j == 0) { - MCHBAR32(0x400*i + addr[j]) = - (MCHBAR32(0x400*i + addr[j]) & ~0xff000) | 0xaa000; - MCHBAR16(0x400*i + 0x320) = (MCHBAR16(0x400*i + 0x320) & ~0xffff) | 0x6666; - for (k = 0; k < 8; k++) { - MCHBAR32(0x400*i + addr[j] + 0xe + (k << 2)) = - (MCHBAR32(0x400*i + addr[j] + 0xe + (k << 2)) & ~0x3f3f3f3f) | x32a[k]; - MCHBAR32(0x400*i + addr[j] + 0x2e + (k << 2)) = - (MCHBAR32(0x400*i + addr[j] + 0x2e + (k << 2)) & ~0x3f3f3f3f) | x32a[k]; + if (s->spd_type == DDR2) { + if (j == 0) { + MCHBAR32(0x400*i + addr[j]) = + (MCHBAR32(0x400*i + addr[j]) & ~0xff000) | 0xaa000; + MCHBAR16(0x400*i + 0x320) = (MCHBAR16(0x400*i + 0x320) & ~0xffff) | 0x6666; + for (k = 0; k < 8; k++) { + MCHBAR32(0x400*i + addr[j] + 0xe + (k << 2)) = + (MCHBAR32(0x400*i + addr[j] + 0xe + (k << 2)) & ~0x3f3f3f3f) | ddr2_x32a[k]; + MCHBAR32(0x400*i + addr[j] + 0x2e + (k << 2)) = + (MCHBAR32(0x400*i + addr[j] + 0x2e + (k << 2)) & ~0x3f3f3f3f) | ddr2_x32a[k]; + } + } else { + MCHBAR16(0x400*i + addr[j]) = (MCHBAR16(0x400*i + addr[j]) & ~0xf000) | 0xa000; + MCHBAR16(0x400*i + addr[j] + 4) = (MCHBAR16(0x400*i + addr[j] + 4) & ~0xffff) | + ddr2_x378[j]; + MCHBAR32(0x400*i + addr[j] + 0xe) = + (MCHBAR32(0x400*i + addr[j] + 0xe) & ~0x3f3f3f3f) | ddr2_x382[j]; + MCHBAR32(0x400*i + addr[j] + 0x12) = + (MCHBAR32(0x400*i + addr[j] + 0x12) & ~0x3f3f3f3f) | ddr2_x386[j]; + MCHBAR32(0x400*i + addr[j] + 0x16) = + (MCHBAR32(0x400*i + addr[j] + 0x16) & ~0x3f3f3f3f) | ddr2_x38a[j]; + MCHBAR32(0x400*i + addr[j] + 0x1a) = + (MCHBAR32(0x400*i + addr[j] + 0x1a) & ~0x3f3f3f3f) | ddr2_x38e[j]; + MCHBAR32(0x400*i + addr[j] + 0x1e) = + (MCHBAR32(0x400*i + addr[j] + 0x1e) & ~0x3f3f3f3f) | ddr2_x392[j]; + MCHBAR32(0x400*i + addr[j] + 0x22) = + (MCHBAR32(0x400*i + addr[j] + 0x22) & ~0x3f3f3f3f) | ddr2_x396[j]; + MCHBAR32(0x400*i + addr[j] + 0x26) = + (MCHBAR32(0x400*i + addr[j] + 0x26) & ~0x3f3f3f3f) | ddr2_x39a[j]; + MCHBAR32(0x400*i + addr[j] + 0x2a) = + (MCHBAR32(0x400*i + addr[j] + 0x2a) & ~0x3f3f3f3f) | ddr2_x39e[j]; } - } else { - MCHBAR16(0x400*i + addr[j]) = (MCHBAR16(0x400*i + addr[j]) & ~0xf000) | 0xa000; - MCHBAR16(0x400*i + addr[j] + 4) = (MCHBAR16(0x400*i + addr[j] + 4) & ~0xffff) | - x378[j]; - MCHBAR32(0x400*i + addr[j] + 0xe) = - (MCHBAR32(0x400*i + addr[j] + 0xe) & ~0x3f3f3f3f) | x382[j]; - MCHBAR32(0x400*i + addr[j] + 0x12) = - (MCHBAR32(0x400*i + addr[j] + 0x12) & ~0x3f3f3f3f) | x386[j]; - MCHBAR32(0x400*i + addr[j] + 0x16) = - (MCHBAR32(0x400*i + addr[j] + 0x16) & ~0x3f3f3f3f) | x38a[j]; - MCHBAR32(0x400*i + addr[j] + 0x1a) = - (MCHBAR32(0x400*i + addr[j] + 0x1a) & ~0x3f3f3f3f) | x38e[j]; - MCHBAR32(0x400*i + addr[j] + 0x1e) = - (MCHBAR32(0x400*i + addr[j] + 0x1e) & ~0x3f3f3f3f) | x392[j]; - MCHBAR32(0x400*i + addr[j] + 0x22) = - (MCHBAR32(0x400*i + addr[j] + 0x22) & ~0x3f3f3f3f) | x396[j]; - MCHBAR32(0x400*i + addr[j] + 0x26) = - (MCHBAR32(0x400*i + addr[j] + 0x26) & ~0x3f3f3f3f) | x39a[j]; - MCHBAR32(0x400*i + addr[j] + 0x2a) = - (MCHBAR32(0x400*i + addr[j] + 0x2a) & ~0x3f3f3f3f) | x39e[j]; + } else { /* DDR3 */ + if (j == 0) { + MCHBAR32(0x400*i + addr[j]) = + (MCHBAR32(0x400*i + addr[j]) & ~0xff000) | 0xaa000; + MCHBAR16(0x400*i + 0x320) = (MCHBAR16(0x400*i + 0x320) & ~0xffff) | 0x6666; + for (k = 0; k < 8; k++) { + MCHBAR32(0x400*i + addr[j] + 0xe + (k << 2)) = + (MCHBAR32(0x400*i + addr[j] + 0xe + (k << 2)) & ~0x3f3f3f3f) | ddr3_x32a[k]; + MCHBAR32(0x400*i + addr[j] + 0x2e + (k << 2)) = + (MCHBAR32(0x400*i + addr[j] + 0x2e + (k << 2)) & ~0x3f3f3f3f) | ddr3_x32a[k]; + } + } else { + MCHBAR16(0x400*i + addr[j]) = (MCHBAR16(0x400*i + addr[j]) & ~0xf000) | 0xa000; + MCHBAR16(0x400*i + addr[j] + 4) = (MCHBAR16(0x400*i + addr[j] + 4) & ~0xffff) | + ddr3_x378[j]; + MCHBAR32(0x400*i + addr[j] + 0xe) = + (MCHBAR32(0x400*i + addr[j] + 0xe) & ~0x3f3f3f3f) | ddr3_x382[j]; + MCHBAR32(0x400*i + addr[j] + 0x12) = + (MCHBAR32(0x400*i + addr[j] + 0x12) & ~0x3f3f3f3f) | ddr3_x386[j]; + MCHBAR32(0x400*i + addr[j] + 0x16) = + (MCHBAR32(0x400*i + addr[j] + 0x16) & ~0x3f3f3f3f) | ddr3_x38a[j]; + MCHBAR32(0x400*i + addr[j] + 0x1a) = + (MCHBAR32(0x400*i + addr[j] + 0x1a) & ~0x3f3f3f3f) | ddr3_x38e[j]; + MCHBAR32(0x400*i + addr[j] + 0x1e) = + (MCHBAR32(0x400*i + addr[j] + 0x1e) & ~0x3f3f3f3f) | ddr3_x392[j]; + MCHBAR32(0x400*i + addr[j] + 0x22) = + (MCHBAR32(0x400*i + addr[j] + 0x22) & ~0x3f3f3f3f) | ddr3_x396[j]; + MCHBAR32(0x400*i + addr[j] + 0x26) = + (MCHBAR32(0x400*i + addr[j] + 0x26) & ~0x3f3f3f3f) | ddr3_x39a[j]; + MCHBAR32(0x400*i + addr[j] + 0x2a) = + (MCHBAR32(0x400*i + addr[j] + 0x2a) & ~0x3f3f3f3f) | ddr3_x39e[j]; + } + if (BOTH_DIMMS_ARE_POPULATED(s->dimms, i)) + MCHBAR16(0x378 + 0x400 * i) = (MCHBAR16(0x378 + 0x400 * i) & ~0xffff) | 0xcccc; } MCHBAR8(0x400*i + addr[j]) = (MCHBAR8(0x400*i + addr[j]) & ~1) | bit[j]; } - MCHBAR8(0x400*i + 0x45a) = (MCHBAR8(0x400*i + 0x45a) & ~0x3f) | 0x12; - MCHBAR8(0x400*i + 0x45e) = (MCHBAR8(0x400*i + 0x45e) & ~0x3f) | 0x12; - MCHBAR8(0x400*i + 0x462) = (MCHBAR8(0x400*i + 0x462) & ~0x3f) | 0x12; - MCHBAR8(0x400*i + 0x466) = (MCHBAR8(0x400*i + 0x466) & ~0x3f) | 0x12; + reg8 = (s->spd_type == DDR2) ? 0x12 : 0x36; + MCHBAR8(0x400*i + 0x45a) = (MCHBAR8(0x400*i + 0x45a) & ~0x3f) | reg8; + MCHBAR8(0x400*i + 0x45e) = (MCHBAR8(0x400*i + 0x45e) & ~0x3f) | reg8; + MCHBAR8(0x400*i + 0x462) = (MCHBAR8(0x400*i + 0x462) & ~0x3f) | reg8; + MCHBAR8(0x400*i + 0x466) = (MCHBAR8(0x400*i + 0x466) & ~0x3f) | reg8; } // END EACH POPULATED CHANNEL MCHBAR32(0x134) = (MCHBAR32(0x134) & ~0x63c00) | 0x63c00; -- To view, visit
https://review.coreboot.org/19875
To unsubscribe, visit
https://review.coreboot.org/settings
Gerrit-MessageType: newchange Gerrit-Change-Id: Ifef905f5115ffc826b1a355e54c4b1ca818e56fa Gerrit-PatchSet: 1 Gerrit-Project: coreboot Gerrit-Branch: master Gerrit-Owner: Arthur Heymans <arthur(a)aheymans.xyz>
1
0
0
0
Change in coreboot[master]: nb/intel/x4x/raminit: Support programming initials DD3 DLL s...
by Arthur Heymans (Code Review)
24 May '17
24 May '17
Arthur Heymans has uploaded a new change for review. (
https://review.coreboot.org/19874
) Change subject: nb/intel/x4x/raminit: Support programming initials DD3 DLL setting ...................................................................... nb/intel/x4x/raminit: Support programming initials DD3 DLL setting Due to shear amount of tables for default DLL settings used, they are mostly pushed to a new file to avoid cluttering up the raminit. Change-Id: Ia79b216ad69a02d4706ffc74f867a85db3eb2d6c Signed-off-by: Arthur Heymans <arthur(a)aheymans.xyz> --- M src/northbridge/intel/x4x/Makefile.inc M src/northbridge/intel/x4x/raminit_ddr23.c A src/northbridge/intel/x4x/raminit_tables.c M src/northbridge/intel/x4x/x4x.h 4 files changed, 470 insertions(+), 136 deletions(-) git pull ssh://review.coreboot.org:29418/coreboot refs/changes/74/19874/1 diff --git a/src/northbridge/intel/x4x/Makefile.inc b/src/northbridge/intel/x4x/Makefile.inc index ae8d388..8b59dbf 100644 --- a/src/northbridge/intel/x4x/Makefile.inc +++ b/src/northbridge/intel/x4x/Makefile.inc @@ -22,6 +22,7 @@ romstage-y += ram_calc.c romstage-y += spd_ddr2_decode.c romstage-y += spd_ddr3_decode.c +romstage-y += raminit_tables.c ramstage-y += acpi.c ramstage-y += ram_calc.c diff --git a/src/northbridge/intel/x4x/raminit_ddr23.c b/src/northbridge/intel/x4x/raminit_ddr23.c index 4db29f5..673ebad 100644 --- a/src/northbridge/intel/x4x/raminit_ddr23.c +++ b/src/northbridge/intel/x4x/raminit_ddr23.c @@ -367,9 +367,10 @@ setting->tap; } -static void dqsset(u8 ch, u8 lane, const struct dll_setting *setting) +void dqsset(u8 ch, u8 lane, const struct dll_setting *setting) { - MCHBAR32(0x400*ch + 0x5fc) = MCHBAR32(0x400*ch + 0x5fc) & ~(2 << (lane*4)); + MCHBAR32(0x400*ch + 0x5fc) = (MCHBAR32(0x400*ch + 0x5fc) & ~(2 << (lane*4))) + | (setting->coarse << ((lane * 4) + 1)); MCHBAR32(0x400*ch + 0x5b4) = (MCHBAR32(0x400*ch + 0x5b4) & ~(0x201 << lane)) | (setting->db_en << (9 + lane)) | @@ -411,10 +412,10 @@ setting->tap; } -static void dqset(u8 ch, u8 lane, const struct dll_setting *setting) +void dqset(u8 ch, u8 lane, const struct dll_setting *setting) { - MCHBAR32(0x400*ch + 0x5fc) = MCHBAR32(0x400*ch + 0x5fc) & ~(1 << (lane*4)); - + MCHBAR32(0x400*ch + 0x5fc) = (MCHBAR32(0x400*ch + 0x5fc) & ~(1 << (lane*4))) | + (setting->coarse << (lane * 4)); MCHBAR32(0x400*ch + 0x5a4) = (MCHBAR32(0x400*ch + 0x5a4) & ~(0x201 << lane)) | (setting->db_en << (9 + lane)) | (setting->db_sel << lane); @@ -615,7 +616,12 @@ MCHBAR16(0x400*i + 0x25b) = ((s->selected_timings.tRP + trpmod) << 9) | s->selected_timings.tRFC; - MCHBAR16(0x400*i + 0x260) = (MCHBAR16(0x400*i + 0x260) & ~0x3fe) | (100 << 1); + if (s->spd_type == DDR2) + MCHBAR16(0x400*i + 0x260) = + (MCHBAR16(0x400*i + 0x260) & ~0x3fe) | (100 << 1); + else + MCHBAR16(0x400*i + 0x260) = + (MCHBAR16(0x400*i + 0x260) & ~0x3fe) | (256 << 1); MCHBAR8(0x400*i + 0x264) = 0xff; MCHBAR8(0x400*i + 0x25d) = (MCHBAR8(0x400*i + 0x25d) & ~0x3f) | s->selected_timings.tRAS; @@ -668,17 +674,30 @@ MCHBAR8(0x400*i + 0x24c) = MCHBAR8(0x400*i + 0x24c) & ~0x3; reg16 = 0; - switch (s->selected_timings.mem_clk) { - default: - case MEM_CLOCK_667MHz: - reg16 = 0x99; - break; - case MEM_CLOCK_800MHz: - if (s->selected_timings.CAS == 5) - reg16 = 0x19a; - else if (s->selected_timings.CAS == 6) - reg16 = 0x9a; - break; + if (s->spd_type == DDR2) { + switch (s->selected_timings.mem_clk) { + default: + case MEM_CLOCK_667MHz: + reg16 = 0x99; + break; + case MEM_CLOCK_800MHz: + if (s->selected_timings.CAS == 5) + reg16 = 0x19a; + else if (s->selected_timings.CAS == 6) + reg16 = 0x9a; + break; + } + } else { /* DDR3 */ + switch (s->selected_timings.mem_clk) { + default: + case MEM_CLOCK_800MHz: + case MEM_CLOCK_1066MHz: + reg16 = 1; + break; + case MEM_CLOCK_1333MHz: + reg16 = 2; + break; + } } reg16 &= 0x7; reg16 += twl + 9; @@ -715,8 +734,37 @@ MCHBAR8(0x12d) = (MCHBAR8(0x12d) & ~0xf) | reg8; MCHBAR8(0x12f) = 0x4c; reg32 = (1 << 31) | (0x80 << 14) | (1 << 13) | (0xa << 9); + if (s->spd_type == DDR3) { + MCHBAR8(0x114) = 0x42; + reg16 = (512 - MAX(5, s->selected_timings.tRFC + + 10000 / ddr2ps[s->selected_timings.mem_clk])) / 2; + reg16 &= 0x1ff; + reg32 = (reg16 << 22) | (0x80 << 14) | (0xa << 9); + } MCHBAR32(0x6c0) = (MCHBAR32(0x6c0) & ~0xffffff00) | reg32; MCHBAR8(0x6c4) = (MCHBAR8(0x6c4) & ~0x7) | 0x2; +} + +static void program_dll_clk_ctrl(int channel, const struct dll_setting *dll_settings) +{ + clkset0(channel, &dll_settings[CLKSET0]); + clkset1(channel, &dll_settings[CLKSET1]); + ctrlset0(channel, &dll_settings[CTRL0]); + ctrlset1(channel, &dll_settings[CTRL1]); + ctrlset2(channel, &dll_settings[CTRL2]); + ctrlset3(channel, &dll_settings[CTRL3]); + cmdset(channel, &dll_settings[CMD]); +} + +static void program_dq_dqs(u8 channel, const struct dll_setting dll_setting[23]) +{ + int lane; + for (lane = 0; lane < 8; lane++) { + dqsset(channel, lane, &dll_setting[DQS1 + lane]); + } + for (lane = 0; lane < 8; lane++) { + dqset(channel, lane, &dll_setting[DQ1 + lane]); + } } static void program_dll(struct sysinfo *s) @@ -726,6 +774,9 @@ u32 reg32 = 0; u8 lane; + const u8 rank2clken[8] = { 0x04, 0x01, 0x20, 0x08, 0x01, 0x04, + 0x08, 0x10 }; + MCHBAR16(0x180) = (MCHBAR16(0x180) & ~0x7e06) | 0xc04; MCHBAR16(0x182) = (MCHBAR16(0x182) & ~0x3ff) | 0xc8; MCHBAR16(0x18a) = (MCHBAR16(0x18a) & ~0x1f1f) | 0x0f0f; @@ -734,10 +785,14 @@ switch (s->selected_timings.mem_clk) { default: case MEM_CLOCK_667MHz: + case MEM_CLOCK_1333MHz: reg16 = (0xa << 9) | 0xa; break; case MEM_CLOCK_800MHz: reg16 = (0x9 << 9) | 0x9; + break; + case MEM_CLOCK_1066MHz: + reg16 = (0x7 << 9) | 0x7; break; } MCHBAR16(0x19c) = (MCHBAR16(0x19c) & ~0x1e0f) | reg16; @@ -762,14 +817,29 @@ udelay(1); // 533ns // ME related - MCHBAR32(0x1a0) = (MCHBAR32(0x1a0) & ~0x7ffffff) | 0x551803; + if (s->spd_type == DDR2) + MCHBAR32(0x1a0) = (MCHBAR32(0x1a0) & ~0x7ffffff) | 0x551803; + else /* DDR3 */ + MCHBAR32(0x1a0) = (MCHBAR32(0x1a0) & ~0x7ffffff) | 0x555801; MCHBAR16(0x1b4) = MCHBAR16(0x1b4) & ~0x800; - MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 0xf0; + if (s->spd_type == DDR2) { + MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 0xf0; + } else { /* DDR3 */ + reg8 = 0x9; /* 0x9 << 4 ?? */ + if (s->dimms[0].ranks == 2) + reg8 &= ~0x80; + if (s->dimms[3].ranks == 2) + reg8 &= ~0x10; + MCHBAR8(0x1a8) = (MCHBAR8(0x1a8) & ~0xf0) | reg8; + } + FOR_EACH_CHANNEL(i) { reg16 = 0; - MCHBAR16(0x400*i + 0x59c) = MCHBAR16(0x400*i + 0x59c) & ~0x3000; + if ((s->spd_type == DDR3) && (i == 0)) + reg16 = (0x3 << 12); + MCHBAR16(0x400*i + 0x59c) = (MCHBAR16(0x400*i + 0x59c) & ~0x3000) | reg16; reg32 = 0; FOR_EACH_RANK_IN_CHANNEL(r) { @@ -780,114 +850,82 @@ MCHBAR32(0x400*i + 0x59c) = (MCHBAR32(0x400*i + 0x59c) & ~0xfff) | reg32; MCHBAR8(0x400*i + 0x594) = MCHBAR8(0x400*i + 0x594) & ~1; - if (!CHANNEL_IS_POPULATED(s->dimms, i)) { - printk(BIOS_DEBUG, "No dimms in channel %d\n", i); - reg8 = 0x3f; - } else if (ONLY_DIMMA_IS_POPULATED(s->dimms, i)) { - printk(BIOS_DEBUG, "DimmA populated only in channel %d\n", i); - reg8 = 0x38; - } else if (ONLY_DIMMB_IS_POPULATED(s->dimms, i)) { - printk(BIOS_DEBUG, "DimmB populated only in channel %d\n", i); - reg8 = 0x7; - } else if (BOTH_DIMMS_ARE_POPULATED(s->dimms, i)) { - printk(BIOS_DEBUG, "Both dimms populated in channel %d\n", i); - reg8 = 0; - } else { - die("Unhandled case\n"); - } - - //reg8 = 0x00; // FIXME don't switch on all clocks anyway - - MCHBAR32(0x400*i + 0x5a0) = (MCHBAR32(0x400*i + 0x5a0) & ~0x3f000000) | + if (s->spd_type == DDR2) { + if (!CHANNEL_IS_POPULATED(s->dimms, i)) { + printk(BIOS_DEBUG, "No dimms in channel %d\n", i); + reg8 = 0x3f; + } else if (ONLY_DIMMA_IS_POPULATED(s->dimms, i)) { + printk(BIOS_DEBUG, "DimmA populated only in channel %d\n", i); + reg8 = 0x38; + } else if (ONLY_DIMMB_IS_POPULATED(s->dimms, i)) { + printk(BIOS_DEBUG, "DimmB populated only in channel %d\n", i); + reg8 = 0x7; + } else if (BOTH_DIMMS_ARE_POPULATED(s->dimms, i)) { + printk(BIOS_DEBUG, "Both dimms populated in channel %d\n", i); + reg8 = 0; + } else { + die("Unhandled case\n"); + } + MCHBAR32(0x400*i + 0x5a0) = (MCHBAR32(0x400*i + 0x5a0) & ~0x3f000000) | ((u32)(reg8 << 24)); + } else { /* DDR3 */ + FOR_EACH_RANK_IN_CHANNEL(r) { + if (RANK_IS_POPULATED(s->dimms, i, r)) { + MCHBAR8(0x400 * i + 0x5a0 + 3) = MCHBAR8(0x400 * i + 0x5a0 + 3) + & ~rank2clken[r + i * 4]; + } + } + } } // END EACH CHANNEL - MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 1; - MCHBAR8(0x1a8) = MCHBAR8(0x1a8) & ~0x4; + if (s->spd_type == DDR2) { + MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 1; + MCHBAR8(0x1a8) = MCHBAR8(0x1a8) & ~0x4; + } else { /* DDR3 */ + MCHBAR8(0x1a8) = MCHBAR8(0x1a8) & ~1; + MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 0x4; + } // Update DLL timing MCHBAR8(0x1a4) = MCHBAR8(0x1a4) & ~0x80; MCHBAR8(0x1a4) = MCHBAR8(0x1a4) | 0x40; MCHBAR16(0x5f0) = (MCHBAR16(0x5f0) & ~0x400) | 0x400; - const struct dll_setting dll_setting_667[23] = { - // tap pi db delay - {13, 0, 1, 0, 0}, - {4, 1, 0, 0, 0}, - {13, 0, 1, 0, 0}, - {4, 5, 0, 0, 0}, - {4, 1, 0, 0, 0}, - {4, 1, 0, 0, 0}, - {4, 1, 0, 0, 0}, - {1, 5, 1, 1, 1}, - {1, 6, 1, 1, 1}, - {2, 0, 1, 1, 1}, - {2, 1, 1, 1, 1}, - {2, 1, 1, 1, 1}, - {14, 6, 1, 0, 0}, - {14, 3, 1, 0, 0}, - {14, 0, 1, 0, 0}, - {9, 0, 0, 0, 1}, - {9, 1, 0, 0, 1}, - {9, 2, 0, 0, 1}, - {9, 2, 0, 0, 1}, - {9, 1, 0, 0, 1}, - {6, 4, 0, 0, 1}, - {6, 2, 0, 0, 1}, - {5, 4, 0, 0, 1} - }; - - const struct dll_setting dll_setting_800[23] = { - // tap pi db delay - {11, 5, 1, 0, 0}, - {0, 5, 1, 1, 0}, - {11, 5, 1, 0, 0}, - {1, 4, 1, 1, 0}, - {0, 5, 1, 1, 0}, - {0, 5, 1, 1, 0}, - {0, 5, 1, 1, 0}, - {2, 5, 1, 1, 1}, - {2, 6, 1, 1, 1}, - {3, 0, 1, 1, 1}, - {3, 0, 1, 1, 1}, - {3, 3, 1, 1, 1}, - {2, 0, 1, 1, 1}, - {1, 3, 1, 1, 1}, - {0, 3, 1, 1, 1}, - {9, 3, 0, 0, 1}, - {9, 4, 0, 0, 1}, - {9, 5, 0, 0, 1}, - {9, 6, 0, 0, 1}, - {10, 0, 0, 0, 1}, - {8, 1, 0, 0, 1}, - {7, 5, 0, 0, 1}, - {6, 2, 0, 0, 1} - }; - FOR_EACH_POPULATED_CHANNEL(s->dimms, i) { MCHBAR16(0x400*i + 0x5f0) = (MCHBAR16(0x400*i + 0x5f0) & ~0x3fc) | 0x3fc; MCHBAR32(0x400*i + 0x5fc) = MCHBAR32(0x400*i + 0x5fc) & ~0xcccccccc; - MCHBAR8(0x400*i + 0x5d9) = (MCHBAR8(0x400*i + 0x5d9) & ~0xf0) | 0x70; - MCHBAR16(0x400*i + 0x590) = (MCHBAR16(0x400*i + 0x590) & ~0xffff) | 0x5555; + if (s->spd_type == DDR2) { + MCHBAR8(0x400*i + 0x5d9) = (MCHBAR8(0x400*i + 0x5d9) + & ~0xf0) | 0x70; + MCHBAR16(0x400*i + 0x590) = (MCHBAR16(0x400*i + 0x590) + & ~0xffff) | 0x5555; + } else { + MCHBAR8(0x400*i + 0x5d9) = (MCHBAR8(0x400*i + 0x5d9) + & ~0xf0) | 0x60; + MCHBAR16(0x400*i + 0x590) = (MCHBAR16(0x400*i + 0x590) + & ~0xffff) | 0xa955; + } } FOR_EACH_POPULATED_CHANNEL(s->dimms, i) { - if (s->selected_timings.mem_clk == MEM_CLOCK_667MHz) { - clkset0(i, &dll_setting_667[CLKSET0]); - clkset1(i, &dll_setting_667[CLKSET1]); - ctrlset0(i, &dll_setting_667[CTRL0]); - ctrlset1(i, &dll_setting_667[CTRL1]); - ctrlset2(i, &dll_setting_667[CTRL2]); - ctrlset3(i, &dll_setting_667[CTRL3]); - cmdset(i, &dll_setting_667[CMD]); - } else { - clkset0(i, &dll_setting_800[CLKSET0]); - clkset1(i, &dll_setting_800[CLKSET1]); - ctrlset0(i, &dll_setting_800[CTRL0]); - ctrlset1(i, &dll_setting_800[CTRL1]); - ctrlset2(i, &dll_setting_800[CTRL2]); - ctrlset3(i, &dll_setting_800[CTRL3]); - cmdset(i, &dll_setting_800[CMD]); + if (s->spd_type == DDR2) { + if (s->selected_timings.mem_clk == MEM_CLOCK_667MHz) + program_dll_clk_ctrl(i, ddr2_dll_setting_667); + else + program_dll_clk_ctrl(i, ddr2_dll_setting_800); + } else { /* DDR3 */ + switch (s->selected_timings.mem_clk) { + default: + case MEM_CLOCK_800MHz: + program_dll_clk_ctrl(i, ddr3_dll_setting_800[s->nmode - 1]); + break; + case MEM_CLOCK_1066MHz: + program_dll_clk_ctrl(i, ddr3_dll_setting_1066[s->nmode - 1]); + break; + case MEM_CLOCK_1333MHz: + program_dll_clk_ctrl(i, ddr3_dll_setting_1333[s->nmode - 1]); + break; + } } } @@ -954,23 +992,38 @@ } clk = 0x1a; + if (s->selected_timings.mem_clk == MEM_CLOCK_1333MHz) + clk = 0x18; if (async != 1) { reg8 = MCHBAR8(0x188) & 0x1e; - if (s->selected_timings.mem_clk == MEM_CLOCK_667MHz && - s->selected_timings.fsb_clk == FSB_CLOCK_800MHz) { - clk = 0x10; - } else if (s->selected_timings.mem_clk == MEM_CLOCK_800MHz) { - clk = 0x10; - } else { + switch (s->selected_timings.mem_clk) { + case MEM_CLOCK_667MHz: clk = 0x1a; + if (s->selected_timings.fsb_clk == FSB_CLOCK_800MHz) + clk = 0x10; + break; + case MEM_CLOCK_800MHz: + case MEM_CLOCK_1066MHz: + clk = 0x10; + break; + case MEM_CLOCK_1333MHz: + clk = 0x18; + break; + default: + clk = 0x1a; + break; } } MCHBAR8(0x180) = MCHBAR8(0x180) & ~0x80; - if ((s->selected_timings.fsb_clk == FSB_CLOCK_800MHz) && - (s->selected_timings.mem_clk == MEM_CLOCK_667MHz)) { + if ((s->spd_type == DDR3 && s->selected_timings.mem_clk == MEM_CLOCK_1066MHz) + || (s->spd_type == DDR2 && s->selected_timings.fsb_clk == FSB_CLOCK_800MHz + && s->selected_timings.mem_clk == MEM_CLOCK_667MHz)) { i = MCHBAR8(0x180) & 0xf; - i = (i + 10) % 14; + if (s->spd_type == DDR2) + i = (i + 10) % 14; + else /* DDR3 */ + i = (i + 3) % 12; MCHBAR8(0x1c8) = (MCHBAR8(0x1c8) & ~0x1f) | i; MCHBAR8(0x180) = MCHBAR8(0x180) | 0x10; while (MCHBAR8(0x180) & 0x10) @@ -991,11 +1044,26 @@ // Program DQ/DQS dll settings reg32 = 0; FOR_EACH_POPULATED_CHANNEL(s->dimms, i) { - for (lane = 0; lane < 8; lane++) { - if (s->selected_timings.mem_clk == MEM_CLOCK_667MHz) - reg32 = 0x06db7777; - else if (s->selected_timings.mem_clk == MEM_CLOCK_800MHz) + switch (s->selected_timings.mem_clk) { + default: /* Should not happen */ + break; + case MEM_CLOCK_667MHz: + reg32 = 0x06db7777; + break; + case MEM_CLOCK_800MHz: + if (s->spd_type == DDR2) reg32 = 0x00007777; + else /* DDR3 */ + reg32 = 0x06db6666; + break; + case MEM_CLOCK_1066MHz: + reg32 = 0x06db5555; + break; + case MEM_CLOCK_1333MHz: + reg32 = 0x00007777; + break; + } + for (lane = 0; lane < 8; lane++) { MCHBAR32(0x400*i + 0x540 + lane*4) = (MCHBAR32(0x400*i + 0x540 + lane*4) & 0x0fffffff) | reg32; @@ -1003,16 +1071,24 @@ } FOR_EACH_POPULATED_CHANNEL(s->dimms, i) { - if (s->selected_timings.mem_clk == MEM_CLOCK_667MHz) { - for (lane = 0; lane < 8; lane++) - dqsset(i, lane, &dll_setting_667[DQS1+lane]); - for (lane = 0; lane < 8; lane++) - dqset(i, lane, &dll_setting_667[DQ1+lane]); - } else { - for (lane = 0; lane < 8; lane++) - dqsset(i, lane, &dll_setting_800[DQS1+lane]); - for (lane = 0; lane < 8; lane++) - dqset(i, lane, &dll_setting_800[DQ1+lane]); + switch (s->selected_timings.mem_clk) { + default: /* Should not happen */ + break; + case MEM_CLOCK_667MHz: + program_dq_dqs(i, ddr2_dll_setting_667); + break; + case MEM_CLOCK_800MHz: + if (s->spd_type == DDR2) + program_dq_dqs(i, ddr2_dll_setting_800); + else /* DDR3 */ + program_dq_dqs(i, ddr3_dll_setting_800[s->nmode - 1]); + break; + case MEM_CLOCK_1066MHz: + program_dq_dqs(i, ddr3_dll_setting_1066[s->nmode - 1]); + break; + case MEM_CLOCK_1333MHz: + program_dq_dqs(i, ddr3_dll_setting_1333[s->nmode - 1]); + break; } } } diff --git a/src/northbridge/intel/x4x/raminit_tables.c b/src/northbridge/intel/x4x/raminit_tables.c new file mode 100644 index 0000000..3349f62 --- /dev/null +++ b/src/northbridge/intel/x4x/raminit_tables.c @@ -0,0 +1,248 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2017 Arthur Heymans <arthur(a)aheymans.xyz> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/io.h> +#include <stdint.h> +#include "x4x.h" + +const struct dll_setting ddr2_dll_setting_667[23] = { + /* tap pi db delay */ + {13, 0, 1, 0, 0, 0}, + {4, 1, 0, 0, 0, 0}, + {13, 0, 1, 0, 0, 0}, + {4, 5, 0, 0, 0, 0}, + {4, 1, 0, 0, 0, 0}, + {4, 1, 0, 0, 0, 0}, + {4, 1, 0, 0, 0, 0}, + {1, 5, 1, 1, 1, 0}, + {1, 6, 1, 1, 1, 0}, + {2, 0, 1, 1, 1, 0}, + {2, 1, 1, 1, 1, 0}, + {2, 1, 1, 1, 1, 0}, + {14, 6, 1, 0, 0, 0}, + {14, 3, 1, 0, 0, 0}, + {14, 0, 1, 0, 0, 0}, + {9, 0, 0, 0, 1, 0}, + {9, 1, 0, 0, 1, 0}, + {9, 2, 0, 0, 1, 0}, + {9, 2, 0, 0, 1, 0}, + {9, 1, 0, 0, 1, 0}, + {6, 4, 0, 0, 1, 0}, + {6, 2, 0, 0, 1, 0}, + {5, 4, 0, 0, 1, 0} +}; + +const struct dll_setting ddr2_dll_setting_800[23] = { + /* tap pi db delay */ + {11, 5, 1, 0, 0, 0}, + {0, 5, 1, 1, 0, 0}, + {11, 5, 1, 0, 0, 0}, + {1, 4, 1, 1, 0, 0}, + {0, 5, 1, 1, 0, 0}, + {0, 5, 1, 1, 0, 0}, + {0, 5, 1, 1, 0, 0}, + {2, 5, 1, 1, 1, 0}, + {2, 6, 1, 1, 1, 0}, + {3, 0, 1, 1, 1, 0}, + {3, 0, 1, 1, 1, 0}, + {3, 3, 1, 1, 1, 0}, + {2, 0, 1, 1, 1, 0}, + {1, 3, 1, 1, 1, 0}, + {0, 3, 1, 1, 1, 0}, + {9, 3, 0, 0, 1, 0}, + {9, 4, 0, 0, 1, 0}, + {9, 5, 0, 0, 1, 0}, + {9, 6, 0, 0, 1, 0}, + {10, 0, 0, 0, 1, 0}, + {8, 1, 0, 0, 1, 0}, + {7, 5, 0, 0, 1, 0}, + {6, 2, 0, 0, 1, 0} +}; + +const struct dll_setting ddr3_dll_setting_800[2][23] = { + { /* 1N */ + /* tap pi db(2) delay coarse */ + {8, 2, 0, 0, 0, 0}, + {8, 4, 0, 0, 0, 0}, + {9, 5, 0, 0, 0, 0}, + {6, 1, 0, 0, 0, 0}, + {8, 4, 0, 0, 0, 0}, + {10, 0, 0, 0, 0, 0}, + {10, 0, 0, 0, 0, 0}, + {12, 0, 1, 0, 0, 0}, + {1, 1, 1, 1, 1, 0}, + {2, 4, 1, 1, 1, 0}, + {3, 5, 0, 0, 1, 0}, + {4, 3, 0, 0, 1, 0}, + {5, 2, 0, 0, 1, 0}, + {6, 1, 0, 0, 1, 0}, + {6, 4, 0, 0, 1, 0}, + {4, 1, 0, 0, 1, 0}, + {6, 4, 0, 0, 1, 0}, + {8, 1, 0, 0, 1, 0}, + {8, 6, 0, 0, 1, 0}, + {9, 5, 0, 0, 1, 0}, + {10, 2, 0, 0, 1, 0}, + {10, 6, 1, 0, 1, 0}, + {11, 4, 1, 0, 1, 0} }, + { /* 2N */ + {2, 2, 1, 1, 0, 0}, + {2, 4, 1, 1, 0, 0}, + {3, 5, 0, 0, 0, 0}, + {3, 2, 1, 1, 0, 0}, + {2, 4, 1, 1, 0, 0}, + {3, 6, 0, 0, 0, 0}, + {3, 6, 0, 0, 0, 0}, + {5, 6, 0, 0, 0, 0}, + {8, 0, 0, 0, 0, 0}, + {9, 4, 0, 0, 0, 0}, + {10, 4, 1, 0, 0, 0}, + {11, 3, 1, 0, 0, 0}, + {12, 1, 1, 0, 0, 0}, + {0, 1, 1, 1, 1, 0}, + {0, 3, 1, 1, 1, 0}, + {11, 0, 1, 0, 0, 0}, + {0, 3, 1, 1, 1, 0}, + {2, 1, 1, 1, 1, 0}, + {2, 5, 1, 1, 1, 0}, + {3, 5, 0, 0, 1, 0}, + {4, 2, 0, 0, 1, 0}, + {4, 6, 0, 0, 1, 0}, + {5, 4, 0, 0, 1, 0} + } +}; + +const struct dll_setting ddr3_dll_setting_1066[2][23] = { + { /* 1N */ + {8, 5, 0, 0, 0, 0}, + {7, 6, 0, 0, 0, 0}, + {10, 2, 1, 0, 0, 0}, + {0, 4, 4, 0, 0, 0}, + {7, 6, 0, 0, 0, 0}, + {9, 2, 1, 0, 0, 0}, + {9, 2, 1, 0, 0, 0}, + {2, 5, 1, 1, 1, 0}, + {5, 1, 0, 0, 1, 0}, + {6, 6, 0, 0, 1, 0}, + {8, 0, 0, 0, 1, 0}, + {8, 6, 0, 0, 1, 0}, + {9, 6, 1, 0, 1, 0}, + {10, 6, 1, 0, 1, 0}, + {0, 1, 1, 1, 0, 0}, + {6, 5, 0, 0, 1, 0}, + {9, 3, 1, 0, 1, 0}, + {0, 2, 1, 1, 0, 1}, + {1, 0, 1, 1, 0, 1}, + {2, 0, 1, 1, 0, 1}, + {2, 5, 1, 1, 0, 1}, + {3, 2, 0, 0, 0, 1}, + {4, 1, 0, 0, 0, 1}, }, + { /* 2N */ + {1, 5, 1, 1, 0, 0}, + {0, 6, 1, 1, 0, 0}, + {3, 2, 0, 0, 0, 0}, + {2, 6, 1, 1, 0, 0}, + {0, 6, 1, 1, 0, 0}, + {2, 2, 1, 1, 0, 0}, + {2, 2, 1, 1, 0, 0}, + {6, 4, 0, 0, 0, 0}, + {9, 1, 1, 0, 0, 0}, + {10, 6, 1, 0, 0, 0}, + {1, 0, 1, 1, 1, 0}, + {1, 6, 1, 1, 1, 0}, + {2, 5, 1, 1, 1, 0}, + {3, 5, 0, 0, 1, 0}, + {4, 1, 0, 0, 1, 0}, + {10, 5, 1, 0, 0, 0}, + {2, 3, 1, 1, 1, 0}, + {4, 1, 0, 0, 1, 0}, + {5, 0, 0, 0, 1, 0}, + {6, 0, 0, 0, 1, 0}, + {6, 5, 0, 0, 1, 0}, + {7, 2, 0, 0, 1, 0}, + {8, 1, 0, 0, 1, 0}, + } +}; +const struct dll_setting ddr3_dll_setting_1333[2][23] = { + { /* 1N */ + {8, 5, 0, 0, 0, 0}, + {9, 0, 1, 0, 0, 0}, + {10, 2, 1, 0, 0, 0}, + {0, 0, 1, 1, 0, 0}, + {9, 0, 1, 0, 0, 0}, + {10, 4, 1, 0, 0, 0}, + {10, 4, 1, 0, 0, 0}, + {2, 4, 1, 1, 1, 0}, + {5, 1, 0, 0, 1, 0}, + {6, 6, 0, 0, 1, 0}, + {8, 0, 0, 0, 1, 0}, + {8, 6, 0, 0, 1, 0}, + {9, 5, 1, 0, 1, 0}, + {10, 6, 1, 0, 1, 0}, + {0, 1, 1, 1, 0, 1}, + {6, 5, 0, 0, 1, 0}, + {9, 3, 1, 0, 1, 0}, + {0, 2, 1, 1, 0, 1}, + {1, 0, 1, 1, 0, 1}, + {2, 0, 1, 1, 0, 1}, + {2, 5, 1, 1, 0, 1}, + {3, 2, 0, 0, 0, 1}, + {4, 1, 0, 0, 0, 1}, }, + { /* 2N */ + {1, 6, 1, 1, 0, 0}, + {2, 2, 1, 1, 0, 0}, + {4, 2, 0, 0, 0, 0}, + {3, 1, 1, 1, 0, 0}, + {2, 2, 1, 1, 0, 0}, + {4, 5, 0, 0, 0, 0}, + {4, 5, 0, 0, 0, 0}, + {10, 4, 0, 0, 0, 0}, + {0, 3, 1, 1, 1, 0}, + {3, 2, 1, 1, 1, 0}, + {5, 0, 0, 0, 1, 0}, + {6, 1, 0, 0, 1, 0}, + {7, 4, 0, 0, 1, 0}, + {9, 2, 0, 0, 1, 0}, + {9, 6, 0, 0, 1, 0}, + {1, 3, 1, 1, 1, 0}, + {5, 6, 0, 0, 1, 0}, + {8, 5, 0, 0, 1, 0}, + {10, 2, 0, 0, 1, 0}, + {11, 1, 0, 0, 1, 0}, + {12, 3, 1, 0, 1, 0}, + {13, 6, 1, 0, 1, 0}, + {0, 3, 1, 1, 0, 1} + } +}; + +const u8 ddr3_emrs1_config[16][4] = { /* [Config][Rank] */ + {0x00, 0x00, 0x00, 0x00}, /* NC_NC */ + {0x11, 0x00, 0x00, 0x00}, /* 8S_NC */ + {0x11, 0x11, 0x00, 0x00}, /* 8D_NC */ + {0x11, 0x00, 0x00, 0x00}, /* 16S_NC */ + {0x00, 0x00, 0x11, 0x00}, /* NC_8S */ + {0x81, 0x00, 0x81, 0x00}, /* 8S_8S */ + {0x81, 0x81, 0x81, 0x00}, /* 8D_8S */ + {0x81, 0x00, 0x81, 0x00}, /* 16S_8S */ + {0x00, 0x00, 0x11, 0x11}, /* NC_8D */ + {0x81, 0x00, 0x81, 0x81}, /* 8S_8D */ + {0x81, 0x81, 0x81, 0x81}, /* 8D_8D */ + {0x81, 0x00, 0x81, 0x81}, /* 16S_8D */ + {0x00, 0x00, 0x11, 0x00}, /* NC_16S */ + {0x81, 0x00, 0x81, 0x00}, /* 8S_16S */ + {0x81, 0x81, 0x81, 0x00}, /* 8D_16S */ + {0x81, 0x00, 0x81, 0x00}, /* 16S_16S */ +}; diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h index 34fef93..9ef07b3 100644 --- a/src/northbridge/intel/x4x/x4x.h +++ b/src/northbridge/intel/x4x/x4x.h @@ -355,6 +355,15 @@ struct abs_timings *saved_timings); int ddr3_save_dimminfo(u8 dimm_idx, u8 *raw_spd, struct abs_timings *saved_timings, struct sysinfo *s); +void dqsset(u8 ch, u8 lane, const struct dll_setting *setting); +void dqset(u8 ch, u8 lane, const struct dll_setting *setting); + +/* Look up tables Tables */ +extern const struct dll_setting ddr2_dll_setting_667[23]; +extern const struct dll_setting ddr2_dll_setting_800[23]; +extern const struct dll_setting ddr3_dll_setting_800[2][23]; +extern const struct dll_setting ddr3_dll_setting_1066[2][23]; +extern const struct dll_setting ddr3_dll_setting_1333[2][23]; struct acpi_rsdp; -- To view, visit
https://review.coreboot.org/19874
To unsubscribe, visit
https://review.coreboot.org/settings
Gerrit-MessageType: newchange Gerrit-Change-Id: Ia79b216ad69a02d4706ffc74f867a85db3eb2d6c Gerrit-PatchSet: 1 Gerrit-Project: coreboot Gerrit-Branch: master Gerrit-Owner: Arthur Heymans <arthur(a)aheymans.xyz>
1
0
0
0
Change in coreboot[master]: nb/intel/x4x/raminit: Support programming DDR3 timings
by Arthur Heymans (Code Review)
24 May '17
24 May '17
Arthur Heymans has uploaded a new change for review. (
https://review.coreboot.org/19873
) Change subject: nb/intel/x4x/raminit: Support programming DDR3 timings ...................................................................... nb/intel/x4x/raminit: Support programming DDR3 timings Change-Id: Ia2494684ec66d84d4dc27c6a6b425a33ace6e827 Signed-off-by: Arthur Heymans <arthur(a)aheymans.xyz> --- M src/northbridge/intel/x4x/raminit_ddr23.c 1 file changed, 74 insertions(+), 35 deletions(-) git pull ssh://review.coreboot.org:29418/coreboot refs/changes/73/19873/1 diff --git a/src/northbridge/intel/x4x/raminit_ddr23.c b/src/northbridge/intel/x4x/raminit_ddr23.c index fc8e5a0..4db29f5 100644 --- a/src/northbridge/intel/x4x/raminit_ddr23.c +++ b/src/northbridge/intel/x4x/raminit_ddr23.c @@ -496,15 +496,77 @@ 5200 }; - ta1 = 6; - ta2 = 6; - ta3 = 5; - ta4 = 8; + const static u8 ddr3_turnaround_tab[3][6][4] = { + { /* DDR3 800 */ + {0x7, 0x7, 0x9, 0x9}, /* CL = 5 */ + {0x7, 0x8, 0x8, 0x9}, /* CL = 6 */ + }, + { /* DDR3 1066 */ + {0x0, 0x0, 0x0, 0x0}, /* CL = 5 - Not supported */ + {0x7, 0x7, 0x9, 0x9}, /* CL = 6 */ + {0x7, 0x8, 0x8, 0x9}, /* CL = 7 */ + {0x7, 0x9, 0x7, 0x9} /* CL = 8 */ + }, + { /* DDR3 1333 */ + {0x0, 0x0, 0x0, 0x0}, /* CL = 5 - Not supported */ + {0x0, 0x0, 0x0, 0x0}, /* CL = 6 - Not supported */ + {0x0, 0x0, 0x0, 0x0}, /* CL = 7 - Not supported */ + {0x7, 0x9, 0x8, 0x9}, /* CL = 8 */ + {0x7, 0xA, 0x7, 0x9}, /* CL = 9 */ + {0x7, 0xB, 0x6, 0x9}, /* CL = 10 */ + } + }; - twl = s->selected_timings.CAS - 1; + /* [DDR freq][0x26F & 1][pagemod] */ + const static u8 ddr2_x252_tab[2][2][2] = { + { /* DDR2 667 */ + {12, 16}, + {14, 18} + }, + { /* DDR2 800 */ + {14, 18}, + {16, 20} + } + }; + + const static u8 ddr3_x252_tab[3][2][2] = { + { /* DDR3 800 */ + {16, 20}, + {18, 22} + }, + { /* DDR3 1067 */ + {20, 26}, + {26, 26} + }, + { /* DDR3 1333 */ + {20, 30}, + {22, 32}, + } + }; + + if (s->spd_type == DDR2) { + ta1 = 6; + ta2 = 6; + ta3 = 5; + ta4 = 8; + } else { + ta1 = ddr3_turnaround_tab[s->selected_timings.mem_clk - MEM_CLOCK_800MHz] + [s->selected_timings.CAS - 5][3]; + ta2 = ddr3_turnaround_tab[s->selected_timings.mem_clk - MEM_CLOCK_800MHz] + [s->selected_timings.CAS - 5][0]; + ta3 = ddr3_turnaround_tab[s->selected_timings.mem_clk - MEM_CLOCK_800MHz] + [s->selected_timings.CAS - 5][1]; + ta4 = ddr3_turnaround_tab[s->selected_timings.mem_clk - MEM_CLOCK_800MHz] + [s->selected_timings.CAS - 5][2]; + } + + if (s->spd_type == DDR2) + twl = s->selected_timings.CAS - 1; + else /* DDR3 */ + twl = s->selected_timings.mem_clk - MEM_CLOCK_800MHz + 5; FOR_EACH_POPULATED_DIMM(s->dimms, i) { - if (s->dimms[i].n_banks == 1) { + if (s->dimms[i].n_banks == 1) { /* 8 banks */ trpmod = 1; bankmod = 0; } @@ -534,35 +596,12 @@ s->selected_timings.tRFC; reg8 = (MCHBAR8(0x400*i + 0x26f) >> 1) & 1; if (bankmod) { - switch (s->selected_timings.mem_clk) { - default: - case MEM_CLOCK_667MHz: - if (reg8) { - if (pagemod) - reg32 |= 16 << 22; - else - reg32 |= 12 << 22; - } else { - if (pagemod) - reg32 |= 18 << 22; - else - reg32 |= 14 << 22; - } - break; - case MEM_CLOCK_800MHz: - if (reg8) { - if (pagemod) - reg32 |= 18 << 22; - else - reg32 |= 14 << 22; - } else { - if (pagemod) - reg32 |= 20 << 22; - else - reg32 |= 16 << 22; - } - break; - } + if (s->spd_type == DDR2) + reg32 |= ddr2_x252_tab[s->selected_timings.mem_clk - MEM_CLOCK_667MHz] + [reg8][pagemod] << 22; + else + reg32 |= ddr3_x252_tab[s->selected_timings.mem_clk - MEM_CLOCK_800MHz] + [reg8][pagemod] << 22; } MCHBAR32(0x400*i + 0x252) = reg32; -- To view, visit
https://review.coreboot.org/19873
To unsubscribe, visit
https://review.coreboot.org/settings
Gerrit-MessageType: newchange Gerrit-Change-Id: Ia2494684ec66d84d4dc27c6a6b425a33ace6e827 Gerrit-PatchSet: 1 Gerrit-Project: coreboot Gerrit-Branch: master Gerrit-Owner: Arthur Heymans <arthur(a)aheymans.xyz>
1
0
0
0
Change in coreboot[master]: nb/intel/x4x/raminit: Make programming launch ddr3 specific
by Arthur Heymans (Code Review)
24 May '17
24 May '17
Arthur Heymans has uploaded a new change for review. (
https://review.coreboot.org/19872
) Change subject: nb/intel/x4x/raminit: Make programming launch ddr3 specific ...................................................................... nb/intel/x4x/raminit: Make programming launch ddr3 specific Change-Id: Ia2ca4a200a1c813b2133eb1004fbe248fa3de9ce Signed-off-by: Arthur Heymans <arthur(a)aheymans.xyz> --- M src/northbridge/intel/x4x/raminit_ddr23.c M src/northbridge/intel/x4x/x4x.h 2 files changed, 76 insertions(+), 6 deletions(-) git pull ssh://review.coreboot.org:29418/coreboot refs/changes/72/19872/1 diff --git a/src/northbridge/intel/x4x/raminit_ddr23.c b/src/northbridge/intel/x4x/raminit_ddr23.c index 253b5ee..fc8e5a0 100644 --- a/src/northbridge/intel/x4x/raminit_ddr23.c +++ b/src/northbridge/intel/x4x/raminit_ddr23.c @@ -194,12 +194,79 @@ u32 launch2 = 0; u32 launch3 = 0; - if (s->selected_timings.CAS == 5) - launch2 = 0x00220201; - else if (s->selected_timings.CAS == 6) - launch2 = 0x00230302; - else - die("Unsupported CAS\n"); + static const u32 ddr3_launch1_tab[2][3] = { + /* 1N */ + {0x58000007, /* DDR3 800 */ + 0x58000007, /* DDR3 1067 */ + 0x58100107}, /* DDR3 1333 */ + /* 2N */ + {0x58001117, /* DDR3 800 */ + 0x58001117, /* DDR3 1067 */ + 0x58001117} /* DDR3 1333 */ + }; + + static const u32 ddr3_launch2_tab[2][3][6] = { + { /* 1N */ + /* DDR3 800 */ + {0x08030000, /* CL = 5 */ + 0x0C040100}, /* CL = 6 */ + /* DDR3 1066 */ + {0x00000000, /* CL = 5 */ + 0x00000000, /* CL = 6 */ + 0x10050100, /* CL = 7 */ + 0x14260200}, /* CL = 8 */ + /* DDR3 1333 */ + {0x00000000, /* CL = 5 */ + 0x00000000, /* CL = 6 */ + 0x00000000, /* CL = 7 */ + 0x14060000, /* CL = 8 */ + 0x18070100, /* CL = 9 */ + 0x1C280200}, /* CL = 10 */ + + }, + { /* 2N */ + /* DDR3 800 */ + {0x00040101, /* CL = 5 */ + 0x00250201}, /* CL = 6 */ + /* DDR3 1066 */ + {0x00000000, /* CL = 5 */ + 0x00050101, /* CL = 6 */ + 0x04260201, /* CL = 7 */ + 0x08470301}, /* CL = 8 */ + /* DDR3 1333 */ + {0x00000000, /* CL = 5 */ + 0x00000000, /* CL = 6 */ + 0x00000000, /* CL = 7 */ + 0x08070100, /* CL = 8 */ + 0x0C280200, /* CL = 9 */ + 0x10490300} /* CL = 10 */ + } + }; + + if (s->spd_type == DDR2) { + if (s->selected_timings.CAS == 5) + launch2 = 0x00220201; + else if (s->selected_timings.CAS == 6) + launch2 = 0x00230302; + else + die("Unsupported CAS\n"); + } else { /* DDR3 */ + /* Default 2N mode */ + s->nmode = 2; + + if (s->max_fsb <= FSB_CLOCK_1066MHz) + s->nmode = 1; + /* 2N on DDR3 1066 with with 2 dimms per channel */ + if ((s->selected_timings.mem_clk == MEM_CLOCK_1066MHz) && + (BOTH_DIMMS_ARE_POPULATED(s->dimms, 0) || + BOTH_DIMMS_ARE_POPULATED(s->dimms, 1))) + s->nmode = 2; + launch1 = ddr3_launch1_tab[s->nmode - 1] + [s->selected_timings.mem_clk - MEM_CLOCK_800MHz]; + launch2 = ddr3_launch2_tab[s->nmode - 1] + [s->selected_timings.mem_clk - MEM_CLOCK_800MHz] + [s->selected_timings.CAS - 5]; + } FOR_EACH_POPULATED_CHANNEL(s->dimms, i) { MCHBAR32(0x400*i + 0x220) = launch1; @@ -211,6 +278,8 @@ MCHBAR32(0x2c0) = (MCHBAR32(0x2c0) & ~0x58000000) | 0x48000000; MCHBAR32(0x2c0) = MCHBAR32(0x2c0) | 0x1e0; MCHBAR32(0x2c4) = (MCHBAR32(0x2c4) & ~0xf) | 0xc; + if (s->spd_type == DDR3) + MCHBAR32(0x2c4) = MCHBAR32(0x2c4) | 0x100; } static void clkset0(u8 ch, const struct dll_setting *setting) diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h index 621a685..34fef93 100644 --- a/src/northbridge/intel/x4x/x4x.h +++ b/src/northbridge/intel/x4x/x4x.h @@ -290,6 +290,7 @@ struct timings selected_timings; struct dimminfo dimms[4]; u8 spd_map[4]; + u8 nmode; }; #define BOOT_PATH_NORMAL 0 #define BOOT_PATH_WARM_RESET 1 -- To view, visit
https://review.coreboot.org/19872
To unsubscribe, visit
https://review.coreboot.org/settings
Gerrit-MessageType: newchange Gerrit-Change-Id: Ia2ca4a200a1c813b2133eb1004fbe248fa3de9ce Gerrit-PatchSet: 1 Gerrit-Project: coreboot Gerrit-Branch: master Gerrit-Owner: Arthur Heymans <arthur(a)aheymans.xyz>
1
0
0
0
Change in coreboot[master]: [WIP]nb/intel/x4x/raminit: Make programming crossclock suppo...
by Arthur Heymans (Code Review)
24 May '17
24 May '17
Arthur Heymans has uploaded a new change for review. (
https://review.coreboot.org/19871
) Change subject: [WIP]nb/intel/x4x/raminit: Make programming crossclock support DDR3 ...................................................................... [WIP]nb/intel/x4x/raminit: Make programming crossclock support DDR3 A few values need to be verified. Change-Id: I86b70e06c81817854994b7feddf9f3638fd16198 Signed-off-by: Arthur Heymans <arthur(a)aheymans.xyz> --- M src/northbridge/intel/x4x/raminit_ddr23.c 1 file changed, 15 insertions(+), 5 deletions(-) git pull ssh://review.coreboot.org:29418/coreboot refs/changes/71/19871/1 diff --git a/src/northbridge/intel/x4x/raminit_ddr23.c b/src/northbridge/intel/x4x/raminit_ddr23.c index 9cb29ef..253b5ee 100644 --- a/src/northbridge/intel/x4x/raminit_ddr23.c +++ b/src/northbridge/intel/x4x/raminit_ddr23.c @@ -71,6 +71,7 @@ static void program_crossclock(struct sysinfo *s) { u8 i, j; + u32 reg32; MCHBAR16(0xc1c) = MCHBAR16(0xc1c) | (1 << 15); static const u32 clkxtab[6][3][13] = { @@ -83,7 +84,7 @@ {{0x1f1f1f1f, 0x1a07070b, 0x00000000, 0x10000000, 0x20010208, 0x04080000, 0x10010002, 0x00000000, 0x00000000, 0x02000000, 0x04000100, 0x08000000, - 0x10200204}, + 0x10200204}, /* Check item[1] : 0x0d07070B ? */ /* FSB 1067 */ {0x6d5b1f1f, 0x0f0f0f0f, 0x00000000, 0x20000000, 0x80020410, 0x02040008, 0x10000100, 0x00000000, @@ -104,7 +105,7 @@ {0x07070707, 0x06030303, 0x00000000, 0x00000000, 0x08010200, 0x00000000, 0x04000102, 0x00000000, 0x00000000, 0x00000000, 0x00020001, 0x00000000, - 0x02040801}, + 0x02040801}, /* item[9] = 0x00020100 ?*/ /* item[11] = 0x04080100 */ /* FSB 1333 */ {0x0d0b0707, 0x3e1f1f2f, 0x01010000, 0x00000000, 0x10020400, 0x02000000, 0x00040100, 0x00000000, @@ -135,7 +136,13 @@ j = (u8)s->selected_timings.fsb_clk; MCHBAR32(0xc04) = clkxtab[i][j][0]; - MCHBAR32(0xc50) = clkxtab[i][j][1]; + reg32 = clkxtab[i][j][1]; + if (s->spd_type == DDR3 && s->max_fsb == FSB_CLOCK_1333MHz + && s->selected_timings.mem_clk == MEM_CLOCK_800MHz) { + reg32 &= ~(0xFF000000); + reg32 |= 0x3d << 24; + } + MCHBAR32(0xc50) = reg32; MCHBAR32(0xc54) = clkxtab[i][j][2]; MCHBAR8(0xc08) = MCHBAR8(0xc08) | (1 << 7); MCHBAR32(0x6d8) = clkxtab[i][j][3]; @@ -1797,8 +1804,11 @@ // Clear host clk gate reg MCHBAR32(0x1c) = MCHBAR32(0x1c) | 0xffffffff; - // Select DDR2 - MCHBAR8(0x1a8) = MCHBAR8(0x1a8) & ~0x4; + // Select type + if (s->spd_type == DDR2) + MCHBAR8(0x1a8) = MCHBAR8(0x1a8) & ~0x4; + else + MCHBAR8(0x1a8) = MCHBAR8(0x1a8) | 0x4; // Set freq MCHBAR32(0xc00) = (MCHBAR32(0xc00) & ~0x70) | -- To view, visit
https://review.coreboot.org/19871
To unsubscribe, visit
https://review.coreboot.org/settings
Gerrit-MessageType: newchange Gerrit-Change-Id: I86b70e06c81817854994b7feddf9f3638fd16198 Gerrit-PatchSet: 1 Gerrit-Project: coreboot Gerrit-Branch: master Gerrit-Owner: Arthur Heymans <arthur(a)aheymans.xyz>
1
0
0
0
Change in coreboot[master]: nb/intel/x4x: Rename a things that are not ddr2 specific
by Arthur Heymans (Code Review)
24 May '17
24 May '17
Arthur Heymans has uploaded a new change for review. (
https://review.coreboot.org/19870
) Change subject: nb/intel/x4x: Rename a things that are not ddr2 specific ...................................................................... nb/intel/x4x: Rename a things that are not ddr2 specific Change-Id: Ib3d10014f530905155e56fc52706edb4ab9f5630 Signed-off-by: Arthur Heymans <arthur(a)aheymans.xyz> --- M src/northbridge/intel/x4x/Makefile.inc M src/northbridge/intel/x4x/raminit.c R src/northbridge/intel/x4x/raminit_ddr23.c M src/northbridge/intel/x4x/x4x.h 4 files changed, 19 insertions(+), 30 deletions(-) git pull ssh://review.coreboot.org:29418/coreboot refs/changes/70/19870/1 diff --git a/src/northbridge/intel/x4x/Makefile.inc b/src/northbridge/intel/x4x/Makefile.inc index 86ecf7b..ae8d388 100644 --- a/src/northbridge/intel/x4x/Makefile.inc +++ b/src/northbridge/intel/x4x/Makefile.inc @@ -18,7 +18,7 @@ romstage-y += early_init.c romstage-y += raminit.c -romstage-y += raminit_ddr2.c +romstage-y += raminit_ddr23.c romstage-y += ram_calc.c romstage-y += spd_ddr2_decode.c romstage-y += spd_ddr3_decode.c diff --git a/src/northbridge/intel/x4x/raminit.c b/src/northbridge/intel/x4x/raminit.c index b2bc280..f3b4928 100644 --- a/src/northbridge/intel/x4x/raminit.c +++ b/src/northbridge/intel/x4x/raminit.c @@ -263,17 +263,7 @@ print_selected_timings(&s); find_dimm_config(&s); - switch (s.spd_type) { - case DDR2: - raminit_ddr2(&s); - break; - case DDR3: - // FIXME Add: raminit_ddr3(&s); - break; - default: - die("Unknown DDR type\n"); - break; - } + do_raminit(&s); reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), 0xa2); pci_write_config8(PCI_DEV(0, 0x1f, 0), 0xa2, reg8 & ~0x80); diff --git a/src/northbridge/intel/x4x/raminit_ddr2.c b/src/northbridge/intel/x4x/raminit_ddr23.c similarity index 98% rename from src/northbridge/intel/x4x/raminit_ddr2.c rename to src/northbridge/intel/x4x/raminit_ddr23.c index e663564..9cb29ef 100644 --- a/src/northbridge/intel/x4x/raminit_ddr2.c +++ b/src/northbridge/intel/x4x/raminit_ddr23.c @@ -68,7 +68,7 @@ return (u8)(pos & 0xff); } -static void clkcross_ddr2(struct sysinfo *s) +static void program_crossclock(struct sysinfo *s) { u8 i, j; MCHBAR16(0xc1c) = MCHBAR16(0xc1c) | (1 << 15); @@ -152,7 +152,7 @@ MCHBAR32(0x70c) = clkxtab[i][j][12]; } -static void setioclk_ddr2(struct sysinfo *s) +static void setioclk_dram(struct sysinfo *s) { MCHBAR32(0x1bc) = 0x08060402; MCHBAR16(0x1c0) = MCHBAR16(0x1c0) | 0x200; @@ -180,7 +180,7 @@ MCHBAR32(0x994) = MCHBAR32(0x994) | (1 << 31); } -static void launch_ddr2(struct sysinfo *s) +static void launch_dram(struct sysinfo *s) { u8 i; u32 launch1 = 0x58001117; @@ -379,7 +379,7 @@ setting->tap; } -static void timings_ddr2(struct sysinfo *s) +static void program_timings(struct sysinfo *s) { u8 i; u8 twl, ta1, ta2, ta3, ta4; @@ -604,7 +604,7 @@ MCHBAR8(0x6c4) = (MCHBAR8(0x6c4) & ~0x7) | 0x2; } -static void dll_ddr2(struct sysinfo *s) +static void program_dll(struct sysinfo *s) { u8 i, j, r, reg8, clk, async; u16 reg16 = 0; @@ -973,7 +973,7 @@ MCHBAR8(0x130) = MCHBAR8(0x130) | 1; } -static void odt_ddr2(struct sysinfo *s) +static void program_odt(struct sysinfo *s) { u8 i; u16 odt[16][2] = { @@ -1003,7 +1003,7 @@ } } -static void dojedec_ddr2(u8 r, u8 ch, u8 cmd, u16 val) +static void send_jedec_cmd(u8 r, u8 ch, u8 cmd, u16 val) { u32 addr = (ch << 29) | (r*0x08000000); volatile u32 rubbish; @@ -1075,7 +1075,7 @@ default: break; } - dojedec_ddr2(r + ch*4, ch, jedec[i][0], v); + send_jedec_cmd(r + ch*4, ch, jedec[i][0], v); udelay(1); //printk(BIOS_DEBUG, "Jedec step %d\n", i); } @@ -1783,7 +1783,7 @@ MCHBAR8(0x561 + (lane << 2)) = MCHBAR8(0x561 + (lane << 2)) & ~(1 << 3); } -void raminit_ddr2(struct sysinfo *s) +void do_raminit(struct sysinfo *s) { u8 ch; u8 r, bank; @@ -1813,25 +1813,24 @@ mdelay(250); // Program clock crossing - clkcross_ddr2(s); + program_crossclock(s); printk(BIOS_DEBUG, "Done clk crossing\n"); - // DDR2 IO if (s->boot_path != BOOT_PATH_WARM_RESET) { - setioclk_ddr2(s); + setioclk_dram(s); printk(BIOS_DEBUG, "Done I/O clk\n"); } // Grant to launch - launch_ddr2(s); + launch_dram(s); printk(BIOS_DEBUG, "Done launch\n"); - // Program DDR2 timings - timings_ddr2(s); + // Program DRAM timings + program_timings(s); printk(BIOS_DEBUG, "Done timings\n"); // Program DLL - dll_ddr2(s); + program_dll(s); // RCOMP if (s->boot_path != BOOT_PATH_WARM_RESET) { @@ -1840,7 +1839,7 @@ } // ODT - odt_ddr2(s); + program_odt(s); printk(BIOS_DEBUG, "Done ODT\n"); // RCOMP update diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h index 43e37ef..621a685 100644 --- a/src/northbridge/intel/x4x/x4x.h +++ b/src/northbridge/intel/x4x/x4x.h @@ -343,7 +343,7 @@ u32 decode_igd_gtt_size(u32 gsm); u8 decode_pciebar(u32 *const base, u32 *const len); void sdram_initialize(int boot_path, const u8 *spd_map); -void raminit_ddr2(struct sysinfo *); +void do_raminit(struct sysinfo *); u32 fsb2mhz(u32 speed); u32 ddr2mhz(u32 speed); void select_cas_dramfreq_ddr2(struct sysinfo *s, -- To view, visit
https://review.coreboot.org/19870
To unsubscribe, visit
https://review.coreboot.org/settings
Gerrit-MessageType: newchange Gerrit-Change-Id: Ib3d10014f530905155e56fc52706edb4ab9f5630 Gerrit-PatchSet: 1 Gerrit-Project: coreboot Gerrit-Branch: master Gerrit-Owner: Arthur Heymans <arthur(a)aheymans.xyz>
1
0
0
0
Change in coreboot[master]: mainboard/google/poppy: Add PowerResource for touchscreen de...
by build bot (Jenkins) (Code Review)
24 May '17
24 May '17
build bot (Jenkins) has posted comments on this change. (
https://review.coreboot.org/19829
) Change subject: mainboard/google/poppy: Add PowerResource for touchscreen device ...................................................................... Patch Set 3: Build Successful
https://qa.coreboot.org/job/coreboot-gerrit/54265/
: SUCCESS -- To view, visit
https://review.coreboot.org/19829
To unsubscribe, visit
https://review.coreboot.org/settings
Gerrit-MessageType: comment Gerrit-Change-Id: Ia0bebc7259b10cc60a9fa5b53542dfdd9685663e Gerrit-PatchSet: 3 Gerrit-Project: coreboot Gerrit-Branch: master Gerrit-Owner: Furquan Shaikh <furquan(a)google.com> Gerrit-Reviewer: Aaron Durbin <adurbin(a)chromium.org> Gerrit-Reviewer: Duncan Laurie <dlaurie(a)chromium.org> Gerrit-Reviewer: Furquan Shaikh <furquan(a)google.com> Gerrit-Reviewer: Paul Menzel <paulepanter(a)users.sourceforge.net> Gerrit-Reviewer: build bot (Jenkins) <no-reply(a)coreboot.org> Gerrit-HasComments: No
1
0
0
0
Change in coreboot[master]: nb/x4x/raminit: Decode ddr3 dimms
by Arthur Heymans (Code Review)
24 May '17
24 May '17
Arthur Heymans has uploaded a new change for review. (
https://review.coreboot.org/19869
) Change subject: nb/x4x/raminit: Decode ddr3 dimms ...................................................................... nb/x4x/raminit: Decode ddr3 dimms The raw_spd array needs to be increased since the ddr3 variant of spd_decode assumes an array of that size. Change-Id: I8dba19ca1e6e6b0a03b56c8de9633f9c1a2eb7d7 Signed-off-by: Arthur Heymans <arthur(a)aheymans.xyz> --- M src/northbridge/intel/x4x/Makefile.inc M src/northbridge/intel/x4x/raminit.c M src/northbridge/intel/x4x/raminit_ddr2.c M src/northbridge/intel/x4x/spd_ddr2_decode.c A src/northbridge/intel/x4x/spd_ddr3_decode.c M src/northbridge/intel/x4x/x4x.h 6 files changed, 197 insertions(+), 8 deletions(-) git pull ssh://review.coreboot.org:29418/coreboot refs/changes/69/19869/1 diff --git a/src/northbridge/intel/x4x/Makefile.inc b/src/northbridge/intel/x4x/Makefile.inc index b433810..86ecf7b 100644 --- a/src/northbridge/intel/x4x/Makefile.inc +++ b/src/northbridge/intel/x4x/Makefile.inc @@ -21,6 +21,7 @@ romstage-y += raminit_ddr2.c romstage-y += ram_calc.c romstage-y += spd_ddr2_decode.c +romstage-y += spd_ddr3_decode.c ramstage-y += acpi.c ramstage-y += ram_calc.c diff --git a/src/northbridge/intel/x4x/raminit.c b/src/northbridge/intel/x4x/raminit.c index 7e69b4c..b2bc280 100644 --- a/src/northbridge/intel/x4x/raminit.c +++ b/src/northbridge/intel/x4x/raminit.c @@ -116,7 +116,7 @@ unsigned int device; u8 dram_type_mask = (1 << DDR2) | (1 << DDR3); u8 dimm_mask = 0; - u8 raw_spd[128]; + u8 raw_spd[256]; int i; struct abs_timings saved_timings = { }; saved_timings.cas_supported = (u32)-1; @@ -151,7 +151,12 @@ continue; } } else { /* DDR3: not implemented so don't decode */ - die("DDR3 support is not implemented\n"); + i2c_block_read(device, 0, 128, raw_spd); + if (ddr3_save_dimminfo(i, raw_spd, &saved_timings, s)) { + /* something in decoded SPD was unsupported */ + s->dimms[i].card_type = RAW_CARD_UNPOPULATED; + continue; + } } dimm_mask = (1 << i); } @@ -159,6 +164,8 @@ die("No memory installed.\n"); if (s->spd_type == DDR2) select_cas_dramfreq_ddr2(s, &saved_timings); + else + select_cas_dramfreq_ddr3(s, &saved_timings); select_discrete_timings(s, &saved_timings); } diff --git a/src/northbridge/intel/x4x/raminit_ddr2.c b/src/northbridge/intel/x4x/raminit_ddr2.c index 8984fad..e663564 100644 --- a/src/northbridge/intel/x4x/raminit_ddr2.c +++ b/src/northbridge/intel/x4x/raminit_ddr2.c @@ -1469,7 +1469,6 @@ }; u8 drbtab[10] = {0x04, 0x02, 0x08, 0x04, 0x08, 0x04, 0x10, 0x08, 0x20, 0x10}; - u8 tab_width; // DRA rankpop0 = 0; @@ -1480,9 +1479,8 @@ i = ch << 1; else i = (ch << 1) + 1; - tab_width = (s->dimms[i].width >> 3) - 1; /* 16->1, 8->0 */ dra = dratab[s->dimms[i].n_banks] - [tab_width] + [s->dimms[i].width] [s->dimms[i].cols-9] [s->dimms[i].rows-12]; if (s->dimms[i].n_banks == 1) diff --git a/src/northbridge/intel/x4x/spd_ddr2_decode.c b/src/northbridge/intel/x4x/spd_ddr2_decode.c index 938aab7..f8f4403 100644 --- a/src/northbridge/intel/x4x/spd_ddr2_decode.c +++ b/src/northbridge/intel/x4x/spd_ddr2_decode.c @@ -82,12 +82,14 @@ * Used to be content of spd byte 62 which does not make * that much sense. */ - s->dimms[dimm_idx].width = decoded_dimm.width; - if (!(s->dimms[dimm_idx].width & (0x8 | 0x10))) { + + if (!(decoded_dimm.width & (0x8 | 0x10))) { printk(BIOS_ERR, "DIMM%d Unsupported width: x%d. Disabling dimm\n", dimm_idx, s->dimms[dimm_idx].width); return 1; } + + s->dimms[dimm_idx].width = (decoded_dimm.width >> 3) - 1; /* * This boils down to: * "Except for the x16 configuration, all DDR2 devices have a @@ -96,7 +98,7 @@ * page size." * Micron, 'TN-47-16 Designing for High-Density DDR2 Memory' */ - s->dimms[dimm_idx].page_size = s->dimms[dimm_idx].width * + s->dimms[dimm_idx].page_size = decoded_dimm.width * (1 << decoded_dimm.col_bits); switch (decoded_dimm.banks) { diff --git a/src/northbridge/intel/x4x/spd_ddr3_decode.c b/src/northbridge/intel/x4x/spd_ddr3_decode.c new file mode 100644 index 0000000..fd69fd4 --- /dev/null +++ b/src/northbridge/intel/x4x/spd_ddr3_decode.c @@ -0,0 +1,175 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 Damien Zammit <damien(a)zamaudio.com> + * Copyright (C) 2017 Arthur Heymans <arthur(a)aheymans.xyz> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/io.h> +#include <console/console.h> +#include <device/dram/ddr3.h> +#include "x4x.h" + +static void normalize_tCLK(u32 *tCLK) +{ + if (*tCLK <= TCK_666MHZ) + *tCLK = TCK_666MHZ; + else if (*tCLK <= TCK_533MHZ) + *tCLK = TCK_533MHZ; + else if (*tCLK <= TCK_400MHZ) + *tCLK = TCK_400MHZ; + else + *tCLK = 0; +} + +static void increase_tCLK(u32 *tCLK) +{ + ++*tCLK; + normalize_tCLK(tCLK); +} + +void select_cas_dramfreq_ddr3(struct sysinfo *s, + struct abs_timings *saved_timings) +{ + /* various constraints must be fulfilled: + CAS * tCK < 20ns == 160MTB + tCK_max >= tCK >= tCK_min + CAS >= roundup(tAA_min/tCK) + CAS supported + AND BTW: Clock(MT) = 2000 / tCK(ns) - intel uses MTs but calls them MHz + */ + + u32 min_tCLK; + u8 try_CAS; + u16 capid = (pci_read_config16(PCI_DEV(0, 0, 0), 0xea) >> 4) & 0x3f; + + switch (s->max_fsb) { + default: + case FSB_CLOCK_800MHz: + min_tCLK = TCK_400MHZ; + break; + case FSB_CLOCK_1066MHz: + min_tCLK = TCK_533MHZ; + break; + case FSB_CLOCK_1333MHz: + min_tCLK = TCK_666MHZ; + break; + } + + switch (capid >> 3) { + default: /* Should not happen */ + min_tCLK = TCK_400MHZ; + break; + case 1: + min_tCLK = MAX(min_tCLK, TCK_400MHZ); + break; + case 2: + min_tCLK = MAX(min_tCLK, TCK_533MHZ); + break; + case 3: /* Only on P45 */ + min_tCLK = MAX(min_tCLK, TCK_666MHZ); + break; + } + + min_tCLK = MAX(min_tCLK, saved_timings->min_tclk); + normalize_tCLK(&min_tCLK); + if (min_tCLK == 0) { + printk(BIOS_ERR, "DRAM frequency is under lowest supported " + "frequency (400 MHz). Increasing to 400 MHz as last resort"); + min_tCLK = TCK_400MHZ; + } + + while (1) { + if (min_tCLK == 0) + die("Couldn't find compatible clock / CAS settings.\n"); + try_CAS = DIV_ROUND_UP(saved_timings->min_tAA, min_tCLK); + printk(BIOS_SPEW, "Trying CAS %u, tCK %u.\n", try_CAS, min_tCLK); + for (; try_CAS <= DDR3_MAX_CAS; ++try_CAS) { + if ((saved_timings->cas_supported << 4) & (1 << try_CAS)) + break; + } + if ((try_CAS <= DDR3_MAX_CAS) && (try_CAS * min_tCLK < 20 * 256)) { + /* Found good CAS. */ + printk(BIOS_SPEW, "Found compatible tCLK / CAS pair: %u / %u.\n", + min_tCLK, try_CAS); + break; + } + increase_tCLK(&min_tCLK); + } + s->selected_timings.tclk = min_tCLK; + s->selected_timings.CAS = try_CAS; + + switch (s->selected_timings.tclk) { + case TCK_400MHZ: + s->selected_timings.mem_clk = MEM_CLOCK_800MHz; break; + case TCK_533MHZ: + s->selected_timings.mem_clk = MEM_CLOCK_1066MHz; break; + case TCK_666MHZ: + s->selected_timings.mem_clk = MEM_CLOCK_1333MHz; break; + } +} + +int ddr3_save_dimminfo(u8 dimm_idx, u8 *raw_spd, + struct abs_timings *saved_timings, struct sysinfo *s) +{ + struct dimm_attr_st decoded_dimm; + + if (spd_decode_ddr3(&decoded_dimm, raw_spd) != SPD_STATUS_OK) + return 1; + + if (IS_ENABLED(CONFIG_DEBUG_RAM_SETUP)) + dram_print_spd_ddr3(&decoded_dimm); + + if (!(decoded_dimm.width & (0x8 | 0x10))) { + printk(BIOS_ERR, "DIMM%d Unsupported width: x%d. Disabling dimm\n", + dimm_idx, s->dimms[dimm_idx].width); + return 1; + } + s->dimms[dimm_idx].width = (decoded_dimm.width >> 3) - 1; + /* + * This boils down to: + * "Except for the x16 configuration, all DDR2 devices have a + * 1KB page size. For the x16 configuration, the page size is 2KB + * for all densities except the 256Mb device, which has a 1KB page size." + * Micron, 'TN-47-16 Designing for High-Density DDR2 Memory' + */ + s->dimms[dimm_idx].page_size = s->dimms[dimm_idx].width * + (1 << decoded_dimm.col_bits); + + s->dimms[dimm_idx].n_banks = 1; /* Always 8 banks on ddr3?? */ + + s->dimms[dimm_idx].ranks = decoded_dimm.ranks; + s->dimms[dimm_idx].rows = decoded_dimm.row_bits; + s->dimms[dimm_idx].cols = decoded_dimm.col_bits; + + saved_timings->min_tRAS = + MAX(saved_timings->min_tRAS, decoded_dimm.tRAS); + saved_timings->min_tRP = + MAX(saved_timings->min_tRP, decoded_dimm.tRP); + saved_timings->min_tRCD = + MAX(saved_timings->min_tRCD, decoded_dimm.tRCD); + saved_timings->min_tWR = + MAX(saved_timings->min_tWR, decoded_dimm.tWR); + saved_timings->min_tRFC = + MAX(saved_timings->min_tRFC, decoded_dimm.tRFC); + saved_timings->min_tWTR = + MAX(saved_timings->min_tWTR, decoded_dimm.tWTR); + saved_timings->min_tRRD = + MAX(saved_timings->min_tRRD, decoded_dimm.tRRD); + saved_timings->min_tRTP = + MAX(saved_timings->min_tRTP, decoded_dimm.tRTP); + saved_timings->min_tAA = + MAX(saved_timings->min_tAA, decoded_dimm.tAA); + saved_timings->cas_supported &= decoded_dimm.cas_supported; + return 0; +} diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h index fc7fbfe..43e37ef 100644 --- a/src/northbridge/intel/x4x/x4x.h +++ b/src/northbridge/intel/x4x/x4x.h @@ -323,6 +323,7 @@ struct abs_timings { u32 min_tclk; + u32 min_tAA; u32 min_tRAS; u32 min_tRP; u32 min_tRCD; @@ -349,6 +350,11 @@ struct abs_timings *saved_timings); int ddr2_save_dimminfo(u8 dimm_idx, u8 *raw_spd, struct abs_timings *saved_timings, struct sysinfo *s); +void select_cas_dramfreq_ddr3(struct sysinfo *s, + struct abs_timings *saved_timings); +int ddr3_save_dimminfo(u8 dimm_idx, u8 *raw_spd, + struct abs_timings *saved_timings, struct sysinfo *s); + struct acpi_rsdp; #ifndef __SIMPLE_DEVICE__ -- To view, visit
https://review.coreboot.org/19869
To unsubscribe, visit
https://review.coreboot.org/settings
Gerrit-MessageType: newchange Gerrit-Change-Id: I8dba19ca1e6e6b0a03b56c8de9633f9c1a2eb7d7 Gerrit-PatchSet: 1 Gerrit-Project: coreboot Gerrit-Branch: master Gerrit-Owner: Arthur Heymans <arthur(a)aheymans.xyz>
1
0
0
0
Change in coreboot[master]: nb/x4x/raminit: Split of DDR2 specific functions to its own ...
by Arthur Heymans (Code Review)
24 May '17
24 May '17
Arthur Heymans has uploaded a new change for review. (
https://review.coreboot.org/19868
) Change subject: nb/x4x/raminit: Split of DDR2 specific functions to its own file ...................................................................... nb/x4x/raminit: Split of DDR2 specific functions to its own file Headers for device/dram/ddr2 and ddr3 conflict so the easy solution is have separate files for functions that use those. Change-Id: I3ab281f4d8fcce3ef3cf8e355e7ea7286c73e4ff Signed-off-by: Arthur Heymans <arthur(a)aheymans.xyz> --- M src/northbridge/intel/x4x/Makefile.inc M src/northbridge/intel/x4x/raminit.c A src/northbridge/intel/x4x/spd_ddr2_decode.c M src/northbridge/intel/x4x/x4x.h 4 files changed, 161 insertions(+), 138 deletions(-) git pull ssh://review.coreboot.org:29418/coreboot refs/changes/68/19868/1 diff --git a/src/northbridge/intel/x4x/Makefile.inc b/src/northbridge/intel/x4x/Makefile.inc index 34d9b0f..b433810 100644 --- a/src/northbridge/intel/x4x/Makefile.inc +++ b/src/northbridge/intel/x4x/Makefile.inc @@ -20,6 +20,7 @@ romstage-y += raminit.c romstage-y += raminit_ddr2.c romstage-y += ram_calc.c +romstage-y += spd_ddr2_decode.c ramstage-y += acpi.c ramstage-y += ram_calc.c diff --git a/src/northbridge/intel/x4x/raminit.c b/src/northbridge/intel/x4x/raminit.c index 67e9a1b..7e69b4c 100644 --- a/src/northbridge/intel/x4x/raminit.c +++ b/src/northbridge/intel/x4x/raminit.c @@ -28,71 +28,10 @@ #include <pc80/mc146818rtc.h> #include <spd.h> #include <string.h> -#include <device/dram/ddr2.h> static inline int spd_read_byte(unsigned int device, unsigned int address) { return smbus_read_byte(device, address); -} - -struct abs_timings { - u32 min_tclk; - u32 min_tRAS; - u32 min_tRP; - u32 min_tRCD; - u32 min_tWR; - u32 min_tRFC; - u32 min_tWTR; - u32 min_tRRD; - u32 min_tRTP; - u32 tCLK_cas[TOTAL_DIMMS][8]; - u32 cas_supported; -}; - -static void select_cas_dramfreq_ddr2(struct sysinfo *s, - struct abs_timings *saved_timings) -{ - u8 selected_cas; - u8 cas_mask = SPD_CAS_LATENCY_DDR2_5 | SPD_CAS_LATENCY_DDR2_6; - u32 common_min_tclk[8]; - u32 common_tCLK; - - cas_mask &= saved_timings->cas_supported; - get_common_min_tclk(cas_mask, TOTAL_DIMMS, common_min_tclk, - saved_timings->tCLK_cas); - /* On this northbridge the highest DDR2 frequency is 800MHz */ - common_tCLK = get_common_freq_cas(cas_mask, common_min_tclk, - &selected_cas, TCK_400MHZ); - - if (common_tCLK == 0) - die("Could not find common memory frequency and CAS\n"); - - s->selected_timings.CAS = selected_cas; - s->selected_timings.tclk = common_tCLK; - - switch (s->selected_timings.tclk) { - case TCK_200MHZ: - case TCK_266MHZ: - /* FIXME: this works on vendor BIOS */ - die("Selected dran frequency not supported\n"); - case TCK_333MHZ: - s->selected_timings.mem_clk = MEM_CLOCK_667MHz; - break; - case TCK_400MHZ: - s->selected_timings.mem_clk = MEM_CLOCK_800MHz; - break; - } - - switch (s->selected_timings.tclk) { - case TCK_200MHZ: - s->selected_timings.mem_clk = MEM_CLOCK_400MHz; break; - case TCK_266MHZ: - s->selected_timings.mem_clk = MEM_CLOCK_533MHz; break; - case TCK_333MHZ: - s->selected_timings.mem_clk = MEM_CLOCK_667MHz; break; - case TCK_400MHZ: - s->selected_timings.mem_clk = MEM_CLOCK_800MHz; break; - } } static void mchinfo_ddr2(struct sysinfo *s) @@ -111,85 +50,8 @@ if (!(capid & (1<<(56-32)))) printk(BIOS_WARNING, "AMT enabled\n"); - s->max_ddr2_mhz = 800; // All chipsets in x4x support up to 800MHz DDR2 - printk(BIOS_WARNING, "Capable of DDR2 of %d MHz or lower\n", s->max_ddr2_mhz); - if (!(capid & (1<<(48-32)))) printk(BIOS_WARNING, "VT-d enabled\n"); -} - -static int ddr2_save_dimminfo(u8 dimm_idx, u8 *raw_spd, - struct abs_timings *saved_timings, struct sysinfo *s) -{ - struct dimm_attr_st decoded_dimm; - int i; - - if (spd_decode_ddr2(&decoded_dimm, raw_spd) != SPD_STATUS_OK) - return 1; - - if (IS_ENABLED(CONFIG_DEBUG_RAM_SETUP)) - dram_print_spd_ddr2(&decoded_dimm); - - /* - * Used to be content of spd byte 62 which does not make - * that much sense. - */ - s->dimms[dimm_idx].width = decoded_dimm.width; - if (!(s->dimms[dimm_idx].width & (0x8 | 0x10))) { - printk(BIOS_ERR, "DIMM%d Unsupported width: x%d. Disabling dimm\n", - dimm_idx, s->dimms[dimm_idx].width); - return 1; - } - /* - * This boils down to: - * "Except for the x16 configuration, all DDR2 devices have a - * 1KB page size. For the x16 configuration, the page size is 2KB - * for all densities except the 256Mb device, which has a 1KB page size." - * Micron, 'TN-47-16 Designing for High-Density DDR2 Memory' - */ - s->dimms[dimm_idx].page_size = s->dimms[dimm_idx].width * - (1 << decoded_dimm.col_bits); - - switch (decoded_dimm.banks) { - case 4: - s->dimms[dimm_idx].n_banks = 0; - break; - case 8: - s->dimms[dimm_idx].n_banks = 1; - break; - default: - printk(BIOS_ERR, "DIMM%d Unsupported #banks: x%d. Disabling dimm\n", - dimm_idx, decoded_dimm.banks); - return 1; - } - - s->dimms[dimm_idx].ranks = decoded_dimm.ranks; - s->dimms[dimm_idx].rows = decoded_dimm.row_bits; - s->dimms[dimm_idx].cols = decoded_dimm.col_bits; - - saved_timings->cas_supported &= decoded_dimm.cas_supported; - - saved_timings->min_tRAS = - MAX(saved_timings->min_tRAS, decoded_dimm.tRAS); - saved_timings->min_tRP = - MAX(saved_timings->min_tRP, decoded_dimm.tRP); - saved_timings->min_tRCD = - MAX(saved_timings->min_tRCD, decoded_dimm.tRCD); - saved_timings->min_tWR = - MAX(saved_timings->min_tWR, decoded_dimm.tWR); - saved_timings->min_tRFC = - MAX(saved_timings->min_tRFC, decoded_dimm.tRFC); - saved_timings->min_tWTR = - MAX(saved_timings->min_tWTR, decoded_dimm.tWTR); - saved_timings->min_tRRD = - MAX(saved_timings->min_tRRD, decoded_dimm.tRRD); - saved_timings->min_tRTP = - MAX(saved_timings->min_tRTP, decoded_dimm.tRTP); - for (i = 0; i < 8; i++) { - saved_timings->tCLK_cas[dimm_idx][i] = - decoded_dimm.cycle_time[i]; - } - return 0; } static void select_discrete_timings(struct sysinfo *s, diff --git a/src/northbridge/intel/x4x/spd_ddr2_decode.c b/src/northbridge/intel/x4x/spd_ddr2_decode.c new file mode 100644 index 0000000..938aab7 --- /dev/null +++ b/src/northbridge/intel/x4x/spd_ddr2_decode.c @@ -0,0 +1,142 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 Damien Zammit <damien(a)zamaudio.com> + * Copyright (C) 2017 Arthur Heymans <arthur(a)aheymans.xyz> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/io.h> +#include <console/console.h> +#include <device/dram/ddr2.h> +#include "x4x.h" + +void select_cas_dramfreq_ddr2(struct sysinfo *s, + struct abs_timings *saved_timings) +{ + u8 selected_cas; + u8 cas_mask = SPD_CAS_LATENCY_DDR2_5 | SPD_CAS_LATENCY_DDR2_6; + u32 common_min_tclk[8]; + u32 common_tCLK; + + cas_mask &= saved_timings->cas_supported; + get_common_min_tclk(cas_mask, TOTAL_DIMMS, common_min_tclk, + saved_timings->tCLK_cas); + /* On this northbridge the highest DDR2 frequency is 800MHz */ + common_tCLK = get_common_freq_cas(cas_mask, common_min_tclk, + &selected_cas, TCK_400MHZ); + + if (common_tCLK == 0) + die("Could not find common memory frequency and CAS\n"); + + s->selected_timings.CAS = selected_cas; + s->selected_timings.tclk = common_tCLK; + + switch (s->selected_timings.tclk) { + case TCK_200MHZ: + case TCK_266MHZ: + /* FIXME: this works on vendor BIOS */ + die("Selected dran frequency not supported\n"); + case TCK_333MHZ: + s->selected_timings.mem_clk = MEM_CLOCK_667MHz; + break; + case TCK_400MHZ: + s->selected_timings.mem_clk = MEM_CLOCK_800MHz; + break; + } + + switch (s->selected_timings.tclk) { + case TCK_200MHZ: + s->selected_timings.mem_clk = MEM_CLOCK_400MHz; break; + case TCK_266MHZ: + s->selected_timings.mem_clk = MEM_CLOCK_533MHz; break; + case TCK_333MHZ: + s->selected_timings.mem_clk = MEM_CLOCK_667MHz; break; + case TCK_400MHZ: + s->selected_timings.mem_clk = MEM_CLOCK_800MHz; break; + } +} + +int ddr2_save_dimminfo(u8 dimm_idx, u8 *raw_spd, + struct abs_timings *saved_timings, struct sysinfo *s) +{ + struct dimm_attr_st decoded_dimm; + int i; + + if (spd_decode_ddr2(&decoded_dimm, raw_spd) != SPD_STATUS_OK) + return 1; + + if (IS_ENABLED(CONFIG_DEBUG_RAM_SETUP)) + dram_print_spd_ddr2(&decoded_dimm); + + /* + * Used to be content of spd byte 62 which does not make + * that much sense. + */ + s->dimms[dimm_idx].width = decoded_dimm.width; + if (!(s->dimms[dimm_idx].width & (0x8 | 0x10))) { + printk(BIOS_ERR, "DIMM%d Unsupported width: x%d. Disabling dimm\n", + dimm_idx, s->dimms[dimm_idx].width); + return 1; + } + /* + * This boils down to: + * "Except for the x16 configuration, all DDR2 devices have a + * 1KB page size. For the x16 configuration, the page size is 2KB + * for all densities except the 256Mb device, which has a 1KB + * page size." + * Micron, 'TN-47-16 Designing for High-Density DDR2 Memory' + */ + s->dimms[dimm_idx].page_size = s->dimms[dimm_idx].width * + (1 << decoded_dimm.col_bits); + + switch (decoded_dimm.banks) { + case 4: + s->dimms[dimm_idx].n_banks = 0; + break; + case 8: + s->dimms[dimm_idx].n_banks = 1; + break; + default: + printk(BIOS_ERR, "DIMM%d Unsupported #banks: x%d. Disabling dimm\n", + dimm_idx, decoded_dimm.banks); + return 1; + } + + s->dimms[dimm_idx].ranks = decoded_dimm.ranks; + s->dimms[dimm_idx].rows = decoded_dimm.row_bits; + s->dimms[dimm_idx].cols = decoded_dimm.col_bits; + + saved_timings->cas_supported &= decoded_dimm.cas_supported; + + saved_timings->min_tRAS = + MAX(saved_timings->min_tRAS, decoded_dimm.tRAS); + saved_timings->min_tRP = + MAX(saved_timings->min_tRP, decoded_dimm.tRP); + saved_timings->min_tRCD = + MAX(saved_timings->min_tRCD, decoded_dimm.tRCD); + saved_timings->min_tWR = + MAX(saved_timings->min_tWR, decoded_dimm.tWR); + saved_timings->min_tRFC = + MAX(saved_timings->min_tRFC, decoded_dimm.tRFC); + saved_timings->min_tWTR = + MAX(saved_timings->min_tWTR, decoded_dimm.tWTR); + saved_timings->min_tRRD = + MAX(saved_timings->min_tRRD, decoded_dimm.tRRD); + saved_timings->min_tRTP = + MAX(saved_timings->min_tRTP, decoded_dimm.tRTP); + for (i = 0; i < 8; i++) { + saved_timings->tCLK_cas[dimm_idx][i] = + decoded_dimm.cycle_time[i]; + } + return 0; +} diff --git a/src/northbridge/intel/x4x/x4x.h b/src/northbridge/intel/x4x/x4x.h index 06d88ee..fc7fbfe 100644 --- a/src/northbridge/intel/x4x/x4x.h +++ b/src/northbridge/intel/x4x/x4x.h @@ -321,6 +321,20 @@ DQ8 }; +struct abs_timings { + u32 min_tclk; + u32 min_tRAS; + u32 min_tRP; + u32 min_tRCD; + u32 min_tWR; + u32 min_tRFC; + u32 min_tWTR; + u32 min_tRRD; + u32 min_tRTP; + u32 tCLK_cas[TOTAL_DIMMS][8]; + u32 cas_supported; +}; + #ifndef __BOOTBLOCK__ void x4x_early_init(void); void x4x_late_init(int s3resume); @@ -331,6 +345,10 @@ void raminit_ddr2(struct sysinfo *); u32 fsb2mhz(u32 speed); u32 ddr2mhz(u32 speed); +void select_cas_dramfreq_ddr2(struct sysinfo *s, + struct abs_timings *saved_timings); +int ddr2_save_dimminfo(u8 dimm_idx, u8 *raw_spd, + struct abs_timings *saved_timings, struct sysinfo *s); struct acpi_rsdp; #ifndef __SIMPLE_DEVICE__ -- To view, visit
https://review.coreboot.org/19868
To unsubscribe, visit
https://review.coreboot.org/settings
Gerrit-MessageType: newchange Gerrit-Change-Id: I3ab281f4d8fcce3ef3cf8e355e7ea7286c73e4ff Gerrit-PatchSet: 1 Gerrit-Project: coreboot Gerrit-Branch: master Gerrit-Owner: Arthur Heymans <arthur(a)aheymans.xyz>
1
0
0
0
← Newer
1
...
92
93
94
95
96
97
98
...
389
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
Results per page:
10
25
50
100
200