NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/38726: Update spdmem driver for DDR3 memory



>Number:         38726
>Category:       kern
>Synopsis:       Update spdmem driver for DDR3
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Thu May 22 11:40:00 +0000 2008
>Originator:     Paul Goyette
>Release:        NetBSD 4.99.62
>Organization:
----------------------------------------------------------------------
|   Paul Goyette   | PGP DSS Key fingerprint: |  E-mail addresses:   |
| Customer Service | FA29 0E3B 35AF E8AE 6651 |  paul%whooppee.com@localhost   |
| Network Engineer | 0786 F758 55DE 53BA 7731 | pgoyette%juniper.net@localhost |
----------------------------------------------------------------------
>Environment:
        
        
System: NetBSD quicky.whooppee.com 4.99.62 NetBSD 4.99.62 (QUICKY (ASUS M2N32 
WS) 2008-05-14 13:20:42) #1: Wed May 14 06:25:08 PDT 2008 
paul%speedy.whooppee.com@localhost:/build/obj/amd64/sys/arch/amd64/compile/QUICKY
 amd64
Architecture: x86_64
Machine: amd64
>Description:
        The spdmem driver currently does not recognize DDR3 SDRAM memory
        modules.
        
>How-To-Repeat:
        
>Fix:
        The following patch provides initial support of DDR3 memory.

        Note:  It has been compile-tested on both i386 and amd64, but
        since I don't have any DDR3 memory yet I cannot be certain that
        it works perfectly.  It has NOT had any negative regressions on
        recognizing my existing DDR2 memory.

Index: src/sys/dev/i2c/spdmem.c
===================================================================
RCS file: /cvsroot/src/sys/dev/i2c/spdmem.c,v
retrieving revision 1.8
diff -u -p -r1.8 spdmem.c
--- src/sys/dev/i2c/spdmem.c    4 May 2008 15:26:29 -0000       1.8
+++ src/sys/dev/i2c/spdmem.c    22 May 2008 11:32:17 -0000
@@ -68,7 +68,8 @@ static const char* spdmem_basic_types[] 
        "DDR SDRAM",
        "DDR2 SDRAM",
        "DDR2 SDRAM FB",
-       "DDR2 SDRAM FB Probe"
+       "DDR2 SDRAM FB Probe",
+       "DDR3 SDRAM"
 };
 
 static const char* spdmem_superset_types[] = {
@@ -116,13 +117,34 @@ static const uint8_t spdmem_cycle_frac[]
 /* sysctl stuff */
 static int hw_node = CTL_EOL;
 
+/* CRC functions used for certain memory types */
+
+static uint8_t spdcrc16 (struct spdmem_softc *sc, int count)
+{
+       uint16_t crc;
+       int i, j;
+       uint8_t val;
+       crc = 0;
+       for (j = 0; j <= count; j++) {
+               val = spdmem_read(sc, j);
+               crc = crc ^ val << 8;
+               for (i = 0; i < 8; ++i)
+                       if (crc & 0x8000)
+                               crc = crc << 1 ^ 0x1021;
+                       else
+                               crc = crc << 1;
+       }
+       return (crc & 0xFFFF);
+}
 static int
 spdmem_match(device_t parent, cfdata_t match, void *aux)
 {
        struct i2c_attach_args *ia = aux;
        struct spdmem_softc sc;
        int cksum = 0;
-       uint8_t i, val;
+       uint8_t i, val, spd_type;
+       int spd_len, spd_crc_cover;
+       int crc_calc, crc_spd;
 
        if (ia->ia_addr < 0x50 || ia->ia_addr > 0x57)
                return 0;
@@ -130,15 +152,63 @@ spdmem_match(device_t parent, cfdata_t m
        sc.sc_tag = ia->ia_tag;
        sc.sc_addr = ia->ia_addr;
 
-       for (i = 0; i < 63; i++)
-               cksum += spdmem_read(&sc, i);
+       spd_type = spdmem_read(&sc, 2);
 
-       val = spdmem_read(&sc, 63);
+       /* For older memory types, validate the checksum over 1st 63 bytes */
+       if (spd_type < SPDMEM_MEMTYPE_DDR3SDRAM &&
+           spd_type != SPDMEM_MEMTYPE_FBDIMM) {
+               for (i = 0; i < 63; i++)
+                       cksum += spdmem_read(&sc, i);
+
+               val = spdmem_read(&sc, 63);
+
+               if (cksum == 0 || (cksum & 0xff) != val) {
+                       aprint_debug("spd addr 0x%2x: ", sc.sc_addr);
+                       aprint_debug("spd checksum failed, calc = 0x%02x, "
+                                    "spd = 0x%02x\n", cksum, val);
+                       return 0;
+               } else
+                       return 1;
+       }
 
-       if (cksum == 0 || (cksum & 0xff) != val)
-               return 0;
+       /* For DDR3, verify the CRC */
+       if (spd_type == SPDMEM_MEMTYPE_DDR3SDRAM ||
+           spd_type == SPDMEM_MEMTYPE_FBDIMM) {
+               spd_len = spdmem_read(&sc, 0);
+               if (spd_len && SPDMEM_SPDCRC_116)
+                       spd_crc_cover = 116;
+               else
+                       spd_crc_cover = 125;
+               switch (spd_len & SPDMEM_SPDLEN_MASK) {
+               case SPDMEM_SPDLEN_128:
+                       spd_len = 128;
+                       break;
+               case SPDMEM_SPDLEN_176:
+                       spd_len = 176;
+                       break;
+               case SPDMEM_SPDLEN_256:
+                       spd_len = 256;
+                       break;
+               default:
+                       return 0;
+               }
+               if (spd_crc_cover > spd_len)
+                       return 0;
+               crc_calc = spdcrc16(&sc, spd_crc_cover);
+               crc_spd = spdmem_read(&sc, 127) << 8;
+               crc_spd |= spdmem_read(&sc, 126);
+               if (crc_calc != crc_spd) {
+                       aprint_debug("spd addr 0x%2x: ", sc.sc_addr);
+                       aprint_debug("crc16 failed, covers %d bytes, "
+                                    "calc = 0x%04x, spd = 0x%04x\n",
+                                    spd_crc_cover, crc_calc, crc_spd);
+                       return 0;
+               }
+               return 1;
+       }
 
-       return 1;
+       /* For unrecognized memory types, don't match at all */
+       return 0;
 }
 
 static void
@@ -155,22 +225,60 @@ spdmem_attach(device_t parent, device_t 
        int per_chip = 0;
        int dimm_size, cycle_time, d_clk, p_clk, bits;
        int i;
+       unsigned int spd_len, spd_size;
        const struct sysctlnode *node = NULL;
 
        sc->sc_tag = ia->ia_tag;
        sc->sc_addr = ia->ia_addr;
 
-       /* All SPD have at least 64 bytes of data including checksum */
-       for (i = 0; i < 64; i++) {
+       /*
+        * FBDIMM and DDR3 (and probably all newer) have a different
+        * encoding of the SPD EEPROM used/total sizes
+        */
+       if (sc->sc_spd_data.sm_type == SPDMEM_MEMTYPE_FBDIMM ||
+           sc->sc_spd_data.sm_type == SPDMEM_MEMTYPE_DDR3SDRAM) {
+               switch (sc->sc_spd_data.sm_len & SPDMEM_SPDSIZE_MASK) {
+               case SPDMEM_SPDSIZE_256:
+                       spd_size = 256;
+                       break;
+               default:
+                       spd_size = 0;
+                       break;
+               }
+               switch (sc->sc_spd_data.sm_len & SPDMEM_SPDLEN_MASK) {
+               case SPDMEM_SPDLEN_128:
+                       spd_len = 128;
+                       break;
+               case SPDMEM_SPDLEN_176:
+                       spd_len = 176;
+                       break;
+               case SPDMEM_SPDLEN_256:
+                       spd_len = 256;
+                       break;
+               default:
+                       spd_len = 64;
+                       break;
+               }
+       } else if (sc->sc_spd_data.sm_type < SPDMEM_MEMTYPE_DDR3SDRAM &&
+                  sc->sc_spd_data.sm_type != SPDMEM_MEMTYPE_FBDIMM) {
+               spd_len = sc->sc_spd_data.sm_len;
+               spd_size = 1 << sc->sc_spd_data.sm_size;
+       } else
+               spd_size = 0;
+       if (spd_len > spd_size)
+               spd_len = spd_size;
+       if (spd_len > sizeof(struct spdmem))
+               spd_len = sizeof(struct spdmem);
+       for (i = 0; i < spd_len; i++)
                ((uint8_t *)s)[i] = spdmem_read(sc, i);
-       }
 
 #ifdef DEBUG
-       for (i = 0; i < 64;  i += 16) {
-               int j;
+       for (i = 0; i < spd_len;  i += 16) {
+               int j, k;
                aprint_debug("\n");
                aprint_debug_dev(self, "0x%02x:", i);
-               for(j = 0; j < 16; j++)
+               k = (spd_len - i < 16) ? spd_len - i : 16;
+               for(j = 0; j < k; j++)
                        aprint_debug(" %02x", ((uint8_t *)s)[i + j]);
        }
        aprint_debug("\n");
@@ -185,21 +293,21 @@ spdmem_attach(device_t parent, device_t 
                    0, CTLTYPE_NODE,
                    device_xname(self), NULL, NULL, 0, NULL, 0,
                    CTL_HW, CTL_CREATE, CTL_EOL);
-       if (node != NULL)
+       if (node != NULL && spd_len != 0)
                 sysctl_createv(NULL, 0, NULL, NULL,
                     0,
                     CTLTYPE_STRUCT, "spd_data",
-                   SYSCTL_DESCR("raw spd data (first 64 bytes)"), NULL,
-                    0, s, sizeof(*s),
+                   SYSCTL_DESCR("raw spd data"), NULL,
+                    0, s, spd_len,
                     CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL);
 
        /*
-        * Decode and print SPD contents
+        * Decode and print key SPD contents
         */
        if (IS_RAMBUS_TYPE)
                type = "Rambus";
        else {
-               if (s->sm_type <= 10)
+               if (s->sm_type <= __arraycount(spdmem_basic_types))
                        type = spdmem_basic_types[s->sm_type];
                else
                        type = "unknown memory type";
@@ -234,8 +342,10 @@ spdmem_attach(device_t parent, device_t 
        if ((s->sm_type == SPDMEM_MEMTYPE_SDRAM ||
             s->sm_type == SPDMEM_MEMTYPE_DDRSDRAM ||
             s->sm_type == SPDMEM_MEMTYPE_DDR2SDRAM ) &&
-           s->sm_config < 8)
+           s->sm_config < __arraycount(spdmem_parity_types))
                aprint_normal(", %s", spdmem_parity_types[s->sm_config]);
+       else if (s->sm_type == SPDMEM_MEMTYPE_DDR3SDRAM)
+               aprint_normal(", %sECC", s->sm_ddr3.ddr3_hasECC?"":"no ");
 
        dimm_size = 0;
        if (IS_RAMBUS_TYPE) {
@@ -253,6 +363,21 @@ spdmem_attach(device_t parent, device_t 
                dimm_size = s->sm_ddr2.ddr2_rows + s->sm_ddr2.ddr2_cols - 17;
                num_banks = s->sm_ddr2.ddr2_ranks + 1;
                per_chip = s->sm_ddr2.ddr2_banks_per_chip;
+       } else if (s->sm_type == SPDMEM_MEMTYPE_DDR3SDRAM) {
+               /*
+                * DDR3 size specification is quite different from DDR2
+                *
+                * Module capacity is defined as
+                *      Chip_Capacity_in_bits / 8bits-per-byte 
+                *              * external_bus_width
+                *              / internal_bus_width
+                * We further divide by 2**20 to get our answer in MB
+                */
+               dimm_size = s->sm_ddr3.ddr3_chipsize + 28 - 20 - 3 +
+                       s->sm_ddr3.ddr3_datawidth + 1 -
+                       s->sm_ddr3.ddr3_chipwidth -2;
+               num_banks = s->sm_ddr3.ddr3_physbanks;
+               per_chip = 1;
        }
        if (!(IS_RAMBUS_TYPE) && num_banks <= 8 && per_chip <= 8 &&
            dimm_size > 0 && dimm_size <= 12) {
@@ -278,6 +403,11 @@ spdmem_attach(device_t parent, device_t 
                cycle_time = s->sm_ddr2.ddr2_cycle_whole * 100 +
                             spdmem_cycle_frac[s->sm_ddr2.ddr2_cycle_frac];
        }
+       else if (s->sm_type == SPDMEM_MEMTYPE_DDR3SDRAM) {
+               cycle_time = ((1000 * s->sm_ddr3.ddr3_mtb_dividend + 5) /
+                               s->sm_ddr3.ddr3_mtb_divisor) / 10;
+               cycle_time *= s->sm_ddr3.ddr3_tCK_min;
+       }
 
        if (cycle_time != 0) {
                /*
@@ -286,7 +416,12 @@ spdmem_attach(device_t parent, device_t 
                 * of cycles per microsecond.
                 */
                d_clk = 100 * 1000;
-               if (s->sm_type == SPDMEM_MEMTYPE_DDR2SDRAM) {
+               if (s->sm_type == SPDMEM_MEMTYPE_DDR3SDRAM) {
+                       /* DDR3 uses an 8X-pumped clock */
+                       d_clk *= 8;
+                       bits = 1 << (s->sm_ddr3.ddr3_datawidth + 3);
+                       ddr_type_string = "PC3";
+               } else if (s->sm_type == SPDMEM_MEMTYPE_DDR2SDRAM) {
                        /* DDR2 uses quad-pumped clock */
                        d_clk *= 4;
                        bits = s->sm_ddr2.ddr2_datawidth;
@@ -317,6 +452,8 @@ spdmem_attach(device_t parent, device_t 
                d_clk /= cycle_time;
                if (s->sm_type == SPDMEM_MEMTYPE_DDR2SDRAM)
                        d_clk = (d_clk + 1) / 2;
+               if (s->sm_type == SPDMEM_MEMTYPE_DDR3SDRAM)
+                       d_clk = (d_clk + 2) / 4;
                p_clk = d_clk * bits / 8;
                if ((p_clk % 100) >= 50)
                        p_clk += 50;
@@ -373,25 +510,35 @@ spdmem_attach(device_t parent, device_t 
                    s->sm_ddr2.ddr2_cycle_whole,
                    spdmem_cycle_frac[s->sm_ddr2.ddr2_cycle_frac]);
                break;
+       case SPDMEM_MEMTYPE_DDR3SDRAM:
+               aprint_verbose(
+                   "%d rows, %d cols, %d log banks, %d phys banks, "
+                   "%d.%02dns cycle time\n",
+                   s->sm_ddr3.ddr3_rows, s->sm_ddr3.ddr3_cols,
+                   s->sm_ddr3.ddr3_logbanks, s->sm_ddr3.ddr3_physbanks,
+                   cycle_time/100, cycle_time % 100);
+               break;
        default:
                break;
        }
 
-       if (s->sm_voltage <= 0x5)
-               voltage = spdmem_voltage_types[s->sm_voltage];
-       else
-               voltage = "unknown";
-
-       if (s->sm_refresh <= 0x05)
-               refresh = spdmem_refresh_types[s->sm_refresh];
-       else
-               refresh = "unknown";
-
-       aprint_verbose_dev(self, "voltage %s, refresh time %s",
-                       voltage, refresh);
-       if (s->sm_selfrefresh)
-               aprint_verbose(" (self-refreshing)");
-       aprint_verbose("\n");
+       if (s->sm_type < SPDMEM_MEMTYPE_DDR3SDRAM) {
+               if (s->sm_voltage <= __arraycount(spdmem_voltage_types))
+                       voltage = spdmem_voltage_types[s->sm_voltage];
+               else
+                       voltage = "unknown";
+
+               if (s->sm_refresh <= __arraycount(spdmem_refresh_types))
+                       refresh = spdmem_refresh_types[s->sm_refresh];
+               else
+                       refresh = "unknown";
+
+               aprint_verbose_dev(self, "voltage %s, refresh time %s",
+                               voltage, refresh);
+               if (s->sm_selfrefresh)
+                       aprint_verbose(" (self-refreshing)");
+               aprint_verbose("\n");
+       }
 
        if (!pmf_device_register(self, NULL, NULL))
                aprint_error_dev(self, "couldn't establish power handler\n");
Index: src/sys/dev/i2c/spdmemreg.h
===================================================================
RCS file: /cvsroot/src/sys/dev/i2c/spdmemreg.h,v
retrieving revision 1.1
diff -u -p -r1.1 spdmemreg.h
--- src/sys/dev/i2c/spdmemreg.h 18 Aug 2007 11:26:37 -0000      1.1
+++ src/sys/dev/i2c/spdmemreg.h 22 May 2008 11:32:17 -0000
@@ -37,6 +37,21 @@
 #define        SPDMEM_MEMTYPE_DDRSGRAM         0x06
 #define        SPDMEM_MEMTYPE_DDRSDRAM         0x07
 #define        SPDMEM_MEMTYPE_DDR2SDRAM        0x08
+#define SPDMEM_MEMTYPE_FBDIMM          0x09
+#define SPDMEM_MEMTYPE_FBDIMM_PROBE    0x0A
+#define        SPDMEM_MEMTYPE_DDR3SDRAM        0x0B
+
+/* Encodings of the size used/total byte for certain memory types    */
+#define SPDMEM_SPDSIZE_256             0x01    /* SPD Bytes written */
+#define        SPDMEM_SPDSIZE_MASK             0x0F    /* Bits 0 - 3        */
+
+#define SPDMEM_SPDLEN_128              0x10    /* SPD EEPROM Sizes  */
+#define SPDMEM_SPDLEN_176              0x20
+#define        SPDMEM_SPDLEN_256               0x30
+#define        SPDMEM_SPDLEN_MASK              0x70    /* Bits 4 - 6        */
+
+#define SPDMEM_SPDCRC_116              0x80    /* CRC Bytes covered */
+#define SPDMEM_SPDCRC_125              0x00
 
 /* possible values for the supply voltage */
 #define        SPDMEM_VOLTAGE_TTL_5V           0x00
Index: src/sys/dev/i2c/spdmemvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/i2c/spdmemvar.h,v
retrieving revision 1.3
diff -u -p -r1.3 spdmemvar.h
--- src/sys/dev/i2c/spdmemvar.h 4 May 2008 15:26:29 -0000       1.3
+++ src/sys/dev/i2c/spdmemvar.h 22 May 2008 11:32:17 -0000
@@ -53,6 +53,7 @@ struct spdmem_fpm {                           /* FPM and EDO 
DI
        uint8_t fpm_unused2[17];
        uint8_t fpm_superset;
        uint8_t fpm_unused3[30];
+       uint8_t fpm_cksum;
 } __packed;
 
 struct spdmem_sdram {                          /* PC66/PC100/PC133 SDRAM */
@@ -115,10 +116,11 @@ struct spdmem_sdram {                             /* 
PC66/PC100/P
        uint8_t sdr_tDH;
        uint8_t sdr_unused2[5];
        uint8_t sdr_tRC;
-       uint8_t sdr_unused3[20];
+       uint8_t sdr_unused3[18];
        uint8_t sdr_esdram;
        uint8_t sdr_super_tech;
        uint8_t sdr_spdrev;
+       uint8_t sdr_cksum;
 } __packed;
 
 struct spdmem_rom {
@@ -136,6 +138,7 @@ struct spdmem_rom {
        uint8_t rom_burstlength;
        uint8_t rom_unused2[14];
        uint8_t rom_superset[31];
+       uint8_t rom_cksum;
 } __packed;
 
 
@@ -206,6 +209,7 @@ struct spdmem_ddr {                         /* Dual Data 
Rate
        uint8_t ddr_unused3;
        uint8_t ddr_height;
        uint8_t ddr_unused4[15];
+       uint8_t ddr_cksum;
 } __packed;
 
 struct spdmem_ddr2 {                           /* Dual Data Rate 2 SDRAM */
@@ -292,6 +296,7 @@ struct spdmem_ddr2 {                                /* Dual 
Data Rat
        uint8_t ddr2_dt_PLL_Active;
        uint8_t ddr2_dt_Reg_Active;
        uint8_t ddr2_spdrev;
+       uint8_t ddr2_cksum;
 } __packed;
 
 struct spdmem_fbdimm {                         /* Fully-buffered DIMM */
@@ -368,6 +373,7 @@ struct spdmem_fbdimm {                              /* 
Fully-buffe
        uint8_t fbdimm_DT5B;
        uint8_t fbdimm_DT7;
        uint8_t fbdimm_unused4[21];
+       uint8_t fbdimm_cksum;
 } __packed;
 
 struct spdmem_rambus {                         /* Direct Rambus DRAM */
@@ -377,8 +383,78 @@ struct spdmem_rambus {                             /* 
Direct Ramb
        );
 } __packed;
 
+struct spdmem_ddr3 {                           /* Dual Data Rate 3 SDRAM */
+       uint8_t ddr3_mod_type;
+       SPD_BITFIELD(                           \
+               uint8_t ddr3_chipsize:5,        \
+               uint8_t ddr3_logbanks:3, ,      \
+       );
+       /* cols is offset by 9, rows offset by 12 */
+       SPD_BITFIELD(                           \
+               uint8_t ddr3_cols:3,            \
+               uint8_t ddr3_rows:5, ,          \
+       );
+       uint8_t ddr3_unused2;
+       /* chipwidth in bits offset by 2 - 0 = X4, 1 = X8, 2 = X16 */
+       /* physbanks is offset by 1 */
+       SPD_BITFIELD(                           \
+               uint8_t ddr3_chipwidth:3,       \
+               uint8_t ddr3_physbanks:5, ,     \
+       );
+       /* datawidth in bits offset by 3 - 1 = 16b, 2 = 32b, 3 = 64b */
+       SPD_BITFIELD(                           \
+               uint8_t ddr3_datawidth:7,       \
+               uint8_t ddr3_hasECC:1, ,        \
+       );
+       uint8_t ddr3_ftb;               /* 0x52 = 2.5ps, 0x55 = 5.0ps */
+       uint8_t ddr3_mtb_dividend;      /* 0x0108 = 0.1250ns */
+       uint8_t ddr3_mtb_divisor;       /* 0x010f = 0.0625ns */
+       uint8_t ddr3_tCK_min;           /* in terms of mtb */
+       uint8_t ddr3_unused3;
+       uint16_t ddr3_CAS_sup;
+       uint8_t ddr3_tAAmin;            /* in terms of mtb */
+       uint8_t ddr3_tWRmin;
+       uint8_t ddr3_tRCDmin;
+       uint8_t ddr3_tRRDmin;
+       uint8_t ddr3_tRPmin;
+       SPD_BITFIELD(                           \
+               uint8_t ddr3_tRAS_msb:4,        \
+               uint8_t ddr3_tRC_msb:4, ,       \
+       );
+       uint8_t ddr3_tRAS_lsb;
+       uint8_t ddr3_tRC_lsb;
+       uint8_t ddr3_tRFCmin_lsb;
+       uint8_t ddr3_tRFCmin_msb;
+       uint8_t ddr3_tWTRmin;
+       uint8_t ddr3_tRTPmin;
+       SPD_BITFIELD(                           \
+               uint8_t ddr3_tFAW_msb:4, , ,    \
+       );
+       uint8_t ddr3_tFAW_lsb;
+       uint8_t ddr3_output_drvrs;
+       SPD_BITFIELD(                           \
+               uint8_t ddr3_ext_temp_range:1,  \
+               uint8_t ddr3_unused6:1,         \
+               uint8_t ddr3_asr_refresh:1,     \
+               uint8_t ddr3_unused7:5          \
+       );
+       uint8_t ddr3_unused4[28];
+       uint8_t ddr3_mod_height;
+       uint8_t ddr3_mod_thickness;
+       uint8_t ddr3_ref_card;
+       uint8_t ddr3_mapping;
+       uint8_t ddr3_unused5[53];
+       uint8_t ddr3_mfgID_lsb;
+       uint8_t ddr3_mfgID_msb;
+       uint8_t ddr3_mfgloc;
+       uint8_t ddr3_mfg_year;
+       uint8_t ddr3_mfg_week;
+       uint8_t ddr3_serial[4];
+       uint16_t ddr3_crc;
+} __packed;
+
 struct spdmem {
-       uint8_t sm_len;
+       uint8_t sm_len;
        uint8_t sm_size;
        uint8_t sm_type;
        union {
@@ -389,19 +465,23 @@ struct spdmem {
                struct spdmem_sdram     u1_sdr;
                struct spdmem_rambus    u1_rdr;
                struct spdmem_rom       u1_rom;
+               struct spdmem_ddr3      u1_ddr3;
        } sm_u1;
+       uint8_t sm_extension[128];
+} __packed;
 #define        sm_fbd          sm_u1.u1_fbd
 #define        sm_fpm          sm_u1.u1_fpm
 #define        sm_ddr          sm_u1.u1_ddr
 #define        sm_ddr2         sm_u1.u1_ddr2
 #define        sm_rdr          sm_u1.u1_rdr
 #define        sm_rom          sm_u1.u1_rom
+#define        sm_ddr3         sm_u1.u1_ddr3
 #define        sm_sdr          sm_u1.u1_sdr
-       uint8_t sm_cksum;
-} __packed;
+
 
 /* some fields are in the same place for all memory types */
 
+#define sm_cksum       sm_fpm.fpm_cksum
 #define sm_config      sm_fpm.fpm_config
 #define sm_voltage     sm_fpm.fpm_voltage
 #define        sm_refresh      sm_fpm.fpm_refresh

>Unformatted:
        
        


Home | Main Index | Thread Index | Old Index