xref: /freebsd/sys/dev/jedec_dimm/jedec_dimm.c (revision 0957b409)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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 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  * $FreeBSD$
31  */
32 
33 /*
34  * This driver is a super-set of the now-deleted jedec_ts(4), and most of the
35  * code for reading and reporting the temperature is either based on that driver,
36  * or copied from it verbatim.
37  */
38 
39 #include <sys/param.h>
40 #include <sys/kernel.h>
41 #include <sys/bus.h>
42 #include <sys/endian.h>
43 #include <sys/malloc.h>
44 #include <sys/module.h>
45 #include <sys/sysctl.h>
46 #include <sys/systm.h>
47 
48 #include <dev/jedec_dimm/jedec_dimm.h>
49 #include <dev/smbus/smbconf.h>
50 #include <dev/smbus/smbus.h>
51 
52 #include "smbus_if.h"
53 
54 struct jedec_dimm_softc {
55 	device_t dev;
56 	device_t smbus;
57 	uint8_t spd_addr;	/* SMBus address of the SPD EEPROM. */
58 	uint8_t tsod_addr;	/* Address of the Thermal Sensor On DIMM */
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_attach(device_t dev);
146 
147 static int jedec_dimm_capacity(struct jedec_dimm_softc *sc, enum dram_type type,
148     uint32_t *capacity_mb);
149 
150 static int jedec_dimm_detach(device_t dev);
151 
152 static int jedec_dimm_dump(struct jedec_dimm_softc *sc, enum dram_type type);
153 
154 static int jedec_dimm_field_to_str(struct jedec_dimm_softc *sc, char *dst,
155     size_t dstsz, uint16_t offset, uint16_t len, bool ascii);
156 
157 static int jedec_dimm_probe(device_t dev);
158 
159 static int jedec_dimm_readw_be(struct jedec_dimm_softc *sc, uint8_t reg,
160     uint16_t *val);
161 
162 static int jedec_dimm_temp_sysctl(SYSCTL_HANDLER_ARGS);
163 
164 static const char *jedec_dimm_tsod_match(uint16_t vid, uint16_t did);
165 
166 
167 /**
168  * device_attach() method. Read the DRAM type, use that to determine the offsets
169  * and lengths of the asset string fields. Calculate the capacity. If a TSOD is
170  * present, figure out exactly what it is, and update the device description.
171  * If all of that was successful, create the sysctls for the DIMM. If an
172  * optional slotid has been hinted, create a sysctl for that too.
173  *
174  * @author rpokala
175  *
176  * @param[in,out] dev
177  *      Device being attached.
178  */
179 static int
180 jedec_dimm_attach(device_t dev)
181 {
182 	uint8_t byte;
183 	uint16_t devid;
184 	uint16_t partnum_len;
185 	uint16_t partnum_offset;
186 	uint16_t serial_len;
187 	uint16_t serial_offset;
188 	uint16_t tsod_present_offset;
189 	uint16_t vendorid;
190 	bool tsod_present;
191 	int rc;
192 	int new_desc_len;
193 	enum dram_type type;
194 	struct jedec_dimm_softc *sc;
195 	struct sysctl_ctx_list *ctx;
196 	struct sysctl_oid *oid;
197 	struct sysctl_oid_list *children;
198 	const char *tsod_match;
199 	const char *slotid_str;
200 	char *new_desc;
201 
202 	sc = device_get_softc(dev);
203 	ctx = device_get_sysctl_ctx(dev);
204 	oid = device_get_sysctl_tree(dev);
205 	children = SYSCTL_CHILDREN(oid);
206 
207 	bzero(sc, sizeof(*sc));
208 	sc->dev = dev;
209 	sc->smbus = device_get_parent(dev);
210 	sc->spd_addr = smbus_get_addr(dev);
211 
212 	/* The TSOD address has a different DTI from the SPD address, but shares
213 	 * the LSA bits.
214 	 */
215 	sc->tsod_addr = JEDEC_DTI_TSOD | (sc->spd_addr & 0x0f);
216 
217 	/* Read the DRAM type, and set the various offsets and lengths. */
218 	rc = smbus_readb(sc->smbus, sc->spd_addr, SPD_OFFSET_DRAM_TYPE, &byte);
219 	if (rc != 0) {
220 		device_printf(dev, "failed to read dram_type: %d\n", rc);
221 		goto out;
222 	}
223 	type = (enum dram_type) byte;
224 	switch (type) {
225 	case DRAM_TYPE_DDR3_SDRAM:
226 		(void) snprintf(sc->type_str, sizeof(sc->type_str), "DDR3");
227 		partnum_len = SPD_LEN_DDR3_PARTNUM;
228 		partnum_offset = SPD_OFFSET_DDR3_PARTNUM;
229 		serial_len = SPD_LEN_DDR3_SERIAL;
230 		serial_offset = SPD_OFFSET_DDR3_SERIAL;
231 		tsod_present_offset = SPD_OFFSET_DDR3_TSOD_PRESENT;
232 		break;
233 	case DRAM_TYPE_DDR4_SDRAM:
234 		(void) snprintf(sc->type_str, sizeof(sc->type_str), "DDR4");
235 		partnum_len = SPD_LEN_DDR4_PARTNUM;
236 		partnum_offset = SPD_OFFSET_DDR4_PARTNUM;
237 		serial_len = SPD_LEN_DDR4_SERIAL;
238 		serial_offset = SPD_OFFSET_DDR4_SERIAL;
239 		tsod_present_offset = SPD_OFFSET_DDR4_TSOD_PRESENT;
240 		break;
241 	default:
242 		device_printf(dev, "unsupported dram_type 0x%02x\n", type);
243 		rc = EINVAL;
244 		goto out;
245 	}
246 
247 	if (bootverbose) {
248 		/* bootverbose debuggery is best-effort, so ignore the rc. */
249 		(void) jedec_dimm_dump(sc, type);
250 	}
251 
252 	/* Read all the required info from the SPD. If any of it fails, error
253 	 * out without creating the sysctls.
254 	 */
255 	rc = jedec_dimm_capacity(sc, type, &sc->capacity_mb);
256 	if (rc != 0) {
257 		goto out;
258 	}
259 
260 	rc = jedec_dimm_field_to_str(sc, sc->part_str, sizeof(sc->part_str),
261 	    partnum_offset, partnum_len, true);
262 	if (rc != 0) {
263 		goto out;
264 	}
265 
266 	rc = jedec_dimm_field_to_str(sc, sc->serial_str, sizeof(sc->serial_str),
267 	    serial_offset, serial_len, false);
268 	if (rc != 0) {
269 		goto out;
270 	}
271 
272 	/* The MSBit of the TSOD-presence byte reports whether or not the TSOD
273 	 * is in fact present. If it is, read manufacturer and device info from
274 	 * it to confirm that it's a valid TSOD device. It's an error if any of
275 	 * those bytes are unreadable; it's not an error if the device is simply
276 	 * not known to us (tsod_match == NULL).
277 	 * While DDR3 and DDR4 don't explicitly require a TSOD, essentially all
278 	 * DDR3 and DDR4 DIMMs include one.
279 	 */
280 	rc = smbus_readb(sc->smbus, sc->spd_addr, tsod_present_offset, &byte);
281 	if (rc != 0) {
282 		device_printf(dev, "failed to read TSOD-present byte: %d\n",
283 		    rc);
284 		goto out;
285 	}
286 	if (byte & 0x80) {
287 		tsod_present = true;
288 		rc = jedec_dimm_readw_be(sc, TSOD_REG_MANUFACTURER, &vendorid);
289 		if (rc != 0) {
290 			device_printf(dev,
291 			    "failed to read TSOD Manufacturer ID\n");
292 			goto out;
293 		}
294 		rc = jedec_dimm_readw_be(sc, TSOD_REG_DEV_REV, &devid);
295 		if (rc != 0) {
296 			device_printf(dev, "failed to read TSOD Device ID\n");
297 			goto out;
298 		}
299 
300 		tsod_match = jedec_dimm_tsod_match(vendorid, devid);
301 		if (bootverbose) {
302 			if (tsod_match == NULL) {
303 				device_printf(dev,
304 				    "Unknown TSOD Manufacturer and Device IDs,"
305 				    " 0x%x and 0x%x\n", vendorid, devid);
306 			} else {
307 				device_printf(dev,
308 				    "TSOD: %s\n", tsod_match);
309 			}
310 		}
311 	} else {
312 		tsod_match = NULL;
313 		tsod_present = false;
314 	}
315 
316 	SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "type",
317 	    CTLFLAG_RD | CTLFLAG_MPSAFE, sc->type_str, 0,
318 	    "DIMM type");
319 
320 	SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "capacity",
321 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, sc->capacity_mb,
322 	    "DIMM capacity (MB)");
323 
324 	SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "part",
325 	    CTLFLAG_RD | CTLFLAG_MPSAFE, sc->part_str, 0,
326 	    "DIMM Part Number");
327 
328 	SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "serial",
329 	    CTLFLAG_RD | CTLFLAG_MPSAFE, sc->serial_str, 0,
330 	    "DIMM Serial Number");
331 
332 	/* Create the temperature sysctl IFF the TSOD is present and valid */
333 	if (tsod_present && (tsod_match != NULL)) {
334 		SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "temp",
335 		    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 0,
336 		    jedec_dimm_temp_sysctl, "IK", "DIMM temperature (deg C)");
337 	}
338 
339 	/* If a "slotid" was hinted, add the sysctl for it. */
340 	if (resource_string_value(device_get_name(dev), device_get_unit(dev),
341 	    "slotid", &slotid_str) == 0) {
342 		if (slotid_str != NULL) {
343 			sc->slotid_str = strdup(slotid_str, M_DEVBUF);
344 			SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "slotid",
345 			    CTLFLAG_RD | CTLFLAG_MPSAFE, sc->slotid_str, 0,
346 			    "DIMM Slot Identifier");
347 		}
348 	}
349 
350 	/* If a TSOD type string or a slotid are present, add them to the
351 	 * device description.
352 	 */
353 	if ((tsod_match != NULL) || (sc->slotid_str != NULL)) {
354 		new_desc_len = strlen(device_get_desc(dev));
355 		if (tsod_match != NULL) {
356 			new_desc_len += strlen(tsod_match);
357 			new_desc_len += 4; /* " w/ " */
358 		}
359 		if (sc->slotid_str != NULL) {
360 			new_desc_len += strlen(sc->slotid_str);
361 			new_desc_len += 3; /* space + parens */
362 		}
363 		new_desc_len++; /* terminator */
364 		new_desc = malloc(new_desc_len, M_TEMP, (M_WAITOK | M_ZERO));
365 		(void) snprintf(new_desc, new_desc_len, "%s%s%s%s%s%s",
366 		    device_get_desc(dev),
367 		    (tsod_match ? " w/ " : ""),
368 		    (tsod_match ? tsod_match : ""),
369 		    (sc->slotid_str ? " (" : ""),
370 		    (sc->slotid_str ? sc->slotid_str : ""),
371 		    (sc->slotid_str ? ")" : ""));
372 		device_set_desc_copy(dev, new_desc);
373 		free(new_desc, M_TEMP);
374 	}
375 
376 out:
377 	return (rc);
378 }
379 
380 /**
381  * Calculate the capacity of a DIMM. Both DDR3 and DDR4 encode "geometry"
382  * information in various SPD bytes. The standards documents codify everything
383  * in look-up tables, but it's trivial to reverse-engineer the the formulas for
384  * most of them. Unless otherwise noted, the same formulas apply for both DDR3
385  * and DDR4. The SPD offsets of where the data comes from are different between
386  * the two types, because having them be the same would be too easy.
387  *
388  * @author rpokala
389  *
390  * @param[in] sc
391  *      Instance-specific context data
392  *
393  * @param[in] dram_type
394  *      The locations of the data used to calculate the capacity depends on the
395  *      type of the DIMM.
396  *
397  * @param[out] capacity_mb
398  *      The calculated capacity, in MB
399  */
400 static int
401 jedec_dimm_capacity(struct jedec_dimm_softc *sc, enum dram_type type,
402     uint32_t *capacity_mb)
403 {
404 	uint8_t bus_width_byte;
405 	uint8_t bus_width_offset;
406 	uint8_t dimm_ranks_byte;
407 	uint8_t dimm_ranks_offset;
408 	uint8_t sdram_capacity_byte;
409 	uint8_t sdram_capacity_offset;
410 	uint8_t sdram_pkg_type_byte;
411 	uint8_t sdram_pkg_type_offset;
412 	uint8_t sdram_width_byte;
413 	uint8_t sdram_width_offset;
414 	uint32_t bus_width;
415 	uint32_t dimm_ranks;
416 	uint32_t sdram_capacity;
417 	uint32_t sdram_pkg_type;
418 	uint32_t sdram_width;
419 	int rc;
420 
421 	switch (type) {
422 	case DRAM_TYPE_DDR3_SDRAM:
423 		bus_width_offset = SPD_OFFSET_DDR3_BUS_WIDTH;
424 		dimm_ranks_offset = SPD_OFFSET_DDR3_DIMM_RANKS;
425 		sdram_capacity_offset = SPD_OFFSET_DDR3_SDRAM_CAPACITY;
426 		sdram_width_offset = SPD_OFFSET_DDR3_SDRAM_WIDTH;
427 		break;
428 	case DRAM_TYPE_DDR4_SDRAM:
429 		bus_width_offset = SPD_OFFSET_DDR4_BUS_WIDTH;
430 		dimm_ranks_offset = SPD_OFFSET_DDR4_DIMM_RANKS;
431 		sdram_capacity_offset = SPD_OFFSET_DDR4_SDRAM_CAPACITY;
432 		sdram_pkg_type_offset = SPD_OFFSET_DDR4_SDRAM_PKG_TYPE;
433 		sdram_width_offset = SPD_OFFSET_DDR4_SDRAM_WIDTH;
434 		break;
435 	default:
436 		device_printf(sc->dev, "unsupported dram_type 0x%02x\n", type);
437 		rc = EINVAL;
438 		goto out;
439 	}
440 
441 	rc = smbus_readb(sc->smbus, sc->spd_addr, bus_width_offset,
442 	    &bus_width_byte);
443 	if (rc != 0) {
444 		device_printf(sc->dev, "failed to read bus_width: %d\n", rc);
445 		goto out;
446 	}
447 
448 	rc = smbus_readb(sc->smbus, sc->spd_addr, dimm_ranks_offset,
449 	    &dimm_ranks_byte);
450 	if (rc != 0) {
451 		device_printf(sc->dev, "failed to read dimm_ranks: %d\n", rc);
452 		goto out;
453 	}
454 
455 	rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_capacity_offset,
456 	    &sdram_capacity_byte);
457 	if (rc != 0) {
458 		device_printf(sc->dev, "failed to read sdram_capacity: %d\n",
459 		    rc);
460 		goto out;
461 	}
462 
463 	rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_width_offset,
464 	    &sdram_width_byte);
465 	if (rc != 0) {
466 		device_printf(sc->dev, "failed to read sdram_width: %d\n", rc);
467 		goto out;
468 	}
469 
470 	/* The "SDRAM Package Type" is only needed for DDR4 DIMMs. */
471 	if (type == DRAM_TYPE_DDR4_SDRAM) {
472 		rc = smbus_readb(sc->smbus, sc->spd_addr, sdram_pkg_type_offset,
473 		    &sdram_pkg_type_byte);
474 		if (rc != 0) {
475 			device_printf(sc->dev,
476 			    "failed to read sdram_pkg_type: %d\n", rc);
477 			goto out;
478 		}
479 	}
480 
481 	/* "Primary bus width, in bits" is in bits [2:0]. */
482 	bus_width_byte &= 0x07;
483 	if (bus_width_byte <= 3) {
484 		bus_width = 1 << bus_width_byte;
485 		bus_width *= 8;
486 	} else {
487 		device_printf(sc->dev, "invalid bus width info\n");
488 		rc = EINVAL;
489 		goto out;
490 	}
491 
492 	/* "Number of ranks per DIMM" is in bits [5:3]. Values 4-7 are only
493 	 * valid for DDR4.
494 	 */
495 	dimm_ranks_byte >>= 3;
496 	dimm_ranks_byte &= 0x07;
497 	if (dimm_ranks_byte <= 7) {
498 		dimm_ranks = dimm_ranks_byte + 1;
499 	} else {
500 		device_printf(sc->dev, "invalid DIMM Rank info\n");
501 		rc = EINVAL;
502 		goto out;
503 	}
504 	if ((dimm_ranks_byte >= 4) && (type != DRAM_TYPE_DDR4_SDRAM)) {
505 		device_printf(sc->dev, "invalid DIMM Rank info\n");
506 		rc = EINVAL;
507 		goto out;
508 	}
509 
510 	/* "Total SDRAM capacity per die, in Mb" is in bits [3:0]. There are two
511 	 * different formulas, for values 0-7 and for values 8-9. Also, values
512 	 * 7-9 are only valid for DDR4.
513 	 */
514 	sdram_capacity_byte &= 0x0f;
515 	if (sdram_capacity_byte <= 7) {
516 		sdram_capacity = 1 << sdram_capacity_byte;
517 		sdram_capacity *= 256;
518 	} else if (sdram_capacity_byte <= 9) {
519 		sdram_capacity = 12 << (sdram_capacity_byte - 8);
520 		sdram_capacity *= 1024;
521 	} else {
522 		device_printf(sc->dev, "invalid SDRAM capacity info\n");
523 		rc = EINVAL;
524 		goto out;
525 	}
526 	if ((sdram_capacity_byte >= 7) && (type != DRAM_TYPE_DDR4_SDRAM)) {
527 		device_printf(sc->dev, "invalid SDRAM capacity info\n");
528 		rc = EINVAL;
529 		goto out;
530 	}
531 
532 	/* "SDRAM device width" is in bits [2:0]. */
533 	sdram_width_byte &= 0x7;
534 	if (sdram_width_byte <= 3) {
535 		sdram_width = 1 << sdram_width_byte;
536 		sdram_width *= 4;
537 	} else {
538 		device_printf(sc->dev, "invalid SDRAM width info\n");
539 		rc = EINVAL;
540 		goto out;
541 	}
542 
543 	/* DDR4 has something called "3DS", which is indicated by [1:0] = 2;
544 	 * when that is the case, the die count is encoded in [6:4], and
545 	 * dimm_ranks is multiplied by it.
546 	 */
547 	if ((type == DRAM_TYPE_DDR4_SDRAM) &&
548 	    ((sdram_pkg_type_byte & 0x3) == 2)) {
549 		sdram_pkg_type_byte >>= 4;
550 		sdram_pkg_type_byte &= 0x07;
551 		sdram_pkg_type = sdram_pkg_type_byte + 1;
552 		dimm_ranks *= sdram_pkg_type;
553 	}
554 
555 	/* Finally, assemble the actual capacity. The formula is the same for
556 	 * both DDR3 and DDR4.
557 	 */
558 	*capacity_mb = sdram_capacity / 8 * bus_width / sdram_width *
559 	    dimm_ranks;
560 
561 out:
562 	return (rc);
563 }
564 
565 /**
566  * device_detach() method. If we allocated sc->slotid_str, free it. Even if we
567  *      didn't allocate, free it anyway; free(NULL) is safe.
568  *
569  * @author rpokala
570  *
571  * @param[in,out] dev
572  *      Device being detached.
573  */
574 static int
575 jedec_dimm_detach(device_t dev)
576 {
577 	struct jedec_dimm_softc *sc;
578 
579 	sc = device_get_softc(dev);
580 	free(sc->slotid_str, M_DEVBUF);
581 
582 	return (0);
583 }
584 
585 /**
586  * Read and dump the entire SPD contents.
587  *
588  * @author rpokala
589  *
590  * @param[in] sc
591  *      Instance-specific context data
592  *
593  * @param[in] dram_type
594  *      The length of data which needs to be read and dumped differs based on
595  *      the type of the DIMM.
596  */
597 static int
598 jedec_dimm_dump(struct jedec_dimm_softc *sc, enum dram_type type)
599 {
600 	int i;
601 	int rc;
602 	bool page_changed;
603 	uint8_t bytes[512];
604 
605 	page_changed = false;
606 
607 	for (i = 0; i < 256; i++) {
608 		rc = smbus_readb(sc->smbus, sc->spd_addr, i, &bytes[i]);
609 		if (rc != 0) {
610 			device_printf(sc->dev,
611 			    "unable to read page0:0x%02x: %d\n", i, rc);
612 			goto out;
613 		}
614 	}
615 
616 	/* The DDR4 SPD is 512 bytes, but SMBus only allows for 8-bit offsets.
617 	 * JEDEC gets around this by defining the "PAGE" DTI and LSAs.
618 	 */
619 	if (type == DRAM_TYPE_DDR4_SDRAM) {
620 		page_changed = true;
621 		rc = smbus_writeb(sc->smbus,
622 		    (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET1), 0, 0);
623 		if (rc != 0) {
624 			device_printf(sc->dev, "unable to change page: %d\n",
625 			    rc);
626 			goto out;
627 		}
628 		/* Add 256 to the store location, because we're in the second
629 		 * page.
630 		 */
631 		for (i = 0; i < 256; i++) {
632 			rc = smbus_readb(sc->smbus, sc->spd_addr, i,
633 			    &bytes[256 + i]);
634 			if (rc != 0) {
635 				device_printf(sc->dev,
636 				    "unable to read page1:0x%02x: %d\n", i, rc);
637 				goto out;
638 			}
639 		}
640 	}
641 
642 	/* Display the data in a nice hexdump format, with byte offsets. */
643 	hexdump(bytes, (page_changed ? 512 : 256), NULL, 0);
644 
645 out:
646 	if (page_changed) {
647 		int rc2;
648 		/* Switch back to page0 before returning. */
649 		rc2 = smbus_writeb(sc->smbus,
650 		    (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET0), 0, 0);
651 		if (rc2 != 0) {
652 			device_printf(sc->dev, "unable to restore page: %d\n",
653 			    rc2);
654 		}
655 	}
656 	return (rc);
657 }
658 
659 /**
660  * Read a specified range of bytes from the SPD, convert them to a string, and
661  * store them in the provided buffer. Some SPD fields are space-padded ASCII,
662  * and some are just a string of bits that we want to convert to a hex string.
663  *
664  * @author rpokala
665  *
666  * @param[in] sc
667  *      Instance-specific context data
668  *
669  * @param[out] dst
670  *      The output buffer to populate
671  *
672  * @param[in] dstsz
673  *      The size of the output buffer
674  *
675  * @param[in] offset
676  *      The starting offset of the field within the SPD
677  *
678  * @param[in] len
679  *      The length in bytes of the field within the SPD
680  *
681  * @param[in] ascii
682  *      Is the field a sequence of ASCII characters? If not, it is binary data
683  *      which should be converted to characters.
684  */
685 static int
686 jedec_dimm_field_to_str(struct jedec_dimm_softc *sc, char *dst, size_t dstsz,
687     uint16_t offset, uint16_t len, bool ascii)
688 {
689 	uint8_t byte;
690 	int i;
691 	int rc;
692 	bool page_changed;
693 
694 	/* Change to the proper page. Offsets [0, 255] are in page0; offsets
695 	 * [256, 512] are in page1.
696 	 *
697 	 * *The page must be reset to page0 before returning.*
698 	 *
699 	 * For the page-change operation, only the DTI and LSA matter; the
700 	 * offset and write-value are ignored, so use just 0.
701 	 *
702 	 * Mercifully, JEDEC defined the fields such that none of them cross
703 	 * pages, so we don't need to worry about that complication.
704 	 */
705 	if (offset < JEDEC_SPD_PAGE_SIZE) {
706 		page_changed = false;
707 	} else if (offset < (2 * JEDEC_SPD_PAGE_SIZE)) {
708 		page_changed = true;
709 		rc = smbus_writeb(sc->smbus,
710 		    (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET1), 0, 0);
711 		if (rc != 0) {
712 			device_printf(sc->dev,
713 			    "unable to change page for offset 0x%04x: %d\n",
714 			    offset, rc);
715 		}
716 		/* Adjust the offset to account for the page change. */
717 		offset -= JEDEC_SPD_PAGE_SIZE;
718 	} else {
719 		page_changed = false;
720 		rc = EINVAL;
721 		device_printf(sc->dev, "invalid offset 0x%04x\n", offset);
722 		goto out;
723 	}
724 
725 	/* Sanity-check (adjusted) offset and length; everything must be within
726 	 * the same page.
727 	 */
728 	if (offset >= JEDEC_SPD_PAGE_SIZE) {
729 		rc = EINVAL;
730 		device_printf(sc->dev, "invalid offset 0x%04x\n", offset);
731 		goto out;
732 	}
733 	if ((offset + len) >= JEDEC_SPD_PAGE_SIZE) {
734 		rc = EINVAL;
735 		device_printf(sc->dev,
736 		    "(offset + len) would cross page (0x%04x + 0x%04x)\n",
737 		    offset, len);
738 		goto out;
739 	}
740 
741 	/* Sanity-check the destination string length. If we're dealing with
742 	 * ASCII chars, then the destination must be at least the same length;
743 	 * otherwise, it must be *twice* the length, because each byte must
744 	 * be converted into two nybble characters.
745 	 *
746 	 * And, of course, there needs to be an extra byte for the terminator.
747 	 */
748 	if (ascii) {
749 		if (dstsz < (len + 1)) {
750 			rc = EINVAL;
751 			device_printf(sc->dev,
752 			    "destination too short (%u < %u)\n",
753 			    (uint16_t) dstsz, (len + 1));
754 			goto out;
755 		}
756 	} else {
757 		if (dstsz < ((2 * len) + 1)) {
758 			rc = EINVAL;
759 			device_printf(sc->dev,
760 			    "destination too short (%u < %u)\n",
761 			    (uint16_t) dstsz, ((2 * len) + 1));
762 			goto out;
763 		}
764 	}
765 
766 	/* Read a byte at a time. */
767 	for (i = 0; i < len; i++) {
768 		rc = smbus_readb(sc->smbus, sc->spd_addr, (offset + i), &byte);
769 		if (rc != 0) {
770 			device_printf(sc->dev,
771 			    "failed to read byte at 0x%02x: %d\n",
772 			    (offset + i), rc);
773 			goto out;
774 		}
775 		if (ascii) {
776 			/* chars can be copied directly. */
777 			dst[i] = byte;
778 		} else {
779 			/* Raw bytes need to be converted to a two-byte hex
780 			 * string, plus the terminator.
781 			 */
782 			(void) snprintf(&dst[(2 * i)], 3, "%02x", byte);
783 		}
784 	}
785 
786 	/* If we're dealing with ASCII, convert trailing spaces to NULs. */
787 	if (ascii) {
788 		for (i = dstsz; i > 0; i--) {
789 			if (dst[i] == ' ') {
790 				dst[i] = 0;
791 			} else if (dst[i] == 0) {
792 				continue;
793 			} else {
794 				break;
795 			}
796 		}
797 	}
798 
799 out:
800 	if (page_changed) {
801 		int rc2;
802 		/* Switch back to page0 before returning. */
803 		rc2 = smbus_writeb(sc->smbus,
804 		    (JEDEC_DTI_PAGE | JEDEC_LSA_PAGE_SET0), 0, 0);
805 		if (rc2 != 0) {
806 			device_printf(sc->dev,
807 			    "unable to restore page for offset 0x%04x: %d\n",
808 			    offset, rc2);
809 		}
810 	}
811 
812 	return (rc);
813 }
814 
815 /**
816  * device_probe() method. Validate the address that was given as a hint, and
817  * display an error if it's bogus. Make sure that we're dealing with one of the
818  * SPD versions that we can handle.
819  *
820  * @author rpokala
821  *
822  * @param[in] dev
823  *      Device being probed.
824  */
825 static int
826 jedec_dimm_probe(device_t dev)
827 {
828 	uint8_t addr;
829 	uint8_t byte;
830 	int rc;
831 	enum dram_type type;
832 	device_t smbus;
833 
834 	smbus = device_get_parent(dev);
835 	addr = smbus_get_addr(dev);
836 
837 	/* Don't bother if this isn't an SPD address, or if the LSBit is set. */
838 	if (((addr & 0xf0) != JEDEC_DTI_SPD) ||
839 	    ((addr & 0x01) != 0)) {
840 		device_printf(dev,
841 		    "invalid \"addr\" hint; address must start with \"0x%x\","
842 		    " and the least-significant bit must be 0\n",
843 		    JEDEC_DTI_SPD);
844 		rc = ENXIO;
845 		goto out;
846 	}
847 
848 	/* Try to read the DRAM_TYPE from the SPD. */
849 	rc = smbus_readb(smbus, addr, SPD_OFFSET_DRAM_TYPE, &byte);
850 	if (rc != 0) {
851 		device_printf(dev, "failed to read dram_type\n");
852 		goto out;
853 	}
854 
855 	/* This driver currently only supports DDR3 and DDR4 SPDs. */
856 	type = (enum dram_type) byte;
857 	switch (type) {
858 	case DRAM_TYPE_DDR3_SDRAM:
859 		rc = BUS_PROBE_DEFAULT;
860 		device_set_desc(dev, "DDR3 DIMM");
861 		break;
862 	case DRAM_TYPE_DDR4_SDRAM:
863 		rc = BUS_PROBE_DEFAULT;
864 		device_set_desc(dev, "DDR4 DIMM");
865 		break;
866 	default:
867 		rc = ENXIO;
868 		break;
869 	}
870 
871 out:
872 	return (rc);
873 }
874 
875 /**
876  * SMBus specifies little-endian byte order, but it looks like the TSODs use
877  * big-endian. Read and convert.
878  *
879  * @author avg
880  *
881  * @param[in] sc
882  *      Instance-specific context data
883  *
884  * @param[in] reg
885  *      The register number to read.
886  *
887  * @param[out] val
888  *      Pointer to populate with the value read.
889  */
890 static int
891 jedec_dimm_readw_be(struct jedec_dimm_softc *sc, uint8_t reg, uint16_t *val)
892 {
893 	int rc;
894 
895 	rc = smbus_readw(sc->smbus, sc->tsod_addr, reg, val);
896 	if (rc != 0) {
897 		goto out;
898 	}
899 	*val = be16toh(*val);
900 
901 out:
902 	return (rc);
903 }
904 
905 /**
906  * Read the temperature data from the TSOD and convert it to the deciKelvin
907  * value that the sysctl expects.
908  *
909  * @author avg
910  */
911 static int
912 jedec_dimm_temp_sysctl(SYSCTL_HANDLER_ARGS)
913 {
914 	uint16_t val;
915 	int rc;
916 	int temp;
917 	device_t dev = arg1;
918 	struct jedec_dimm_softc *sc;
919 
920 	sc = device_get_softc(dev);
921 
922 	rc = jedec_dimm_readw_be(sc, TSOD_REG_TEMPERATURE, &val);
923 	if (rc != 0) {
924 		goto out;
925 	}
926 
927 	/* The three MSBits are flags, and the next bit is a sign bit. */
928 	temp = val & 0xfff;
929 	if ((val & 0x1000) != 0)
930 		temp = -temp;
931 	/* Each step is 0.0625 degrees, so convert to 1000ths of a degree C. */
932 	temp *= 625;
933 	/* ... and then convert to 1000ths of a Kelvin */
934 	temp += 2731500;
935 	/* As a practical matter, few (if any) TSODs are more accurate than
936 	 * about a tenth of a degree, so round accordingly. This correlates with
937 	 * the "IK" formatting used for this sysctl.
938 	 */
939 	temp = (temp + 500) / 1000;
940 
941 	rc = sysctl_handle_int(oidp, &temp, 0, req);
942 
943 out:
944 	return (rc);
945 }
946 
947 /**
948  * Check the TSOD's Vendor ID and Device ID against the list of known TSOD
949  * devices. Return the description, or NULL if this doesn't look like a valid
950  * TSOD.
951  *
952  * @author avg
953  *
954  * @param[in] vid
955  *      The Vendor ID of the TSOD device
956  *
957  * @param[in] did
958  *      The Device ID of the TSOD device
959  *
960  * @return
961  *      The description string, or NULL for a failure to match.
962  */
963 static const char *
964 jedec_dimm_tsod_match(uint16_t vid, uint16_t did)
965 {
966 	const struct jedec_dimm_tsod_dev *d;
967 	int i;
968 
969 	for (i = 0; i < nitems(known_tsod_devices); i++) {
970 		d = &known_tsod_devices[i];
971 		if ((vid == d->vendor_id) && ((did >> 8) == d->device_id)) {
972 			return (d->description);
973 		}
974 	}
975 
976 	/* If no matches for a specific device, then check for a generic
977 	 * TSE2004av-compliant device.
978 	 */
979 	if ((did >> 8) == 0x22) {
980 		return ("TSE2004av compliant TSOD");
981 	}
982 
983 	return (NULL);
984 }
985 
986 static device_method_t jedec_dimm_methods[] = {
987 	/* Methods from the device interface */
988 	DEVMETHOD(device_probe,		jedec_dimm_probe),
989 	DEVMETHOD(device_attach,	jedec_dimm_attach),
990 	DEVMETHOD(device_detach,	jedec_dimm_detach),
991 	DEVMETHOD_END
992 };
993 
994 static driver_t jedec_dimm_driver = {
995 	.name = "jedec_dimm",
996 	.methods = jedec_dimm_methods,
997 	.size = sizeof(struct jedec_dimm_softc),
998 };
999 
1000 static devclass_t jedec_dimm_devclass;
1001 
1002 DRIVER_MODULE(jedec_dimm, smbus, jedec_dimm_driver, jedec_dimm_devclass, 0, 0);
1003 MODULE_DEPEND(jedec_dimm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
1004 MODULE_VERSION(jedec_dimm, 1);
1005 
1006 /* vi: set ts=8 sw=4 sts=8 noet: */
1007