blob: eac8fa745547712cc96e909c6b6a85717dfcb9c1 [file] [log] [blame]
Jordan Crouse68182452007-05-03 21:36:51 +00001/*
Stefan Reinauer7e61e452008-01-18 10:35:56 +00002 * This file is part of the coreboot project.
Stefan Reinauer5ff7c132011-10-31 12:56:45 -07003 *
Jordan Crouse68182452007-05-03 21:36:51 +00004 * Copyright (C) 2006 Indrek Kruusa <indrek.kruusa@artecdesign.ee>
5 * Copyright (C) 2006 Ronald G. Minnich <rminnich@gmail.com>
6 * Copyright (C) 2007 Advanced Micro Devices, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
Jordan Crouse68182452007-05-03 21:36:51 +000017 */
Ron Minnich5e9dc232006-07-28 16:06:16 +000018
Edward O'Callaghancd2c1242014-08-09 15:51:19 +100019/* SetDelayControl */
Edwin Beasantf333ba02010-06-10 15:24:57 +000020#include "cpu/x86/msr.h"
21
22
Edwin Beasantf333ba02010-06-10 15:24:57 +000023/**
24 * Delay Control Settings table from AMD (MCP 0x4C00000F).
25 */
26static const msrinit_t delay_msr_table[] = {
27 {CPU_BC_MSS_ARRAY_CTL0, {.hi = 0x00000000, .lo = 0x2814D352}},
28 {CPU_BC_MSS_ARRAY_CTL1, {.hi = 0x00000000, .lo = 0x1068334D}},
29 {CPU_BC_MSS_ARRAY_CTL2, {.hi = 0x00000106, .lo = 0x83104104}},
30};
31
Edwin Beasantf333ba02010-06-10 15:24:57 +000032static const struct delay_controls {
33 u8 dimms;
34 u8 devices;
35 u32 slow_hi;
36 u32 slow_low;
37 u32 fast_hi;
38 u32 fast_low;
39} delay_control_table[] = {
40 /* DIMMs Devs Slow (<=333MHz) Fast (>334MHz) */
41 { 1, 4, 0x0837100FF, 0x056960004, 0x0827100FF, 0x056960004 },
42 { 1, 8, 0x0837100AA, 0x056960004, 0x0827100AA, 0x056960004 },
43 { 1, 16, 0x0837100AA, 0x056960004, 0x082710055, 0x056960004 },
44 { 2, 8, 0x0837100A5, 0x056960004, 0x082710000, 0x056960004 },
45 { 2, 16, 0x0937100A5, 0x056960004, 0x0C27100A5, 0x056960004 },
46 { 2, 20, 0x0B37100A5, 0x056960004, 0x0B27100A5, 0x056960004 },
47 { 2, 24, 0x0B37100A5, 0x056960004, 0x0B27100A5, 0x056960004 },
48 { 2, 32, 0x0B37100A5, 0x056960004, 0x0B2710000, 0x056960004 },
49};
50
51/*
52 * Bit 55 (disable SDCLK 1,3,5) should be set if there is a single DIMM
53 * in slot 0, but it should be clear for all 2 DIMM settings and if a
54 * single DIMM is in slot 1. Bits 54:52 should always be set to '111'.
55 *
56 * Settings for single DIMM and no VTT termination (like DB800 platform)
57 * 0xF2F100FF 0x56960004
58 * -------------------------------------
59 * ADDR/CTL have 22 ohm series R
60 * DQ/DQM/DQS have 33 ohm series R
61 */
62
63/**
64 * This is Black Magic DRAM timing juju[1].
65 *
66 * DRAM delay depends on CPU clock, memory bus clock, memory bus loading,
67 * memory bus termination, your middle initial (ha! caught you!), GeodeLink
68 * clock rate, and DRAM timing specifications.
69 *
70 * From this the code computes a number which is "known to work". No,
71 * hardware is not an exact science. And, finally, if an FS2 (JTAG debugger)
72 * is hooked up, then just don't do anything. This code was written by a master
73 * of the Dark Arts at AMD and should not be modified in any way.
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070074 *
Edwin Beasantf333ba02010-06-10 15:24:57 +000075 * [1] (http://www.thefreedictionary.com/juju)
76 *
77 * @param dimm0 The SMBus address of DIMM 0 (mainboard dependent).
78 * @param dimm1 The SMBus address of DIMM 1 (mainboard dependent).
79 * @param terminated The bus is terminated. (mainboard dependent).
80 */
81static void SetDelayControl(u8 dimm0, u8 dimm1, int terminated)
Jordan Crouse9934b812007-05-10 18:32:28 +000082{
Edwin Beasantf333ba02010-06-10 15:24:57 +000083 u32 glspeed;
84 u8 spdbyte0, spdbyte1, dimms, i;
Ron Minnich5e9dc232006-07-28 16:06:16 +000085 msr_t msr;
86
Marc Jonesbc8176c2007-05-04 18:24:55 +000087 glspeed = GeodeLinkSpeed();
88
Edwin Beasantf333ba02010-06-10 15:24:57 +000089 /* Fix delay controls for DM and IM arrays. */
90 for (i = 0; i < ARRAY_SIZE(delay_msr_table); i++)
91 wrmsr(delay_msr_table[i].index, delay_msr_table[i].msr);
Jordan Crouse9934b812007-05-10 18:32:28 +000092
Edwin Beasantf333ba02010-06-10 15:24:57 +000093 msr = rdmsr(GLCP_FIFOCTL);
Marc Jonesbc8176c2007-05-04 18:24:55 +000094 msr.hi = 0x00000005;
Edwin Beasantf333ba02010-06-10 15:24:57 +000095 wrmsr(GLCP_FIFOCTL, msr);
Ron Minnich5e9dc232006-07-28 16:06:16 +000096
Edwin Beasantf333ba02010-06-10 15:24:57 +000097 /* Enable setting. */
Marc Jonesbc8176c2007-05-04 18:24:55 +000098 msr.hi = 0;
99 msr.lo = 0x00000001;
Edwin Beasantf333ba02010-06-10 15:24:57 +0000100 wrmsr(CPU_BC_MSS_ARRAY_CTL_ENA, msr);
Ron Minnich5e9dc232006-07-28 16:06:16 +0000101
Edwin Beasantf333ba02010-06-10 15:24:57 +0000102 /* Debug Delay Control setup check.
103 * Leave it alone if it has been setup. FS2 or something is here.
Jordan Crouse9934b812007-05-10 18:32:28 +0000104 */
Edwin Beasantf333ba02010-06-10 15:24:57 +0000105 msr = rdmsr(GLCP_DELAY_CONTROLS);
106 if (msr.lo & ~(DELAY_LOWER_STATUS_MASK))
107 return;
108
109 /* Delay Controls based on DIMM loading. UGH!
110 * Number of devices = module width (SPD 6) / device width (SPD 13)
111 * * physical banks (SPD 5)
112 *
113 * Note: We only support a module width of 64.
114 */
115 dimms = 0;
116 spdbyte0 = spd_read_byte(dimm0, SPD_PRIMARY_SDRAM_WIDTH);
Jordan Crouse9934b812007-05-10 18:32:28 +0000117 if (spdbyte0 != 0xFF) {
Edwin Beasantf333ba02010-06-10 15:24:57 +0000118 dimms++;
119 spdbyte0 = (u8)64 / spdbyte0 *
120 (u8)(spd_read_byte(dimm0, SPD_NUM_DIMM_BANKS));
Jordan Crouse9934b812007-05-10 18:32:28 +0000121 } else {
122 spdbyte0 = 0;
Marc Jonesbc8176c2007-05-04 18:24:55 +0000123 }
124
Edwin Beasantf333ba02010-06-10 15:24:57 +0000125 spdbyte1 = spd_read_byte(dimm1, SPD_PRIMARY_SDRAM_WIDTH);
Jordan Crouse9934b812007-05-10 18:32:28 +0000126 if (spdbyte1 != 0xFF) {
Edwin Beasantf333ba02010-06-10 15:24:57 +0000127 dimms++;
128 spdbyte1 = (u8)64 / spdbyte1 *
129 (u8)(spd_read_byte(dimm1, SPD_NUM_DIMM_BANKS));
Jordan Crouse9934b812007-05-10 18:32:28 +0000130 } else {
131 spdbyte1 = 0;
Marc Jonesbc8176c2007-05-04 18:24:55 +0000132 }
Marc Jonesbc8176c2007-05-04 18:24:55 +0000133
Edwin Beasantf333ba02010-06-10 15:24:57 +0000134 /* Zero GLCP_DELAY_CONTROLS MSR */
Marc Jonesbc8176c2007-05-04 18:24:55 +0000135 msr.hi = msr.lo = 0;
136
Edwin Beasantf333ba02010-06-10 15:24:57 +0000137 /* Save some power, disable clock to second DIMM if it is empty. */
138 if (spdbyte1 == 0)
139 msr.hi |= DELAY_UPPER_DISABLE_CLK135;
140
141 spdbyte0 += spdbyte1;
142
143 if ((dimms == 1) && (terminated == DRAM_TERMINATED)) {
144 msr.hi = 0xF2F100FF;
145 msr.lo = 0x56960004;
146 } else for (i = 0; i < ARRAY_SIZE(delay_control_table); i++) {
147 if ((dimms == delay_control_table[i].dimms) &&
148 (spdbyte0 <= delay_control_table[i].devices)) {
Jordan Crouse9934b812007-05-10 18:32:28 +0000149 if (glspeed < 334) {
Edwin Beasantf333ba02010-06-10 15:24:57 +0000150 msr.hi |= delay_control_table[i].slow_hi;
151 msr.lo |= delay_control_table[i].slow_low;
Jordan Crouse9934b812007-05-10 18:32:28 +0000152 } else {
Edwin Beasantf333ba02010-06-10 15:24:57 +0000153 msr.hi |= delay_control_table[i].fast_hi;
154 msr.lo |= delay_control_table[i].fast_low;
Marc Jonesbc8176c2007-05-04 18:24:55 +0000155 }
Edwin Beasantf333ba02010-06-10 15:24:57 +0000156 break;
Marc Jonesbc8176c2007-05-04 18:24:55 +0000157 }
158 }
Jordan Crouse9934b812007-05-10 18:32:28 +0000159 wrmsr(GLCP_DELAY_CONTROLS, msr);
Ron Minnich5e9dc232006-07-28 16:06:16 +0000160}
Marc Jonesbc8176c2007-05-04 18:24:55 +0000161
Edwin Beasantf333ba02010-06-10 15:24:57 +0000162void cpuRegInit(int debug_clock_disable, u8 dimm0, u8 dimm1, int terminated)
Jordan Crouse9934b812007-05-10 18:32:28 +0000163{
Ron Minnich5e9dc232006-07-28 16:06:16 +0000164 int msrnum;
165 msr_t msr;
Jordan Crouse9934b812007-05-10 18:32:28 +0000166
Marc Jonesbc8176c2007-05-04 18:24:55 +0000167 /* Castle 2.0 BTM periodic sync period. */
Jordan Crouse9934b812007-05-10 18:32:28 +0000168 /* [40:37] 1 sync record per 256 bytes */
Stefan Reinauer5491ca22015-01-05 13:07:39 -0800169 printk(BIOS_DEBUG, "Castle 2.0 BTM periodic sync period.\n");
Marc Jonesbc8176c2007-05-04 18:24:55 +0000170 msrnum = CPU_PF_CONF;
Ron Minnich5e9dc232006-07-28 16:06:16 +0000171 msr = rdmsr(msrnum);
Marc Jonesbc8176c2007-05-04 18:24:55 +0000172 msr.hi |= (0x8 << 5);
Ron Minnich5e9dc232006-07-28 16:06:16 +0000173 wrmsr(msrnum, msr);
Ron Minnich5e9dc232006-07-28 16:06:16 +0000174
Marc Jonesbc8176c2007-05-04 18:24:55 +0000175 /*
Marc Jonesddf845f2007-05-10 23:22:27 +0000176 * LX performance setting.
177 * Enable Quack for fewer re-RAS on the MC
Jordan Crouse9934b812007-05-10 18:32:28 +0000178 */
Stefan Reinauer5491ca22015-01-05 13:07:39 -0800179 printk(BIOS_DEBUG, "Enable Quack for fewer re-RAS on the MC\n");
Marc Jonesbc8176c2007-05-04 18:24:55 +0000180 msrnum = GLIU0_ARB;
181 msr = rdmsr(msrnum);
182 msr.hi &= ~ARB_UPPER_DACK_EN_SET;
183 msr.hi |= ARB_UPPER_QUACK_EN_SET;
184 wrmsr(msrnum, msr);
Ron Minnich5e9dc232006-07-28 16:06:16 +0000185
Marc Jonesbc8176c2007-05-04 18:24:55 +0000186 msrnum = GLIU1_ARB;
187 msr = rdmsr(msrnum);
188 msr.hi &= ~ARB_UPPER_DACK_EN_SET;
189 msr.hi |= ARB_UPPER_QUACK_EN_SET;
190 wrmsr(msrnum, msr);
191
Stefan Reinauer14e22772010-04-27 06:56:47 +0000192 /* GLIU port active enable, limit south pole masters
193 * (AES and PCI) to one outstanding transaction.
Ronald G. Minnich65bc4602007-10-26 14:57:46 +0000194 */
Stefan Reinauer5491ca22015-01-05 13:07:39 -0800195 printk(BIOS_DEBUG, " GLIU port active enable\n");
Marc Jonesbc8176c2007-05-04 18:24:55 +0000196 msrnum = GLIU1_PORT_ACTIVE;
197 msr = rdmsr(msrnum);
198 msr.lo &= ~0x880;
199 wrmsr(msrnum, msr);
200
201 /* Set the Delay Control in GLCP */
Stefan Reinauer5491ca22015-01-05 13:07:39 -0800202 printk(BIOS_DEBUG, "Set the Delay Control in GLCP\n");
Edwin Beasantf333ba02010-06-10 15:24:57 +0000203 SetDelayControl(dimm0, dimm1, terminated);
Marc Jonesbc8176c2007-05-04 18:24:55 +0000204
Jordan Crouse9934b812007-05-10 18:32:28 +0000205 /* Enable RSDC */
Stefan Reinauer5491ca22015-01-05 13:07:39 -0800206 printk(BIOS_DEBUG, "Enable RSDC\n");
Marc Jonesbc8176c2007-05-04 18:24:55 +0000207 msrnum = CPU_AC_SMM_CTL;
208 msr = rdmsr(msrnum);
209 msr.lo |= SMM_INST_EN_SET;
Jordan Crouse9934b812007-05-10 18:32:28 +0000210 wrmsr(msrnum, msr);
Ron Minnich5e9dc232006-07-28 16:06:16 +0000211
Marc Jonesbc8176c2007-05-04 18:24:55 +0000212 /* FPU imprecise exceptions bit */
Stefan Reinauer5491ca22015-01-05 13:07:39 -0800213 printk(BIOS_DEBUG, "FPU imprecise exceptions bit\n");
Jordan Crouse9934b812007-05-10 18:32:28 +0000214 msrnum = CPU_FPU_MSR_MODE;
215 msr = rdmsr(msrnum);
216 msr.lo |= FPU_IE_SET;
217 wrmsr(msrnum, msr);
Ron Minnich5e9dc232006-07-28 16:06:16 +0000218
Marc Jonesbc8176c2007-05-04 18:24:55 +0000219 /* Power Savers (Do after BIST) */
Jordan Crouse9934b812007-05-10 18:32:28 +0000220 /* Enable Suspend on HLT & PAUSE instructions */
Stefan Reinauer5491ca22015-01-05 13:07:39 -0800221 printk(BIOS_DEBUG, "Enable Suspend on HLT & PAUSE instructions\n");
Marc Jonesbc8176c2007-05-04 18:24:55 +0000222 msrnum = CPU_XC_CONFIG;
Jordan Crouse9934b812007-05-10 18:32:28 +0000223 msr = rdmsr(msrnum);
224 msr.lo |= XC_CONFIG_SUSP_ON_HLT | XC_CONFIG_SUSP_ON_PAUSE;
225 wrmsr(msrnum, msr);
Marc Jonesbc8176c2007-05-04 18:24:55 +0000226
227 /* Enable SUSP and allow TSC to run in Suspend (keep speed detection happy) */
Stefan Reinauer5491ca22015-01-05 13:07:39 -0800228 printk(BIOS_DEBUG, "Enable SUSP and allow TSC to run in Suspend\n");
Marc Jonesbc8176c2007-05-04 18:24:55 +0000229 msrnum = CPU_BC_CONF_0;
Jordan Crouse9934b812007-05-10 18:32:28 +0000230 msr = rdmsr(msrnum);
Marc Jonesbc8176c2007-05-04 18:24:55 +0000231 msr.lo |= TSC_SUSP_SET | SUSP_EN_SET;
232 msr.lo &= 0x0F0FFFFFF;
Jordan Crouse9934b812007-05-10 18:32:28 +0000233 msr.lo |= 0x002000000; /* PBZ213: Set PAUSEDLY = 2 */
234 wrmsr(msrnum, msr);
Ron Minnich5e9dc232006-07-28 16:06:16 +0000235
Jordan Crouse9934b812007-05-10 18:32:28 +0000236 /* Disable the debug clock to save power. */
Marc Jonesbc8176c2007-05-04 18:24:55 +0000237 /* NOTE: leave it enabled for fs2 debug */
Edwin Beasantf333ba02010-06-10 15:24:57 +0000238 if (debug_clock_disable && 0) {
239 msrnum = GLCP_DBGCLKCTL;
240 msr.hi = 0;
241 msr.lo = 0;
242 wrmsr(msrnum, msr);
243 }
Ron Minnich5e9dc232006-07-28 16:06:16 +0000244
Marc Jonesbc8176c2007-05-04 18:24:55 +0000245 /* Setup throttling delays to proper mode if it is ever enabled. */
Stefan Reinauer5491ca22015-01-05 13:07:39 -0800246 printk(BIOS_DEBUG, "Setup throttling delays to proper mode\n");
Marc Jonesbc8176c2007-05-04 18:24:55 +0000247 msrnum = GLCP_TH_OD;
248 msr.hi = 0;
249 msr.lo = 0x00000603C;
Jordan Crouse9934b812007-05-10 18:32:28 +0000250 wrmsr(msrnum, msr);
Stefan Reinauer5491ca22015-01-05 13:07:39 -0800251 printk(BIOS_DEBUG, "Done cpuRegInit\n");
Jordan Crouse9934b812007-05-10 18:32:28 +0000252}