Module Name:    src
Committed By:   pgoyette
Date:           Tue Feb 23 00:13:06 UTC 2010

Modified Files:
        src/sys/dev/i2c: spdmem.c

Log Message:
Correct calculation and display of SDR DRAM speed.  From OpenBSD.

Fixes PR kern/42736


To generate a diff of this commit:
cvs rdiff -u -r1.15 -r1.16 src/sys/dev/i2c/spdmem.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/i2c/spdmem.c
diff -u src/sys/dev/i2c/spdmem.c:1.15 src/sys/dev/i2c/spdmem.c:1.16
--- src/sys/dev/i2c/spdmem.c:1.15	Sat May  9 17:32:27 2009
+++ src/sys/dev/i2c/spdmem.c	Tue Feb 23 00:13:06 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: spdmem.c,v 1.15 2009/05/09 17:32:27 pgoyette Exp $ */
+/* $NetBSD: spdmem.c,v 1.16 2010/02/23 00:13:06 pgoyette Exp $ */
 
 /*
  * Copyright (c) 2007 Nicolas Joly
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: spdmem.c,v 1.15 2009/05/09 17:32:27 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: spdmem.c,v 1.16 2010/02/23 00:13:06 pgoyette Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -56,14 +56,15 @@
 /* Routines for decoding spd data */
 static void decode_edofpm(const struct sysctlnode *, device_t, struct spdmem *);
 static void decode_rom(const struct sysctlnode *, device_t, struct spdmem *);
-static void decode_sdram(const struct sysctlnode *, device_t, struct spdmem *);
+static void decode_sdram(const struct sysctlnode *, device_t, struct spdmem *,
+	int);
 static void decode_ddr(const struct sysctlnode *, device_t, struct spdmem *);
 static void decode_ddr2(const struct sysctlnode *, device_t, struct spdmem *);
 static void decode_ddr3(const struct sysctlnode *, device_t, struct spdmem *);
 static void decode_fbdimm(const struct sysctlnode *, device_t, struct spdmem *);
 
 static void decode_size_speed(const struct sysctlnode *, int, int, int, int,
-			      bool, const char *);
+			      bool, const char *, int);
 static void decode_voltage_refresh(device_t, struct spdmem *);
 
 CFATTACH_DECL_NEW(spdmem, sizeof(struct spdmem_softc),
@@ -390,7 +391,7 @@
 		decode_rom(node, self, s);
 		break;
 	case SPDMEM_MEMTYPE_SDRAM:
-		decode_sdram(node, self, s);
+		decode_sdram(node, self, s, spd_len);
 		break;
 	case SPDMEM_MEMTYPE_DDRSDRAM:
 		decode_ddr(node, self, s);
@@ -437,7 +438,8 @@
 
 static void
 decode_size_speed(const struct sysctlnode *node, int dimm_size, int cycle_time,
-		  int d_clk, int bits, bool round, const char *ddr_type_string)
+		  int d_clk, int bits, bool round, const char *ddr_type_string,
+		  int speed)
 {
 	int p_clk;
 
@@ -462,9 +464,14 @@
 	 * Calculate p_clk first, since for DDR3 we need maximum significance.
 	 * DDR3 rating is not rounded to a multiple of 100.  This results in
 	 * cycle_time of 1.5ns displayed as PC3-10666.
+	 *
+	 * For SDRAM, the speed is provided by the caller so we use it.
 	 */
 	d_clk *= 1000 * 1000;
-	p_clk = (d_clk * bits) / 8 / cycle_time;
+	if (speed)
+		p_clk = speed;
+	else
+		p_clk = (d_clk * bits) / 8 / cycle_time;
 	d_clk = ((d_clk + cycle_time / 2) ) / cycle_time;
 	if (round) {
 		if ((p_clk % 100) >= 50)
@@ -519,8 +526,9 @@
 }
 
 static void
-decode_sdram(const struct sysctlnode *node, device_t self, struct spdmem *s) {
-	int dimm_size, cycle_time, bits, tAA, i;
+decode_sdram(const struct sysctlnode *node, device_t self, struct spdmem *s,
+	     int spd_len) {
+	int dimm_size, cycle_time, bits, tAA, i, speed, freq;
 
 	aprint_normal("%s, %s, ",
 		(s->sm_sdr.sdr_mod_attrs & SPDMEM_SDR_MASK_REG)?
@@ -536,7 +544,30 @@
 	bits = le16toh(s->sm_sdr.sdr_datawidth);
 	if (s->sm_config == 1 || s->sm_config == 2)
 		bits -= 8;
-	decode_size_speed(node, dimm_size, cycle_time, 1, bits, TRUE, "PC");
+
+	/* Calculate speed here - from OpenBSD */
+	if (spd_len >= 128)
+		freq = ((uint8_t *)s)[126];
+	else
+		freq = 0;
+	switch (freq) {
+		/*
+		 * Must check cycle time since some PC-133 DIMMs 
+		 * actually report PC-100
+		 */
+	    case 100:
+	    case 133:
+		if (cycle_time < 8000)
+			speed = 133;
+		else
+			speed = 100;
+		break;
+	    case 0x66:		/* Legacy DIMMs use _hex_ 66! */
+	    default:
+		speed = 66;
+	}
+	decode_size_speed(node, dimm_size, cycle_time, 1, bits, FALSE, "PC",
+			  speed);
 
 	aprint_verbose_dev(self,
 	    "%d rows, %d cols, %d banks, %d banks/chip, %d.%dns cycle time\n",
@@ -573,7 +604,7 @@
 	bits = le16toh(s->sm_ddr.ddr_datawidth);
 	if (s->sm_config == 1 || s->sm_config == 2)
 		bits -= 8;
-	decode_size_speed(node, dimm_size, cycle_time, 2, bits, TRUE, "PC");
+	decode_size_speed(node, dimm_size, cycle_time, 2, bits, TRUE, "PC", 0);
 
 	aprint_verbose_dev(self,
 	    "%d rows, %d cols, %d ranks, %d banks/chip, %d.%dns cycle time\n",
@@ -617,7 +648,7 @@
 	bits = s->sm_ddr2.ddr2_datawidth;
 	if ((s->sm_config & 0x03) != 0)
 		bits -= 8;
-	decode_size_speed(node, dimm_size, cycle_time, 2, bits, TRUE, "PC2");
+	decode_size_speed(node, dimm_size, cycle_time, 2, bits, TRUE, "PC2", 0);
 
 	aprint_verbose_dev(self,
 	    "%d rows, %d cols, %d ranks, %d banks/chip, %d.%02dns cycle time\n",
@@ -671,7 +702,7 @@
 		     s->sm_ddr3.ddr3_mtb_divisor;
 	cycle_time *= s->sm_ddr3.ddr3_tCKmin;
 	bits = 1 << (s->sm_ddr3.ddr3_datawidth + 3);
-	decode_size_speed(node, dimm_size, cycle_time, 2, bits, FALSE, "PC3");
+	decode_size_speed(node, dimm_size, cycle_time, 2, bits, FALSE, "PC3", 0);
 
 	aprint_verbose_dev(self,
 	    "%d rows, %d cols, %d log. banks, %d phys. banks, "
@@ -706,7 +737,7 @@
 			    (s->sm_fbd.fbdimm_mtb_divisor / 2)) /
 		     s->sm_fbd.fbdimm_mtb_divisor;
 	bits = 1 << (s->sm_fbd.fbdimm_dev_width + 2);
-	decode_size_speed(node, dimm_size, cycle_time, 2, bits, TRUE, "PC2");
+	decode_size_speed(node, dimm_size, cycle_time, 2, bits, TRUE, "PC2", 0);
 
 	aprint_verbose_dev(self,
 	    "%d rows, %d cols, %d banks, %d.%02dns cycle time\n",

Reply via email to