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