xref: /freebsd/sys/dev/jedec_dimm/jedec_dimm.c (revision 83caa244bc9eef6949a1250a875ad1409775a46e)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Authors: Ravi Pokala (rpokala@freebsd.org), Andriy Gapon (avg@FreeBSD.org)
5  *
6  * Copyright (c) 2016 Andriy Gapon <avg@FreeBSD.org>
7  * Copyright (c) 2018-2023 Panasas
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 /*
32  * This driver is a super-set of the now-deleted jedec_ts(4), and most of the
33  * code for reading and reporting the temperature is either based on that driver,
34  * or copied from it verbatim.
35  */
36 
37 #include <sys/param.h>
38 #include <sys/kernel.h>
39 #include <sys/bus.h>
40 #include <sys/endian.h>
41 #include <sys/malloc.h>
42 #include <sys/module.h>
43 #include <sys/sysctl.h>
44 #include <sys/systm.h>
45 
46 #include <dev/jedec_dimm/jedec_dimm.h>
47 #include <dev/smbus/smbconf.h>
48 #include <dev/smbus/smbus.h>
49 
50 #include "smbus_if.h"
51 
52 struct jedec_dimm_softc {
53 	device_t dev;
54 	device_t smbus;
55 	uint8_t spd_addr;	/* SMBus address of the SPD EEPROM. */
56 	uint8_t tsod_addr;	/* Address of the Thermal Sensor On DIMM */
57 	uint8_t mfg_year;
58 	uint8_t mfg_week;
59 	uint32_t capacity_mb;
60 	char type_str[5];
61 	char part_str[21]; /* 18 (DDR3) or 20 (DDR4) chars, plus terminator */
62 	char serial_str[9]; /* 4 bytes = 8 nybble characters, plus terminator */
63 	char *slotid_str; /* Optional DIMM slot identifier (silkscreen) */
64 };
65 
66 /* General Thermal Sensor on DIMM (TSOD) identification notes.
67  *
68  * The JEDEC TSE2004av specification defines the device ID that all compliant
69  * devices should use, but very few do in practice. Maybe that's because the
70  * earlier TSE2002av specification was rather vague about that.
71  * Rare examples are IDT TSE2004GB2B0 and Atmel AT30TSE004A, not sure if
72  * they are TSE2004av compliant by design or by accident.
73  * Also, the specification mandates that PCI SIG manufacturer IDs are to be
74  * used, but in practice the JEDEC manufacturer IDs are often used.
75  */
76 const struct jedec_dimm_tsod_dev {
77 	uint16_t	vendor_id;
78 	uint8_t		device_id;
79 	const char	*description;
80 } known_tsod_devices[] = {
81 	/* Analog Devices ADT7408.
82 	 * http://www.analog.com/media/en/technical-documentation/data-sheets/ADT7408.pdf
83 	 */
84 	{ 0x11d4, 0x08, "Analog Devices TSOD" },
85 
86 	/* Atmel AT30TSE002B, AT30TSE004A.
87 	 * http://www.atmel.com/images/doc8711.pdf
88 	 * http://www.atmel.com/images/atmel-8868-dts-at30tse004a-datasheet.pdf
89 	 * Note how one chip uses the JEDEC Manufacturer ID while the other
90 	 * uses the PCI SIG one.
91 	 */
92 	{ 0x001f, 0x82, "Atmel TSOD" },
93 	{ 0x1114, 0x22, "Atmel TSOD" },
94 
95 	/* Integrated Device Technology (IDT) TS3000B3A, TSE2002B3C,
96 	 * TSE2004GB2B0 chips and their variants.
97 	 * http://www.idt.com/sites/default/files/documents/IDT_TSE2002B3C_DST_20100512_120303152056.pdf
98 	 * http://www.idt.com/sites/default/files/documents/IDT_TS3000B3A_DST_20101129_120303152013.pdf
99 	 * https://www.idt.com/document/dst/tse2004gb2b0-datasheet
100 	 */
101 	{ 0x00b3, 0x29, "IDT TSOD" },
102 	{ 0x00b3, 0x22, "IDT TSOD" },
103 
104 	/* Maxim Integrated MAX6604.
105 	 * Different document revisions specify different Device IDs.
106 	 * Document 19-3837; Rev 0; 10/05 has 0x3e00 while
107 	 * 19-3837; Rev 3; 10/11 has 0x5400.
108 	 * http://datasheets.maximintegrated.com/en/ds/MAX6604.pdf
109 	 */
110 	{ 0x004d, 0x3e, "Maxim Integrated TSOD" },
111 	{ 0x004d, 0x54, "Maxim Integrated TSOD" },
112 
113 	/* Microchip Technology MCP9805, MCP9843, MCP98242, MCP98243
114 	 * and their variants.
115 	 * http://ww1.microchip.com/downloads/en/DeviceDoc/21977b.pdf
116 	 * Microchip Technology EMC1501.
117 	 * http://ww1.microchip.com/downloads/en/DeviceDoc/00001605A.pdf
118 	 */
119 	{ 0x0054, 0x00, "Microchip TSOD" },
120 	{ 0x0054, 0x20, "Microchip TSOD" },
121 	{ 0x0054, 0x21, "Microchip TSOD" },
122 	{ 0x1055, 0x08, "Microchip TSOD" },
123 
124 	/* NXP Semiconductors SE97 and SE98.
125 	 * http://www.nxp.com/docs/en/data-sheet/SE97B.pdf
126 	 */
127 	{ 0x1131, 0xa1, "NXP TSOD" },
128 	{ 0x1131, 0xa2, "NXP TSOD" },
129 
130 	/* ON Semiconductor CAT34TS02 revisions B and C, CAT6095 and compatible.
131 	 * https://www.onsemi.com/pub/Collateral/CAT34TS02-D.PDF
132 	 * http://www.onsemi.com/pub/Collateral/CAT6095-D.PDF
133 	 */
134 	{ 0x1b09, 0x08, "ON Semiconductor TSOD" },
135 	{ 0x1b09, 0x0a, "ON Semiconductor TSOD" },
136 
137 	/* ST[Microelectronics] STTS424E02, STTS2002 and others.
138 	 * http://www.st.com/resource/en/datasheet/cd00157558.pdf
139 	 * http://www.st.com/resource/en/datasheet/stts2002.pdf
140 	 */
141 	{ 0x104a, 0x00, "ST Microelectronics TSOD" },
142 	{ 0x104a, 0x03, "ST Microelectronics TSOD" },
143 };
144 
145 static int jedec_dimm_adjust_offset(struct jedec_dimm_softc *sc,
146     uint16_t orig_offset, uint16_t *new_offset, bool *page_changed);
147 
148 static int jedec_dimm_attach(device_t dev);
149 
150 static int jedec_dimm_capacity(struct jedec_dimm_softc *sc, enum dram_type type,
151     uint32_t *capacity_mb);
152 
153 static int jedec_dimm_detach(device_t dev);
154 
155 static int jedec_dimm_dump(struct jedec_dimm_softc *sc, enum dram_type type);
156 
157 static int jedec_dimm_field_to_str(struct jedec_dimm_softc *sc, char *dst,
158     size_t dstsz, uint16_t offset, uint16_t len, bool ascii);
159 
160 static int jedec_dimm_mfg_date(struct jedec_dimm_softc *sc, enum dram_type type,
161     uint8_t *year, uint8_t *week);
162 
163 static int jedec_dimm_probe(device_t dev);
164 
165 static int jedec_dimm_readw_be(struct jedec_dimm_softc *sc, uint8_t reg,
166     uint16_t *val);
167 
168 static int jedec_dimm_reset_page0(struct jedec_dimm_softc *sc);
169 
170 static int jedec_dimm_temp_sysctl(SYSCTL_HANDLER_ARGS);
171 
172 static const char *jedec_dimm_tsod_match(uint16_t vid, uint16_t did);
173 
174 
175 /**
176  * The DDR4 SPD information is spread across two 256-byte pages, but the
177  * offsets in the spec are absolute, not per-page. If a given offset is on the
178  * second page, we need to change to that page and adjust the offset to be
179  * relative to that page.
180  *
181  * @author rpokala
182  *
183  * @param[in] sc
184  *      Instance-specific context data
185  *
186  * @param[in] orig_offset
187  *      The original value of the offset, before any adjustment is made.
188  *
189  * @param[out] new_offset
190  *      The offset to actually read from, adjusted if needed.
191  *
192  * @param[out] page_changed
193  *      Whether or not the page was actually changed, and the offset adjusted.
194  *      *If 'true', caller must call reset_page0() before itself returning.*
195  */
196 static int
jedec_dimm_adjust_offset(struct jedec_dimm_softc * sc,uint16_t orig_offset,uint16_t * new_offset,bool * page_changed)197 jedec_dimm_adjust_offset(struct jedec_dimm_softc *sc, uint16_t orig_offset,
198 	uint16_t *new_offset, bool *page_changed)
199 {
200 	int rc;
201 
202 	/* Don't change the offset, or indicate that the page has been changed,
203 	 * until the page has actually been changed.
204 	 */
205 	*new_offset = orig_offset;
206 	*page_changed = false;
207 
208 	/* Change to the proper page. Offsets [0, 255] are in page0; offsets
209 	 * [256, 511] are in page1.
210 	 */
211 	if (orig_offset < JEDEC_SPD_PAGE_SIZE) {
212 		/* Within page0; no adjustment or page-change required. */
213 		rc = 0;
214 		goto out;
215 	} else if (orig_offset >= (2 * JEDEC_SPD_PAGE_SIZE)) {
216 		/* Outside of expected range. */
217 		rc = EINVAL;
218 		device_printf(sc->dev, "invalid offset 0x%04x\n", orig_offset);
219 		goto out;
220 	}
221 
222 	/* 'orig_offset' is in page1. Switch to that page, and adjust
223 	 * 'new_offset' accordingly if successful.
224 	 *
225 	 * For the page-change operation, only the DTI and LSA matter; the
226 	 * offset and write-value are ignored, so just use 0.
227 	 */
228 	rc = smbus_writeb(sc->smbus, (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET1),
229 	    0, 0);
230 	if (rc != 0) {
231 		device_printf(sc->dev,
232 		    "unable to change page for offset 0x%04x: %d\n",
233 		    orig_offset, rc);
234 		goto out;
235 	}
236 	*page_changed = true;
237 	*new_offset = orig_offset - JEDEC_SPD_PAGE_SIZE;
238 
239 out:
240 	return (rc);
241 }
242 
243 /**
244  * device_attach() method. Read the DRAM type, use that to determine the offsets
245  * and lengths of the asset string fields. Calculate the capacity. If a TSOD is
246  * present, figure out exactly what it is, and update the device description.
247  * If all of that was successful, create the sysctls for the DIMM. If an
248  * optional slotid has been hinted, create a sysctl for that too.
249  *
250  * @author rpokala
251  *
252  * @param[in,out] dev
253  *      Device being attached.
254  */
255 static int
jedec_dimm_attach(device_t dev)256 jedec_dimm_attach(device_t dev)
257 {
258 	uint8_t byte;
259 	uint16_t devid;
260 	uint16_t partnum_len;
261 	uint16_t partnum_offset;
262 	uint16_t serial_len;
263 	uint16_t serial_offset;
264 	uint16_t tsod_present_offset;
265 	uint16_t vendorid;
266 	bool tsod_present;
267 	int rc;
268 	enum dram_type type;
269 	struct jedec_dimm_softc *sc;
270 	struct sysctl_ctx_list *ctx;
271 	struct sysctl_oid *oid;
272 	struct sysctl_oid_list *children;
273 	const char *tsod_match;
274 	const char *slotid_str;
275 
276 	sc = device_get_softc(dev);
277 	ctx = device_get_sysctl_ctx(dev);
278 	oid = device_get_sysctl_tree(dev);
279 	children = SYSCTL_CHILDREN(oid);
280 
281 	bzero(sc, sizeof(*sc));
282 	sc->dev = dev;
283 	sc->smbus = device_get_parent(dev);
284 	sc->spd_addr = smbus_get_addr(dev);
285 
286 	/* The TSOD address has a different DTI from the SPD address, but shares
287 	 * the LSA bits.
288 	 */
289 	sc->tsod_addr = JEDEC_DTI_TSOD | (sc->spd_addr & 0x0f);
290 
291 	/* Read the DRAM type, and set the various offsets and lengths. */
292 	rc = smbus_readb(sc->smbus, sc->spd_addr, SPD_OFFSET_DRAM_TYPE, &byte);
293 	if (rc != 0) {
294 		device_printf(dev, "failed to read dram_type: %d\n", rc);
295 		goto out;
296 	}
297 	type = (enum dram_type) byte;
298 	switch (type) {
299 	case DRAM_TYPE_DDR3_SDRAM:
300 		(void) snprintf(sc->type_str, sizeof(sc->type_str), "DDR3");
301 		partnum_len = SPD_LEN_DDR3_PARTNUM;
302 		partnum_offset = SPD_OFFSET_DDR3_PARTNUM;
303 		serial_len = SPD_LEN_DDR3_SERIAL;
304 		serial_offset = SPD_OFFSET_DDR3_SERIAL;
305 		tsod_present_offset = SPD_OFFSET_DDR3_TSOD_PRESENT;
306 		break;
307 	case DRAM_TYPE_DDR4_SDRAM:
308 		(void) snprintf(sc->type_str, sizeof(sc->type_str), "DDR4");
309 		partnum_len = SPD_LEN_DDR4_PARTNUM;
310 		partnum_offset = SPD_OFFSET_DDR4_PARTNUM;
311 		serial_len = SPD_LEN_DDR4_SERIAL;
312 		serial_offset = SPD_OFFSET_DDR4_SERIAL;
313 		tsod_present_offset = SPD_OFFSET_DDR4_TSOD_PRESENT;
314 		break;
315 	default:
316 		device_printf(dev, "unsupported dram_type 0x%02x\n", type);
317 		rc = EINVAL;
318 		goto out;
319 	}
320 
321 	if (bootverbose) {
322 		/* bootverbose debuggery is best-effort, so ignore the rc. */
323 		(void) jedec_dimm_dump(sc, type);
324 	}
325 
326 	/* Read all the required info from the SPD. If any of it fails, error
327 	 * out without creating the sysctls.
328 	 */
329 	rc = jedec_dimm_capacity(sc, type, &sc->capacity_mb);
330 	if (rc != 0) {
331 		goto out;
332 	}
333 
334 	rc = jedec_dimm_mfg_date(sc, type, &sc->mfg_year, &sc->mfg_week);
335 	if (rc != 0) {
336 		goto out;
337 	}
338 
339 	rc = jedec_dimm_field_to_str(sc, sc->part_str, sizeof(sc->part_str),
340 	    partnum_offset, partnum_len, true);
341 	if (rc != 0) {
342 		goto out;
343 	}
344 
345 	rc = jedec_dimm_field_to_str(sc, sc->serial_str, sizeof(sc->serial_str),
346 	    serial_offset, serial_len, false);
347 	if (rc != 0) {
348 		goto out;
349 	}
350 
351 	/* The MSBit of the TSOD-presence byte reports whether or not the TSOD
352 	 * is in fact present. (While DDR3 and DDR4 don't explicitly require a
353 	 * TSOD, essentially all DDR3 and DDR4 DIMMs include one.) But, as
354 	 * discussed in [PR 235944], it turns out that some DIMMs claim to have
355 	 * a TSOD when they actually don't. (Or maybe the firmware blocks it?)
356 	 * <sigh>
357 	 * If the SPD data says the TSOD is present, try to read manufacturer
358 	 * and device info from it to confirm that it's a valid TSOD device.
359 	 * If the data is unreadable, just continue as if the TSOD isn't there.
360 	 * If the data was read successfully, see if it is a known TSOD device;
361 	 * it's okay if it isn't (tsod_match == NULL).
362 	 */
363 	rc = smbus_readb(sc->smbus, sc->spd_addr, tsod_present_offset, &byte);
364 	if (rc != 0) {
365 		device_printf(dev, "failed to read TSOD-present byte: %d\n",
366 		    rc);
367 		goto out;
368 	}
369 	if (byte & 0x80) {
370 		tsod_present = true;
371 		rc = jedec_dimm_readw_be(sc, TSOD_REG_MANUFACTURER, &vendorid);
372 		if (rc != 0) {
373 			device_printf(dev,
374 			    "failed to read TSOD Manufacturer ID\n");
375 			rc = 0;
376 			goto no_tsod;
377 		}
378 		rc = jedec_dimm_readw_be(sc, TSOD_REG_DEV_REV, &devid);
379 		if (rc != 0) {
380 			device_printf(dev, "failed to read TSOD Device ID\n");
381 			rc = 0;
382 			goto no_tsod;
383 		}
384 
385 		tsod_match = jedec_dimm_tsod_match(vendorid, devid);
386 		if (bootverbose) {
387 			if (tsod_match == NULL) {
388 				device_printf(dev,
389 				    "Unknown TSOD Manufacturer and Device IDs,"
390 				    " 0x%x and 0x%x\n", vendorid, devid);
391 			} else {
392 				device_printf(dev,
393 				    "TSOD: %s\n", tsod_match);
394 			}
395 		}
396 	} else {
397 no_tsod:
398 		tsod_match = NULL;
399 		tsod_present = false;
400 	}
401 
402 	SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "type",
403 	    CTLFLAG_RD | CTLFLAG_MPSAFE, sc->type_str, 0,
404 	    "DIMM type");
405 
406 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "capacity",
407 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, sc->capacity_mb,
408 	    "DIMM capacity (MB)");
409 
410 	SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "part",
411 	    CTLFLAG_RD | CTLFLAG_MPSAFE, sc->part_str, 0,
412 	    "DIMM Part Number");
413 
414 	SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "serial",
415 	    CTLFLAG_RD | CTLFLAG_MPSAFE, sc->serial_str, 0,
416 	    "DIMM Serial Number");
417 
418 	SYSCTL_ADD_U8(ctx, children, OID_AUTO, "mfg_year",
419 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, sc->mfg_year,
420 	    "DIMM manufacturing year (20xx)");
421 
422 	SYSCTL_ADD_U8(ctx, children, OID_AUTO, "mfg_week",
423 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, sc->mfg_week,
424 	    "DIMM manufacturing week");
425 
426 	/* Create the temperature sysctl IFF the TSOD is present and valid */
427 	if (tsod_present && (tsod_match != NULL)) {
428 		SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "temp",
429 		    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 0,
430 		    jedec_dimm_temp_sysctl, "IK", "DIMM temperature (deg C)");
431 	}
432 
433 	/* If a "slotid" was hinted, add the sysctl for it. */
434 	if (resource_string_value(device_get_name(dev), device_get_unit(dev),
435 	    "slotid", &slotid_str) == 0) {
436 		if (slotid_str != NULL) {
437 			sc->slotid_str = strdup(slotid_str, M_DEVBUF);
438 			SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "slotid",
439 			    CTLFLAG_RD | CTLFLAG_MPSAFE, sc->slotid_str, 0,
440 			    "DIMM Slot Identifier");
441 		}
442 	}
443 
444 	/* If a TSOD type string or a slotid are present, add them to the
445 	 * device description.
446 	 */
447 	if ((tsod_match != NULL) || (sc->slotid_str != NULL)) {
448 		device_set_descf(dev, "%s%s%s%s%s%s",
449 		    device_get_desc(dev),
450 		    (tsod_match ? " w/ " : ""),
451 		    (tsod_match ? tsod_match : ""),
452 		    (sc->slotid_str ? " (" : ""),
453 		    (sc->slotid_str ? sc->slotid_str : ""),
454 		    (sc->slotid_str ? ")" : ""));
455 	}
456 
457 out:
458 	return (rc);
459 }
460 
461 /**
462  * Calculate the capacity of a DIMM. Both DDR3 and DDR4 encode "geometry"
463  * information in various SPD bytes. The standards documents codify everything
464  * in look-up tables, but it's trivial to reverse-engineer the the formulas for
465  * most of them. Unless otherwise noted, the same formulas apply for both DDR3
466  * and DDR4. The SPD offsets of where the data comes from are different between
467  * the two types, because having them be the same would be too easy.
468  *
469  * @author rpokala
470  *
471  * @param[in] sc
472  *      Instance-specific context data
473  *
474  * @param[in] dram_type
475  *      The locations of the data used to calculate the capacity depends on the
476  *      type of the DIMM.
477  *
478  * @param[out] capacity_mb
479  *      The calculated capacity, in MB
480  */
481 static int
jedec_dimm_capacity(struct jedec_dimm_softc * sc,enum dram_type type,uint32_t * capacity_mb)482 jedec_dimm_capacity(struct jedec_dimm_softc *sc, enum dram_type type,
483     uint32_t *capacity_mb)
484 {
485 	uint8_t bus_width_byte;
486 	uint8_t bus_width_offset;
487 	uint8_t dimm_ranks_byte;
488 	uint8_t dimm_ranks_offset;
489 	uint8_t sdram_capacity_byte;
490 	uint8_t sdram_capacity_offset;
491 	uint8_t sdram_pkg_type_byte;
492 	uint8_t sdram_pkg_type_offset;
493 	uint8_t sdram_width_byte;
494 	uint8_t sdram_width_offset;
495 	uint32_t bus_width;
496 	uint32_t dimm_ranks;
497 	uint32_t sdram_capacity;
498 	uint32_t sdram_pkg_type;
499 	uint32_t sdram_width;
500 	int rc;
501 
502 	switch (type) {
503 	case DRAM_TYPE_DDR3_SDRAM:
504 		bus_width_offset = SPD_OFFSET_DDR3_BUS_WIDTH;
505 		dimm_ranks_offset = SPD_OFFSET_DDR3_DIMM_RANKS;
506 		sdram_capacity_offset = SPD_OFFSET_DDR3_SDRAM_CAPACITY;
507 		sdram_width_offset = SPD_OFFSET_DDR3_SDRAM_WIDTH;
508 		break;
509 	case DRAM_TYPE_DDR4_SDRAM:
510 		bus_width_offset = SPD_OFFSET_DDR4_BUS_WIDTH;
511 		dimm_ranks_offset = SPD_OFFSET_DDR4_DIMM_RANKS;
512 		sdram_capacity_offset = SPD_OFFSET_DDR4_SDRAM_CAPACITY;
513 		sdram_pkg_type_offset = SPD_OFFSET_DDR4_SDRAM_PKG_TYPE;
514 		sdram_width_offset = SPD_OFFSET_DDR4_SDRAM_WIDTH;
515 		break;
516 	default:
517 		__assert_unreachable();
518 	}
519 
520 	rc = smbus_readb(sc->smbus, sc->spd_addr, bus_width_offset,
521 	    &bus_width_byte);
522 	if (rc != 0) {
523 		device_printf(sc->dev, "failed to read bus_width: %d\n", rc);
524 		goto out;
525 	}
526 
527 	rc = smbus_readb(sc->smbus, sc->spd_addr, dimm_ranks_offset,
528 	    &dimm_ranks_byte);
529 	if (rc != 0) {
530 		device_printf(sc->dev, "failed to read dimm_ranks: %d\n", rc);
531 		goto out;
532 	}
533 
534 	rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_capacity_offset,
535 	    &sdram_capacity_byte);
536 	if (rc != 0) {
537 		device_printf(sc->dev, "failed to read sdram_capacity: %d\n",
538 		    rc);
539 		goto out;
540 	}
541 
542 	rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_width_offset,
543 	    &sdram_width_byte);
544 	if (rc != 0) {
545 		device_printf(sc->dev, "failed to read sdram_width: %d\n", rc);
546 		goto out;
547 	}
548 
549 	/* The "SDRAM Package Type" is only needed for DDR4 DIMMs. */
550 	if (type == DRAM_TYPE_DDR4_SDRAM) {
551 		rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_pkg_type_offset,
552 		    &sdram_pkg_type_byte);
553 		if (rc != 0) {
554 			device_printf(sc->dev,
555 			    "failed to read sdram_pkg_type: %d\n", rc);
556 			goto out;
557 		}
558 	}
559 
560 	/* "Primary bus width, in bits" is in bits [2:0]. */
561 	bus_width_byte &= 0x07;
562 	if (bus_width_byte <= 3) {
563 		bus_width = 1 << bus_width_byte;
564 		bus_width *= 8;
565 	} else {
566 		device_printf(sc->dev, "invalid bus width info\n");
567 		rc = EINVAL;
568 		goto out;
569 	}
570 
571 	/* "Number of ranks per DIMM" is in bits [5:3]. Values 4-7 are only
572 	 * valid for DDR4.
573 	 */
574 	dimm_ranks_byte >>= 3;
575 	dimm_ranks_byte &= 0x07;
576 	if (dimm_ranks_byte <= 7) {
577 		dimm_ranks = dimm_ranks_byte + 1;
578 	} else {
579 		device_printf(sc->dev, "invalid DIMM Rank info\n");
580 		rc = EINVAL;
581 		goto out;
582 	}
583 	if ((dimm_ranks_byte >= 4) && (type != DRAM_TYPE_DDR4_SDRAM)) {
584 		device_printf(sc->dev, "invalid DIMM Rank info\n");
585 		rc = EINVAL;
586 		goto out;
587 	}
588 
589 	/* "Total SDRAM capacity per die, in Mb" is in bits [3:0]. There are two
590 	 * different formulas, for values 0-7 and for values 8-9. Also, values
591 	 * 7-9 are only valid for DDR4.
592 	 */
593 	sdram_capacity_byte &= 0x0f;
594 	if (sdram_capacity_byte <= 7) {
595 		sdram_capacity = 1 << sdram_capacity_byte;
596 		sdram_capacity *= 256;
597 	} else if (sdram_capacity_byte <= 9) {
598 		sdram_capacity = 12 << (sdram_capacity_byte - 8);
599 		sdram_capacity *= 1024;
600 	} else {
601 		device_printf(sc->dev, "invalid SDRAM capacity info\n");
602 		rc = EINVAL;
603 		goto out;
604 	}
605 	if ((sdram_capacity_byte >= 7) && (type != DRAM_TYPE_DDR4_SDRAM)) {
606 		device_printf(sc->dev, "invalid SDRAM capacity info\n");
607 		rc = EINVAL;
608 		goto out;
609 	}
610 
611 	/* "SDRAM device width" is in bits [2:0]. */
612 	sdram_width_byte &= 0x7;
613 	if (sdram_width_byte <= 3) {
614 		sdram_width = 1 << sdram_width_byte;
615 		sdram_width *= 4;
616 	} else {
617 		device_printf(sc->dev, "invalid SDRAM width info\n");
618 		rc = EINVAL;
619 		goto out;
620 	}
621 
622 	/* DDR4 has something called "3DS", which is indicated by [1:0] = 2;
623 	 * when that is the case, the die count is encoded in [6:4], and
624 	 * dimm_ranks is multiplied by it.
625 	 */
626 	if ((type == DRAM_TYPE_DDR4_SDRAM) &&
627 	    ((sdram_pkg_type_byte & 0x3) == 2)) {
628 		sdram_pkg_type_byte >>= 4;
629 		sdram_pkg_type_byte &= 0x07;
630 		sdram_pkg_type = sdram_pkg_type_byte + 1;
631 		dimm_ranks *= sdram_pkg_type;
632 	}
633 
634 	/* Finally, assemble the actual capacity. The formula is the same for
635 	 * both DDR3 and DDR4.
636 	 */
637 	*capacity_mb = sdram_capacity / 8 * bus_width / sdram_width *
638 	    dimm_ranks;
639 
640 out:
641 	return (rc);
642 }
643 
644 /**
645  * device_detach() method. If we allocated sc->slotid_str, free it. Even if we
646  *      didn't allocate, free it anyway; free(NULL) is safe.
647  *
648  * @author rpokala
649  *
650  * @param[in,out] dev
651  *      Device being detached.
652  */
653 static int
jedec_dimm_detach(device_t dev)654 jedec_dimm_detach(device_t dev)
655 {
656 	struct jedec_dimm_softc *sc;
657 
658 	sc = device_get_softc(dev);
659 	free(sc->slotid_str, M_DEVBUF);
660 
661 	return (0);
662 }
663 
664 /**
665  * Read and dump the entire SPD contents.
666  *
667  * @author rpokala
668  *
669  * @param[in] sc
670  *      Instance-specific context data
671  *
672  * @param[in] dram_type
673  *      The length of data which needs to be read and dumped differs based on
674  *      the type of the DIMM.
675  */
676 static int
jedec_dimm_dump(struct jedec_dimm_softc * sc,enum dram_type type)677 jedec_dimm_dump(struct jedec_dimm_softc *sc, enum dram_type type)
678 {
679 	int i;
680 	int rc;
681 	bool page_changed;
682 	uint8_t bytes[512];
683 
684 	page_changed = false;
685 
686 	for (i = 0; i < 256; i++) {
687 		rc = smbus_readb(sc->smbus, sc->spd_addr, i, &bytes[i]);
688 		if (rc != 0) {
689 			device_printf(sc->dev,
690 			    "unable to read page0:0x%02x: %d\n", i, rc);
691 			goto out;
692 		}
693 	}
694 
695 	/* The DDR4 SPD is 512 bytes, but SMBus only allows for 8-bit offsets.
696 	 * JEDEC gets around this by defining the "PAGE" DTI and LSAs.
697 	 */
698 	if (type == DRAM_TYPE_DDR4_SDRAM) {
699 		page_changed = true;
700 		rc = smbus_writeb(sc->smbus,
701 		    (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET1), 0, 0);
702 		if (rc != 0) {
703 			/* Some SPD devices (or SMBus controllers?) claim the
704 			 * page-change command failed when it actually
705 			 * succeeded. Log a message but soldier on.
706 			 */
707 			device_printf(sc->dev, "unable to change page: %d\n",
708 			    rc);
709 		}
710 		/* Add 256 to the store location, because we're in the second
711 		 * page.
712 		 */
713 		for (i = 0; i < 256; i++) {
714 			rc = smbus_readb(sc->smbus, sc->spd_addr, i,
715 			    &bytes[256 + i]);
716 			if (rc != 0) {
717 				device_printf(sc->dev,
718 				    "unable to read page1:0x%02x: %d\n", i, rc);
719 				goto out;
720 			}
721 		}
722 	}
723 
724 	/* Display the data in a nice hexdump format, with byte offsets. */
725 	hexdump(bytes, (page_changed ? 512 : 256), NULL, 0);
726 
727 out:
728 	if (page_changed) {
729 		int rc2;
730 
731 		rc2 = jedec_dimm_reset_page0(sc);
732 		if ((rc2 != 0) && (rc == 0)) {
733 			rc = rc2;
734 		}
735 	}
736 
737 	return (rc);
738 }
739 
740 /**
741  * Read a specified range of bytes from the SPD, convert them to a string, and
742  * store them in the provided buffer. Some SPD fields are space-padded ASCII,
743  * and some are just a string of bits that we want to convert to a hex string.
744  *
745  * @author rpokala
746  *
747  * @param[in] sc
748  *      Instance-specific context data
749  *
750  * @param[out] dst
751  *      The output buffer to populate
752  *
753  * @param[in] dstsz
754  *      The size of the output buffer
755  *
756  * @param[in] offset
757  *      The starting offset of the field within the SPD
758  *
759  * @param[in] len
760  *      The length in bytes of the field within the SPD
761  *
762  * @param[in] ascii
763  *      Is the field a sequence of ASCII characters? If not, it is binary data
764  *      which should be converted to characters.
765  */
766 static int
jedec_dimm_field_to_str(struct jedec_dimm_softc * sc,char * dst,size_t dstsz,uint16_t offset,uint16_t len,bool ascii)767 jedec_dimm_field_to_str(struct jedec_dimm_softc *sc, char *dst, size_t dstsz,
768     uint16_t offset, uint16_t len, bool ascii)
769 {
770 	uint8_t byte;
771 	uint16_t new_offset;
772 	int i;
773 	int rc;
774 	bool page_changed;
775 
776 	rc = jedec_dimm_adjust_offset(sc, offset, &new_offset, &page_changed);
777 	if (rc != 0) {
778 		goto out;
779 	}
780 
781 	/* Sanity-check (adjusted) offset and length; everything must be within
782 	 * the same page.
783 	 */
784 	if (new_offset >= JEDEC_SPD_PAGE_SIZE) {
785 		rc = EINVAL;
786 		device_printf(sc->dev, "invalid offset 0x%04x\n", new_offset);
787 		goto out;
788 	}
789 	if ((new_offset + len) >= JEDEC_SPD_PAGE_SIZE) {
790 		rc = EINVAL;
791 		device_printf(sc->dev,
792 		    "(new_offset + len) would cross page (0x%04x + 0x%04x)\n",
793 		    new_offset, len);
794 		goto out;
795 	}
796 
797 	/* Sanity-check the destination string length. If we're dealing with
798 	 * ASCII chars, then the destination must be at least the same length;
799 	 * otherwise, it must be *twice* the length, because each byte must
800 	 * be converted into two nybble characters.
801 	 *
802 	 * And, of course, there needs to be an extra byte for the terminator.
803 	 */
804 	if (ascii) {
805 		if (dstsz < (len + 1)) {
806 			rc = EINVAL;
807 			device_printf(sc->dev,
808 			    "destination too short (%u < %u)\n",
809 			    (uint16_t) dstsz, (len + 1));
810 			goto out;
811 		}
812 	} else {
813 		if (dstsz < ((2 * len) + 1)) {
814 			rc = EINVAL;
815 			device_printf(sc->dev,
816 			    "destination too short (%u < %u)\n",
817 			    (uint16_t) dstsz, ((2 * len) + 1));
818 			goto out;
819 		}
820 	}
821 
822 	/* Read a byte at a time. */
823 	for (i = 0; i < len; i++) {
824 		rc = smbus_readb(sc->smbus, sc->spd_addr, (new_offset + i),
825 		    &byte);
826 		if (rc != 0) {
827 			device_printf(sc->dev,
828 			    "failed to read byte at 0x%02x: %d\n",
829 			    (new_offset + i), rc);
830 			goto out;
831 		}
832 		if (ascii) {
833 			/* chars can be copied directly. */
834 			dst[i] = byte;
835 		} else {
836 			/* Raw bytes need to be converted to a two-byte hex
837 			 * string, plus the terminator.
838 			 */
839 			(void) snprintf(&dst[(2 * i)], 3, "%02x", byte);
840 		}
841 	}
842 
843 	/* If we're dealing with ASCII, convert trailing spaces to NULs. */
844 	if (ascii) {
845 		for (i = dstsz - 1; i > 0; i--) {
846 			if (dst[i] == ' ') {
847 				dst[i] = 0;
848 			} else if (dst[i] == 0) {
849 				continue;
850 			} else {
851 				break;
852 			}
853 		}
854 	}
855 
856 out:
857 	if (page_changed) {
858 		int rc2;
859 
860 		rc2 = jedec_dimm_reset_page0(sc);
861 		if ((rc2 != 0) && (rc == 0)) {
862 			rc = rc2;
863 		}
864 	}
865 
866 	return (rc);
867 }
868 
869 /**
870  * Both DDR3 and DDR4 encode manufacturing date as a one-byte BCD-encoded
871  * year (offset from 2000) and a one-byte BCD-encoded week within that year.
872  * The SPD offsets are different between the two types.
873  *
874  * @author rpokala
875  *
876  * @param[in] sc
877  *      Instance-specific context data
878  *
879  * @param[in] dram_type
880  *      The locations of the manufacturing date depends on the type of the DIMM.
881  *
882  * @param[out] year
883  *      The manufacturing year, offset from 2000
884  *
885  * @param[out] week
886  *      The manufacturing week within the year
887  */
888 static int
jedec_dimm_mfg_date(struct jedec_dimm_softc * sc,enum dram_type type,uint8_t * year,uint8_t * week)889 jedec_dimm_mfg_date(struct jedec_dimm_softc *sc, enum dram_type type,
890     uint8_t *year, uint8_t *week)
891 {
892 	uint8_t year_bcd;
893 	uint8_t week_bcd;
894 	uint16_t year_offset;
895 	uint16_t week_offset;
896 	bool page_changed;
897 	int rc;
898 
899 	switch (type) {
900 	case DRAM_TYPE_DDR3_SDRAM:
901 		year_offset = SPD_OFFSET_DDR3_MOD_MFG_YEAR;
902 		week_offset = SPD_OFFSET_DDR3_MOD_MFG_WEEK;
903 		break;
904 	case DRAM_TYPE_DDR4_SDRAM:
905 		year_offset = SPD_OFFSET_DDR4_MOD_MFG_YEAR;
906 		week_offset = SPD_OFFSET_DDR4_MOD_MFG_WEEK;
907 		break;
908 	default:
909 		__assert_unreachable();
910 	}
911 
912 	/* Change to the proper page. Offsets [0, 255] are in page0; offsets
913 	 * [256, 512] are in page1.
914 	 *
915 	 * *The page must be reset to page0 before returning.*
916 	 *
917 	 * For the page-change operation, only the DTI and LSA matter; the
918 	 * offset and write-value are ignored, so use just 0.
919 	 *
920 	 * Mercifully, JEDEC defined the fields such that all of the
921 	 * manufacturing-related ones are on the same page, so we don't need to
922 	 * worry about that complication.
923 	 */
924 	if (year_offset < JEDEC_SPD_PAGE_SIZE) {
925 		page_changed = false;
926 	} else if (year_offset < (2 * JEDEC_SPD_PAGE_SIZE)) {
927 		page_changed = true;
928 		rc = smbus_writeb(sc->smbus,
929 		    (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET1), 0, 0);
930 		if (rc != 0) {
931 			device_printf(sc->dev,
932 			    "unable to change page for offset 0x%04x: %d\n",
933 			    year_offset, rc);
934 		}
935 		/* Adjust the offset to account for the page change. */
936 		year_offset -= JEDEC_SPD_PAGE_SIZE;
937 		week_offset -= JEDEC_SPD_PAGE_SIZE;
938 	} else {
939 		device_printf(sc->dev, "invalid offset 0x%04x\n", year_offset);
940 		rc = EINVAL;
941 		page_changed = false;
942 		goto out;
943 	}
944 
945 	rc = smbus_readb(sc->smbus, sc->spd_addr, year_offset, &year_bcd);
946 	if (rc != 0) {
947 		device_printf(sc->dev, "failed to read mfg year: %d\n", rc);
948 		goto out;
949 	}
950 
951 	rc = smbus_readb(sc->smbus, sc->spd_addr, week_offset, &week_bcd);
952 	if (rc != 0) {
953 		device_printf(sc->dev, "failed to read mfg week: %d\n", rc);
954 		goto out;
955 	}
956 
957 	/* Convert from one-byte BCD to one-byte integer. */
958 	*year = (((year_bcd & 0xf0) >> 4) * 10) + (year_bcd & 0x0f);
959 	*week = (((week_bcd & 0xf0) >> 4) * 10) + (week_bcd & 0x0f);
960 
961 out:
962 	if (page_changed) {
963 		int rc2;
964 		/* Switch back to page0 before returning. */
965 		rc2 = smbus_writeb(sc->smbus,
966 		    (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET0), 0, 0);
967 		if (rc2 != 0) {
968 			device_printf(sc->dev,
969 			    "unable to restore page for offset 0x%04x: %d\n",
970 			    year_offset, rc2);
971 		}
972 	}
973 
974 	return (rc);
975 }
976 
977 /**
978  * device_probe() method. Validate the address that was given as a hint, and
979  * display an error if it's bogus. Make sure that we're dealing with one of the
980  * SPD versions that we can handle.
981  *
982  * @author rpokala
983  *
984  * @param[in] dev
985  *      Device being probed.
986  */
987 static int
jedec_dimm_probe(device_t dev)988 jedec_dimm_probe(device_t dev)
989 {
990 	uint8_t addr;
991 	uint8_t byte;
992 	int rc;
993 	enum dram_type type;
994 	device_t smbus;
995 
996 	smbus = device_get_parent(dev);
997 	addr = smbus_get_addr(dev);
998 
999 	/* Don't bother if this isn't an SPD address, or if the LSBit is set. */
1000 	if (((addr & 0xf0) != JEDEC_DTI_SPD) ||
1001 	    ((addr & 0x01) != 0)) {
1002 		device_printf(dev,
1003 		    "invalid \"addr\" hint; address must start with \"0x%x\","
1004 		    " and the least-significant bit must be 0\n",
1005 		    JEDEC_DTI_SPD);
1006 		rc = ENXIO;
1007 		goto out;
1008 	}
1009 
1010 	/* Try to read the DRAM_TYPE from the SPD. */
1011 	rc = smbus_readb(smbus, addr, SPD_OFFSET_DRAM_TYPE, &byte);
1012 	if (rc != 0) {
1013 		device_printf(dev, "failed to read dram_type\n");
1014 		goto out;
1015 	}
1016 
1017 	/* This driver currently only supports DDR3 and DDR4 SPDs. */
1018 	type = (enum dram_type) byte;
1019 	switch (type) {
1020 	case DRAM_TYPE_DDR3_SDRAM:
1021 		rc = BUS_PROBE_DEFAULT;
1022 		device_set_desc(dev, "DDR3 DIMM");
1023 		break;
1024 	case DRAM_TYPE_DDR4_SDRAM:
1025 		rc = BUS_PROBE_DEFAULT;
1026 		device_set_desc(dev, "DDR4 DIMM");
1027 		break;
1028 	default:
1029 		rc = ENXIO;
1030 		break;
1031 	}
1032 
1033 out:
1034 	return (rc);
1035 }
1036 
1037 /**
1038  * SMBus specifies little-endian byte order, but it looks like the TSODs use
1039  * big-endian. Read and convert.
1040  *
1041  * @author avg
1042  *
1043  * @param[in] sc
1044  *      Instance-specific context data
1045  *
1046  * @param[in] reg
1047  *      The register number to read.
1048  *
1049  * @param[out] val
1050  *      Pointer to populate with the value read.
1051  */
1052 static int
jedec_dimm_readw_be(struct jedec_dimm_softc * sc,uint8_t reg,uint16_t * val)1053 jedec_dimm_readw_be(struct jedec_dimm_softc *sc, uint8_t reg, uint16_t *val)
1054 {
1055 	int rc;
1056 
1057 	rc = smbus_readw(sc->smbus, sc->tsod_addr, reg, val);
1058 	if (rc != 0) {
1059 		goto out;
1060 	}
1061 	*val = be16toh(*val);
1062 
1063 out:
1064 	return (rc);
1065 }
1066 
1067 /**
1068  * Reset to the default condition of operating on page0. This must be called
1069  * after a previous operation changed to page1.
1070  *
1071  * @author rpokala
1072  *
1073  * @param[in] sc
1074  *      Instance-specific context data
1075  */
1076 static int
jedec_dimm_reset_page0(struct jedec_dimm_softc * sc)1077 jedec_dimm_reset_page0(struct jedec_dimm_softc *sc)
1078 {
1079 	int rc;
1080 
1081 	/* For the page-change operation, only the DTI and LSA matter; the
1082 	 * offset and write-value are ignored, so just use 0.
1083 	 */
1084 	rc = smbus_writeb(sc->smbus, (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET0),
1085 	    0, 0);
1086 	if (rc != 0) {
1087 		device_printf(sc->dev, "unable to restore page: %d\n", rc);
1088 	}
1089 
1090 	return (rc);
1091 }
1092 
1093 /**
1094  * Read the temperature data from the TSOD and convert it to the deciKelvin
1095  * value that the sysctl expects.
1096  *
1097  * @author avg
1098  */
1099 static int
jedec_dimm_temp_sysctl(SYSCTL_HANDLER_ARGS)1100 jedec_dimm_temp_sysctl(SYSCTL_HANDLER_ARGS)
1101 {
1102 	uint16_t val;
1103 	int rc;
1104 	int temp;
1105 	device_t dev = arg1;
1106 	struct jedec_dimm_softc *sc;
1107 
1108 	sc = device_get_softc(dev);
1109 
1110 	rc = jedec_dimm_readw_be(sc, TSOD_REG_TEMPERATURE, &val);
1111 	if (rc != 0) {
1112 		goto out;
1113 	}
1114 
1115 	/* The three MSBits are flags, and the next bit is a sign bit. */
1116 	temp = val & 0xfff;
1117 	if ((val & 0x1000) != 0)
1118 		temp = -temp;
1119 	/* Each step is 0.0625 degrees, so convert to 1000ths of a degree C. */
1120 	temp *= 625;
1121 	/* ... and then convert to 1000ths of a Kelvin */
1122 	temp += 2731500;
1123 	/* As a practical matter, few (if any) TSODs are more accurate than
1124 	 * about a tenth of a degree, so round accordingly. This correlates with
1125 	 * the "IK" formatting used for this sysctl.
1126 	 */
1127 	temp = (temp + 500) / 1000;
1128 
1129 	rc = sysctl_handle_int(oidp, &temp, 0, req);
1130 
1131 out:
1132 	return (rc);
1133 }
1134 
1135 /**
1136  * Check the TSOD's Vendor ID and Device ID against the list of known TSOD
1137  * devices. Return the description, or NULL if this doesn't look like a valid
1138  * TSOD.
1139  *
1140  * @author avg
1141  *
1142  * @param[in] vid
1143  *      The Vendor ID of the TSOD device
1144  *
1145  * @param[in] did
1146  *      The Device ID of the TSOD device
1147  *
1148  * @return
1149  *      The description string, or NULL for a failure to match.
1150  */
1151 static const char *
jedec_dimm_tsod_match(uint16_t vid,uint16_t did)1152 jedec_dimm_tsod_match(uint16_t vid, uint16_t did)
1153 {
1154 	const struct jedec_dimm_tsod_dev *d;
1155 	int i;
1156 
1157 	for (i = 0; i < nitems(known_tsod_devices); i++) {
1158 		d = &known_tsod_devices[i];
1159 		if ((vid == d->vendor_id) && ((did >> 8) == d->device_id)) {
1160 			return (d->description);
1161 		}
1162 	}
1163 
1164 	/* If no matches for a specific device, then check for a generic
1165 	 * TSE2004av-compliant device.
1166 	 */
1167 	if ((did >> 8) == 0x22) {
1168 		return ("TSE2004av compliant TSOD");
1169 	}
1170 
1171 	return (NULL);
1172 }
1173 
1174 static device_method_t jedec_dimm_methods[] = {
1175 	/* Methods from the device interface */
1176 	DEVMETHOD(device_probe,		jedec_dimm_probe),
1177 	DEVMETHOD(device_attach,	jedec_dimm_attach),
1178 	DEVMETHOD(device_detach,	jedec_dimm_detach),
1179 	DEVMETHOD_END
1180 };
1181 
1182 static driver_t jedec_dimm_driver = {
1183 	.name = "jedec_dimm",
1184 	.methods = jedec_dimm_methods,
1185 	.size = sizeof(struct jedec_dimm_softc),
1186 };
1187 
1188 DRIVER_MODULE(jedec_dimm, smbus, jedec_dimm_driver, 0, 0);
1189 MODULE_DEPEND(jedec_dimm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
1190 MODULE_VERSION(jedec_dimm, 1);
1191 
1192 /* vi: set ts=8 sw=4 sts=8 noet: */
1193