#include <stdlib.h>
#include "raminit.h"
#include "amdk8_f.h"
-#include "spd_ddr2.h"
+#include <spd_ddr2.h>
#ifndef QRANK_DIMM_SUPPORT
#define QRANK_DIMM_SUPPORT 0
/* Check for FID control support */
struct cpuid_result cpuid1;
- cpuid1 = cpuid(0x8000007);
+ cpuid1 = cpuid(0x80000007);
if( cpuid1.edx & 0x02 ) {
/* Use current FID */
unsigned fid_cur;
return value;
}
+static const uint8_t latency_indicies[] = { 25, 23, 9 };
+
+int find_optimum_spd_latency(u32 spd_device, unsigned *min_latency, unsigned *min_cycle_time)
+{
+ int new_cycle_time, new_latency;
+ int index;
+ int latencies;
+ int latency;
+
+ /* First find the supported CAS latencies
+ * Byte 18 for DDR SDRAM is interpreted:
+ * bit 3 == CAS Latency = 3
+ * bit 4 == CAS Latency = 4
+ * bit 5 == CAS Latency = 5
+ * bit 6 == CAS Latency = 6
+ */
+ new_cycle_time = 0x500;
+ new_latency = 6;
+
+ latencies = spd_read_byte(spd_device, SPD_CAS_LAT);
+ if (latencies <= 0)
+ return 1;
+
+ printk_raminit("\tlatencies: %08x\n", latencies);
+ /* Compute the lowest cas latency which can be expressed in this
+ * particular SPD EEPROM. You can store at most settings for 3
+ * contiguous CAS latencies, so by taking the highest CAS
+ * latency maked as supported in the SPD and subtracting 2 you
+ * get the lowest expressable CAS latency. That latency is not
+ * necessarily supported, but a (maybe invalid) entry exists
+ * for it.
+ */
+ latency = log2(latencies) - 2;
+
+ /* Loop through and find a fast clock with a low latency */
+ for (index = 0; index < 3; index++, latency++) {
+ int value;
+ if ((latency < 3) || (latency > 6) ||
+ (!(latencies & (1 << latency)))) {
+ continue;
+ }
+ value = spd_read_byte(spd_device, latency_indicies[index]);
+ if (value < 0) {
+ return -1;
+ }
+
+ printk_raminit("\tindex: %08x\n", index);
+ printk_raminit("\t\tlatency: %08x\n", latency);
+ printk_raminit("\t\tvalue1: %08x\n", value);
+
+ value = convert_to_linear(value);
+
+ printk_raminit("\t\tvalue2: %08x\n", value);
+
+ /* Only increase the latency if we decrease the clock */
+ if (value >= *min_cycle_time ) {
+ if (value < new_cycle_time) {
+ new_cycle_time = value;
+ new_latency = latency;
+ } else if (value == new_cycle_time) {
+ if (new_latency > latency) {
+ new_latency = latency;
+ }
+ }
+ }
+ printk_raminit("\t\tnew_cycle_time: %08x\n", new_cycle_time);
+ printk_raminit("\t\tnew_latency: %08x\n", new_latency);
+
+ }
+
+ if (new_latency > 6){
+ return 1;
+ }
+
+ /* Does min_latency need to be increased? */
+ if (new_cycle_time > *min_cycle_time) {
+ *min_cycle_time = new_cycle_time;
+ }
+
+ /* Does min_cycle_time need to be increased? */
+ if (new_latency > *min_latency) {
+ *min_latency = new_latency;
+ }
+
+ printk_raminit("2 min_cycle_time: %08x\n", *min_cycle_time);
+ printk_raminit("2 min_latency: %08x\n", *min_latency);
+
+ return 0;
+}
+
static struct spd_set_memclk_result spd_set_memclk(const struct mem_controller *ctrl, struct mem_info *meminfo)
{
/* Compute the minimum cycle time for these dimms */
int i;
uint32_t value;
- static const uint8_t latency_indicies[] = { 25, 23, 9 };
-
static const uint16_t min_cycle_times[] = { // use full speed to compare
[NBCAP_MEMCLK_NOLIMIT] = 0x250, /*2.5ns */
[NBCAP_MEMCLK_333MHZ] = 0x300, /* 3.0ns */
* by both the memory controller and the dimms.
*/
for (i = 0; i < DIMM_SOCKETS; i++) {
- int new_cycle_time, new_latency;
- int index;
- int latencies;
- int latency;
- u32 spd_device = ctrl->channel0[i];
+ u32 spd_device;
printk_raminit("1.1 dimm_mask: %08x\n", meminfo->dimm_mask);
- if (!(meminfo->dimm_mask & (1 << i))) {
- if (meminfo->dimm_mask & (1 << (DIMM_SOCKETS + i))) { /* channelB only? */
- spd_device = ctrl->channel1[i];
- } else {
- continue;
- }
- }
-
- /* First find the supported CAS latencies
- * Byte 18 for DDR SDRAM is interpreted:
- * bit 3 == CAS Latency = 3
- * bit 4 == CAS Latency = 4
- * bit 5 == CAS Latency = 5
- * bit 6 == CAS Latency = 6
- */
- new_cycle_time = 0x500;
- new_latency = 6;
-
- latencies = spd_read_byte(spd_device, SPD_CAS_LAT);
- if (latencies <= 0) continue;
-
printk_raminit("i: %08x\n",i);
- printk_raminit("\tlatencies: %08x\n", latencies);
- /* Compute the lowest cas latency which can be expressed in this
- * particular SPD EEPROM. You can store at most settings for 3
- * contiguous CAS latencies, so by taking the highest CAS
- * latency maked as supported in the SPD and subtracting 2 you
- * get the lowest expressable CAS latency. That latency is not
- * necessarily supported, but a (maybe invalid) entry exists
- * for it.
- */
- latency = log2(latencies) - 2;
- /* Loop through and find a fast clock with a low latency */
- for (index = 0; index < 3; index++, latency++) {
- int value;
- if ((latency < 3) || (latency > 6) ||
- (!(latencies & (1 << latency)))) {
- continue;
- }
- value = spd_read_byte(spd_device, latency_indicies[index]);
- if (value < 0) {
- goto hw_error;
- }
-
- printk_raminit("\tindex: %08x\n", index);
- printk_raminit("\t\tlatency: %08x\n", latency);
- printk_raminit("\t\tvalue1: %08x\n", value);
-
- value = convert_to_linear(value);
+ if (meminfo->dimm_mask & (1 << i)) {
+ spd_device = ctrl->channel0[i];
+ printk_raminit("Channel 0 settings:\n");
- printk_raminit("\t\tvalue2: %08x\n", value);
-
- /* Only increase the latency if we decrease the clock */
- if (value >= min_cycle_time ) {
- if (value < new_cycle_time) {
- new_cycle_time = value;
- new_latency = latency;
- } else if (value == new_cycle_time) {
- if (new_latency > latency) {
- new_latency = latency;
- }
- }
+ switch (find_optimum_spd_latency(spd_device, &min_latency, &min_cycle_time)) {
+ case -1:
+ goto hw_error;
+ break;
+ case 1:
+ continue;
}
- printk_raminit("\t\tnew_cycle_time: %08x\n", new_cycle_time);
- printk_raminit("\t\tnew_latency: %08x\n", new_latency);
-
}
+ if (meminfo->dimm_mask & (1 << (DIMM_SOCKETS + i))) {
+ spd_device = ctrl->channel1[i];
+ printk_raminit("Channel 1 settings:\n");
- if (new_latency > 6){
- continue;
- }
-
- /* Does min_latency need to be increased? */
- if (new_cycle_time > min_cycle_time) {
- min_cycle_time = new_cycle_time;
- }
-
- /* Does min_cycle_time need to be increased? */
- if (new_latency > min_latency) {
- min_latency = new_latency;
+ switch (find_optimum_spd_latency(spd_device, &min_latency, &min_cycle_time)) {
+ case -1:
+ goto hw_error;
+ break;
+ case 1:
+ continue;
+ }
}
-
- printk_raminit("2 min_cycle_time: %08x\n", min_cycle_time);
- printk_raminit("2 min_latency: %08x\n", min_latency);
+
}
/* Make a second pass through the dimms and disable
* any that cannot support the selected memclk and cas latency.
valuex = fraction [value & 0x7];
return valuex;
}
-static int update_dimm_Trc(const struct mem_controller *ctrl,
- const struct mem_param *param,
- int i, long dimm_mask)
+
+int get_dimm_Trc_clocks(u32 spd_device, const struct mem_param *param)
{
- unsigned clocks, old_clocks;
- uint32_t dtl;
int value;
int value2;
- u32 spd_device = ctrl->channel0[i];
-
- if (!(dimm_mask & (1 << i)) && (dimm_mask & (1 << (DIMM_SOCKETS + i)))) { /* channelB only? */
- spd_device = ctrl->channel1[i];
- }
-
+ int clocks;
value = spd_read_byte(spd_device, SPD_TRC);
- if (value < 0) return -1;
+ if (value < 0)
+ return -1;
+ printk_raminit("update_dimm_Trc: tRC (41) = %08x\n", value);
value2 = spd_read_byte(spd_device, SPD_TRC -1);
value <<= 2;
value += convert_to_1_4(value2>>4);
- value *=10;
+ value *= 10;
+ printk_raminit("update_dimm_Trc: tRC final value = %i\n", value);
clocks = (value + param->divisor - 1)/param->divisor;
+ printk_raminit("update_dimm_Trc: clocks = %i\n", clocks);
if (clocks < DTL_TRC_MIN) {
+#warning We should die here or at least disable this bank.
+ printk_notice("update_dimm_Trc: can't refresh fast enough, "
+ "want %i clocks, can %i clocks\n", clocks, DTL_TRC_MIN);
clocks = DTL_TRC_MIN;
}
+ return clocks;
+}
+
+static int update_dimm_Trc(const struct mem_controller *ctrl,
+ const struct mem_param *param,
+ int i, long dimm_mask)
+{
+ int clocks, old_clocks;
+ uint32_t dtl;
+ u32 spd_device = ctrl->channel0[i];
+
+ if (!(dimm_mask & (1 << i)) && (dimm_mask & (1 << (DIMM_SOCKETS + i)))) { /* channelB only? */
+ spd_device = ctrl->channel1[i];
+ }
+
+ clocks = get_dimm_Trc_clocks(spd_device, param);
+ if (clocks == -1)
+ return clocks;
if (clocks > DTL_TRC_MAX) {
return 0;
}
+ printk_raminit("update_dimm_Trc: clocks after adjustment = %i\n", clocks);
dtl = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW);
old_clocks = ((dtl >> DTL_TRC_SHIFT) & DTL_TRC_MASK) + DTL_TRC_BASE;
}
if (clocks > TT_MAX) {
- return 0;
+ printk_info("warning spd byte : %x = %x > TT_MAX: %x, setting TT_MAX", SPD_TT, value, TT_MAX);
+ clocks = TT_MAX;
}
dtl = pci_read_config32(ctrl->f2, TT_REG);
}
#endif
+#include "exit_from_self.c"
static void sdram_enable(int controllers, const struct mem_controller *ctrl,
struct sys_info *sysinfo)
{
int i;
-
+#ifdef ACPI_IS_WAKEUP_EARLY
+ int suspend = acpi_is_wakeup_early();
+#else
+ int suspend = 0;
+#endif
+
#if K8_REV_F_SUPPORT_F0_F1_WORKAROUND == 1
unsigned cpu_f0_f1[8];
/* FIXME: How about 32 node machine later? */
printk_debug("\n");
#endif
+ /* lets override the rest of the routine */
+ if (suspend) {
+ printk_debug("Wakeup!\n");
+ exit_from_self(controllers, ctrl, sysinfo);
+ printk_debug("Mem running !\n");
+ return;
+ }
+
for (i = 0; i < controllers; i++) {
uint32_t dcl, dch;
if (!sysinfo->ctrl_present[ i ])