This patch changes the "if else" style of parameter matching to table and also changes the rdpreamble parameter, which will cause that more then one DIMM will work for 939 motherboard.
Signed-off-by: Rudolf Marek <r.marek@assembler.cz> Acked-by: Jordan Crouse <jordan.crouse@amd.com> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2935 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
parent
1a0025675f
commit
ec70af6470
|
@ -134,7 +134,9 @@
|
||||||
#define DCL_D_DRV (1<<1)
|
#define DCL_D_DRV (1<<1)
|
||||||
#define DCL_QFC_EN (1<<2)
|
#define DCL_QFC_EN (1<<2)
|
||||||
#define DCL_DisDqsHys (1<<3)
|
#define DCL_DisDqsHys (1<<3)
|
||||||
|
#define DCL_Burst2Opt (1<<5)
|
||||||
#define DCL_DramInit (1<<8)
|
#define DCL_DramInit (1<<8)
|
||||||
|
#define DCL_DualDIMMen (1<<9)
|
||||||
#define DCL_DramEnable (1<<10)
|
#define DCL_DramEnable (1<<10)
|
||||||
#define DCL_MemClrStatus (1<<11)
|
#define DCL_MemClrStatus (1<<11)
|
||||||
#define DCL_ESR (1<<12)
|
#define DCL_ESR (1<<12)
|
||||||
|
@ -147,7 +149,8 @@
|
||||||
#define DCL_DisInRcvrs (1<<24)
|
#define DCL_DisInRcvrs (1<<24)
|
||||||
#define DCL_BypMax_SHIFT 25
|
#define DCL_BypMax_SHIFT 25
|
||||||
#define DCL_En2T (1<<28)
|
#define DCL_En2T (1<<28)
|
||||||
|
#define DCL_UpperCSMap (1<<29)
|
||||||
|
|
||||||
#define DRAM_CONFIG_HIGH 0x94
|
#define DRAM_CONFIG_HIGH 0x94
|
||||||
#define DCH_ASYNC_LAT_SHIFT 0
|
#define DCH_ASYNC_LAT_SHIFT 0
|
||||||
#define DCH_ASYNC_LAT_MASK 0xf
|
#define DCH_ASYNC_LAT_MASK 0xf
|
||||||
|
|
|
@ -1177,6 +1177,7 @@ static long spd_handle_unbuffered_dimms(const struct mem_controller *ctrl, long
|
||||||
int i;
|
int i;
|
||||||
int registered;
|
int registered;
|
||||||
int unbuffered;
|
int unbuffered;
|
||||||
|
int has_dualch = is_opteron(ctrl);
|
||||||
uint32_t dcl;
|
uint32_t dcl;
|
||||||
unbuffered = 0;
|
unbuffered = 0;
|
||||||
registered = 0;
|
registered = 0;
|
||||||
|
@ -1201,17 +1202,22 @@ static long spd_handle_unbuffered_dimms(const struct mem_controller *ctrl, long
|
||||||
if (unbuffered && registered) {
|
if (unbuffered && registered) {
|
||||||
die("Mixed buffered and registered dimms not supported");
|
die("Mixed buffered and registered dimms not supported");
|
||||||
}
|
}
|
||||||
#if 1
|
|
||||||
// yhlu debug: Athlon64 939 can do dual channel, but it uses unbuffered DIMMs
|
|
||||||
if (unbuffered && is_opteron(ctrl)) {
|
|
||||||
die("Unbuffered Dimms not supported on Opteron");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW);
|
dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW);
|
||||||
dcl &= ~DCL_UnBufDimm;
|
dcl &= ~DCL_UnBufDimm;
|
||||||
if (unbuffered) {
|
if (unbuffered) {
|
||||||
dcl |= DCL_UnBufDimm;
|
if ((has_dualch) && (!is_cpu_pre_d0())) {
|
||||||
|
dcl |= DCL_UnBufDimm; /* set DCL_DualDIMMen too? */
|
||||||
|
|
||||||
|
/* set DCL_En2T if you have non-equal DDR mem types! */
|
||||||
|
|
||||||
|
if ((cpuid_eax(1) & 0x30) == 0x30) {
|
||||||
|
/* CS[7:4] is copy of CS[3:0], should be set for 939 socket */
|
||||||
|
dcl |= DCL_UpperCSMap;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dcl |= DCL_UnBufDimm;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl);
|
pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl);
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -1333,6 +1339,9 @@ struct mem_param {
|
||||||
uint32_t dch_memclk;
|
uint32_t dch_memclk;
|
||||||
uint16_t dch_tref4k, dch_tref8k;
|
uint16_t dch_tref4k, dch_tref8k;
|
||||||
uint8_t dtl_twr;
|
uint8_t dtl_twr;
|
||||||
|
uint8_t dtl_twtr;
|
||||||
|
uint8_t dtl_trwt[3][3]; /* first index is CAS_LAT 2/2.5/3 and 128/registered64/64 */
|
||||||
|
uint8_t rdpreamble[4]; /* 0 is for registered, 1 for 1-2 DIMMS, 2 and 3 for 3 or 4 unreg dimm slots */
|
||||||
char name[9];
|
char name[9];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1349,6 +1358,9 @@ static const struct mem_param *get_mem_param(unsigned min_cycle_time)
|
||||||
.dch_tref4k = DTH_TREF_100MHZ_4K,
|
.dch_tref4k = DTH_TREF_100MHZ_4K,
|
||||||
.dch_tref8k = DTH_TREF_100MHZ_8K,
|
.dch_tref8k = DTH_TREF_100MHZ_8K,
|
||||||
.dtl_twr = 2,
|
.dtl_twr = 2,
|
||||||
|
.dtl_twtr = 1,
|
||||||
|
.dtl_trwt = { { 2, 2, 3 }, { 3, 3, 4 }, { 3, 3, 4 }},
|
||||||
|
.rdpreamble = { ((9 << 1) + 0), ((9 << 1) + 0), ((9 << 1) + 0), ((9 << 1) + 0) }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "133Mhz\r\n",
|
.name = "133Mhz\r\n",
|
||||||
|
@ -1360,6 +1372,9 @@ static const struct mem_param *get_mem_param(unsigned min_cycle_time)
|
||||||
.dch_tref4k = DTH_TREF_133MHZ_4K,
|
.dch_tref4k = DTH_TREF_133MHZ_4K,
|
||||||
.dch_tref8k = DTH_TREF_133MHZ_8K,
|
.dch_tref8k = DTH_TREF_133MHZ_8K,
|
||||||
.dtl_twr = 2,
|
.dtl_twr = 2,
|
||||||
|
.dtl_twtr = 1,
|
||||||
|
.dtl_trwt = { { 2, 2, 3 }, { 3, 3, 4 }, { 3, 3, 4 }},
|
||||||
|
.rdpreamble = { ((8 << 1) + 0), ((7 << 1) + 0), ((7 << 1) + 1), ((7 << 1) + 0) }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "166Mhz\r\n",
|
.name = "166Mhz\r\n",
|
||||||
|
@ -1371,6 +1386,9 @@ static const struct mem_param *get_mem_param(unsigned min_cycle_time)
|
||||||
.dch_tref4k = DTH_TREF_166MHZ_4K,
|
.dch_tref4k = DTH_TREF_166MHZ_4K,
|
||||||
.dch_tref8k = DTH_TREF_166MHZ_8K,
|
.dch_tref8k = DTH_TREF_166MHZ_8K,
|
||||||
.dtl_twr = 3,
|
.dtl_twr = 3,
|
||||||
|
.dtl_twtr = 1,
|
||||||
|
.dtl_trwt = { { 3, 2, 3 }, { 3, 3, 4 }, { 4, 3, 4 }},
|
||||||
|
.rdpreamble = { ((7 << 1) + 1), ((6 << 1) + 0), ((6 << 1) + 1), ((6 << 1) + 0) }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "200Mhz\r\n",
|
.name = "200Mhz\r\n",
|
||||||
|
@ -1382,6 +1400,9 @@ static const struct mem_param *get_mem_param(unsigned min_cycle_time)
|
||||||
.dch_tref4k = DTH_TREF_200MHZ_4K,
|
.dch_tref4k = DTH_TREF_200MHZ_4K,
|
||||||
.dch_tref8k = DTH_TREF_200MHZ_8K,
|
.dch_tref8k = DTH_TREF_200MHZ_8K,
|
||||||
.dtl_twr = 3,
|
.dtl_twr = 3,
|
||||||
|
.dtl_twtr = 2,
|
||||||
|
.dtl_trwt = { { 0, 2, 3 }, { 3, 3, 4 }, { 3, 3, 4 }},
|
||||||
|
.rdpreamble = { ((7 << 1) + 0), ((5 << 1) + 0), ((5 << 1) + 1), ((5 << 1) + 1) }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.cycle_time = 0x00,
|
.cycle_time = 0x00,
|
||||||
|
@ -1423,8 +1444,8 @@ static struct spd_set_memclk_result spd_set_memclk(const struct mem_controller *
|
||||||
[NBCAP_MEMCLK_100MHZ] = 0xa0, /* 10ns */
|
[NBCAP_MEMCLK_100MHZ] = 0xa0, /* 10ns */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
value = pci_read_config32(ctrl->f3, NORTHBRIDGE_CAP);
|
value = pci_read_config32(ctrl->f3, NORTHBRIDGE_CAP);
|
||||||
|
|
||||||
min_cycle_time = min_cycle_times[(value >> NBCAP_MEMCLK_SHIFT) & NBCAP_MEMCLK_MASK];
|
min_cycle_time = min_cycle_times[(value >> NBCAP_MEMCLK_SHIFT) & NBCAP_MEMCLK_MASK];
|
||||||
bios_cycle_time = min_cycle_times[
|
bios_cycle_time = min_cycle_times[
|
||||||
read_option(CMOS_VSTART_max_mem_clock, CMOS_VLEN_max_mem_clock, 0)];
|
read_option(CMOS_VSTART_max_mem_clock, CMOS_VLEN_max_mem_clock, 0)];
|
||||||
|
@ -1877,75 +1898,47 @@ static int count_dimms(const struct mem_controller *ctrl)
|
||||||
static void set_Twtr(const struct mem_controller *ctrl, const struct mem_param *param)
|
static void set_Twtr(const struct mem_controller *ctrl, const struct mem_param *param)
|
||||||
{
|
{
|
||||||
uint32_t dth;
|
uint32_t dth;
|
||||||
unsigned clocks;
|
|
||||||
clocks = 1; /* AMD says hard code this */
|
|
||||||
dth = pci_read_config32(ctrl->f2, DRAM_TIMING_HIGH);
|
dth = pci_read_config32(ctrl->f2, DRAM_TIMING_HIGH);
|
||||||
dth &= ~(DTH_TWTR_MASK << DTH_TWTR_SHIFT);
|
dth &= ~(DTH_TWTR_MASK << DTH_TWTR_SHIFT);
|
||||||
dth |= ((clocks - DTH_TWTR_BASE) << DTH_TWTR_SHIFT);
|
dth |= ((param->dtl_twtr - DTH_TWTR_BASE) << DTH_TWTR_SHIFT);
|
||||||
pci_write_config32(ctrl->f2, DRAM_TIMING_HIGH, dth);
|
pci_write_config32(ctrl->f2, DRAM_TIMING_HIGH, dth);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_Trwt(const struct mem_controller *ctrl, const struct mem_param *param)
|
static void set_Trwt(const struct mem_controller *ctrl, const struct mem_param *param)
|
||||||
{
|
{
|
||||||
uint32_t dth, dtl;
|
uint32_t dth, dtl;
|
||||||
unsigned divisor;
|
|
||||||
unsigned latency;
|
unsigned latency;
|
||||||
unsigned clocks;
|
unsigned clocks;
|
||||||
|
int lat, mtype;
|
||||||
|
|
||||||
clocks = 0;
|
clocks = 0;
|
||||||
dtl = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW);
|
dtl = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW);
|
||||||
latency = (dtl >> DTL_TCL_SHIFT) & DTL_TCL_MASK;
|
latency = (dtl >> DTL_TCL_SHIFT) & DTL_TCL_MASK;
|
||||||
divisor = param->divisor;
|
|
||||||
|
|
||||||
if (is_opteron(ctrl)) {
|
if (is_opteron(ctrl)) {
|
||||||
if (latency == DTL_CL_2) {
|
mtype = 0; /* dual channel */
|
||||||
if (divisor == ((6 << 0) + 0)) {
|
} else if (is_registered(ctrl)) {
|
||||||
/* 166Mhz */
|
mtype = 1; /* registered 64bit interface */
|
||||||
clocks = 3;
|
} else {
|
||||||
}
|
mtype = 2; /* unbuffered 64bit interface */
|
||||||
else if (divisor > ((6 << 0)+0)) {
|
|
||||||
/* 100Mhz && 133Mhz */
|
|
||||||
clocks = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (latency == DTL_CL_2_5) {
|
|
||||||
clocks = 3;
|
|
||||||
}
|
|
||||||
else if (latency == DTL_CL_3) {
|
|
||||||
if (divisor == ((6 << 0)+0)) {
|
|
||||||
/* 166Mhz */
|
|
||||||
clocks = 4;
|
|
||||||
}
|
|
||||||
else if (divisor > ((6 << 0)+0)) {
|
|
||||||
/* 100Mhz && 133Mhz */
|
|
||||||
clocks = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else /* Athlon64 */ {
|
|
||||||
if (is_registered(ctrl)) {
|
switch (latency) {
|
||||||
if (latency == DTL_CL_2) {
|
case DTL_CL_2:
|
||||||
clocks = 2;
|
lat = 0;
|
||||||
}
|
break;
|
||||||
else if (latency == DTL_CL_2_5) {
|
case DTL_CL_2_5:
|
||||||
clocks = 3;
|
lat = 1;
|
||||||
}
|
break;
|
||||||
else if (latency == DTL_CL_3) {
|
case DTL_CL_3:
|
||||||
clocks = 3;
|
lat = 2;
|
||||||
}
|
break;
|
||||||
}
|
default:
|
||||||
else /* Unbuffered */{
|
die("Unknown LAT for Trwt");
|
||||||
if (latency == DTL_CL_2) {
|
|
||||||
clocks = 3;
|
|
||||||
}
|
|
||||||
else if (latency == DTL_CL_2_5) {
|
|
||||||
clocks = 4;
|
|
||||||
}
|
|
||||||
else if (latency == DTL_CL_3) {
|
|
||||||
clocks = 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clocks = param->dtl_trwt[lat][mtype];
|
||||||
if ((clocks < DTH_TRWT_MIN) || (clocks > DTH_TRWT_MAX)) {
|
if ((clocks < DTH_TRWT_MIN) || (clocks > DTH_TRWT_MAX)) {
|
||||||
die("Unknown Trwt\r\n");
|
die("Unknown Trwt\r\n");
|
||||||
}
|
}
|
||||||
|
@ -1977,83 +1970,38 @@ static void set_Twcl(const struct mem_controller *ctrl, const struct mem_param *
|
||||||
static void set_read_preamble(const struct mem_controller *ctrl, const struct mem_param *param)
|
static void set_read_preamble(const struct mem_controller *ctrl, const struct mem_param *param)
|
||||||
{
|
{
|
||||||
uint32_t dch;
|
uint32_t dch;
|
||||||
unsigned divisor;
|
|
||||||
unsigned rdpreamble;
|
unsigned rdpreamble;
|
||||||
divisor = param->divisor;
|
int slots, i;
|
||||||
|
|
||||||
|
slots = 0;
|
||||||
|
|
||||||
|
for(i = 0; i < 4; i++) {
|
||||||
|
if (ctrl->channel0[i]) {
|
||||||
|
slots += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* map to index to param.rdpreamble array */
|
||||||
|
if (is_registered(ctrl)) {
|
||||||
|
i = 0;
|
||||||
|
} else if (slots < 3) {
|
||||||
|
i = 1;
|
||||||
|
} else if (slots == 3) {
|
||||||
|
i = 2;
|
||||||
|
} else if (slots == 4) {
|
||||||
|
i = 3;
|
||||||
|
} else {
|
||||||
|
die("Unknown rdpreamble for this nr of slots");
|
||||||
|
}
|
||||||
|
|
||||||
dch = pci_read_config32(ctrl->f2, DRAM_CONFIG_HIGH);
|
dch = pci_read_config32(ctrl->f2, DRAM_CONFIG_HIGH);
|
||||||
dch &= ~(DCH_RDPREAMBLE_MASK << DCH_RDPREAMBLE_SHIFT);
|
dch &= ~(DCH_RDPREAMBLE_MASK << DCH_RDPREAMBLE_SHIFT);
|
||||||
rdpreamble = 0;
|
rdpreamble = param->rdpreamble[i];
|
||||||
if (is_registered(ctrl)) {
|
|
||||||
if (divisor == ((10 << 1)+0)) {
|
|
||||||
/* 100Mhz, 9ns */
|
|
||||||
rdpreamble = ((9 << 1)+ 0);
|
|
||||||
}
|
|
||||||
else if (divisor == ((7 << 1)+1)) {
|
|
||||||
/* 133Mhz, 8ns */
|
|
||||||
rdpreamble = ((8 << 1)+0);
|
|
||||||
}
|
|
||||||
else if (divisor == ((6 << 1)+0)) {
|
|
||||||
/* 166Mhz, 7.5ns */
|
|
||||||
rdpreamble = ((7 << 1)+1);
|
|
||||||
}
|
|
||||||
else if (divisor == ((5 << 1)+0)) {
|
|
||||||
/* 200Mhz, 7ns */
|
|
||||||
rdpreamble = ((7 << 1)+0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
int slots;
|
|
||||||
int i;
|
|
||||||
slots = 0;
|
|
||||||
for(i = 0; i < 4; i++) {
|
|
||||||
if (ctrl->channel0[i]) {
|
|
||||||
slots += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (divisor == ((10 << 1)+0)) {
|
|
||||||
/* 100Mhz */
|
|
||||||
if (slots <= 2) {
|
|
||||||
/* 9ns */
|
|
||||||
rdpreamble = ((9 << 1)+0);
|
|
||||||
} else {
|
|
||||||
/* 14ns */
|
|
||||||
rdpreamble = ((14 << 1)+0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (divisor == ((7 << 1)+1)) {
|
|
||||||
/* 133Mhz */
|
|
||||||
if (slots <= 2) {
|
|
||||||
/* 7ns */
|
|
||||||
rdpreamble = ((7 << 1)+0);
|
|
||||||
} else {
|
|
||||||
/* 11 ns */
|
|
||||||
rdpreamble = ((11 << 1)+0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (divisor == ((6 << 1)+0)) {
|
|
||||||
/* 166Mhz */
|
|
||||||
if (slots <= 2) {
|
|
||||||
/* 6ns */
|
|
||||||
rdpreamble = ((7 << 1)+0);
|
|
||||||
} else {
|
|
||||||
/* 9ns */
|
|
||||||
rdpreamble = ((9 << 1)+0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (divisor == ((5 << 1)+0)) {
|
|
||||||
/* 200Mhz */
|
|
||||||
if (slots <= 2) {
|
|
||||||
/* 5ns */
|
|
||||||
rdpreamble = ((5 << 1)+0);
|
|
||||||
} else {
|
|
||||||
/* 7ns */
|
|
||||||
rdpreamble = ((7 << 1)+0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((rdpreamble < DCH_RDPREAMBLE_MIN) || (rdpreamble > DCH_RDPREAMBLE_MAX)) {
|
if ((rdpreamble < DCH_RDPREAMBLE_MIN) || (rdpreamble > DCH_RDPREAMBLE_MAX)) {
|
||||||
die("Unknown rdpreamble");
|
die("Unknown rdpreamble");
|
||||||
}
|
}
|
||||||
|
|
||||||
dch |= (rdpreamble - DCH_RDPREAMBLE_BASE) << DCH_RDPREAMBLE_SHIFT;
|
dch |= (rdpreamble - DCH_RDPREAMBLE_BASE) << DCH_RDPREAMBLE_SHIFT;
|
||||||
pci_write_config32(ctrl->f2, DRAM_CONFIG_HIGH, dch);
|
pci_write_config32(ctrl->f2, DRAM_CONFIG_HIGH, dch);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue