Mon Aug 1 03:49:52 2011 UTC ()
Modularize the spdmem(4) driver


(pgoyette)
diff -r1.1 -r1.2 src/sys/dev/i2c/spdmem_i2c.c
diff -r1.2 -r1.3 src/sys/dev/ic/spdmem.c
diff -r1.1 -r1.2 src/sys/dev/ic/spdmemvar.h

cvs diff -r1.1 -r1.2 src/sys/dev/i2c/spdmem_i2c.c (switch to unified diff)

--- src/sys/dev/i2c/spdmem_i2c.c 2010/03/24 00:31:41 1.1
+++ src/sys/dev/i2c/spdmem_i2c.c 2011/08/01 03:49:52 1.2
@@ -1,122 +1,164 @@ @@ -1,122 +1,164 @@
1/* $NetBSD: spdmem_i2c.c,v 1.1 2010/03/24 00:31:41 pgoyette Exp $ */ 1/* $NetBSD: spdmem_i2c.c,v 1.2 2011/08/01 03:49:52 pgoyette Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2007 Nicolas Joly 4 * Copyright (c) 2007 Nicolas Joly
5 * Copyright (c) 2007 Paul Goyette 5 * Copyright (c) 2007 Paul Goyette
6 * Copyright (c) 2007 Tobias Nygren 6 * Copyright (c) 2007 Tobias Nygren
7 * All rights reserved. 7 * All rights reserved.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products 17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission. 18 * derived from this software without specific prior written permission.
19 * 19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE. 30 * POSSIBILITY OF SUCH DAMAGE.
31 */ 31 */
32 32
33/* 33/*
34 * Serial Presence Detect (SPD) memory identification 34 * Serial Presence Detect (SPD) memory identification
35 */ 35 */
36 36
37#include <sys/cdefs.h> 37#include <sys/cdefs.h>
38__KERNEL_RCSID(0, "$NetBSD: spdmem_i2c.c,v 1.1 2010/03/24 00:31:41 pgoyette Exp $"); 38__KERNEL_RCSID(0, "$NetBSD: spdmem_i2c.c,v 1.2 2011/08/01 03:49:52 pgoyette Exp $");
39 39
40#include <sys/param.h> 40#include <sys/param.h>
41#include <sys/device.h> 41#include <sys/device.h>
42#include <sys/endian.h> 42#include <sys/endian.h>
 43#include <sys/module.h>
43#include <sys/sysctl.h> 44#include <sys/sysctl.h>
44#include <machine/bswap.h> 45#include <machine/bswap.h>
45 46
46#include <dev/i2c/i2cvar.h> 47#include <dev/i2c/i2cvar.h>
47#include <dev/ic/spdmemreg.h> 48#include <dev/ic/spdmemreg.h>
48#include <dev/ic/spdmemvar.h> 49#include <dev/ic/spdmemvar.h>
49 50
50/* Constants for matching i2c bus address */ 51/* Constants for matching i2c bus address */
51#define SPDMEM_I2C_ADDRMASK 0x78 52#define SPDMEM_I2C_ADDRMASK 0x78
52#define SPDMEM_I2C_ADDR 0x50 53#define SPDMEM_I2C_ADDR 0x50
53 54
54struct spdmem_i2c_softc { 55struct spdmem_i2c_softc {
55 struct spdmem_softc sc_base; 56 struct spdmem_softc sc_base;
56 i2c_tag_t sc_tag; 57 i2c_tag_t sc_tag;
57 i2c_addr_t sc_addr; 58 i2c_addr_t sc_addr;
58}; 59};
59 60
60static int spdmem_i2c_match(device_t, cfdata_t, void *); 61static int spdmem_i2c_match(device_t, cfdata_t, void *);
61static void spdmem_i2c_attach(device_t, device_t, void *); 62static void spdmem_i2c_attach(device_t, device_t, void *);
62SYSCTL_SETUP_PROTO(sysctl_spdmem_setup); 63static int spdmem_i2c_detach(device_t, int);
 64
 65CFATTACH_DECL_NEW(spdmem_iic, sizeof(struct spdmem_i2c_softc),
 66 spdmem_i2c_match, spdmem_i2c_attach, spdmem_i2c_detach, NULL);
63 67
64static uint8_t spdmem_i2c_read(struct spdmem_softc *, uint8_t); 68static uint8_t spdmem_i2c_read(struct spdmem_softc *, uint8_t);
65 69
66CFATTACH_DECL_NEW(spdmem_iic, sizeof(struct spdmem_i2c_softc), 70SYSCTL_SETUP_PROTO(sysctl_spdmem_setup);
67 spdmem_i2c_match, spdmem_i2c_attach, NULL, NULL); 
68 71
69static int 72static int
70spdmem_i2c_match(device_t parent, cfdata_t match, void *aux) 73spdmem_i2c_match(device_t parent, cfdata_t match, void *aux)
71{ 74{
72 struct i2c_attach_args *ia = aux; 75 struct i2c_attach_args *ia = aux;
73 struct spdmem_i2c_softc sc; 76 struct spdmem_i2c_softc sc;
74 77
75 if (ia->ia_name) { 78 if (ia->ia_name) {
76 /* add other names as we find more firmware variations */ 79 /* add other names as we find more firmware variations */
77 if (strcmp(ia->ia_name, "dimm-spd")) 80 if (strcmp(ia->ia_name, "dimm-spd"))
78 return 0; 81 return 0;
79 } 82 }
80 83
81 /* only do this lame test when not using direct config */ 84 /* only do this lame test when not using direct config */
82 if (ia->ia_name == NULL) { 85 if (ia->ia_name == NULL) {
83 if ((ia->ia_addr & SPDMEM_I2C_ADDRMASK) != SPDMEM_I2C_ADDR) 86 if ((ia->ia_addr & SPDMEM_I2C_ADDRMASK) != SPDMEM_I2C_ADDR)
84 return 0; 87 return 0;
85 } 88 }
86 89
87 sc.sc_tag = ia->ia_tag; 90 sc.sc_tag = ia->ia_tag;
88 sc.sc_addr = ia->ia_addr; 91 sc.sc_addr = ia->ia_addr;
89 sc.sc_base.sc_read = spdmem_i2c_read; 92 sc.sc_base.sc_read = spdmem_i2c_read;
90 93
91 return spdmem_common_probe(&sc.sc_base); 94 return spdmem_common_probe(&sc.sc_base);
92} 95}
93 96
94static void 97static void
95spdmem_i2c_attach(device_t parent, device_t self, void *aux) 98spdmem_i2c_attach(device_t parent, device_t self, void *aux)
96{ 99{
97 struct spdmem_i2c_softc *sc = device_private(self); 100 struct spdmem_i2c_softc *sc = device_private(self);
98 struct i2c_attach_args *ia = aux; 101 struct i2c_attach_args *ia = aux;
99 102
100 sc->sc_tag = ia->ia_tag; 103 sc->sc_tag = ia->ia_tag;
101 sc->sc_addr = ia->ia_addr; 104 sc->sc_addr = ia->ia_addr;
102 sc->sc_base.sc_read = spdmem_i2c_read; 105 sc->sc_base.sc_read = spdmem_i2c_read;
103 106
104 if (!pmf_device_register(self, NULL, NULL)) 107 if (!pmf_device_register(self, NULL, NULL))
105 aprint_error_dev(self, "couldn't establish power handler\n"); 108 aprint_error_dev(self, "couldn't establish power handler\n");
106 109
107 spdmem_common_attach(&sc->sc_base, self); 110 spdmem_common_attach(&sc->sc_base, self);
108} 111}
109 112
 113static int
 114spdmem_i2c_detach(device_t self, int flags)
 115{
 116 struct spdmem_i2c_softc *sc = device_private(self);
 117
 118 pmf_device_deregister(self);
 119
 120 return spdmem_common_detach(&sc->sc_base, self);
 121}
 122
110static uint8_t 123static uint8_t
111spdmem_i2c_read(struct spdmem_softc *softc, uint8_t reg) 124spdmem_i2c_read(struct spdmem_softc *softc, uint8_t reg)
112{ 125{
113 uint8_t val; 126 uint8_t val;
114 struct spdmem_i2c_softc *sc = (struct spdmem_i2c_softc *)softc; 127 struct spdmem_i2c_softc *sc = (struct spdmem_i2c_softc *)softc;
115 128
116 iic_acquire_bus(sc->sc_tag, 0); 129 iic_acquire_bus(sc->sc_tag, 0);
117 iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, &reg, 1, 130 iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, &reg, 1,
118 &val, 1, 0); 131 &val, 1, 0);
119 iic_release_bus(sc->sc_tag, 0); 132 iic_release_bus(sc->sc_tag, 0);
120 133
121 return val; 134 return val;
122} 135}
 136
 137MODULE(MODULE_CLASS_DRIVER, spdmem, NULL);
 138
 139#ifdef _MODULE
 140#include "ioconf.c"
 141#endif
 142
 143static int
 144spdmem_modcmd(modcmd_t cmd, void *opaque)
 145{
 146 int error = 0;
 147
 148 switch (cmd) {
 149 case MODULE_CMD_INIT:
 150#ifdef _MODULE
 151 error = config_init_component(cfdriver_ioconf_spdmem,
 152 cfattach_ioconf_spdmem, cfdata_ioconf_spdmem);
 153#endif
 154 return error;
 155 case MODULE_CMD_FINI:
 156#ifdef _MODULE
 157 error = config_fini_component(cfdriver_ioconf_spdmem,
 158 cfattach_ioconf_spdmem, cfdata_ioconf_spdmem);
 159#endif
 160 return error;
 161 default:
 162 return ENOTTY;
 163 }
 164}

cvs diff -r1.2 -r1.3 src/sys/dev/ic/spdmem.c (switch to unified diff)

--- src/sys/dev/ic/spdmem.c 2010/06/29 04:42:30 1.2
+++ src/sys/dev/ic/spdmem.c 2011/08/01 03:49:52 1.3
@@ -1,723 +1,737 @@ @@ -1,723 +1,737 @@
1/* $NetBSD: spdmem.c,v 1.2 2010/06/29 04:42:30 pgoyette Exp $ */ 1/* $NetBSD: spdmem.c,v 1.3 2011/08/01 03:49:52 pgoyette Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2007 Nicolas Joly 4 * Copyright (c) 2007 Nicolas Joly
5 * Copyright (c) 2007 Paul Goyette 5 * Copyright (c) 2007 Paul Goyette
6 * Copyright (c) 2007 Tobias Nygren 6 * Copyright (c) 2007 Tobias Nygren
7 * All rights reserved. 7 * All rights reserved.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products 17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission. 18 * derived from this software without specific prior written permission.
19 * 19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE. 30 * POSSIBILITY OF SUCH DAMAGE.
31 */ 31 */
32 32
33/* 33/*
34 * Serial Presence Detect (SPD) memory identification 34 * Serial Presence Detect (SPD) memory identification
35 */ 35 */
36 36
37#include <sys/cdefs.h> 37#include <sys/cdefs.h>
38__KERNEL_RCSID(0, "$NetBSD: spdmem.c,v 1.2 2010/06/29 04:42:30 pgoyette Exp $"); 38__KERNEL_RCSID(0, "$NetBSD: spdmem.c,v 1.3 2011/08/01 03:49:52 pgoyette Exp $");
39 39
40#include <sys/param.h> 40#include <sys/param.h>
41#include <sys/device.h> 41#include <sys/device.h>
42#include <sys/endian.h> 42#include <sys/endian.h>
43#include <sys/sysctl.h> 43#include <sys/sysctl.h>
44#include <machine/bswap.h> 44#include <machine/bswap.h>
45 45
46#include <dev/i2c/i2cvar.h> 46#include <dev/i2c/i2cvar.h>
47#include <dev/ic/spdmemreg.h> 47#include <dev/ic/spdmemreg.h>
48#include <dev/ic/spdmemvar.h> 48#include <dev/ic/spdmemvar.h>
49 49
50SYSCTL_SETUP_PROTO(sysctl_spdmem_setup); 50SYSCTL_SETUP_PROTO(sysctl_spdmem_setup);
51 51
52/* Routines for decoding spd data */ 52/* Routines for decoding spd data */
53static void decode_edofpm(const struct sysctlnode *, device_t, struct spdmem *); 53static void decode_edofpm(const struct sysctlnode *, device_t, struct spdmem *);
54static void decode_rom(const struct sysctlnode *, device_t, struct spdmem *); 54static void decode_rom(const struct sysctlnode *, device_t, struct spdmem *);
55static void decode_sdram(const struct sysctlnode *, device_t, struct spdmem *, 55static void decode_sdram(const struct sysctlnode *, device_t, struct spdmem *,
56 int); 56 int);
57static void decode_ddr(const struct sysctlnode *, device_t, struct spdmem *); 57static void decode_ddr(const struct sysctlnode *, device_t, struct spdmem *);
58static void decode_ddr2(const struct sysctlnode *, device_t, struct spdmem *); 58static void decode_ddr2(const struct sysctlnode *, device_t, struct spdmem *);
59static void decode_ddr3(const struct sysctlnode *, device_t, struct spdmem *); 59static void decode_ddr3(const struct sysctlnode *, device_t, struct spdmem *);
60static void decode_fbdimm(const struct sysctlnode *, device_t, struct spdmem *); 60static void decode_fbdimm(const struct sysctlnode *, device_t, struct spdmem *);
61 61
62static void decode_size_speed(const struct sysctlnode *, int, int, int, int, 62static void decode_size_speed(device_t, const struct sysctlnode *,
63 bool, const char *, int); 63 int, int, int, int, bool, const char *, int);
64static void decode_voltage_refresh(device_t, struct spdmem *); 64static void decode_voltage_refresh(device_t, struct spdmem *);
65 65
66#define IS_RAMBUS_TYPE (s->sm_len < 4) 66#define IS_RAMBUS_TYPE (s->sm_len < 4)
67 67
68static const char* spdmem_basic_types[] = { 68static const char* spdmem_basic_types[] = {
69 "unknown", 69 "unknown",
70 "FPM", 70 "FPM",
71 "EDO", 71 "EDO",
72 "Pipelined Nibble", 72 "Pipelined Nibble",
73 "SDRAM", 73 "SDRAM",
74 "ROM", 74 "ROM",
75 "DDR SGRAM", 75 "DDR SGRAM",
76 "DDR SDRAM", 76 "DDR SDRAM",
77 "DDR2 SDRAM", 77 "DDR2 SDRAM",
78 "DDR2 SDRAM FB", 78 "DDR2 SDRAM FB",
79 "DDR2 SDRAM FB Probe", 79 "DDR2 SDRAM FB Probe",
80 "DDR3 SDRAM" 80 "DDR3 SDRAM"
81}; 81};
82 82
83static const char* spdmem_superset_types[] = { 83static const char* spdmem_superset_types[] = {
84 "unknown", 84 "unknown",
85 "ESDRAM", 85 "ESDRAM",
86 "DDR ESDRAM", 86 "DDR ESDRAM",
87 "PEM EDO", 87 "PEM EDO",
88 "PEM SDRAM" 88 "PEM SDRAM"
89}; 89};
90 90
91static const char* spdmem_voltage_types[] = { 91static const char* spdmem_voltage_types[] = {
92 "TTL (5V tolerant)", 92 "TTL (5V tolerant)",
93 "LvTTL (not 5V tolerant)", 93 "LvTTL (not 5V tolerant)",
94 "HSTL 1.5V", 94 "HSTL 1.5V",
95 "SSTL 3.3V", 95 "SSTL 3.3V",
96 "SSTL 2.5V", 96 "SSTL 2.5V",
97 "SSTL 1.8V" 97 "SSTL 1.8V"
98}; 98};
99 99
100static const char* spdmem_refresh_types[] = { 100static const char* spdmem_refresh_types[] = {
101 "15.625us", 101 "15.625us",
102 "3.9us", 102 "3.9us",
103 "7.8us", 103 "7.8us",
104 "31.3us", 104 "31.3us",
105 "62.5us", 105 "62.5us",
106 "125us" 106 "125us"
107}; 107};
108 108
109static const char* spdmem_parity_types[] = { 109static const char* spdmem_parity_types[] = {
110 "no parity or ECC", 110 "no parity or ECC",
111 "data parity", 111 "data parity",
112 "data ECC", 112 "data ECC",
113 "data parity and ECC", 113 "data parity and ECC",
114 "cmd/addr parity", 114 "cmd/addr parity",
115 "cmd/addr/data parity", 115 "cmd/addr/data parity",
116 "cmd/addr parity, data ECC", 116 "cmd/addr parity, data ECC",
117 "cmd/addr/data parity, data ECC" 117 "cmd/addr/data parity, data ECC"
118}; 118};
119 119
120/* Cycle time fractional values (units of .001 ns) for DDR2 SDRAM */ 120/* Cycle time fractional values (units of .001 ns) for DDR2 SDRAM */
121static const uint16_t spdmem_cycle_frac[] = { 121static const uint16_t spdmem_cycle_frac[] = {
122 0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 122 0, 100, 200, 300, 400, 500, 600, 700, 800, 900,
123 250, 333, 667, 750, 999, 999 123 250, 333, 667, 750, 999, 999
124}; 124};
125 125
126/* Format string for timing info */ 126/* Format string for timing info */
127static const char* latency="tAA-tRCD-tRP-tRAS: %d-%d-%d-%d\n"; 127static const char* latency="tAA-tRCD-tRP-tRAS: %d-%d-%d-%d\n";
128 128
129/* sysctl stuff */ 129/* sysctl stuff */
130static int hw_node = CTL_EOL; 130static int hw_node = CTL_EOL;
131 131
132/* CRC functions used for certain memory types */ 132/* CRC functions used for certain memory types */
133 133
134static uint16_t spdcrc16 (struct spdmem_softc *sc, int count) 134static uint16_t spdcrc16 (struct spdmem_softc *sc, int count)
135{ 135{
136 uint16_t crc; 136 uint16_t crc;
137 int i, j; 137 int i, j;
138 uint8_t val; 138 uint8_t val;
139 crc = 0; 139 crc = 0;
140 for (j = 0; j <= count; j++) { 140 for (j = 0; j <= count; j++) {
141 val = (sc->sc_read)(sc, j); 141 val = (sc->sc_read)(sc, j);
142 crc = crc ^ val << 8; 142 crc = crc ^ val << 8;
143 for (i = 0; i < 8; ++i) 143 for (i = 0; i < 8; ++i)
144 if (crc & 0x8000) 144 if (crc & 0x8000)
145 crc = crc << 1 ^ 0x1021; 145 crc = crc << 1 ^ 0x1021;
146 else 146 else
147 crc = crc << 1; 147 crc = crc << 1;
148 } 148 }
149 return (crc & 0xFFFF); 149 return (crc & 0xFFFF);
150} 150}
151 151
152int 152int
153spdmem_common_probe(struct spdmem_softc *sc) 153spdmem_common_probe(struct spdmem_softc *sc)
154{ 154{
155 int cksum = 0; 155 int cksum = 0;
156 uint8_t i, val, spd_type; 156 uint8_t i, val, spd_type;
157 int spd_len, spd_crc_cover; 157 int spd_len, spd_crc_cover;
158 uint16_t crc_calc, crc_spd; 158 uint16_t crc_calc, crc_spd;
159 159
160 spd_type = (sc->sc_read)(sc, 2); 160 spd_type = (sc->sc_read)(sc, 2);
161 161
162 /* For older memory types, validate the checksum over 1st 63 bytes */ 162 /* For older memory types, validate the checksum over 1st 63 bytes */
163 if (spd_type <= SPDMEM_MEMTYPE_DDR2SDRAM) { 163 if (spd_type <= SPDMEM_MEMTYPE_DDR2SDRAM) {
164 for (i = 0; i < 63; i++) 164 for (i = 0; i < 63; i++)
165 cksum += (sc->sc_read)(sc, i); 165 cksum += (sc->sc_read)(sc, i);
166 166
167 val = (sc->sc_read)(sc, 63); 167 val = (sc->sc_read)(sc, 63);
168 168
169 if (cksum == 0 || (cksum & 0xff) != val) { 169 if (cksum == 0 || (cksum & 0xff) != val) {
170 aprint_debug("spd checksum failed, calc = 0x%02x, " 170 aprint_debug("spd checksum failed, calc = 0x%02x, "
171 "spd = 0x%02x\n", cksum, val); 171 "spd = 0x%02x\n", cksum, val);
172 return 0; 172 return 0;
173 } else 173 } else
174 return 1; 174 return 1;
175 } 175 }
176 176
177 /* For DDR3 and FBDIMM, verify the CRC */ 177 /* For DDR3 and FBDIMM, verify the CRC */
178 else if (spd_type <= SPDMEM_MEMTYPE_DDR3SDRAM) { 178 else if (spd_type <= SPDMEM_MEMTYPE_DDR3SDRAM) {
179 spd_len = (sc->sc_read)(sc, 0); 179 spd_len = (sc->sc_read)(sc, 0);
180 if (spd_len & SPDMEM_SPDCRC_116) 180 if (spd_len & SPDMEM_SPDCRC_116)
181 spd_crc_cover = 116; 181 spd_crc_cover = 116;
182 else 182 else
183 spd_crc_cover = 125; 183 spd_crc_cover = 125;
184 switch (spd_len & SPDMEM_SPDLEN_MASK) { 184 switch (spd_len & SPDMEM_SPDLEN_MASK) {
185 case SPDMEM_SPDLEN_128: 185 case SPDMEM_SPDLEN_128:
186 spd_len = 128; 186 spd_len = 128;
187 break; 187 break;
188 case SPDMEM_SPDLEN_176: 188 case SPDMEM_SPDLEN_176:
189 spd_len = 176; 189 spd_len = 176;
190 break; 190 break;
191 case SPDMEM_SPDLEN_256: 191 case SPDMEM_SPDLEN_256:
192 spd_len = 256; 192 spd_len = 256;
193 break; 193 break;
194 default: 194 default:
195 return 0; 195 return 0;
196 } 196 }
197 if (spd_crc_cover > spd_len) 197 if (spd_crc_cover > spd_len)
198 return 0; 198 return 0;
199 crc_calc = spdcrc16(sc, spd_crc_cover); 199 crc_calc = spdcrc16(sc, spd_crc_cover);
200 crc_spd = (sc->sc_read)(sc, 127) << 8; 200 crc_spd = (sc->sc_read)(sc, 127) << 8;
201 crc_spd |= (sc->sc_read)(sc, 126); 201 crc_spd |= (sc->sc_read)(sc, 126);
202 if (crc_calc != crc_spd) { 202 if (crc_calc != crc_spd) {
203 aprint_debug("crc16 failed, covers %d bytes, " 203 aprint_debug("crc16 failed, covers %d bytes, "
204 "calc = 0x%04x, spd = 0x%04x\n", 204 "calc = 0x%04x, spd = 0x%04x\n",
205 spd_crc_cover, crc_calc, crc_spd); 205 spd_crc_cover, crc_calc, crc_spd);
206 return 0; 206 return 0;
207 } 207 }
208 return 1; 208 return 1;
209 } 209 }
210 210
211 /* For unrecognized memory types, don't match at all */ 211 /* For unrecognized memory types, don't match at all */
212 return 0; 212 return 0;
213} 213}
214 214
215void 215void
216spdmem_common_attach(struct spdmem_softc *sc, device_t self) 216spdmem_common_attach(struct spdmem_softc *sc, device_t self)
217{ 217{
218 struct spdmem *s = &(sc->sc_spd_data); 218 struct spdmem *s = &(sc->sc_spd_data);
219 const char *type; 219 const char *type;
220 const char *rambus_rev = "Reserved"; 220 const char *rambus_rev = "Reserved";
221 int dimm_size; 221 int dimm_size;
222 int i; 222 unsigned int i, spd_len, spd_size;
223 unsigned int spd_len, spd_size; 
224 const struct sysctlnode *node = NULL; 223 const struct sysctlnode *node = NULL;
225 224
226 /* 225 /*
227 * FBDIMM and DDR3 (and probably all newer) have a different 226 * FBDIMM and DDR3 (and probably all newer) have a different
228 * encoding of the SPD EEPROM used/total sizes 227 * encoding of the SPD EEPROM used/total sizes
229 */ 228 */
230 s->sm_len = (sc->sc_read)(sc, 0); 229 s->sm_len = (sc->sc_read)(sc, 0);
231 s->sm_size = (sc->sc_read)(sc, 1); 230 s->sm_size = (sc->sc_read)(sc, 1);
232 s->sm_type = (sc->sc_read)(sc, 2); 231 s->sm_type = (sc->sc_read)(sc, 2);
233 232
234 if (s->sm_type >= SPDMEM_MEMTYPE_FBDIMM) { 233 if (s->sm_type >= SPDMEM_MEMTYPE_FBDIMM) {
235 spd_size = 64 << (s->sm_len & SPDMEM_SPDSIZE_MASK); 234 spd_size = 64 << (s->sm_len & SPDMEM_SPDSIZE_MASK);
236 switch (s->sm_len & SPDMEM_SPDLEN_MASK) { 235 switch (s->sm_len & SPDMEM_SPDLEN_MASK) {
237 case SPDMEM_SPDLEN_128: 236 case SPDMEM_SPDLEN_128:
238 spd_len = 128; 237 spd_len = 128;
239 break; 238 break;
240 case SPDMEM_SPDLEN_176: 239 case SPDMEM_SPDLEN_176:
241 spd_len = 176; 240 spd_len = 176;
242 break; 241 break;
243 case SPDMEM_SPDLEN_256: 242 case SPDMEM_SPDLEN_256:
244 spd_len = 256; 243 spd_len = 256;
245 break; 244 break;
246 default: 245 default:
247 spd_len = 64; 246 spd_len = 64;
248 break; 247 break;
249 } 248 }
250 } else { 249 } else {
251 spd_size = 1 << s->sm_size; 250 spd_size = 1 << s->sm_size;
252 spd_len = s->sm_len; 251 spd_len = s->sm_len;
253 if (spd_len < 64) 252 if (spd_len < 64)
254 spd_len = 64; 253 spd_len = 64;
255 } 254 }
256 if (spd_len > spd_size) 255 if (spd_len > spd_size)
257 spd_len = spd_size; 256 spd_len = spd_size;
258 if (spd_len > sizeof(struct spdmem)) 257 if (spd_len > sizeof(struct spdmem))
259 spd_len = sizeof(struct spdmem); 258 spd_len = sizeof(struct spdmem);
260 for (i = 3; i < spd_len; i++) 259 for (i = 3; i < spd_len; i++)
261 ((uint8_t *)s)[i] = (sc->sc_read)(sc, i); 260 ((uint8_t *)s)[i] = (sc->sc_read)(sc, i);
262 261
263#ifdef DEBUG 262#ifdef DEBUG
264 for (i = 0; i < spd_len; i += 16) { 263 for (i = 0; i < spd_len; i += 16) {
265 int j, k; 264 unsigned int j, k;
266 aprint_debug("\n"); 265 aprint_debug("\n");
267 aprint_debug_dev(self, "0x%02x:", i); 266 aprint_debug_dev(self, "0x%02x:", i);
268 k = (spd_len > i + 16) ? spd_len : i + 16; 267 k = (spd_len > i + 16) ? spd_len : i + 16;
269 for (j = i; j < k; j++) 268 for (j = i; j < k; j++)
270 aprint_debug(" %02x", ((uint8_t *)s)[j]); 269 aprint_debug(" %02x", ((uint8_t *)s)[j]);
271 } 270 }
272 aprint_debug("\n"); 271 aprint_debug("\n");
273 aprint_debug_dev(self, ""); 272 aprint_debug_dev(self, "");
274#endif 273#endif
275 274
276 /* 275 /*
277 * Setup our sysctl subtree, hw.spdmemN 276 * Setup our sysctl subtree, hw.spdmemN
278 */ 277 */
 278 sc->sc_sysctl_log = NULL;
 279#ifdef _MODULE
 280 sysctl_spdmem_setup(&sc->sc_sysctl_log);
 281#endif
279 if (hw_node != CTL_EOL) 282 if (hw_node != CTL_EOL)
280 sysctl_createv(NULL, 0, NULL, &node, 283 sysctl_createv(&sc->sc_sysctl_log, 0, NULL, &node,
281 0, CTLTYPE_NODE, 284 0, CTLTYPE_NODE,
282 device_xname(self), NULL, NULL, 0, NULL, 0, 285 device_xname(self), NULL, NULL, 0, NULL, 0,
283 CTL_HW, CTL_CREATE, CTL_EOL); 286 CTL_HW, CTL_CREATE, CTL_EOL);
284 if (node != NULL && spd_len != 0) 287 if (node != NULL && spd_len != 0)
285 sysctl_createv(NULL, 0, NULL, NULL, 288 sysctl_createv(&sc->sc_sysctl_log, 0, NULL, NULL,
286 0, 289 0,
287 CTLTYPE_STRUCT, "spd_data", 290 CTLTYPE_STRUCT, "spd_data",
288 SYSCTL_DESCR("raw spd data"), NULL, 291 SYSCTL_DESCR("raw spd data"), NULL,
289 0, s, spd_len, 292 0, s, spd_len,
290 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL); 293 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL);
291 294
292 /* 295 /*
293 * Decode and print key SPD contents 296 * Decode and print key SPD contents
294 */ 297 */
295 if (IS_RAMBUS_TYPE) { 298 if (IS_RAMBUS_TYPE) {
296 if (s->sm_type == SPDMEM_MEMTYPE_RAMBUS) 299 if (s->sm_type == SPDMEM_MEMTYPE_RAMBUS)
297 type = "Rambus"; 300 type = "Rambus";
298 else if (s->sm_type == SPDMEM_MEMTYPE_DIRECTRAMBUS) 301 else if (s->sm_type == SPDMEM_MEMTYPE_DIRECTRAMBUS)
299 type = "Direct Rambus"; 302 type = "Direct Rambus";
300 else 303 else
301 type = "Rambus (unknown)"; 304 type = "Rambus (unknown)";
302 305
303 switch (s->sm_len) { 306 switch (s->sm_len) {
304 case 0: 307 case 0:
305 rambus_rev = "Invalid"; 308 rambus_rev = "Invalid";
306 break; 309 break;
307 case 1: 310 case 1:
308 rambus_rev = "0.7"; 311 rambus_rev = "0.7";
309 break; 312 break;
310 case 2: 313 case 2:
311 rambus_rev = "1.0"; 314 rambus_rev = "1.0";
312 break; 315 break;
313 default: 316 default:
314 rambus_rev = "Reserved"; 317 rambus_rev = "Reserved";
315 break; 318 break;
316 } 319 }
317 } else { 320 } else {
318 if (s->sm_type < __arraycount(spdmem_basic_types)) 321 if (s->sm_type < __arraycount(spdmem_basic_types))
319 type = spdmem_basic_types[s->sm_type]; 322 type = spdmem_basic_types[s->sm_type];
320 else 323 else
321 type = "unknown memory type"; 324 type = "unknown memory type";
322 325
323 if (s->sm_type == SPDMEM_MEMTYPE_EDO && 326 if (s->sm_type == SPDMEM_MEMTYPE_EDO &&
324 s->sm_fpm.fpm_superset == SPDMEM_SUPERSET_EDO_PEM) 327 s->sm_fpm.fpm_superset == SPDMEM_SUPERSET_EDO_PEM)
325 type = spdmem_superset_types[SPDMEM_SUPERSET_EDO_PEM]; 328 type = spdmem_superset_types[SPDMEM_SUPERSET_EDO_PEM];
326 if (s->sm_type == SPDMEM_MEMTYPE_SDRAM && 329 if (s->sm_type == SPDMEM_MEMTYPE_SDRAM &&
327 s->sm_sdr.sdr_superset == SPDMEM_SUPERSET_SDRAM_PEM) 330 s->sm_sdr.sdr_superset == SPDMEM_SUPERSET_SDRAM_PEM)
328 type = spdmem_superset_types[SPDMEM_SUPERSET_SDRAM_PEM]; 331 type = spdmem_superset_types[SPDMEM_SUPERSET_SDRAM_PEM];
329 if (s->sm_type == SPDMEM_MEMTYPE_DDRSDRAM && 332 if (s->sm_type == SPDMEM_MEMTYPE_DDRSDRAM &&
330 s->sm_ddr.ddr_superset == SPDMEM_SUPERSET_DDR_ESDRAM) 333 s->sm_ddr.ddr_superset == SPDMEM_SUPERSET_DDR_ESDRAM)
331 type = 334 type =
332 spdmem_superset_types[SPDMEM_SUPERSET_DDR_ESDRAM]; 335 spdmem_superset_types[SPDMEM_SUPERSET_DDR_ESDRAM];
333 if (s->sm_type == SPDMEM_MEMTYPE_SDRAM && 336 if (s->sm_type == SPDMEM_MEMTYPE_SDRAM &&
334 s->sm_sdr.sdr_superset == SPDMEM_SUPERSET_ESDRAM) { 337 s->sm_sdr.sdr_superset == SPDMEM_SUPERSET_ESDRAM) {
335 type = spdmem_superset_types[SPDMEM_SUPERSET_ESDRAM]; 338 type = spdmem_superset_types[SPDMEM_SUPERSET_ESDRAM];
336 } 339 }
337 } 340 }
338 341
339 aprint_naive("\n"); 342 aprint_naive("\n");
340 aprint_normal("\n"); 343 aprint_normal("\n");
341 aprint_normal_dev(self, "%s", type); 344 aprint_normal_dev(self, "%s", type);
342 strlcpy(sc->sc_type, type, SPDMEM_TYPE_MAXLEN); 345 strlcpy(sc->sc_type, type, SPDMEM_TYPE_MAXLEN);
343 if (node != NULL) 346 if (node != NULL)
344 sysctl_createv(NULL, 0, NULL, NULL, 347 sysctl_createv(&sc->sc_sysctl_log, 0, NULL, NULL,
345 0, 348 0,
346 CTLTYPE_STRING, "mem_type", 349 CTLTYPE_STRING, "mem_type",
347 SYSCTL_DESCR("memory module type"), NULL, 350 SYSCTL_DESCR("memory module type"), NULL,
348 0, sc->sc_type, 0, 351 0, sc->sc_type, 0,
349 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL); 352 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL);
350 353
351 if (IS_RAMBUS_TYPE) { 354 if (IS_RAMBUS_TYPE) {
352 aprint_normal(", SPD Revision %s", rambus_rev); 355 aprint_normal(", SPD Revision %s", rambus_rev);
353 dimm_size = 1 << (s->sm_rdr.rdr_rows + s->sm_rdr.rdr_cols - 13); 356 dimm_size = 1 << (s->sm_rdr.rdr_rows + s->sm_rdr.rdr_cols - 13);
354 if (dimm_size >= 1024) 357 if (dimm_size >= 1024)
355 aprint_normal(", %dGB\n", dimm_size / 1024); 358 aprint_normal(", %dGB\n", dimm_size / 1024);
356 else 359 else
357 aprint_normal(", %dMB\n", dimm_size); 360 aprint_normal(", %dMB\n", dimm_size);
358 361
359 /* No further decode for RAMBUS memory */ 362 /* No further decode for RAMBUS memory */
360 return; 363 return;
361 } 364 }
362 switch (s->sm_type) { 365 switch (s->sm_type) {
363 case SPDMEM_MEMTYPE_EDO: 366 case SPDMEM_MEMTYPE_EDO:
364 case SPDMEM_MEMTYPE_FPM: 367 case SPDMEM_MEMTYPE_FPM:
365 decode_edofpm(node, self, s); 368 decode_edofpm(node, self, s);
366 break; 369 break;
367 case SPDMEM_MEMTYPE_ROM: 370 case SPDMEM_MEMTYPE_ROM:
368 decode_rom(node, self, s); 371 decode_rom(node, self, s);
369 break; 372 break;
370 case SPDMEM_MEMTYPE_SDRAM: 373 case SPDMEM_MEMTYPE_SDRAM:
371 decode_sdram(node, self, s, spd_len); 374 decode_sdram(node, self, s, spd_len);
372 break; 375 break;
373 case SPDMEM_MEMTYPE_DDRSDRAM: 376 case SPDMEM_MEMTYPE_DDRSDRAM:
374 decode_ddr(node, self, s); 377 decode_ddr(node, self, s);
375 break; 378 break;
376 case SPDMEM_MEMTYPE_DDR2SDRAM: 379 case SPDMEM_MEMTYPE_DDR2SDRAM:
377 decode_ddr2(node, self, s); 380 decode_ddr2(node, self, s);
378 break; 381 break;
379 case SPDMEM_MEMTYPE_DDR3SDRAM: 382 case SPDMEM_MEMTYPE_DDR3SDRAM:
380 decode_ddr3(node, self, s); 383 decode_ddr3(node, self, s);
381 break; 384 break;
382 case SPDMEM_MEMTYPE_FBDIMM: 385 case SPDMEM_MEMTYPE_FBDIMM:
383 case SPDMEM_MEMTYPE_FBDIMM_PROBE: 386 case SPDMEM_MEMTYPE_FBDIMM_PROBE:
384 decode_fbdimm(node, self, s); 387 decode_fbdimm(node, self, s);
385 break; 388 break;
386 } 389 }
387} 390}
388 391
 392int
 393spdmem_common_detach(struct spdmem_softc *sc, device_t self)
 394{
 395 sysctl_teardown(&sc->sc_sysctl_log);
 396
 397 return 0;
 398}
 399
389SYSCTL_SETUP(sysctl_spdmem_setup, "sysctl hw.spdmem subtree setup") 400SYSCTL_SETUP(sysctl_spdmem_setup, "sysctl hw.spdmem subtree setup")
390{ 401{
391 const struct sysctlnode *node; 402 const struct sysctlnode *node;
392 403
393 if (sysctl_createv(clog, 0, NULL, &node, 404 if (sysctl_createv(clog, 0, NULL, &node, CTLFLAG_PERMANENT,
394 CTLFLAG_PERMANENT, 405 CTLTYPE_NODE, "hw", NULL, NULL, 0, NULL, 0,
395 CTLTYPE_NODE, "hw", NULL, 406 CTL_HW, CTL_EOL) != 0)
396 NULL, 0, NULL, 0, 
397 CTL_HW, CTL_EOL) != 0) 
398 return; 407 return;
399 408
400 hw_node = node->sysctl_num; 409 hw_node = node->sysctl_num;
401} 410}
402 411
403static void 412static void
404decode_size_speed(const struct sysctlnode *node, int dimm_size, int cycle_time, 413decode_size_speed(device_t self, const struct sysctlnode *node,
405 int d_clk, int bits, bool round, const char *ddr_type_string, 414 int dimm_size, int cycle_time, int d_clk, int bits,
406 int speed) 415 bool round, const char *ddr_type_string, int speed)
407{ 416{
408 int p_clk; 417 int p_clk;
 418 struct spdmem_softc *sc = (struct spdmem_softc *)device_private(self);
409 419
410 if (dimm_size < 1024) 420 if (dimm_size < 1024)
411 aprint_normal("%dMB", dimm_size); 421 aprint_normal("%dMB", dimm_size);
412 else 422 else
413 aprint_normal("%dGB", dimm_size / 1024); 423 aprint_normal("%dGB", dimm_size / 1024);
414 if (node != NULL) 424 if (node != NULL)
415 sysctl_createv(NULL, 0, NULL, NULL, 425 sysctl_createv(&sc->sc_sysctl_log, 0, NULL, NULL,
416 CTLFLAG_IMMEDIATE, 426 CTLFLAG_IMMEDIATE,
417 CTLTYPE_INT, "size", 427 CTLTYPE_INT, "size",
418 SYSCTL_DESCR("module size in MB"), NULL, 428 SYSCTL_DESCR("module size in MB"), NULL,
419 dimm_size, NULL, 0, 429 dimm_size, NULL, 0,
420 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL); 430 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL);
421 431
422 if (cycle_time == 0) { 432 if (cycle_time == 0) {
423 aprint_normal("\n"); 433 aprint_normal("\n");
424 return; 434 return;
425 } 435 }
426 436
427 /* 437 /*
428 * Calculate p_clk first, since for DDR3 we need maximum significance. 438 * Calculate p_clk first, since for DDR3 we need maximum significance.
429 * DDR3 rating is not rounded to a multiple of 100. This results in 439 * DDR3 rating is not rounded to a multiple of 100. This results in
430 * cycle_time of 1.5ns displayed as PC3-10666. 440 * cycle_time of 1.5ns displayed as PC3-10666.
431 * 441 *
432 * For SDRAM, the speed is provided by the caller so we use it. 442 * For SDRAM, the speed is provided by the caller so we use it.
433 */ 443 */
434 d_clk *= 1000 * 1000; 444 d_clk *= 1000 * 1000;
435 if (speed) 445 if (speed)
436 p_clk = speed; 446 p_clk = speed;
437 else 447 else
438 p_clk = (d_clk * bits) / 8 / cycle_time; 448 p_clk = (d_clk * bits) / 8 / cycle_time;
439 d_clk = ((d_clk + cycle_time / 2) ) / cycle_time; 449 d_clk = ((d_clk + cycle_time / 2) ) / cycle_time;
440 if (round) { 450 if (round) {
441 if ((p_clk % 100) >= 50) 451 if ((p_clk % 100) >= 50)
442 p_clk += 50; 452 p_clk += 50;
443 p_clk -= p_clk % 100; 453 p_clk -= p_clk % 100;
444 } 454 }
445 aprint_normal(", %dMHz (%s-%d)\n", 455 aprint_normal(", %dMHz (%s-%d)\n",
446 d_clk, ddr_type_string, p_clk); 456 d_clk, ddr_type_string, p_clk);
447 if (node != NULL) 457 if (node != NULL)
448 sysctl_createv(NULL, 0, NULL, NULL, 458 sysctl_createv(&sc->sc_sysctl_log, 0, NULL, NULL,
449 CTLFLAG_IMMEDIATE, 459 CTLFLAG_IMMEDIATE,
450 CTLTYPE_INT, "speed", 460 CTLTYPE_INT, "speed",
451 SYSCTL_DESCR("memory speed in MHz"), 461 SYSCTL_DESCR("memory speed in MHz"),
452 NULL, d_clk, NULL, 0, 462 NULL, d_clk, NULL, 0,
453 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL); 463 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL);
454} 464}
455 465
456static void 466static void
457decode_voltage_refresh(device_t self, struct spdmem *s) 467decode_voltage_refresh(device_t self, struct spdmem *s)
458{ 468{
459 const char *voltage, *refresh; 469 const char *voltage, *refresh;
460 470
461 if (s->sm_voltage < __arraycount(spdmem_voltage_types)) 471 if (s->sm_voltage < __arraycount(spdmem_voltage_types))
462 voltage = spdmem_voltage_types[s->sm_voltage]; 472 voltage = spdmem_voltage_types[s->sm_voltage];
463 else 473 else
464 voltage = "unknown"; 474 voltage = "unknown";
465 475
466 if (s->sm_refresh < __arraycount(spdmem_refresh_types)) 476 if (s->sm_refresh < __arraycount(spdmem_refresh_types))
467 refresh = spdmem_refresh_types[s->sm_refresh]; 477 refresh = spdmem_refresh_types[s->sm_refresh];
468 else 478 else
469 refresh = "unknown"; 479 refresh = "unknown";
470 480
471 aprint_verbose_dev(self, "voltage %s, refresh time %s%s\n", 481 aprint_verbose_dev(self, "voltage %s, refresh time %s%s\n",
472 voltage, refresh, 482 voltage, refresh,
473 s->sm_selfrefresh?" (self-refreshing)":""); 483 s->sm_selfrefresh?" (self-refreshing)":"");
474} 484}
475 485
476static void 486static void
477decode_edofpm(const struct sysctlnode *node, device_t self, struct spdmem *s) { 487decode_edofpm(const struct sysctlnode *node, device_t self, struct spdmem *s) {
478 aprint_normal("\n"); 488 aprint_normal("\n");
479 aprint_verbose_dev(self, 489 aprint_verbose_dev(self,
480 "%d rows, %d cols, %d banks, %dns tRAC, %dns tCAC\n", 490 "%d rows, %d cols, %d banks, %dns tRAC, %dns tCAC\n",
481 s->sm_fpm.fpm_rows, s->sm_fpm.fpm_cols, s->sm_fpm.fpm_banks, 491 s->sm_fpm.fpm_rows, s->sm_fpm.fpm_cols, s->sm_fpm.fpm_banks,
482 s->sm_fpm.fpm_tRAC, s->sm_fpm.fpm_tCAC); 492 s->sm_fpm.fpm_tRAC, s->sm_fpm.fpm_tCAC);
483} 493}
484 494
485static void 495static void
486decode_rom(const struct sysctlnode *node, device_t self, struct spdmem *s) { 496decode_rom(const struct sysctlnode *node, device_t self, struct spdmem *s) {
487 aprint_normal("\n"); 497 aprint_normal("\n");
488 aprint_verbose_dev(self, "%d rows, %d cols, %d banks\n", 498 aprint_verbose_dev(self, "%d rows, %d cols, %d banks\n",
489 s->sm_rom.rom_rows, s->sm_rom.rom_cols, s->sm_rom.rom_banks); 499 s->sm_rom.rom_rows, s->sm_rom.rom_cols, s->sm_rom.rom_banks);
490} 500}
491 501
492static void 502static void
493decode_sdram(const struct sysctlnode *node, device_t self, struct spdmem *s, 503decode_sdram(const struct sysctlnode *node, device_t self, struct spdmem *s,
494 int spd_len) { 504 int spd_len) {
495 int dimm_size, cycle_time, bits, tAA, i, speed, freq; 505 int dimm_size, cycle_time, bits, tAA, i, speed, freq;
496 506
497 aprint_normal("%s, %s, ", 507 aprint_normal("%s, %s, ",
498 (s->sm_sdr.sdr_mod_attrs & SPDMEM_SDR_MASK_REG)? 508 (s->sm_sdr.sdr_mod_attrs & SPDMEM_SDR_MASK_REG)?
499 " (registered)":"", 509 " (registered)":"",
500 (s->sm_config < __arraycount(spdmem_parity_types))? 510 (s->sm_config < __arraycount(spdmem_parity_types))?
501 spdmem_parity_types[s->sm_config]:"invalid parity"); 511 spdmem_parity_types[s->sm_config]:"invalid parity");
502 512
503 dimm_size = 1 << (s->sm_sdr.sdr_rows + s->sm_sdr.sdr_cols - 17); 513 dimm_size = 1 << (s->sm_sdr.sdr_rows + s->sm_sdr.sdr_cols - 17);
504 dimm_size *= s->sm_sdr.sdr_banks * s->sm_sdr.sdr_banks_per_chip; 514 dimm_size *= s->sm_sdr.sdr_banks * s->sm_sdr.sdr_banks_per_chip;
505 515
506 cycle_time = s->sm_sdr.sdr_cycle_whole * 1000 + 516 cycle_time = s->sm_sdr.sdr_cycle_whole * 1000 +
507 s->sm_sdr.sdr_cycle_tenths * 100; 517 s->sm_sdr.sdr_cycle_tenths * 100;
508 bits = le16toh(s->sm_sdr.sdr_datawidth); 518 bits = le16toh(s->sm_sdr.sdr_datawidth);
509 if (s->sm_config == 1 || s->sm_config == 2) 519 if (s->sm_config == 1 || s->sm_config == 2)
510 bits -= 8; 520 bits -= 8;
511 521
512 /* Calculate speed here - from OpenBSD */ 522 /* Calculate speed here - from OpenBSD */
513 if (spd_len >= 128) 523 if (spd_len >= 128)
514 freq = ((uint8_t *)s)[126]; 524 freq = ((uint8_t *)s)[126];
515 else 525 else
516 freq = 0; 526 freq = 0;
517 switch (freq) { 527 switch (freq) {
518 /* 528 /*
519 * Must check cycle time since some PC-133 DIMMs  529 * Must check cycle time since some PC-133 DIMMs
520 * actually report PC-100 530 * actually report PC-100
521 */ 531 */
522 case 100: 532 case 100:
523 case 133: 533 case 133:
524 if (cycle_time < 8000) 534 if (cycle_time < 8000)
525 speed = 133; 535 speed = 133;
526 else 536 else
527 speed = 100; 537 speed = 100;
528 break; 538 break;
529 case 0x66: /* Legacy DIMMs use _hex_ 66! */ 539 case 0x66: /* Legacy DIMMs use _hex_ 66! */
530 default: 540 default:
531 speed = 66; 541 speed = 66;
532 } 542 }
533 decode_size_speed(node, dimm_size, cycle_time, 1, bits, FALSE, "PC", 543 decode_size_speed(self, node, dimm_size, cycle_time, 1, bits, FALSE,
534 speed); 544 "PC", speed);
535 545
536 aprint_verbose_dev(self, 546 aprint_verbose_dev(self,
537 "%d rows, %d cols, %d banks, %d banks/chip, %d.%dns cycle time\n", 547 "%d rows, %d cols, %d banks, %d banks/chip, %d.%dns cycle time\n",
538 s->sm_sdr.sdr_rows, s->sm_sdr.sdr_cols, s->sm_sdr.sdr_banks, 548 s->sm_sdr.sdr_rows, s->sm_sdr.sdr_cols, s->sm_sdr.sdr_banks,
539 s->sm_sdr.sdr_banks_per_chip, cycle_time/1000, 549 s->sm_sdr.sdr_banks_per_chip, cycle_time/1000,
540 (cycle_time % 1000) / 100); 550 (cycle_time % 1000) / 100);
541 551
542 tAA = 0; 552 tAA = 0;
543 for (i = 0; i < 8; i++) 553 for (i = 0; i < 8; i++)
544 if (s->sm_sdr.sdr_tCAS & (1 << i)) 554 if (s->sm_sdr.sdr_tCAS & (1 << i))
545 tAA = i; 555 tAA = i;
546 tAA++; 556 tAA++;
547 aprint_verbose_dev(self, latency, tAA, s->sm_sdr.sdr_tRCD, 557 aprint_verbose_dev(self, latency, tAA, s->sm_sdr.sdr_tRCD,
548 s->sm_sdr.sdr_tRP, s->sm_sdr.sdr_tRAS); 558 s->sm_sdr.sdr_tRP, s->sm_sdr.sdr_tRAS);
549 559
550 decode_voltage_refresh(self, s); 560 decode_voltage_refresh(self, s);
551} 561}
552 562
553static void 563static void
554decode_ddr(const struct sysctlnode *node, device_t self, struct spdmem *s) { 564decode_ddr(const struct sysctlnode *node, device_t self, struct spdmem *s) {
555 int dimm_size, cycle_time, bits, tAA, i; 565 int dimm_size, cycle_time, bits, tAA, i;
556 566
557 aprint_normal("%s, %s, ", 567 aprint_normal("%s, %s, ",
558 (s->sm_ddr.ddr_mod_attrs & SPDMEM_DDR_MASK_REG)? 568 (s->sm_ddr.ddr_mod_attrs & SPDMEM_DDR_MASK_REG)?
559 " (registered)":"", 569 " (registered)":"",
560 (s->sm_config < __arraycount(spdmem_parity_types))? 570 (s->sm_config < __arraycount(spdmem_parity_types))?
561 spdmem_parity_types[s->sm_config]:"invalid parity"); 571 spdmem_parity_types[s->sm_config]:"invalid parity");
562 572
563 dimm_size = 1 << (s->sm_ddr.ddr_rows + s->sm_ddr.ddr_cols - 17); 573 dimm_size = 1 << (s->sm_ddr.ddr_rows + s->sm_ddr.ddr_cols - 17);
564 dimm_size *= s->sm_ddr.ddr_ranks * s->sm_ddr.ddr_banks_per_chip; 574 dimm_size *= s->sm_ddr.ddr_ranks * s->sm_ddr.ddr_banks_per_chip;
565 575
566 cycle_time = s->sm_ddr.ddr_cycle_whole * 1000 + 576 cycle_time = s->sm_ddr.ddr_cycle_whole * 1000 +
567 spdmem_cycle_frac[s->sm_ddr.ddr_cycle_tenths]; 577 spdmem_cycle_frac[s->sm_ddr.ddr_cycle_tenths];
568 bits = le16toh(s->sm_ddr.ddr_datawidth); 578 bits = le16toh(s->sm_ddr.ddr_datawidth);
569 if (s->sm_config == 1 || s->sm_config == 2) 579 if (s->sm_config == 1 || s->sm_config == 2)
570 bits -= 8; 580 bits -= 8;
571 decode_size_speed(node, dimm_size, cycle_time, 2, bits, TRUE, "PC", 0); 581 decode_size_speed(self, node, dimm_size, cycle_time, 2, bits, TRUE,
 582 "PC", 0);
572 583
573 aprint_verbose_dev(self, 584 aprint_verbose_dev(self,
574 "%d rows, %d cols, %d ranks, %d banks/chip, %d.%dns cycle time\n", 585 "%d rows, %d cols, %d ranks, %d banks/chip, %d.%dns cycle time\n",
575 s->sm_ddr.ddr_rows, s->sm_ddr.ddr_cols, s->sm_ddr.ddr_ranks, 586 s->sm_ddr.ddr_rows, s->sm_ddr.ddr_cols, s->sm_ddr.ddr_ranks,
576 s->sm_ddr.ddr_banks_per_chip, cycle_time/1000, 587 s->sm_ddr.ddr_banks_per_chip, cycle_time/1000,
577 (cycle_time % 1000 + 50) / 100); 588 (cycle_time % 1000 + 50) / 100);
578 589
579 tAA = 0; 590 tAA = 0;
580 for (i = 2; i < 8; i++) 591 for (i = 2; i < 8; i++)
581 if (s->sm_ddr.ddr_tCAS & (1 << i)) 592 if (s->sm_ddr.ddr_tCAS & (1 << i))
582 tAA = i; 593 tAA = i;
583 tAA /= 2; 594 tAA /= 2;
584 595
585#define __DDR_ROUND(scale, field) \ 596#define __DDR_ROUND(scale, field) \
586 ((scale * s->sm_ddr.field + cycle_time - 1) / cycle_time) 597 ((scale * s->sm_ddr.field + cycle_time - 1) / cycle_time)
587 598
588 aprint_verbose_dev(self, latency, tAA, __DDR_ROUND(250, ddr_tRCD), 599 aprint_verbose_dev(self, latency, tAA, __DDR_ROUND(250, ddr_tRCD),
589 __DDR_ROUND(250, ddr_tRP), __DDR_ROUND(1000, ddr_tRAS)); 600 __DDR_ROUND(250, ddr_tRP), __DDR_ROUND(1000, ddr_tRAS));
590 601
591#undef __DDR_ROUND 602#undef __DDR_ROUND
592 603
593 decode_voltage_refresh(self, s); 604 decode_voltage_refresh(self, s);
594} 605}
595 606
596static void 607static void
597decode_ddr2(const struct sysctlnode *node, device_t self, struct spdmem *s) { 608decode_ddr2(const struct sysctlnode *node, device_t self, struct spdmem *s) {
598 int dimm_size, cycle_time, bits, tAA, i; 609 int dimm_size, cycle_time, bits, tAA, i;
599 610
600 aprint_normal("%s, %s, ", 611 aprint_normal("%s, %s, ",
601 (s->sm_ddr2.ddr2_mod_attrs & SPDMEM_DDR2_MASK_REG)? 612 (s->sm_ddr2.ddr2_mod_attrs & SPDMEM_DDR2_MASK_REG)?
602 " (registered)":"", 613 " (registered)":"",
603 (s->sm_config < __arraycount(spdmem_parity_types))? 614 (s->sm_config < __arraycount(spdmem_parity_types))?
604 spdmem_parity_types[s->sm_config]:"invalid parity"); 615 spdmem_parity_types[s->sm_config]:"invalid parity");
605 616
606 dimm_size = 1 << (s->sm_ddr2.ddr2_rows + s->sm_ddr2.ddr2_cols - 17); 617 dimm_size = 1 << (s->sm_ddr2.ddr2_rows + s->sm_ddr2.ddr2_cols - 17);
607 dimm_size *= (s->sm_ddr2.ddr2_ranks + 1) * 618 dimm_size *= (s->sm_ddr2.ddr2_ranks + 1) *
608 s->sm_ddr2.ddr2_banks_per_chip; 619 s->sm_ddr2.ddr2_banks_per_chip;
609 620
610 cycle_time = s->sm_ddr2.ddr2_cycle_whole * 1000 + 621 cycle_time = s->sm_ddr2.ddr2_cycle_whole * 1000 +
611 spdmem_cycle_frac[s->sm_ddr2.ddr2_cycle_frac]; 622 spdmem_cycle_frac[s->sm_ddr2.ddr2_cycle_frac];
612 bits = s->sm_ddr2.ddr2_datawidth; 623 bits = s->sm_ddr2.ddr2_datawidth;
613 if ((s->sm_config & 0x03) != 0) 624 if ((s->sm_config & 0x03) != 0)
614 bits -= 8; 625 bits -= 8;
615 decode_size_speed(node, dimm_size, cycle_time, 2, bits, TRUE, "PC2", 0); 626 decode_size_speed(self, node, dimm_size, cycle_time, 2, bits, TRUE,
 627 "PC2", 0);
616 628
617 aprint_verbose_dev(self, 629 aprint_verbose_dev(self,
618 "%d rows, %d cols, %d ranks, %d banks/chip, %d.%02dns cycle time\n", 630 "%d rows, %d cols, %d ranks, %d banks/chip, %d.%02dns cycle time\n",
619 s->sm_ddr2.ddr2_rows, s->sm_ddr2.ddr2_cols, 631 s->sm_ddr2.ddr2_rows, s->sm_ddr2.ddr2_cols,
620 s->sm_ddr2.ddr2_ranks + 1, s->sm_ddr2.ddr2_banks_per_chip, 632 s->sm_ddr2.ddr2_ranks + 1, s->sm_ddr2.ddr2_banks_per_chip,
621 cycle_time / 1000, (cycle_time % 1000 + 5) /10 ); 633 cycle_time / 1000, (cycle_time % 1000 + 5) /10 );
622 634
623 tAA = 0; 635 tAA = 0;
624 for (i = 2; i < 8; i++) 636 for (i = 2; i < 8; i++)
625 if (s->sm_ddr2.ddr2_tCAS & (1 << i)) 637 if (s->sm_ddr2.ddr2_tCAS & (1 << i))
626 tAA = i; 638 tAA = i;
627 639
628#define __DDR2_ROUND(scale, field) \ 640#define __DDR2_ROUND(scale, field) \
629 ((scale * s->sm_ddr2.field + cycle_time - 1) / cycle_time) 641 ((scale * s->sm_ddr2.field + cycle_time - 1) / cycle_time)
630 642
631 aprint_verbose_dev(self, latency, tAA, __DDR2_ROUND(250, ddr2_tRCD), 643 aprint_verbose_dev(self, latency, tAA, __DDR2_ROUND(250, ddr2_tRCD),
632 __DDR2_ROUND(250, ddr2_tRP), __DDR2_ROUND(1000, ddr2_tRAS)); 644 __DDR2_ROUND(250, ddr2_tRP), __DDR2_ROUND(1000, ddr2_tRAS));
633 645
634#undef __DDR_ROUND 646#undef __DDR_ROUND
635 647
636 decode_voltage_refresh(self, s); 648 decode_voltage_refresh(self, s);
637} 649}
638 650
639static void 651static void
640decode_ddr3(const struct sysctlnode *node, device_t self, struct spdmem *s) { 652decode_ddr3(const struct sysctlnode *node, device_t self, struct spdmem *s) {
641 int dimm_size, cycle_time, bits; 653 int dimm_size, cycle_time, bits;
642 654
643 if (s->sm_ddr3.ddr3_mod_type == 655 if (s->sm_ddr3.ddr3_mod_type ==
644 SPDMEM_DDR3_TYPE_MINI_RDIMM || 656 SPDMEM_DDR3_TYPE_MINI_RDIMM ||
645 s->sm_ddr3.ddr3_mod_type == SPDMEM_DDR3_TYPE_RDIMM) 657 s->sm_ddr3.ddr3_mod_type == SPDMEM_DDR3_TYPE_RDIMM)
646 aprint_normal(" (registered)"); 658 aprint_normal(" (registered)");
647 aprint_normal(", %sECC, %stemp-sensor, ", 659 aprint_normal(", %sECC, %stemp-sensor, ",
648 (s->sm_ddr3.ddr3_hasECC)?"":"no ", 660 (s->sm_ddr3.ddr3_hasECC)?"":"no ",
649 (s->sm_ddr3.ddr3_has_therm_sensor)?"":"no "); 661 (s->sm_ddr3.ddr3_has_therm_sensor)?"":"no ");
650 662
651 /* 663 /*
652 * DDR3 size specification is quite different from others 664 * DDR3 size specification is quite different from others
653 * 665 *
654 * Module capacity is defined as 666 * Module capacity is defined as
655 * Chip_Capacity_in_bits / 8bits-per-byte * 667 * Chip_Capacity_in_bits / 8bits-per-byte *
656 * external_bus_width / internal_bus_width 668 * external_bus_width / internal_bus_width
657 * We further divide by 2**20 to get our answer in MB 669 * We further divide by 2**20 to get our answer in MB
658 */ 670 */
659 dimm_size = (s->sm_ddr3.ddr3_chipsize + 28 - 20) - 3 + 671 dimm_size = (s->sm_ddr3.ddr3_chipsize + 28 - 20) - 3 +
660 (s->sm_ddr3.ddr3_datawidth + 3) - 672 (s->sm_ddr3.ddr3_datawidth + 3) -
661 (s->sm_ddr3.ddr3_chipwidth + 2); 673 (s->sm_ddr3.ddr3_chipwidth + 2);
662 dimm_size = (1 << dimm_size) * (s->sm_ddr3.ddr3_physbanks + 1); 674 dimm_size = (1 << dimm_size) * (s->sm_ddr3.ddr3_physbanks + 1);
663 675
664 cycle_time = (1000 * s->sm_ddr3.ddr3_mtb_dividend +  676 cycle_time = (1000 * s->sm_ddr3.ddr3_mtb_dividend +
665 (s->sm_ddr3.ddr3_mtb_divisor / 2)) / 677 (s->sm_ddr3.ddr3_mtb_divisor / 2)) /
666 s->sm_ddr3.ddr3_mtb_divisor; 678 s->sm_ddr3.ddr3_mtb_divisor;
667 cycle_time *= s->sm_ddr3.ddr3_tCKmin; 679 cycle_time *= s->sm_ddr3.ddr3_tCKmin;
668 bits = 1 << (s->sm_ddr3.ddr3_datawidth + 3); 680 bits = 1 << (s->sm_ddr3.ddr3_datawidth + 3);
669 decode_size_speed(node, dimm_size, cycle_time, 2, bits, FALSE, "PC3", 0); 681 decode_size_speed(self, node, dimm_size, cycle_time, 2, bits, FALSE,
 682 "PC3", 0);
670 683
671 aprint_verbose_dev(self, 684 aprint_verbose_dev(self,
672 "%d rows, %d cols, %d log. banks, %d phys. banks, " 685 "%d rows, %d cols, %d log. banks, %d phys. banks, "
673 "%d.%03dns cycle time\n", 686 "%d.%03dns cycle time\n",
674 s->sm_ddr3.ddr3_rows + 9, s->sm_ddr3.ddr3_cols + 12, 687 s->sm_ddr3.ddr3_rows + 9, s->sm_ddr3.ddr3_cols + 12,
675 1 << (s->sm_ddr3.ddr3_logbanks + 3), 688 1 << (s->sm_ddr3.ddr3_logbanks + 3),
676 s->sm_ddr3.ddr3_physbanks + 1, 689 s->sm_ddr3.ddr3_physbanks + 1,
677 cycle_time/1000, cycle_time % 1000); 690 cycle_time/1000, cycle_time % 1000);
678 691
679#define __DDR3_CYCLES(field) (s->sm_ddr3.field / s->sm_ddr3.ddr3_tCKmin) 692#define __DDR3_CYCLES(field) (s->sm_ddr3.field / s->sm_ddr3.ddr3_tCKmin)
680 693
681 aprint_verbose_dev(self, latency, __DDR3_CYCLES(ddr3_tAAmin), 694 aprint_verbose_dev(self, latency, __DDR3_CYCLES(ddr3_tAAmin),
682 __DDR3_CYCLES(ddr3_tRCDmin), __DDR3_CYCLES(ddr3_tRPmin),  695 __DDR3_CYCLES(ddr3_tRCDmin), __DDR3_CYCLES(ddr3_tRPmin),
683 (s->sm_ddr3.ddr3_tRAS_msb * 256 + s->sm_ddr3.ddr3_tRAS_lsb) / 696 (s->sm_ddr3.ddr3_tRAS_msb * 256 + s->sm_ddr3.ddr3_tRAS_lsb) /
684 s->sm_ddr3.ddr3_tCKmin); 697 s->sm_ddr3.ddr3_tCKmin);
685 698
686#undef __DDR3_CYCLES 699#undef __DDR3_CYCLES
687} 700}
688 701
689static void 702static void
690decode_fbdimm(const struct sysctlnode *node, device_t self, struct spdmem *s) { 703decode_fbdimm(const struct sysctlnode *node, device_t self, struct spdmem *s) {
691 int dimm_size, cycle_time, bits; 704 int dimm_size, cycle_time, bits;
692 705
693 /* 706 /*
694 * FB-DIMM module size calculation is very much like DDR3 707 * FB-DIMM module size calculation is very much like DDR3
695 */ 708 */
696 dimm_size = s->sm_fbd.fbdimm_rows + 12 + 709 dimm_size = s->sm_fbd.fbdimm_rows + 12 +
697 s->sm_fbd.fbdimm_cols + 9 - 20 - 3; 710 s->sm_fbd.fbdimm_cols + 9 - 20 - 3;
698 dimm_size = (1 << dimm_size) * (1 << (s->sm_fbd.fbdimm_banks + 2)); 711 dimm_size = (1 << dimm_size) * (1 << (s->sm_fbd.fbdimm_banks + 2));
699 712
700 cycle_time = (1000 * s->sm_fbd.fbdimm_mtb_dividend + 713 cycle_time = (1000 * s->sm_fbd.fbdimm_mtb_dividend +
701 (s->sm_fbd.fbdimm_mtb_divisor / 2)) / 714 (s->sm_fbd.fbdimm_mtb_divisor / 2)) /
702 s->sm_fbd.fbdimm_mtb_divisor; 715 s->sm_fbd.fbdimm_mtb_divisor;
703 bits = 1 << (s->sm_fbd.fbdimm_dev_width + 2); 716 bits = 1 << (s->sm_fbd.fbdimm_dev_width + 2);
704 decode_size_speed(node, dimm_size, cycle_time, 2, bits, TRUE, "PC2", 0); 717 decode_size_speed(self, node, dimm_size, cycle_time, 2, bits, TRUE,
 718 "PC2", 0);
705 719
706 aprint_verbose_dev(self, 720 aprint_verbose_dev(self,
707 "%d rows, %d cols, %d banks, %d.%02dns cycle time\n", 721 "%d rows, %d cols, %d banks, %d.%02dns cycle time\n",
708 s->sm_fbd.fbdimm_rows, s->sm_fbd.fbdimm_cols, 722 s->sm_fbd.fbdimm_rows, s->sm_fbd.fbdimm_cols,
709 1 << (s->sm_fbd.fbdimm_banks + 2), 723 1 << (s->sm_fbd.fbdimm_banks + 2),
710 cycle_time / 1000, (cycle_time % 1000 + 5) /10 ); 724 cycle_time / 1000, (cycle_time % 1000 + 5) /10 );
711 725
712#define __FBDIMM_CYCLES(field) (s->sm_fbd.field / s->sm_fbd.fbdimm_tCKmin) 726#define __FBDIMM_CYCLES(field) (s->sm_fbd.field / s->sm_fbd.fbdimm_tCKmin)
713 727
714 aprint_verbose_dev(self, latency, __FBDIMM_CYCLES(fbdimm_tAAmin), 728 aprint_verbose_dev(self, latency, __FBDIMM_CYCLES(fbdimm_tAAmin),
715 __FBDIMM_CYCLES(fbdimm_tRCDmin), __FBDIMM_CYCLES(fbdimm_tRPmin),  729 __FBDIMM_CYCLES(fbdimm_tRCDmin), __FBDIMM_CYCLES(fbdimm_tRPmin),
716 (s->sm_fbd.fbdimm_tRAS_msb * 256 + 730 (s->sm_fbd.fbdimm_tRAS_msb * 256 +
717 s->sm_fbd.fbdimm_tRAS_lsb) / 731 s->sm_fbd.fbdimm_tRAS_lsb) /
718 s->sm_fbd.fbdimm_tCKmin); 732 s->sm_fbd.fbdimm_tCKmin);
719 733
720#undef __FBDIMM_CYCLES 734#undef __FBDIMM_CYCLES
721 735
722 decode_voltage_refresh(self, s); 736 decode_voltage_refresh(self, s);
723} 737}

cvs diff -r1.1 -r1.2 src/sys/dev/ic/spdmemvar.h (switch to unified diff)

--- src/sys/dev/ic/spdmemvar.h 2010/03/24 00:31:41 1.1
+++ src/sys/dev/ic/spdmemvar.h 2011/08/01 03:49:52 1.2
@@ -1,525 +1,527 @@ @@ -1,525 +1,527 @@
1/* $NetBSD: spdmemvar.h,v 1.1 2010/03/24 00:31:41 pgoyette Exp $ */ 1/* $NetBSD: spdmemvar.h,v 1.2 2011/08/01 03:49:52 pgoyette Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2007 Paul Goyette 4 * Copyright (c) 2007 Paul Goyette
5 * Copyright (c) 2007 Tobias Nygren 5 * Copyright (c) 2007 Tobias Nygren
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products 16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission. 17 * derived from this software without specific prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * This information is extracted from JEDEC standard SPD4_01 (www.jedec.org) 33 * This information is extracted from JEDEC standard SPD4_01 (www.jedec.org)
34 */ 34 */
35 35
36#if BYTE_ORDER == BIG_ENDIAN 36#if BYTE_ORDER == BIG_ENDIAN
37#define SPD_BITFIELD(a, b, c, d) d; c; b; a 37#define SPD_BITFIELD(a, b, c, d) d; c; b; a
38#else 38#else
39#define SPD_BITFIELD(a, b, c, d) a; b; c; d 39#define SPD_BITFIELD(a, b, c, d) a; b; c; d
40#endif 40#endif
41 41
42struct spdmem_fpm { /* FPM and EDO DIMMS */ 42struct spdmem_fpm { /* FPM and EDO DIMMS */
43 uint8_t fpm_rows; 43 uint8_t fpm_rows;
44 uint8_t fpm_cols; 44 uint8_t fpm_cols;
45 uint8_t fpm_banks; 45 uint8_t fpm_banks;
46 uint16_t fpm_datawidth; /* endian-sensitive */ 46 uint16_t fpm_datawidth; /* endian-sensitive */
47 uint8_t fpm_voltage; 47 uint8_t fpm_voltage;
48 uint8_t fpm_tRAC; 48 uint8_t fpm_tRAC;
49 uint8_t fpm_tCAC; 49 uint8_t fpm_tCAC;
50 uint8_t fpm_config; 50 uint8_t fpm_config;
51 SPD_BITFIELD( \ 51 SPD_BITFIELD( \
52 uint8_t fpm_refresh:7, \ 52 uint8_t fpm_refresh:7, \
53 uint8_t fpm_selfrefresh:1, , \ 53 uint8_t fpm_selfrefresh:1, , \
54 ); 54 );
55 uint8_t fpm_dram_dramwidth; 55 uint8_t fpm_dram_dramwidth;
56 uint8_t fpm_dram_eccwidth; 56 uint8_t fpm_dram_eccwidth;
57 uint8_t fpm_unused2[17]; 57 uint8_t fpm_unused2[17];
58 uint8_t fpm_superset; 58 uint8_t fpm_superset;
59 uint8_t fpm_unused3[30]; 59 uint8_t fpm_unused3[30];
60 uint8_t fpm_cksum; 60 uint8_t fpm_cksum;
61} __packed; 61} __packed;
62 62
63struct spdmem_sdram { /* PC66/PC100/PC133 SDRAM */ 63struct spdmem_sdram { /* PC66/PC100/PC133 SDRAM */
64 SPD_BITFIELD( \ 64 SPD_BITFIELD( \
65 uint8_t sdr_rows:4, \ 65 uint8_t sdr_rows:4, \
66 uint8_t sdr_rows2:4, , \ 66 uint8_t sdr_rows2:4, , \
67 ); 67 );
68 SPD_BITFIELD( \ 68 SPD_BITFIELD( \
69 uint8_t sdr_cols:4, \ 69 uint8_t sdr_cols:4, \
70 uint8_t sdr_cols2:4, , \ 70 uint8_t sdr_cols2:4, , \
71 ); 71 );
72 uint8_t sdr_banks; 72 uint8_t sdr_banks;
73 uint16_t sdr_datawidth; /* endian-sensitive */ 73 uint16_t sdr_datawidth; /* endian-sensitive */
74 uint8_t sdr_voltage; 74 uint8_t sdr_voltage;
75 SPD_BITFIELD( \ 75 SPD_BITFIELD( \
76 uint8_t sdr_cycle_tenths:4, \ 76 uint8_t sdr_cycle_tenths:4, \
77 uint8_t sdr_cycle_whole:4, , \ 77 uint8_t sdr_cycle_whole:4, , \
78 ); 78 );
79 SPD_BITFIELD( 79 SPD_BITFIELD(
80 uint8_t sdr_tAC_tenths:4, \ 80 uint8_t sdr_tAC_tenths:4, \
81 uint8_t sdr_tAC_whole:4, , \ 81 uint8_t sdr_tAC_whole:4, , \
82 ); 82 );
83 uint8_t sdr_config; 83 uint8_t sdr_config;
84 SPD_BITFIELD( \ 84 SPD_BITFIELD( \
85 uint8_t sdr_refresh:7, \ 85 uint8_t sdr_refresh:7, \
86 uint8_t sdr_selfrefresh:1, , \ 86 uint8_t sdr_selfrefresh:1, , \
87 ); 87 );
88 SPD_BITFIELD( \ 88 SPD_BITFIELD( \
89 uint8_t sdr_dramwidth:7, \ 89 uint8_t sdr_dramwidth:7, \
90 uint8_t sdr_dram_asym_bank2:1, ,\ 90 uint8_t sdr_dram_asym_bank2:1, ,\
91 ); 91 );
92 SPD_BITFIELD( \ 92 SPD_BITFIELD( \
93 uint8_t sdr_eccwidth:7, \ 93 uint8_t sdr_eccwidth:7, \
94 uint8_t sdr_ecc_asym_bank2:1, , \ 94 uint8_t sdr_ecc_asym_bank2:1, , \
95 ); 95 );
96 uint8_t sdr_min_clk_delay; 96 uint8_t sdr_min_clk_delay;
97 SPD_BITFIELD( \ 97 SPD_BITFIELD( \
98 uint8_t sdr_burstlengths:4, \ 98 uint8_t sdr_burstlengths:4, \
99 uint8_t sdr_unused1:4, , \ 99 uint8_t sdr_unused1:4, , \
100 ); 100 );
101 uint8_t sdr_banks_per_chip; 101 uint8_t sdr_banks_per_chip;
102 uint8_t sdr_tCAS; 102 uint8_t sdr_tCAS;
103 uint8_t sdr_tCS; 103 uint8_t sdr_tCS;
104 uint8_t sdr_tWE; 104 uint8_t sdr_tWE;
105 uint8_t sdr_mod_attrs; 105 uint8_t sdr_mod_attrs;
106 uint8_t sdr_dev_attrs; 106 uint8_t sdr_dev_attrs;
107 uint8_t sdr_min_cc_1; 107 uint8_t sdr_min_cc_1;
108 uint8_t sdr_max_tAC_1; 108 uint8_t sdr_max_tAC_1;
109 uint8_t sdr_min_cc_2; 109 uint8_t sdr_min_cc_2;
110 uint8_t sdr_max_tAC_2; 110 uint8_t sdr_max_tAC_2;
111 uint8_t sdr_tRP; 111 uint8_t sdr_tRP;
112 uint8_t sdr_tRRD; 112 uint8_t sdr_tRRD;
113 uint8_t sdr_tRCD; 113 uint8_t sdr_tRCD;
114 uint8_t sdr_tRAS; 114 uint8_t sdr_tRAS;
115 uint8_t sdr_module_rank_density; 115 uint8_t sdr_module_rank_density;
116 uint8_t sdr_tIS; 116 uint8_t sdr_tIS;
117#define sdr_superset sdr_tIS 117#define sdr_superset sdr_tIS
118 uint8_t sdr_tIH; 118 uint8_t sdr_tIH;
119 uint8_t sdr_tDS; 119 uint8_t sdr_tDS;
120 uint8_t sdr_tDH; 120 uint8_t sdr_tDH;
121 uint8_t sdr_unused2[5]; 121 uint8_t sdr_unused2[5];
122 uint8_t sdr_tRC; 122 uint8_t sdr_tRC;
123 uint8_t sdr_unused3[18]; 123 uint8_t sdr_unused3[18];
124 uint8_t sdr_esdram; 124 uint8_t sdr_esdram;
125 uint8_t sdr_super_tech; 125 uint8_t sdr_super_tech;
126 uint8_t sdr_spdrev; 126 uint8_t sdr_spdrev;
127 uint8_t sdr_cksum; 127 uint8_t sdr_cksum;
128} __packed; 128} __packed;
129 129
130struct spdmem_rom { 130struct spdmem_rom {
131 uint8_t rom_rows; 131 uint8_t rom_rows;
132 uint8_t rom_cols; 132 uint8_t rom_cols;
133 uint8_t rom_banks; 133 uint8_t rom_banks;
134 uint16_t rom_datawidth; /* endian-sensitive */ 134 uint16_t rom_datawidth; /* endian-sensitive */
135 uint8_t rom_voltage; 135 uint8_t rom_voltage;
136 uint16_t rom_tAA; /* endian-sensitive */ 136 uint16_t rom_tAA; /* endian-sensitive */
137 uint8_t rom_config; 137 uint8_t rom_config;
138 uint8_t rom_unused1; 138 uint8_t rom_unused1;
139 uint8_t rom_tPA; 139 uint8_t rom_tPA;
140 uint8_t rom_tOE; 140 uint8_t rom_tOE;
141 uint16_t rom_tCE; /* endian-sensitive */ 141 uint16_t rom_tCE; /* endian-sensitive */
142 uint8_t rom_burstlength; 142 uint8_t rom_burstlength;
143 uint8_t rom_unused2[14]; 143 uint8_t rom_unused2[14];
144 uint8_t rom_superset[31]; 144 uint8_t rom_superset[31];
145 uint8_t rom_cksum; 145 uint8_t rom_cksum;
146} __packed; 146} __packed;
147 147
148 148
149struct spdmem_ddr { /* Dual Data Rate SDRAM */ 149struct spdmem_ddr { /* Dual Data Rate SDRAM */
150 SPD_BITFIELD( \ 150 SPD_BITFIELD( \
151 uint8_t ddr_rows:4, \ 151 uint8_t ddr_rows:4, \
152 uint8_t ddr_rows2:4, , \ 152 uint8_t ddr_rows2:4, , \
153 ); 153 );
154 SPD_BITFIELD( \ 154 SPD_BITFIELD( \
155 uint8_t ddr_cols:4, \ 155 uint8_t ddr_cols:4, \
156 uint8_t ddr_cols2:4, , \ 156 uint8_t ddr_cols2:4, , \
157 ); 157 );
158 uint8_t ddr_ranks; 158 uint8_t ddr_ranks;
159 uint16_t ddr_datawidth; /* endian-sensitive */ 159 uint16_t ddr_datawidth; /* endian-sensitive */
160 uint8_t ddr_voltage; 160 uint8_t ddr_voltage;
161 SPD_BITFIELD( \ 161 SPD_BITFIELD( \
162 uint8_t ddr_cycle_tenths:4, \ 162 uint8_t ddr_cycle_tenths:4, \
163 uint8_t ddr_cycle_whole:4, , \ 163 uint8_t ddr_cycle_whole:4, , \
164 ); 164 );
165 SPD_BITFIELD( \ 165 SPD_BITFIELD( \
166 uint8_t ddr_tAC_hundredths:4, \ 166 uint8_t ddr_tAC_hundredths:4, \
167 uint8_t ddr_tAC_tenths:4, , \ 167 uint8_t ddr_tAC_tenths:4, , \
168 ); 168 );
169 uint8_t ddr_config; 169 uint8_t ddr_config;
170 SPD_BITFIELD( \ 170 SPD_BITFIELD( \
171 uint8_t ddr_refresh:7, \ 171 uint8_t ddr_refresh:7, \
172 uint8_t ddr_selfrefresh:1, , \ 172 uint8_t ddr_selfrefresh:1, , \
173 ); 173 );
174 SPD_BITFIELD( \ 174 SPD_BITFIELD( \
175 uint8_t ddr_dramwidth:7, \ 175 uint8_t ddr_dramwidth:7, \
176 uint8_t ddr_dram_asym_bank2:1, ,\ 176 uint8_t ddr_dram_asym_bank2:1, ,\
177 ); 177 );
178 SPD_BITFIELD( \ 178 SPD_BITFIELD( \
179 uint8_t ddr_eccwidth:7, \ 179 uint8_t ddr_eccwidth:7, \
180 uint8_t ddr_ecc_asym_bank2:1, , \ 180 uint8_t ddr_ecc_asym_bank2:1, , \
181 ); 181 );
182 uint8_t ddr_min_clk_delay; 182 uint8_t ddr_min_clk_delay;
183 SPD_BITFIELD( \ 183 SPD_BITFIELD( \
184 uint8_t ddr_burstlengths:4, \ 184 uint8_t ddr_burstlengths:4, \
185 uint8_t ddr_unused1:4, , \ 185 uint8_t ddr_unused1:4, , \
186 ); 186 );
187 uint8_t ddr_banks_per_chip; 187 uint8_t ddr_banks_per_chip;
188 uint8_t ddr_tCAS; 188 uint8_t ddr_tCAS;
189 uint8_t ddr_tCS; 189 uint8_t ddr_tCS;
190 uint8_t ddr_tWE; 190 uint8_t ddr_tWE;
191 uint8_t ddr_mod_attrs; 191 uint8_t ddr_mod_attrs;
192 uint8_t ddr_dev_attrs; 192 uint8_t ddr_dev_attrs;
193 uint8_t ddr_min_cc_05; 193 uint8_t ddr_min_cc_05;
194 uint8_t ddr_max_tAC_05; 194 uint8_t ddr_max_tAC_05;
195 uint8_t ddr_min_cc_1; 195 uint8_t ddr_min_cc_1;
196 uint8_t ddr_max_tAC_1; 196 uint8_t ddr_max_tAC_1;
197 uint8_t ddr_tRP; 197 uint8_t ddr_tRP;
198 uint8_t ddr_tRRD; 198 uint8_t ddr_tRRD;
199 uint8_t ddr_tRCD; 199 uint8_t ddr_tRCD;
200 uint8_t ddr_tRAS; 200 uint8_t ddr_tRAS;
201 uint8_t ddr_module_rank_density; 201 uint8_t ddr_module_rank_density;
202 uint8_t ddr_tIS; 202 uint8_t ddr_tIS;
203#define ddr_superset ddr_tIS 203#define ddr_superset ddr_tIS
204 uint8_t ddr_tIH; 204 uint8_t ddr_tIH;
205 uint8_t ddr_tDS; 205 uint8_t ddr_tDS;
206 uint8_t ddr_tDH; 206 uint8_t ddr_tDH;
207 uint8_t ddr_unused2[5]; 207 uint8_t ddr_unused2[5];
208 uint8_t ddr_tRC; 208 uint8_t ddr_tRC;
209 uint8_t ddr_tRFC; 209 uint8_t ddr_tRFC;
210 uint8_t ddr_tCK; 210 uint8_t ddr_tCK;
211 uint8_t ddr_tDQSQ; 211 uint8_t ddr_tDQSQ;
212 uint8_t ddr_tQHS; 212 uint8_t ddr_tQHS;
213 uint8_t ddr_unused3; 213 uint8_t ddr_unused3;
214 uint8_t ddr_height; 214 uint8_t ddr_height;
215 uint8_t ddr_unused4[15]; 215 uint8_t ddr_unused4[15];
216 uint8_t ddr_cksum; 216 uint8_t ddr_cksum;
217} __packed; 217} __packed;
218 218
219struct spdmem_ddr2 { /* Dual Data Rate 2 SDRAM */ 219struct spdmem_ddr2 { /* Dual Data Rate 2 SDRAM */
220 SPD_BITFIELD( \ 220 SPD_BITFIELD( \
221 uint8_t ddr2_rows:5, \ 221 uint8_t ddr2_rows:5, \
222 uint8_t ddr2_unused1:3, , \ 222 uint8_t ddr2_unused1:3, , \
223 ); 223 );
224 SPD_BITFIELD( \ 224 SPD_BITFIELD( \
225 uint8_t ddr2_cols:4, \ 225 uint8_t ddr2_cols:4, \
226 uint8_t ddr2_unused2:4, , \ 226 uint8_t ddr2_unused2:4, , \
227 ); 227 );
228 SPD_BITFIELD( \ 228 SPD_BITFIELD( \
229 uint8_t ddr2_ranks:3, 229 uint8_t ddr2_ranks:3,
230 uint8_t ddr2_cardoncard:1, \ 230 uint8_t ddr2_cardoncard:1, \
231 uint8_t ddr2_package:1, \ 231 uint8_t ddr2_package:1, \
232 uint8_t ddr2_height:3 \ 232 uint8_t ddr2_height:3 \
233 ); 233 );
234 uint8_t ddr2_datawidth; 234 uint8_t ddr2_datawidth;
235 uint8_t ddr2_unused3; 235 uint8_t ddr2_unused3;
236 uint8_t ddr2_voltage; 236 uint8_t ddr2_voltage;
237 SPD_BITFIELD( \ 237 SPD_BITFIELD( \
238 uint8_t ddr2_cycle_frac:4, \ 238 uint8_t ddr2_cycle_frac:4, \
239 uint8_t ddr2_cycle_whole:4, , \ 239 uint8_t ddr2_cycle_whole:4, , \
240 ); 240 );
241 SPD_BITFIELD( \ 241 SPD_BITFIELD( \
242 uint8_t ddr2_tAC_hundredths:4, \ 242 uint8_t ddr2_tAC_hundredths:4, \
243 uint8_t ddr2_tAC_tenths:4, , \ 243 uint8_t ddr2_tAC_tenths:4, , \
244 ); 244 );
245 uint8_t ddr2_config; 245 uint8_t ddr2_config;
246 SPD_BITFIELD( \ 246 SPD_BITFIELD( \
247 uint8_t ddr2_refresh:7, \ 247 uint8_t ddr2_refresh:7, \
248 uint8_t ddr2_selfrefresh:1, , \ 248 uint8_t ddr2_selfrefresh:1, , \
249 ); 249 );
250 uint8_t ddr2_dramwidth; 250 uint8_t ddr2_dramwidth;
251 uint8_t ddr2_eccwidth; 251 uint8_t ddr2_eccwidth;
252 uint8_t ddr2_unused4; 252 uint8_t ddr2_unused4;
253 SPD_BITFIELD( \ 253 SPD_BITFIELD( \
254 uint8_t ddr2_burstlengths:4, \ 254 uint8_t ddr2_burstlengths:4, \
255 uint8_t ddr2_unused5:4, , \ 255 uint8_t ddr2_unused5:4, , \
256 ); 256 );
257 uint8_t ddr2_banks_per_chip; 257 uint8_t ddr2_banks_per_chip;
258 uint8_t ddr2_tCAS; 258 uint8_t ddr2_tCAS;
259 uint8_t ddr2_mechanical; 259 uint8_t ddr2_mechanical;
260 uint8_t ddr2_dimm_type; 260 uint8_t ddr2_dimm_type;
261 uint8_t ddr2_mod_attrs; 261 uint8_t ddr2_mod_attrs;
262 uint8_t ddr2_dev_attrs; 262 uint8_t ddr2_dev_attrs;
263 uint8_t ddr2_min_cc_1; 263 uint8_t ddr2_min_cc_1;
264 uint8_t ddr2_max_tAC_1; 264 uint8_t ddr2_max_tAC_1;
265 uint8_t ddr2_min_cc_2; 265 uint8_t ddr2_min_cc_2;
266 uint8_t ddr2_max_tAC_2; 266 uint8_t ddr2_max_tAC_2;
267 uint8_t ddr2_tRP; 267 uint8_t ddr2_tRP;
268 uint8_t ddr2_tRRD; 268 uint8_t ddr2_tRRD;
269 uint8_t ddr2_tRCD; 269 uint8_t ddr2_tRCD;
270 uint8_t ddr2_tRAS; 270 uint8_t ddr2_tRAS;
271 uint8_t ddr2_module_rank_density; 271 uint8_t ddr2_module_rank_density;
272 uint8_t ddr2_tIS; 272 uint8_t ddr2_tIS;
273 uint8_t ddr2_tIH; 273 uint8_t ddr2_tIH;
274 uint8_t ddr2_tDS; 274 uint8_t ddr2_tDS;
275 uint8_t ddr2_tDH; 275 uint8_t ddr2_tDH;
276 uint8_t ddr2_tWR; 276 uint8_t ddr2_tWR;
277 uint8_t ddr2_tWTR; 277 uint8_t ddr2_tWTR;
278 uint8_t ddr2_tRTP; 278 uint8_t ddr2_tRTP;
279 uint8_t ddr2_probe; 279 uint8_t ddr2_probe;
280 uint8_t ddr2_extensions; 280 uint8_t ddr2_extensions;
281 uint8_t ddr2_tRC; 281 uint8_t ddr2_tRC;
282 uint8_t ddr2_tRFC; 282 uint8_t ddr2_tRFC;
283 uint8_t ddr2_tCK; 283 uint8_t ddr2_tCK;
284 uint8_t ddr2_tDQSQ; 284 uint8_t ddr2_tDQSQ;
285 uint8_t ddr2_tQHS; 285 uint8_t ddr2_tQHS;
286 uint8_t ddr2_pll_relock; 286 uint8_t ddr2_pll_relock;
287 uint8_t ddr2_Tcasemax; 287 uint8_t ddr2_Tcasemax;
288 uint8_t ddr2_Psi_TA_DRAM; 288 uint8_t ddr2_Psi_TA_DRAM;
289 uint8_t ddr2_dt0; 289 uint8_t ddr2_dt0;
290 uint8_t ddr2_dt2NQ; 290 uint8_t ddr2_dt2NQ;
291 uint8_t ddr2_dr2P; 291 uint8_t ddr2_dr2P;
292 uint8_t ddr2_dt3N; 292 uint8_t ddr2_dt3N;
293 uint8_t ddr2_dt3Pfast; 293 uint8_t ddr2_dt3Pfast;
294 uint8_t ddr2_dt3Pslow; 294 uint8_t ddr2_dt3Pslow;
295 uint8_t ddr2_dt4R_4R4W_mode; 295 uint8_t ddr2_dt4R_4R4W_mode;
296 uint8_t ddr2_dt5B; 296 uint8_t ddr2_dt5B;
297 uint8_t ddr2_dt7; 297 uint8_t ddr2_dt7;
298 uint8_t ddr2_Psi_TA_PLL; 298 uint8_t ddr2_Psi_TA_PLL;
299 uint8_t ddr2_Psi_TA_Reg; 299 uint8_t ddr2_Psi_TA_Reg;
300 uint8_t ddr2_dt_PLL_Active; 300 uint8_t ddr2_dt_PLL_Active;
301 uint8_t ddr2_dt_Reg_Active; 301 uint8_t ddr2_dt_Reg_Active;
302 uint8_t ddr2_spdrev; 302 uint8_t ddr2_spdrev;
303 uint8_t ddr2_cksum; 303 uint8_t ddr2_cksum;
304} __packed; 304} __packed;
305 305
306struct spdmem_fbdimm { /* Fully-buffered DIMM */ 306struct spdmem_fbdimm { /* Fully-buffered DIMM */
307 SPD_BITFIELD( \ 307 SPD_BITFIELD( \
308 uint8_t fbdimm_ps1_voltage:4, \ 308 uint8_t fbdimm_ps1_voltage:4, \
309 uint8_t fbdimm_ps2_voltage:4, , \ 309 uint8_t fbdimm_ps2_voltage:4, , \
310 ); 310 );
311 SPD_BITFIELD( \ 311 SPD_BITFIELD( \
312 uint8_t fbdimm_banks:2, \ 312 uint8_t fbdimm_banks:2, \
313 uint8_t fbdimm_cols:3, \ 313 uint8_t fbdimm_cols:3, \
314 uint8_t fbdimm_rows:3, \ 314 uint8_t fbdimm_rows:3, \
315 ); 315 );
316 SPD_BITFIELD( \ 316 SPD_BITFIELD( \
317 uint8_t fbdimm_thick:3, \ 317 uint8_t fbdimm_thick:3, \
318 uint8_t fbdimm_height:3, \ 318 uint8_t fbdimm_height:3, \
319 uint8_t fbdimm_unused1:2, \ 319 uint8_t fbdimm_unused1:2, \
320 ); 320 );
321 uint8_t fbdimm_mod_type; 321 uint8_t fbdimm_mod_type;
322 SPD_BITFIELD( \ 322 SPD_BITFIELD( \
323 uint8_t fbdimm_dev_width:3, \ 323 uint8_t fbdimm_dev_width:3, \
324 uint8_t fbdimm_ranks:3, \ 324 uint8_t fbdimm_ranks:3, \
325 uint8_t fbdimm_unused2:2, \ 325 uint8_t fbdimm_unused2:2, \
326 ); 326 );
327 SPD_BITFIELD( \ 327 SPD_BITFIELD( \
328 uint8_t fbdimm_ftb_divisor:4, \ 328 uint8_t fbdimm_ftb_divisor:4, \
329 uint8_t fbdimm_ftp_dividend:4, ,\ 329 uint8_t fbdimm_ftp_dividend:4, ,\
330 ); 330 );
331 uint8_t fbdimm_mtb_dividend; 331 uint8_t fbdimm_mtb_dividend;
332 uint8_t fbdimm_mtb_divisor; 332 uint8_t fbdimm_mtb_divisor;
333 uint8_t fbdimm_tCKmin; 333 uint8_t fbdimm_tCKmin;
334 uint8_t fbdimm_tCKmax; 334 uint8_t fbdimm_tCKmax;
335 uint8_t fbdimm_tCAS; 335 uint8_t fbdimm_tCAS;
336 uint8_t fbdimm_tAAmin; 336 uint8_t fbdimm_tAAmin;
337 SPD_BITFIELD( \ 337 SPD_BITFIELD( \
338 uint8_t fbdimm_tWR_min:4, \ 338 uint8_t fbdimm_tWR_min:4, \
339 uint8_t fbdimm_WR_range:4, , \ 339 uint8_t fbdimm_WR_range:4, , \
340 ); 340 );
341 uint8_t fbdimm_tWR; 341 uint8_t fbdimm_tWR;
342 SPD_BITFIELD( \ 342 SPD_BITFIELD( \
343 uint8_t fbdimm_tWL_min:4, \ 343 uint8_t fbdimm_tWL_min:4, \
344 uint8_t fbdimm_tWL_range:4, , \ 344 uint8_t fbdimm_tWL_range:4, , \
345 ); 345 );
346 SPD_BITFIELD( \ 346 SPD_BITFIELD( \
347 uint8_t fbdimm_tAL_min:4, \ 347 uint8_t fbdimm_tAL_min:4, \
348 uint8_t fbdimm_tAL_range:4, , \ 348 uint8_t fbdimm_tAL_range:4, , \
349 ); 349 );
350 uint8_t fbdimm_tRCDmin; 350 uint8_t fbdimm_tRCDmin;
351 uint8_t fbdimm_tRRDmin; 351 uint8_t fbdimm_tRRDmin;
352 uint8_t fbdimm_tRPmin; 352 uint8_t fbdimm_tRPmin;
353 SPD_BITFIELD( \ 353 SPD_BITFIELD( \
354 uint8_t fbdimm_tRAS_msb:4, \ 354 uint8_t fbdimm_tRAS_msb:4, \
355 uint8_t fbdimm_tRC_msb:4, , \ 355 uint8_t fbdimm_tRC_msb:4, , \
356 ); 356 );
357 uint8_t fbdimm_tRAS_lsb; 357 uint8_t fbdimm_tRAS_lsb;
358 uint8_t fbdimm_tRC_lsb; 358 uint8_t fbdimm_tRC_lsb;
359 uint16_t fbdimm_tRFC; /* endian-sensitive */ 359 uint16_t fbdimm_tRFC; /* endian-sensitive */
360 uint8_t fbdimm_tWTR; 360 uint8_t fbdimm_tWTR;
361 uint8_t fbdimm_tRTP; 361 uint8_t fbdimm_tRTP;
362 SPD_BITFIELD( \ 362 SPD_BITFIELD( \
363 uint8_t fbdimm_burst_4:1, \ 363 uint8_t fbdimm_burst_4:1, \
364 uint8_t fbdimm_burst_8:1, \ 364 uint8_t fbdimm_burst_8:1, \
365 uint8_t fbdimm_unused3:6, \ 365 uint8_t fbdimm_unused3:6, \
366 ); 366 );
367 uint8_t fbdimm_terms; 367 uint8_t fbdimm_terms;
368 uint8_t fbdimm_drivers; 368 uint8_t fbdimm_drivers;
369 uint8_t fbdimm_tREFI; 369 uint8_t fbdimm_tREFI;
370 uint8_t fbdimm_Tcasemax; 370 uint8_t fbdimm_Tcasemax;
371 uint8_t fbdimm_Psi_TA_SDRAM; 371 uint8_t fbdimm_Psi_TA_SDRAM;
372 uint8_t fbdimm_DT0; 372 uint8_t fbdimm_DT0;
373 uint8_t fbdimm_DT2N_DT2Q; 373 uint8_t fbdimm_DT2N_DT2Q;
374 uint8_t fbdimm_DT2P; 374 uint8_t fbdimm_DT2P;
375 uint8_t fbdimm_DT3N; 375 uint8_t fbdimm_DT3N;
376 uint8_t fbdimm_DT4R_DT4R4W; 376 uint8_t fbdimm_DT4R_DT4R4W;
377 uint8_t fbdimm_DT5B; 377 uint8_t fbdimm_DT5B;
378 uint8_t fbdimm_DT7; 378 uint8_t fbdimm_DT7;
379 uint8_t fbdimm_unused4[84]; 379 uint8_t fbdimm_unused4[84];
380 uint16_t fbdimm_crc; 380 uint16_t fbdimm_crc;
381} __packed; 381} __packed;
382 382
383struct spdmem_rambus { /* Direct Rambus DRAM */ 383struct spdmem_rambus { /* Direct Rambus DRAM */
384 SPD_BITFIELD( \ 384 SPD_BITFIELD( \
385 uint8_t rdr_rows:4, \ 385 uint8_t rdr_rows:4, \
386 uint8_t rdr_cols:4, , \ 386 uint8_t rdr_cols:4, , \
387 ); 387 );
388} __packed; 388} __packed;
389 389
390struct spdmem_ddr3 { /* Dual Data Rate 3 SDRAM */ 390struct spdmem_ddr3 { /* Dual Data Rate 3 SDRAM */
391 uint8_t ddr3_mod_type; 391 uint8_t ddr3_mod_type;
392 SPD_BITFIELD( \ 392 SPD_BITFIELD( \
393 /* chipsize is offset by 28: 0 = 256M, 1 = 512M, ... */ \ 393 /* chipsize is offset by 28: 0 = 256M, 1 = 512M, ... */ \
394 uint8_t ddr3_chipsize:4, \ 394 uint8_t ddr3_chipsize:4, \
395 /* logbanks is offset by 3 */ \ 395 /* logbanks is offset by 3 */ \
396 uint8_t ddr3_logbanks:3, \ 396 uint8_t ddr3_logbanks:3, \
397 uint8_t ddr3_unused1:1, \ 397 uint8_t ddr3_unused1:1, \
398 ); 398 );
399 /* cols is offset by 9, rows offset by 12 */ 399 /* cols is offset by 9, rows offset by 12 */
400 SPD_BITFIELD( \ 400 SPD_BITFIELD( \
401 uint8_t ddr3_cols:3, \ 401 uint8_t ddr3_cols:3, \
402 uint8_t ddr3_rows:5, , \ 402 uint8_t ddr3_rows:5, , \
403 ); 403 );
404 SPD_BITFIELD( \ 404 SPD_BITFIELD( \
405 uint8_t ddr3_NOT15V:1, \ 405 uint8_t ddr3_NOT15V:1, \
406 uint8_t ddr3_135V:1, \ 406 uint8_t ddr3_135V:1, \
407 uint8_t ddr3_12XV:1, \ 407 uint8_t ddr3_12XV:1, \
408 uint8_t ddr3_unused2:5 \ 408 uint8_t ddr3_unused2:5 \
409 ); 409 );
410 /* chipwidth in bits offset by 2: 0 = X4, 1 = X8, 2 = X16 */ 410 /* chipwidth in bits offset by 2: 0 = X4, 1 = X8, 2 = X16 */
411 /* physbanks is offset by 1 */ 411 /* physbanks is offset by 1 */
412 SPD_BITFIELD( \ 412 SPD_BITFIELD( \
413 uint8_t ddr3_chipwidth:3, \ 413 uint8_t ddr3_chipwidth:3, \
414 uint8_t ddr3_physbanks:5, , \ 414 uint8_t ddr3_physbanks:5, , \
415 ); 415 );
416 /* datawidth in bits offset by 3: 1 = 16b, 2 = 32b, 3 = 64b */ 416 /* datawidth in bits offset by 3: 1 = 16b, 2 = 32b, 3 = 64b */
417 SPD_BITFIELD( \ 417 SPD_BITFIELD( \
418 uint8_t ddr3_datawidth:3, \ 418 uint8_t ddr3_datawidth:3, \
419 uint8_t ddr3_hasECC:2, \ 419 uint8_t ddr3_hasECC:2, \
420 uint8_t ddr3_unused2a:3 , \ 420 uint8_t ddr3_unused2a:3 , \
421 ); 421 );
422 /* Fine time base, in pico-seconds */ 422 /* Fine time base, in pico-seconds */
423 SPD_BITFIELD( \ 423 SPD_BITFIELD( \
424 uint8_t ddr3_ftb_divisor:4, \ 424 uint8_t ddr3_ftb_divisor:4, \
425 uint8_t ddr3_ftb_dividend:4, , \ 425 uint8_t ddr3_ftb_dividend:4, , \
426 ); 426 );
427 uint8_t ddr3_mtb_dividend; /* 0x0108 = 0.1250ns */ 427 uint8_t ddr3_mtb_dividend; /* 0x0108 = 0.1250ns */
428 uint8_t ddr3_mtb_divisor; /* 0x010f = 0.0625ns */ 428 uint8_t ddr3_mtb_divisor; /* 0x010f = 0.0625ns */
429 uint8_t ddr3_tCKmin; /* in terms of mtb */ 429 uint8_t ddr3_tCKmin; /* in terms of mtb */
430 uint8_t ddr3_unused3; 430 uint8_t ddr3_unused3;
431 uint16_t ddr3_CAS_sup; /* Bit 0 ==> CAS 4 cycles */ 431 uint16_t ddr3_CAS_sup; /* Bit 0 ==> CAS 4 cycles */
432 uint8_t ddr3_tAAmin; /* in terms of mtb */ 432 uint8_t ddr3_tAAmin; /* in terms of mtb */
433 uint8_t ddr3_tWRmin; 433 uint8_t ddr3_tWRmin;
434 uint8_t ddr3_tRCDmin; 434 uint8_t ddr3_tRCDmin;
435 uint8_t ddr3_tRRDmin; 435 uint8_t ddr3_tRRDmin;
436 uint8_t ddr3_tRPmin; 436 uint8_t ddr3_tRPmin;
437 SPD_BITFIELD( \ 437 SPD_BITFIELD( \
438 uint8_t ddr3_tRAS_msb:4, \ 438 uint8_t ddr3_tRAS_msb:4, \
439 uint8_t ddr3_tRC_msb:4, , \ 439 uint8_t ddr3_tRC_msb:4, , \
440 ); 440 );
441 uint8_t ddr3_tRAS_lsb; 441 uint8_t ddr3_tRAS_lsb;
442 uint8_t ddr3_tRC_lsb; 442 uint8_t ddr3_tRC_lsb;
443 uint8_t ddr3_tRFCmin_lsb; 443 uint8_t ddr3_tRFCmin_lsb;
444 uint8_t ddr3_tRFCmin_msb; 444 uint8_t ddr3_tRFCmin_msb;
445 uint8_t ddr3_tWTRmin; 445 uint8_t ddr3_tWTRmin;
446 uint8_t ddr3_tRTPmin; 446 uint8_t ddr3_tRTPmin;
447 SPD_BITFIELD( \ 447 SPD_BITFIELD( \
448 uint8_t ddr3_tFAW_msb:4, , , \ 448 uint8_t ddr3_tFAW_msb:4, , , \
449 ); 449 );
450 uint8_t ddr3_tFAW_lsb; 450 uint8_t ddr3_tFAW_lsb;
451 uint8_t ddr3_output_drvrs; 451 uint8_t ddr3_output_drvrs;
452 SPD_BITFIELD( \ 452 SPD_BITFIELD( \
453 uint8_t ddr3_ext_temp_range:1, \ 453 uint8_t ddr3_ext_temp_range:1, \
454 uint8_t ddr3_ext_temp_2x_refresh:1, \ 454 uint8_t ddr3_ext_temp_2x_refresh:1, \
455 uint8_t ddr3_asr_refresh:1, \ 455 uint8_t ddr3_asr_refresh:1, \
456 /* Bit 4 indicates on-die thermal sensor */ 456 /* Bit 4 indicates on-die thermal sensor */
457 /* Bit 7 indicates Partial-Array Self-Refresh (PASR) */ 457 /* Bit 7 indicates Partial-Array Self-Refresh (PASR) */
458 uint8_t ddr3_unused7:5 \ 458 uint8_t ddr3_unused7:5 \
459 ); 459 );
460 SPD_BITFIELD( \ 460 SPD_BITFIELD( \
461 uint8_t ddr3_therm_sensor_acc:7,\ 461 uint8_t ddr3_therm_sensor_acc:7,\
462 uint8_t ddr3_has_therm_sensor:1, , \ 462 uint8_t ddr3_has_therm_sensor:1, , \
463 ); 463 );
464 SPD_BITFIELD( \ 464 SPD_BITFIELD( \
465 uint8_t ddr3_non_std_devtype:7, \ 465 uint8_t ddr3_non_std_devtype:7, \
466 uint8_t ddr3_std_device:1, , \ 466 uint8_t ddr3_std_device:1, , \
467 ); 467 );
468 uint8_t ddr3_unused4[26]; 468 uint8_t ddr3_unused4[26];
469 uint8_t ddr3_mod_height; 469 uint8_t ddr3_mod_height;
470 uint8_t ddr3_mod_thickness; 470 uint8_t ddr3_mod_thickness;
471 uint8_t ddr3_ref_card; 471 uint8_t ddr3_ref_card;
472 uint8_t ddr3_mapping; 472 uint8_t ddr3_mapping;
473 uint8_t ddr3_unused5[53]; 473 uint8_t ddr3_unused5[53];
474 uint8_t ddr3_mfgID_lsb; 474 uint8_t ddr3_mfgID_lsb;
475 uint8_t ddr3_mfgID_msb; 475 uint8_t ddr3_mfgID_msb;
476 uint8_t ddr3_mfgloc; 476 uint8_t ddr3_mfgloc;
477 uint8_t ddr3_mfg_year; 477 uint8_t ddr3_mfg_year;
478 uint8_t ddr3_mfg_week; 478 uint8_t ddr3_mfg_week;
479 uint8_t ddr3_serial[4]; 479 uint8_t ddr3_serial[4];
480 uint16_t ddr3_crc; 480 uint16_t ddr3_crc;
481} __packed; 481} __packed;
482 482
483struct spdmem { 483struct spdmem {
484 uint8_t sm_len; 484 uint8_t sm_len;
485 uint8_t sm_size; 485 uint8_t sm_size;
486 uint8_t sm_type; 486 uint8_t sm_type;
487 union { 487 union {
488 struct spdmem_fbdimm u1_fbd; 488 struct spdmem_fbdimm u1_fbd;
489 struct spdmem_fpm u1_fpm; 489 struct spdmem_fpm u1_fpm;
490 struct spdmem_ddr u1_ddr; 490 struct spdmem_ddr u1_ddr;
491 struct spdmem_ddr2 u1_ddr2; 491 struct spdmem_ddr2 u1_ddr2;
492 struct spdmem_sdram u1_sdr; 492 struct spdmem_sdram u1_sdr;
493 struct spdmem_rambus u1_rdr; 493 struct spdmem_rambus u1_rdr;
494 struct spdmem_rom u1_rom; 494 struct spdmem_rom u1_rom;
495 struct spdmem_ddr3 u1_ddr3; 495 struct spdmem_ddr3 u1_ddr3;
496 } sm_u1; 496 } sm_u1;
497 uint8_t sm_extension[128]; 497 uint8_t sm_extension[128];
498} __packed; 498} __packed;
499#define sm_fbd sm_u1.u1_fbd 499#define sm_fbd sm_u1.u1_fbd
500#define sm_fpm sm_u1.u1_fpm 500#define sm_fpm sm_u1.u1_fpm
501#define sm_ddr sm_u1.u1_ddr 501#define sm_ddr sm_u1.u1_ddr
502#define sm_ddr2 sm_u1.u1_ddr2 502#define sm_ddr2 sm_u1.u1_ddr2
503#define sm_rdr sm_u1.u1_rdr 503#define sm_rdr sm_u1.u1_rdr
504#define sm_rom sm_u1.u1_rom 504#define sm_rom sm_u1.u1_rom
505#define sm_ddr3 sm_u1.u1_ddr3 505#define sm_ddr3 sm_u1.u1_ddr3
506#define sm_sdr sm_u1.u1_sdr 506#define sm_sdr sm_u1.u1_sdr
507 507
508/* some fields are in the same place for all memory types */ 508/* some fields are in the same place for all memory types */
509 509
510#define sm_cksum sm_fpm.fpm_cksum 510#define sm_cksum sm_fpm.fpm_cksum
511#define sm_config sm_fpm.fpm_config 511#define sm_config sm_fpm.fpm_config
512#define sm_voltage sm_fpm.fpm_voltage 512#define sm_voltage sm_fpm.fpm_voltage
513#define sm_refresh sm_fpm.fpm_refresh 513#define sm_refresh sm_fpm.fpm_refresh
514#define sm_selfrefresh sm_fpm.fpm_selfrefresh 514#define sm_selfrefresh sm_fpm.fpm_selfrefresh
515 515
516#define SPDMEM_TYPE_MAXLEN 16 516#define SPDMEM_TYPE_MAXLEN 16
517 517
518struct spdmem_softc { 518struct spdmem_softc {
519 uint8_t (*sc_read)(struct spdmem_softc *, uint8_t); 519 uint8_t (*sc_read)(struct spdmem_softc *, uint8_t);
520 struct spdmem sc_spd_data; 520 struct spdmem sc_spd_data;
 521 struct sysctllog *sc_sysctl_log;
521 char sc_type[SPDMEM_TYPE_MAXLEN]; 522 char sc_type[SPDMEM_TYPE_MAXLEN];
522}; 523};
523 524
524int spdmem_common_probe(struct spdmem_softc *); 525int spdmem_common_probe(struct spdmem_softc *);
525void spdmem_common_attach(struct spdmem_softc *, device_t); 526void spdmem_common_attach(struct spdmem_softc *, device_t);
 527int spdmem_common_detach(struct spdmem_softc *, device_t);