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