mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [RFC V3 0/3] add decode command (SPD EEPROM data decoder)
@ 2015-06-29 14:26 Alexander Smirnov
  2015-06-29 14:26 ` [RFC V3 1/3] common: move DDR_SPD to common/Kconfig Alexander Smirnov
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Alexander Smirnov @ 2015-06-29 14:26 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox, Alexander Smirnov

Alexander Smirnov (3):
  common: move DDR_SPD to common/Kconfig
  ddr_spd: add routune for printing SPD contents in human readable
    format
  add decode command (SPD EEPROM data decoder)

 arch/ppc/mach-mpc85xx/Kconfig  |   4 -
 arch/ppc/mach-mpc85xx/Makefile |   3 +-
 commands/Kconfig               |   7 ++
 commands/Makefile              |   1 +
 commands/decode.c              |  53 +++++++++
 common/Kconfig                 |   4 +
 common/ddr_spd.c               | 239 +++++++++++++++++++++++++++++++++++++++++
 include/ddr_spd.h              |   1 +
 8 files changed, 307 insertions(+), 5 deletions(-)
 create mode 100644 commands/decode.c

-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC V3 1/3] common: move DDR_SPD to common/Kconfig
  2015-06-29 14:26 [RFC V3 0/3] add decode command (SPD EEPROM data decoder) Alexander Smirnov
@ 2015-06-29 14:26 ` Alexander Smirnov
  2015-06-29 14:26 ` [RFC V3 2/3] ddr_spd: add routune for printing SPD contents in human readable format Alexander Smirnov
  2015-06-29 14:26 ` [RFC V3 3/3] add decode command (SPD EEPROM data decoder) Alexander Smirnov
  2 siblings, 0 replies; 6+ messages in thread
From: Alexander Smirnov @ 2015-06-29 14:26 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox, Alexander Smirnov

This patch makes it possible to use ddr_spd-related
routines in any arch not only in ppc.

Signed-off-by: Alexander Smirnov <alllecs@yandex.ru>
---
 arch/ppc/mach-mpc85xx/Kconfig  | 4 ----
 arch/ppc/mach-mpc85xx/Makefile | 3 ++-
 common/Kconfig                 | 4 ++++
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/arch/ppc/mach-mpc85xx/Kconfig b/arch/ppc/mach-mpc85xx/Kconfig
index e29be9c..aa518b9 100644
--- a/arch/ppc/mach-mpc85xx/Kconfig
+++ b/arch/ppc/mach-mpc85xx/Kconfig
@@ -81,10 +81,6 @@ config P1022
 config MPC8544
 	bool
 
-config DDR_SPD
-	bool
-	select CRC16
-
 config FSL_DDR2
 	bool
 
diff --git a/arch/ppc/mach-mpc85xx/Makefile b/arch/ppc/mach-mpc85xx/Makefile
index 3e64617..de4f5ef 100644
--- a/arch/ppc/mach-mpc85xx/Makefile
+++ b/arch/ppc/mach-mpc85xx/Makefile
@@ -9,5 +9,6 @@ obj-y			+= fsl_i2c.o
 obj-$(CONFIG_MP)	+= mp.o
 obj-$(CONFIG_OFTREE)	+= fdt.o
 obj-$(CONFIG_DRIVER_NET_GIANFAR) += eth-devices.o
-obj-$(CONFIG_DDR_SPD)	+= ../ddr-8xxx/
+obj-$(CONFIG_FSL_DDR2) += ../ddr-8xxx/
+obj-$(CONFIG_FSL_DDR3) += ../ddr-8xxx/
 extra-y += barebox.lds
diff --git a/common/Kconfig b/common/Kconfig
index 925fe4b..91e4ef3 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -941,3 +941,7 @@ endmenu
 
 config HAS_DEBUG_LL
 	bool
+
+config DDR_SPD
+	bool
+	select CRC16
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC V3 2/3] ddr_spd: add routune for printing SPD contents in human readable format
  2015-06-29 14:26 [RFC V3 0/3] add decode command (SPD EEPROM data decoder) Alexander Smirnov
  2015-06-29 14:26 ` [RFC V3 1/3] common: move DDR_SPD to common/Kconfig Alexander Smirnov
@ 2015-06-29 14:26 ` Alexander Smirnov
  2015-06-29 15:51   ` Antony Pavlov
  2015-06-29 16:15   ` Antony Pavlov
  2015-06-29 14:26 ` [RFC V3 3/3] add decode command (SPD EEPROM data decoder) Alexander Smirnov
  2 siblings, 2 replies; 6+ messages in thread
From: Alexander Smirnov @ 2015-06-29 14:26 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox, Alexander Smirnov

Signed-off-by: Alexander Smirnov <alllecs@yandex.ru>
---
 common/ddr_spd.c  | 239 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/ddr_spd.h |   1 +
 2 files changed, 240 insertions(+)

diff --git a/common/ddr_spd.c b/common/ddr_spd.c
index ea0b529..380ea18 100644
--- a/common/ddr_spd.c
+++ b/common/ddr_spd.c
@@ -61,3 +61,242 @@ uint32_t ddr3_spd_checksum_pass(const struct ddr3_spd_eeprom_s *spd)
 
 	return 0;
 }
+
+static char *heights[] = {
+	"<25.4",
+	"25.4",
+	"25.4 - 30.0",
+	"30.0",
+	"30.5",
+	"> 30.5"
+};
+
+static char *sdram_voltage_interface_level[] = {
+	"TTL (5V tolerant)",
+	"LVTTL (not 5V tolerant)",
+	"HSTL 1.5V",
+	"SSTL 3.3V",
+	"SSTL 2.5V",
+	"SSTL 1.8V"
+};
+
+static char *ddr2_module_types[] = {
+	"RDIMM (133.35 mm)",
+	"UDIMM (133.25 mm)",
+	"SO-DIMM (67.6 mm)",
+	"Micro-DIMM (45.5 mm)",
+	"Mini-RDIMM (82.0 mm)",
+	"Mini-UDIMM (82.0 mm)"
+};
+
+static char *refresh[] = {
+	"15.625",
+	"3.9",
+	"7.8",
+	"31.3",
+	"62.5",
+	"125"
+};
+
+static char *type_list[] = {
+	"Reserved",
+	"FPM DRAM",
+	"EDO",
+	"Pipelined Nibble",
+	"SDR SDRAM",
+	"Multiplexed ROM",
+	"DDR SGRAM",
+	"DDR SDRAM",
+	"DDR2 SDRAM",
+	"FB-DIMM",
+	"FB-DIMM Probe",
+	"DDR3 SDRAM"
+};
+
+static int funct(uint8_t addr)
+{
+	int t;
+
+	t = ((addr >> 4) * 10 + (addr & 0xf));
+
+	return t;
+}
+
+static int des(uint8_t byte)
+{
+	int k;
+
+	k = (byte & 0x3) * 10 / 4;
+
+	return k;
+}
+
+static int integ(uint8_t byte)
+{
+	int k;
+
+	k = (byte >> 2);
+
+	return k;
+}
+
+static int ddr2_sdram_ctime(uint8_t byte)
+{
+	int ctime;
+
+	ctime = (byte >> 4) * 100;
+	if ((byte & 0xf) <= 9)
+		ctime += (byte & 0xf) * 10;
+	else if ((byte & 0xf) == 10)
+		ctime += 25;
+	else if ((byte & 0xf) == 11)
+		ctime += 33;
+	else if ((byte & 0xf) == 12)
+		ctime += 66;
+	else if ((byte & 0xf) == 13)
+		ctime += 75;
+
+	return ctime;
+}
+
+void ddr_spd_print(uint8_t *record)
+{
+	int highestCAS = 0;
+	int cas[256];
+	int i, i_i, k, x, y;
+	int ddrclk, tbits, pcclk;
+	int trcd, trp, tras;
+	int ctime;
+	uint8_t parity;
+	char *ref;
+	struct ddr2_spd_eeprom_s *s = (struct ddr2_spd_eeprom_s *)record;
+
+	ctime = ddr2_sdram_ctime(s->clk_cycle);
+	ddrclk = 2 * (1000 / ctime) * 100;
+	tbits = ((s->res_7) << 8) + (s->dataw);
+	if (((s->config) & 0x03) == 1)
+		tbits = tbits - 8;
+
+	pcclk = ddrclk * tbits / 8;
+	pcclk = pcclk - (pcclk % 100);
+	i_i = ((s->nrow_addr) & 0x0f) + ((s->ncol_addr) & 0x0f) - 17;
+	k = (((s->mod_ranks) & 0x7) + 1) * (s->nbanks);
+	trcd = (((s->trcd) >> 2) + (((s->trcd) & 3) * 0.25)) / ctime * 100;
+	trp = (((s->trp) >> 2) + (((s->trp) & 3) * 0.25)) / ctime * 100;
+	tras = (s->tras) * 100 / ctime ;
+	x = (int)(ctime / 100);
+	y = (ctime - (int)((ctime / 100) * 100)) / 10;
+
+	for (i_i = 2; i_i < 7; i_i++) {
+		if ((s->cas_lat) & (1 << i_i)) {
+			highestCAS = i_i;
+			cas[highestCAS]++;
+		}
+	}
+	printf("---=== SPD EEPROM Information ===---\n");
+	printf("%-50s OK (0x%0X)\n", "EEPROM Checksum of bytes 0-62", s->cksum);
+	printf("%-50s %d\n", "# of bytes written to SDRAM EEPROM", s->info_size);
+	printf("%-50s %d\n", "Total number of bytes in EEPROM", 1 << (s->chip_size));
+
+	if ((s->mem_type) < 11)
+		printf("%-50s %s\n", "Fundamental Memory type", type_list[(s->mem_type)]);
+	else
+		printf("%-50s (%02x)\n", "Warning: unknown memory type", s->mem_type);
+
+	printf("%-50s %x.%x\n", "SPD Revision", (s->spd_rev) >> 4, (s->spd_rev) & 0x0f);
+
+	printf("\n---=== Memory Characteristics ===---\n");
+	printf("%-50s %d MHz (PC2-%d)\n", "Maximum module speed", ddrclk, pcclk);
+	if (i_i > 0 && i_i <= 12 && k > 0)
+		printf("%-50s %d MB\n", "Size", ((1 << i_i) * k));
+	else
+		printf("%-50s INVALID: %02x %02x %02x %02x\n", "Size", s->nrow_addr, s->ncol_addr, s->mod_ranks, s->nbanks);
+
+	printf("%-50s %d x %d x %d x %d\n", "Banks x Rows x Columns x Bits", s->nbanks, s->nrow_addr, s->ncol_addr, s->dataw);
+	printf("%-50s %d\n", "Ranks", ((s->mod_ranks) & 0x7) + 1);
+	printf("%-50s %d bits\n", "SDRAM Device Width", (s->primw));
+
+	if (((s->mod_ranks) >> 5) < 7)
+		printf("%-50s %s mm\n", "Module Height", heights[((s->mod_ranks) >> 5)]);
+	else
+		printf("Error height\n");
+
+	printf("%-50s %s\n", "Module Type", ddr2_module_types[fls(s->dimm_type) - 1]);
+	printf("%-50s ", "DRAM Package ");
+	if (((s->mod_ranks) & 0x10) == 1)
+		printf("Stack\n");
+	else
+		printf("Planar\n");
+	if ((s->voltage) < 7)
+		printf("%-50s %s\n", "Voltage Interface Level", sdram_voltage_interface_level[s->voltage]);
+	else
+		printf("Error Voltage Interface Level\n");
+
+	printf("%-50s ", "Module Configuration Type ");
+
+	parity = (s->config) & 0x07;
+	if (parity == 0)
+		printf("No Parity\n");
+
+	if ((parity & 0x03) == 0x01)
+		printf("Data Parity\n");
+	if (parity & 0x02)
+		printf("Data ECC\n");
+
+	if (parity & 0x04)
+		printf("Address/Command Parity\n");
+
+	if (((s->refresh) >> 7) == 1)
+		ref = "- Self Refresh";
+	else
+		ref = " ";
+
+	printf("%-50s Reduced (%s us) %s\n", "Refresh Rate", refresh[(s->refresh) & 0x7f], ref);
+	printf("%-50s %d, %d\n", "Supported Burst Lengths", (s->burstl) & 4, (s->burstl) & 8);
+
+	printf("%-50s %dT\n", "Supported CAS Latencies (tCL)", highestCAS);
+	printf("%-50s %d-%d-%d-%d as DDR2-%d\n", "tCL-tRCD-tRP-tRAS", highestCAS, trcd, trp, tras, ddrclk);
+	printf("%-50s %d.%d ns at CAS %d\n", "Minimum Cycle Time", x, y, highestCAS);
+	printf("%-50s 0.%d%d ns at CAS %d\n", "Maximum Access Time", ((s->clk_access) >> 4), ((s->clk_access) & 0xf), highestCAS);
+	printf("%-50s %d ns\n", "Maximum Cycle Time (tCK max)", ((s->tckmax) >> 4) + ((s->tckmax) & 0x0f));
+printf("\n---=== Timing Parameters ===---\n");
+	printf("%-50s 0.%d ns\n", "Address/Command Setup Time Before Clock (tIS)", (funct(s->ca_setup)));
+	printf("%-50s 0.%d ns\n", "Address/Command Hold Time After Clock (tIH)", (funct(s->ca_hold)));
+	printf("%-50s 0.%d%d ns\n", "Data Input Setup Time Before Strobe (tDS)", ((s->data_setup) >> 4), ((s->data_setup) & 0xf));
+	printf("%-50s 0.%d%d ns\n", "Data Input Hold Time After Strobe (tDH)", ((s->data_hold) >> 4), ((s->data_hold) & 0xf));
+
+	printf("%-50s %d.%d ns\n", "Minimum Row Precharge Delay (tRP)", integ(s->trp), des(s->trp));
+	printf("%-50s %d.%d ns\n", "Minimum Row Active to Row Active Delay (tRRD)", integ(s->trrd), des(s->trrd));
+	printf("%-50s %d.%d ns\n", "Minimum RAS# to CAS# Delay (tRCD)", integ(s->trcd), des(s->trcd));
+	printf("%-50s %d ns\n", "Minimum RAS# Pulse Width (tRAS)", (((s->tras) & 0xfc) + ((s->tras) & 0x3)));
+	printf("%-50s %d.%d ns\n", "Write Recovery Time (tWR)", integ(s->twr), des(s->twr));
+	printf("%-50s %d.%d ns\n", "Minimum Write to Read CMD Delay (tWTR)", integ(s->twtr), des(s->twtr));
+	printf("%-50s %d.%d ns\n", "Minimum Read to Pre-charge CMD Delay (tRTP)", integ(s->trtp), des(s->trtp));
+	printf("%-50s %d ns\n", "Minimum Active to Auto-refresh Delay (tRC)", s->trc);
+	printf("%-50s %d ns\n", "Minimum Recovery Delay (tRFC)", s->trfc);
+	printf("%-50s 0.%d ns\n", "Maximum DQS to DQ Skew (tDQSQ)", s->tdqsq);
+	printf("%-50s 0.%d ns\n", "Maximum Read Data Hold Skew (tQHS)", s->tqhs);
+
+	printf("\n---=== Manufacturing Information ===---\n");
+
+	printf("%-50s", "Manufacturer JEDEC ID");
+	for (i = 64; i < 72; i++)
+		printf(" %02x", record[i]);
+
+	printf("\n");
+	if (s->mloc)
+		printf("%-50s 0x%02x\n", "Manufacturing Location Code", s->mloc);
+
+	printf("%-50s ", "Part Number");
+	for (i = 73; i < 91; i++) {
+		if (record[i] >= 32 && record[i] < 127)
+			printf("%c", record[i]);
+		else
+			printf("%d", record[i]);
+	}
+	printf("\n");
+	printf("%-50s 20%d-W%d\n", "Manufacturing Date", record[93], record[94]);
+	printf("%-50s 0x", "Assembly Serial Number");
+	for (i = 95; i < 99; i++)
+		printf("%02X", record[i]);
+}
diff --git a/include/ddr_spd.h b/include/ddr_spd.h
index fc03bac..01fe73c 100644
--- a/include/ddr_spd.h
+++ b/include/ddr_spd.h
@@ -228,6 +228,7 @@ struct ddr3_spd_eeprom_s {
 	uint8_t cust[80];        /* 176-255 Open for Customer Use */
 };
 
+extern void ddr_spd_print(uint8_t *record);
 extern uint32_t ddr3_spd_checksum_pass(const struct ddr3_spd_eeprom_s *spd);
 extern uint32_t ddr2_spd_checksum_pass(const struct ddr2_spd_eeprom_s *spd);
 
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [RFC V3 3/3] add decode command (SPD EEPROM data decoder)
  2015-06-29 14:26 [RFC V3 0/3] add decode command (SPD EEPROM data decoder) Alexander Smirnov
  2015-06-29 14:26 ` [RFC V3 1/3] common: move DDR_SPD to common/Kconfig Alexander Smirnov
  2015-06-29 14:26 ` [RFC V3 2/3] ddr_spd: add routune for printing SPD contents in human readable format Alexander Smirnov
@ 2015-06-29 14:26 ` Alexander Smirnov
  2 siblings, 0 replies; 6+ messages in thread
From: Alexander Smirnov @ 2015-06-29 14:26 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox, Alexander Smirnov

decode-dimms perl script is used as prototype
(see https://github.com/groeck/i2c-tools/blob/master/eeprom/decode-dimms).

Here is a sample decode output:

barebox@barebox sandbox:/ decode env/crucial_pc2-6400_ddr2
Decoding EEPROM: env/crucial_pc2-6400_ddr2

---=== SPD EEPROM Information ===---
EEPROM Checksum of bytes 0-62                      OK (0xCA)
Total number of bytes in EEPROM                    256
Fundamental Memory type                            DDR2 SDRAM
SPD Revision                                       1.3

---=== Memory Characteristics ===---
Maximum module speed                               800 MHz (PC2-6400)
Size                                               1024 MB
Banks x Rows x Columns x Bits                      8 x 14 x 10 x 64
Ranks                                              1
SDRAM Device Width                                 8 bits
Module Height                                      30.0 mm
Module Type                                        SO-DIMM (67.6 mm)
DRAM Package                                       Planar
Voltage Interface Level                            SSTL 1.8V
Module Configuration Type                          No Parity
Refresh Rate                                       Reduced (7.8 us) - Self Refresh
Supported Burst Lengths                            4, 8
Supported CAS Latencies (tCL)                      6T
tCL-tRCD-tRP-tRAS                                  6-6-6-18 as DDR2-800
Minimum Cycle Time                                 2.5 ns at CAS 6
Maximum Access Time                                0.40 ns at CAS 6
Maximum Cycle Time (tCK max)                       8 ns

---=== Timing Parameters ===---
Address/Command Setup Time Before Clock (tIS)      0.17 ns
Address/Command Hold Time After Clock (tIH)        0.25 ns
Data Input Setup Time Before Strobe (tDS)          0.05 ns
Data Input Hold Time After Strobe (tDH)            0.12 ns
Minimum Row Precharge Delay (tRP)                  15.0 ns
Minimum Row Active to Row Active Delay (tRRD)      7.5 ns
Minimum RAS# to CAS# Delay (tRCD)                  15.0 ns
Minimum RAS# Pulse Width (tRAS)                    45 ns
Write Recovery Time (tWR)                          15.0 ns
Minimum Write to Read CMD Delay (tWTR)             7.5 ns
Minimum Read to Pre-charge CMD Delay (tRTP)        7.5 ns
Minimum Active to Auto-refresh Delay (tRC)         60 ns
Minimum Recovery Delay (tRFC)                      127 ns
Maximum DQS to DQ Skew (tDQSQ)                     0.20 ns
Maximum Read Data Hold Skew (tQHS)                 0.30 ns

---=== Manufacturing Information ===---
Manufacturer JEDEC ID                              7f 7f 7f 7f 7f 9b 00 00
Part Number                                        CT12864AC800.M8FM8
Manufacturing Date                                 2014-W24
Assembly Serial Number                             0x00000000

TODOs:

  * Timing Parameters section output format is slightly
    differ from decode-dimms' format;
  * supports only DDR2 SPD EEPROM.

Signed-off-by: Alexander Smirnov <alllecs@yandex.ru>
---
 commands/Kconfig  |  7 +++++++
 commands/Makefile |  1 +
 commands/decode.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 61 insertions(+)

diff --git a/commands/Kconfig b/commands/Kconfig
index bb6674e..9230873 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -2102,6 +2102,13 @@ config CMD_STATE
 	depends on STATE
 	prompt "state"
 
+config CMD_DECODE
+	tristate
+	prompt "decode"
+	select DDR_SPD
+	help
+	  decode spd eeprom
+
 # end Miscellaneous commands
 endmenu
 
diff --git a/commands/Makefile b/commands/Makefile
index 3698347..71cd877 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -112,3 +112,4 @@ obj-$(CONFIG_CMD_NV)		+= nv.o
 obj-$(CONFIG_CMD_DEFAULTENV)	+= defaultenv.o
 obj-$(CONFIG_CMD_STATE)		+= state.o
 obj-$(CONFIG_CMD_DHCP)		+= dhcp.o
+obj-$(CONFIG_CMD_DECODE)	+= decode.o
diff --git a/commands/decode.c b/commands/decode.c
new file mode 100644
index 0000000..f8e7264
--- /dev/null
+++ b/commands/decode.c
@@ -0,0 +1,53 @@
+/*
+ * This program is decoding and printing SPD contents
+ * in human readable format
+ * As an argument program, you must specify the file name.
+ *
+ * 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.
+ *
+ * Copyright (C) 2015 Alexander Smirnov <alllecs@yandex.ru>
+ *
+ * Originally from https://github.com/groeck/i2c-tools/blob/master/eeprom/decode-dimms
+ */
+
+#include <common.h>
+#include <command.h>
+#include <libfile.h>
+#include <malloc.h>
+#include <ddr_spd.h>
+
+static int do_decode(int argc, char *argv[])
+{
+	int ret;
+	size_t size;
+	void *data;
+
+	if (argc != 2)
+		return COMMAND_ERROR_USAGE;
+
+	ret = read_file_2(argv[1], &size, &data, 256);
+	if (ret && ret != -EFBIG) {
+		printf("unable to read %s: %s\n", argv[1], strerror(-ret));
+		return COMMAND_ERROR;
+	}
+
+	printf("Decoding EEPROM: %s\n\n", argv[1]);
+	ddr_spd_print(data);
+	printf("\n\n");
+
+	free(data);
+
+	return 0;
+}
+
+BAREBOX_CMD_HELP_START(decode)
+BAREBOX_CMD_HELP_TEXT("Not enough or more than one argument to continue.")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(decode)
+	.cmd	= do_decode,
+	BAREBOX_CMD_HELP(cmd_decode_help)
+BAREBOX_CMD_END
-- 
2.1.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC V3 2/3] ddr_spd: add routune for printing SPD contents in human readable format
  2015-06-29 14:26 ` [RFC V3 2/3] ddr_spd: add routune for printing SPD contents in human readable format Alexander Smirnov
@ 2015-06-29 15:51   ` Antony Pavlov
  2015-06-29 16:15   ` Antony Pavlov
  1 sibling, 0 replies; 6+ messages in thread
From: Antony Pavlov @ 2015-06-29 15:51 UTC (permalink / raw)
  To: Alexander Smirnov; +Cc: barebox

On Mon, 29 Jun 2015 17:26:56 +0300
Alexander Smirnov <alllecs@yandex.ru> wrote:

> Signed-off-by: Alexander Smirnov <alllecs@yandex.ru>
> ---
>  common/ddr_spd.c  | 239 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/ddr_spd.h |   1 +
>  2 files changed, 240 insertions(+)
> 
> diff --git a/common/ddr_spd.c b/common/ddr_spd.c
> index ea0b529..380ea18 100644
> --- a/common/ddr_spd.c
> +++ b/common/ddr_spd.c
> @@ -61,3 +61,242 @@ uint32_t ddr3_spd_checksum_pass(const struct ddr3_spd_eeprom_s *spd)
>  
>  	return 0;
>  }
> +
> +static char *heights[] = {
> +	"<25.4",
> +	"25.4",
> +	"25.4 - 30.0",
> +	"30.0",
> +	"30.5",
> +	"> 30.5"
> +};
> +
> +static char *sdram_voltage_interface_level[] = {
> +	"TTL (5V tolerant)",
> +	"LVTTL (not 5V tolerant)",
> +	"HSTL 1.5V",
> +	"SSTL 3.3V",
> +	"SSTL 2.5V",
> +	"SSTL 1.8V"
> +};
> +
> +static char *ddr2_module_types[] = {
> +	"RDIMM (133.35 mm)",
> +	"UDIMM (133.25 mm)",
> +	"SO-DIMM (67.6 mm)",
> +	"Micro-DIMM (45.5 mm)",
> +	"Mini-RDIMM (82.0 mm)",
> +	"Mini-UDIMM (82.0 mm)"
> +};
> +
> +static char *refresh[] = {
> +	"15.625",
> +	"3.9",
> +	"7.8",
> +	"31.3",
> +	"62.5",
> +	"125"
> +};
> +
> +static char *type_list[] = {
> +	"Reserved",
> +	"FPM DRAM",
> +	"EDO",
> +	"Pipelined Nibble",
> +	"SDR SDRAM",
> +	"Multiplexed ROM",
> +	"DDR SGRAM",
> +	"DDR SDRAM",
> +	"DDR2 SDRAM",
> +	"FB-DIMM",
> +	"FB-DIMM Probe",
> +	"DDR3 SDRAM"
> +};
> +
> +static int funct(uint8_t addr)
> +{
> +	int t;
> +
> +	t = ((addr >> 4) * 10 + (addr & 0xf));
> +
> +	return t;
> +}
> +
> +static int des(uint8_t byte)
> +{
> +	int k;
> +
> +	k = (byte & 0x3) * 10 / 4;
> +
> +	return k;
> +}
> +
> +static int integ(uint8_t byte)
> +{
> +	int k;
> +
> +	k = (byte >> 2);
> +
> +	return k;
> +}
> +
> +static int ddr2_sdram_ctime(uint8_t byte)
> +{
> +	int ctime;
> +
> +	ctime = (byte >> 4) * 100;
> +	if ((byte & 0xf) <= 9)
> +		ctime += (byte & 0xf) * 10;
> +	else if ((byte & 0xf) == 10)
> +		ctime += 25;
> +	else if ((byte & 0xf) == 11)
> +		ctime += 33;
> +	else if ((byte & 0xf) == 12)
> +		ctime += 66;
> +	else if ((byte & 0xf) == 13)
> +		ctime += 75;
> +
> +	return ctime;
> +}
> +
> +void ddr_spd_print(uint8_t *record)
> +{
> +	int highestCAS = 0;
> +	int cas[256];
> +	int i, i_i, k, x, y;
> +	int ddrclk, tbits, pcclk;
> +	int trcd, trp, tras;
> +	int ctime;
> +	uint8_t parity;
> +	char *ref;
> +	struct ddr2_spd_eeprom_s *s = (struct ddr2_spd_eeprom_s *)record;
> +
> +	ctime = ddr2_sdram_ctime(s->clk_cycle);
> +	ddrclk = 2 * (1000 / ctime) * 100;
> +	tbits = ((s->res_7) << 8) + (s->dataw);
> +	if (((s->config) & 0x03) == 1)
> +		tbits = tbits - 8;
> +
> +	pcclk = ddrclk * tbits / 8;
> +	pcclk = pcclk - (pcclk % 100);
> +	i_i = ((s->nrow_addr) & 0x0f) + ((s->ncol_addr) & 0x0f) - 17;
> +	k = (((s->mod_ranks) & 0x7) + 1) * (s->nbanks);
> +	trcd = (((s->trcd) >> 2) + (((s->trcd) & 3) * 0.25)) / ctime * 100;
> +	trp = (((s->trp) >> 2) + (((s->trp) & 3) * 0.25)) / ctime * 100;
> +	tras = (s->tras) * 100 / ctime ;
> +	x = (int)(ctime / 100);
> +	y = (ctime - (int)((ctime / 100) * 100)) / 10;
> +
> +	for (i_i = 2; i_i < 7; i_i++) {
> +		if ((s->cas_lat) & (1 << i_i)) {
> +			highestCAS = i_i;
> +			cas[highestCAS]++;
> +		}
> +	}
> +	printf("---=== SPD EEPROM Information ===---\n");
> +	printf("%-50s OK (0x%0X)\n", "EEPROM Checksum of bytes 0-62", s->cksum);


Hmmmm.
Your checksum is always OK :)

Please use ddr2_spd_checksum_pass().

-- 
Best regards,
  Antony Pavlov

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFC V3 2/3] ddr_spd: add routune for printing SPD contents in human readable format
  2015-06-29 14:26 ` [RFC V3 2/3] ddr_spd: add routune for printing SPD contents in human readable format Alexander Smirnov
  2015-06-29 15:51   ` Antony Pavlov
@ 2015-06-29 16:15   ` Antony Pavlov
  1 sibling, 0 replies; 6+ messages in thread
From: Antony Pavlov @ 2015-06-29 16:15 UTC (permalink / raw)
  To: Alexander Smirnov; +Cc: barebox

On Mon, 29 Jun 2015 17:26:56 +0300
Alexander Smirnov <alllecs@yandex.ru> wrote:

> Signed-off-by: Alexander Smirnov <alllecs@yandex.ru>
> ---
>  common/ddr_spd.c  | 239 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/ddr_spd.h |   1 +
>  2 files changed, 240 insertions(+)
> 
> diff --git a/common/ddr_spd.c b/common/ddr_spd.c
> index ea0b529..380ea18 100644
> --- a/common/ddr_spd.c
> +++ b/common/ddr_spd.c
> @@ -61,3 +61,242 @@ uint32_t ddr3_spd_checksum_pass(const struct ddr3_spd_eeprom_s *spd)
>  
>  	return 0;
>  }
> +
> +static char *heights[] = {
> +	"<25.4",
> +	"25.4",
> +	"25.4 - 30.0",
> +	"30.0",
> +	"30.5",
> +	"> 30.5"
> +};
> +
> +static char *sdram_voltage_interface_level[] = {
> +	"TTL (5V tolerant)",
> +	"LVTTL (not 5V tolerant)",
> +	"HSTL 1.5V",
> +	"SSTL 3.3V",
> +	"SSTL 2.5V",
> +	"SSTL 1.8V"
> +};
> +
> +static char *ddr2_module_types[] = {
> +	"RDIMM (133.35 mm)",
> +	"UDIMM (133.25 mm)",
> +	"SO-DIMM (67.6 mm)",
> +	"Micro-DIMM (45.5 mm)",
> +	"Mini-RDIMM (82.0 mm)",
> +	"Mini-UDIMM (82.0 mm)"
> +};
> +
> +static char *refresh[] = {
> +	"15.625",
> +	"3.9",
> +	"7.8",
> +	"31.3",
> +	"62.5",
> +	"125"
> +};
> +
> +static char *type_list[] = {
> +	"Reserved",
> +	"FPM DRAM",
> +	"EDO",
> +	"Pipelined Nibble",
> +	"SDR SDRAM",
> +	"Multiplexed ROM",
> +	"DDR SGRAM",
> +	"DDR SDRAM",
> +	"DDR2 SDRAM",
> +	"FB-DIMM",
> +	"FB-DIMM Probe",
> +	"DDR3 SDRAM"
> +};
> +
> +static int funct(uint8_t addr)
> +{
> +	int t;
> +
> +	t = ((addr >> 4) * 10 + (addr & 0xf));
> +
> +	return t;
> +}
> +
> +static int des(uint8_t byte)
> +{
> +	int k;
> +
> +	k = (byte & 0x3) * 10 / 4;
> +
> +	return k;
> +}
> +
> +static int integ(uint8_t byte)
> +{
> +	int k;
> +
> +	k = (byte >> 2);
> +
> +	return k;
> +}
> +
> +static int ddr2_sdram_ctime(uint8_t byte)
> +{
> +	int ctime;
> +
> +	ctime = (byte >> 4) * 100;
> +	if ((byte & 0xf) <= 9)
> +		ctime += (byte & 0xf) * 10;
> +	else if ((byte & 0xf) == 10)
> +		ctime += 25;
> +	else if ((byte & 0xf) == 11)
> +		ctime += 33;
> +	else if ((byte & 0xf) == 12)
> +		ctime += 66;
> +	else if ((byte & 0xf) == 13)
> +		ctime += 75;
> +
> +	return ctime;
> +}
> +
> +void ddr_spd_print(uint8_t *record)
> +{
> +	int highestCAS = 0;
> +	int cas[256];
> +	int i, i_i, k, x, y;
> +	int ddrclk, tbits, pcclk;
> +	int trcd, trp, tras;
> +	int ctime;
> +	uint8_t parity;
> +	char *ref;
> +	struct ddr2_spd_eeprom_s *s = (struct ddr2_spd_eeprom_s *)record;
> +
> +	ctime = ddr2_sdram_ctime(s->clk_cycle);
> +	ddrclk = 2 * (1000 / ctime) * 100;
> +	tbits = ((s->res_7) << 8) + (s->dataw);
> +	if (((s->config) & 0x03) == 1)
> +		tbits = tbits - 8;
> +
> +	pcclk = ddrclk * tbits / 8;
> +	pcclk = pcclk - (pcclk % 100);
> +	i_i = ((s->nrow_addr) & 0x0f) + ((s->ncol_addr) & 0x0f) - 17;
> +	k = (((s->mod_ranks) & 0x7) + 1) * (s->nbanks);
> +	trcd = (((s->trcd) >> 2) + (((s->trcd) & 3) * 0.25)) / ctime * 100;
> +	trp = (((s->trp) >> 2) + (((s->trp) & 3) * 0.25)) / ctime * 100;
> +	tras = (s->tras) * 100 / ctime ;
> +	x = (int)(ctime / 100);
> +	y = (ctime - (int)((ctime / 100) * 100)) / 10;
> +
> +	for (i_i = 2; i_i < 7; i_i++) {
> +		if ((s->cas_lat) & (1 << i_i)) {
> +			highestCAS = i_i;
> +			cas[highestCAS]++;
> +		}
> +	}
> +	printf("---=== SPD EEPROM Information ===---\n");
> +	printf("%-50s OK (0x%0X)\n", "EEPROM Checksum of bytes 0-62", s->cksum);
> +	printf("%-50s %d\n", "# of bytes written to SDRAM EEPROM", s->info_size);
> +	printf("%-50s %d\n", "Total number of bytes in EEPROM", 1 << (s->chip_size));
> +
> +	if ((s->mem_type) < 11)
> +		printf("%-50s %s\n", "Fundamental Memory type", type_list[(s->mem_type)]);
> +	else
> +		printf("%-50s (%02x)\n", "Warning: unknown memory type", s->mem_type);
> +
> +	printf("%-50s %x.%x\n", "SPD Revision", (s->spd_rev) >> 4, (s->spd_rev) & 0x0f);
> +
> +	printf("\n---=== Memory Characteristics ===---\n");
> +	printf("%-50s %d MHz (PC2-%d)\n", "Maximum module speed", ddrclk, pcclk);
> +	if (i_i > 0 && i_i <= 12 && k > 0)
> +		printf("%-50s %d MB\n", "Size", ((1 << i_i) * k));

extra brackets here.

> +	else
> +		printf("%-50s INVALID: %02x %02x %02x %02x\n", "Size", s->nrow_addr, s->ncol_addr, s->mod_ranks, s->nbanks);
> +
> +	printf("%-50s %d x %d x %d x %d\n", "Banks x Rows x Columns x Bits", s->nbanks, s->nrow_addr, s->ncol_addr, s->dataw);
> +	printf("%-50s %d\n", "Ranks", ((s->mod_ranks) & 0x7) + 1);

and here

> +	printf("%-50s %d bits\n", "SDRAM Device Width", (s->primw));
and here
> +	if (((s->mod_ranks) >> 5) < 7)

Please use ARRAY_SIZE(heights) instead of 7.

> +		printf("%-50s %s mm\n", "Module Height", heights[((s->mod_ranks) >> 5)]);
> +	else
> +		printf("Error height\n");
> +
> +	printf("%-50s %s\n", "Module Type", ddr2_module_types[fls(s->dimm_type) - 1]);
> +	printf("%-50s ", "DRAM Package ");
> +	if (((s->mod_ranks) & 0x10) == 1)
> +		printf("Stack\n");
> +	else
> +		printf("Planar\n");
> +	if ((s->voltage) < 7)
> +		printf("%-50s %s\n", "Voltage Interface Level", sdram_voltage_interface_level[s->voltage]);
> +	else
> +		printf("Error Voltage Interface Level\n");
> +
> +	printf("%-50s ", "Module Configuration Type ");
> +
> +	parity = (s->config) & 0x07;
> +	if (parity == 0)
> +		printf("No Parity\n");
> +
> +	if ((parity & 0x03) == 0x01)
> +		printf("Data Parity\n");
> +	if (parity & 0x02)
> +		printf("Data ECC\n");
> +
> +	if (parity & 0x04)
> +		printf("Address/Command Parity\n");
> +
> +	if (((s->refresh) >> 7) == 1)
> +		ref = "- Self Refresh";
> +	else
> +		ref = " ";
> +
> +	printf("%-50s Reduced (%s us) %s\n", "Refresh Rate", refresh[(s->refresh) & 0x7f], ref);
> +	printf("%-50s %d, %d\n", "Supported Burst Lengths", (s->burstl) & 4, (s->burstl) & 8);
> +
> +	printf("%-50s %dT\n", "Supported CAS Latencies (tCL)", highestCAS);
> +	printf("%-50s %d-%d-%d-%d as DDR2-%d\n", "tCL-tRCD-tRP-tRAS", highestCAS, trcd, trp, tras, ddrclk);
> +	printf("%-50s %d.%d ns at CAS %d\n", "Minimum Cycle Time", x, y, highestCAS);
> +	printf("%-50s 0.%d%d ns at CAS %d\n", "Maximum Access Time", ((s->clk_access) >> 4), ((s->clk_access) & 0xf), highestCAS);
> +	printf("%-50s %d ns\n", "Maximum Cycle Time (tCK max)", ((s->tckmax) >> 4) + ((s->tckmax) & 0x0f));
> +printf("\n---=== Timing Parameters ===---\n");

wrong formatting here.

> +	printf("%-50s 0.%d ns\n", "Address/Command Setup Time Before Clock (tIS)", (funct(s->ca_setup)));
> +	printf("%-50s 0.%d ns\n", "Address/Command Hold Time After Clock (tIH)", (funct(s->ca_hold)));
> +	printf("%-50s 0.%d%d ns\n", "Data Input Setup Time Before Strobe (tDS)", ((s->data_setup) >> 4), ((s->data_setup) & 0xf));
> +	printf("%-50s 0.%d%d ns\n", "Data Input Hold Time After Strobe (tDH)", ((s->data_hold) >> 4), ((s->data_hold) & 0xf));
> +
> +	printf("%-50s %d.%d ns\n", "Minimum Row Precharge Delay (tRP)", integ(s->trp), des(s->trp));
> +	printf("%-50s %d.%d ns\n", "Minimum Row Active to Row Active Delay (tRRD)", integ(s->trrd), des(s->trrd));
> +	printf("%-50s %d.%d ns\n", "Minimum RAS# to CAS# Delay (tRCD)", integ(s->trcd), des(s->trcd));
> +	printf("%-50s %d ns\n", "Minimum RAS# Pulse Width (tRAS)", (((s->tras) & 0xfc) + ((s->tras) & 0x3)));
> +	printf("%-50s %d.%d ns\n", "Write Recovery Time (tWR)", integ(s->twr), des(s->twr));
> +	printf("%-50s %d.%d ns\n", "Minimum Write to Read CMD Delay (tWTR)", integ(s->twtr), des(s->twtr));
> +	printf("%-50s %d.%d ns\n", "Minimum Read to Pre-charge CMD Delay (tRTP)", integ(s->trtp), des(s->trtp));
> +	printf("%-50s %d ns\n", "Minimum Active to Auto-refresh Delay (tRC)", s->trc);
> +	printf("%-50s %d ns\n", "Minimum Recovery Delay (tRFC)", s->trfc);
> +	printf("%-50s 0.%d ns\n", "Maximum DQS to DQ Skew (tDQSQ)", s->tdqsq);
> +	printf("%-50s 0.%d ns\n", "Maximum Read Data Hold Skew (tQHS)", s->tqhs);
> +
> +	printf("\n---=== Manufacturing Information ===---\n");
> +
> +	printf("%-50s", "Manufacturer JEDEC ID");
> +	for (i = 64; i < 72; i++)
> +		printf(" %02x", record[i]);
> +
> +	printf("\n");
> +	if (s->mloc)
> +		printf("%-50s 0x%02x\n", "Manufacturing Location Code", s->mloc);
> +
> +	printf("%-50s ", "Part Number");
> +	for (i = 73; i < 91; i++) {
> +		if (record[i] >= 32 && record[i] < 127)
> +			printf("%c", record[i]);
> +		else
> +			printf("%d", record[i]);
> +	}
> +	printf("\n");
> +	printf("%-50s 20%d-W%d\n", "Manufacturing Date", record[93], record[94]);
> +	printf("%-50s 0x", "Assembly Serial Number");
> +	for (i = 95; i < 99; i++)
> +		printf("%02X", record[i]);
> +}
> diff --git a/include/ddr_spd.h b/include/ddr_spd.h
> index fc03bac..01fe73c 100644
> --- a/include/ddr_spd.h
> +++ b/include/ddr_spd.h
> @@ -228,6 +228,7 @@ struct ddr3_spd_eeprom_s {
>  	uint8_t cust[80];        /* 176-255 Open for Customer Use */
>  };
>  
> +extern void ddr_spd_print(uint8_t *record);
>  extern uint32_t ddr3_spd_checksum_pass(const struct ddr3_spd_eeprom_s *spd);
>  extern uint32_t ddr2_spd_checksum_pass(const struct ddr2_spd_eeprom_s *spd);
>  
> -- 
> 2.1.4
> 
> 
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox


-- 
-- 
Best regards,
  Antony Pavlov

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2015-06-29 16:09 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-29 14:26 [RFC V3 0/3] add decode command (SPD EEPROM data decoder) Alexander Smirnov
2015-06-29 14:26 ` [RFC V3 1/3] common: move DDR_SPD to common/Kconfig Alexander Smirnov
2015-06-29 14:26 ` [RFC V3 2/3] ddr_spd: add routune for printing SPD contents in human readable format Alexander Smirnov
2015-06-29 15:51   ` Antony Pavlov
2015-06-29 16:15   ` Antony Pavlov
2015-06-29 14:26 ` [RFC V3 3/3] add decode command (SPD EEPROM data decoder) Alexander Smirnov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox