Bug Summary

File:dev/spdmem.c
Warning:line 721, column 3
Value stored to 'd_clk' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name spdmem.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/spdmem.c
1/* $OpenBSD: spdmem.c,v 1.7 2019/12/21 12:33:03 kettenis Exp $ */
2/* $NetBSD: spdmem.c,v 1.3 2007/09/20 23:09:59 xtraeme Exp $ */
3
4/*
5 * Copyright (c) 2007 Jonathan Gray <jsg@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20/*
21 * Copyright (c) 2007 Nicolas Joly
22 * Copyright (c) 2007 Paul Goyette
23 * Copyright (c) 2007 Tobias Nygren
24 * All rights reserved.
25 *
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
28 * are met:
29 * 1. Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 * 3. The name of the author may not be used to endorse or promote products
35 * derived from this software without specific prior written permission.
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS
38 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
39 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
40 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
41 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
43 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
44 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
45 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
47 * POSSIBILITY OF SUCH DAMAGE.
48 */
49
50/*
51 * Serial Presence Detect (SPD) memory identification
52 */
53
54#include <sys/param.h>
55#include <sys/systm.h>
56#include <sys/device.h>
57
58#include <dev/spdmemvar.h>
59
60/* Encodings of the size used/total byte for certain memory types */
61#define SPDMEM_SPDSIZE_MASK0x0F 0x0F /* SPD EEPROM Size */
62
63#define SPDMEM_SPDLEN_1280x00 0x00 /* SPD EEPROM Sizes */
64#define SPDMEM_SPDLEN_1760x10 0x10
65#define SPDMEM_SPDLEN_2560x20 0x20
66#define SPDMEM_SPDLEN_MASK0x70 0x70 /* Bits 4 - 6 */
67
68#define SPDMEM_DDR4_SPDLEN_1280x01 0x01 /* SPD EEPROM Sizes */
69#define SPDMEM_DDR4_SPDLEN_2560x02 0x02
70#define SPDMEM_DDR4_SPDLEN_3840x03 0x03
71#define SPDMEM_DDR4_SPDLEN_5120x04 0x04
72#define SPDMEM_DDR4_SPDLEN_MASK0x0f 0x0f /* Bits 4 - 6 */
73
74#define SPDMEM_SPDCRC_1160x80 0x80 /* CRC Bytes covered */
75#define SPDMEM_SPDCRC_1250x00 0x00
76#define SPDMEM_SPDCRC_MASK0x80 0x80 /* Bit 7 */
77
78/* possible values for the memory type */
79#define SPDMEM_MEMTYPE_FPM0x01 0x01
80#define SPDMEM_MEMTYPE_EDO0x02 0x02
81#define SPDMEM_MEMTYPE_PIPE_NIBBLE0x03 0x03
82#define SPDMEM_MEMTYPE_SDRAM0x04 0x04
83#define SPDMEM_MEMTYPE_ROM0x05 0x05
84#define SPDMEM_MEMTYPE_DDRSGRAM0x06 0x06
85#define SPDMEM_MEMTYPE_DDRSDRAM0x07 0x07
86#define SPDMEM_MEMTYPE_DDR2SDRAM0x08 0x08
87#define SPDMEM_MEMTYPE_FBDIMM0x09 0x09
88#define SPDMEM_MEMTYPE_FBDIMM_PROBE0x0a 0x0a
89#define SPDMEM_MEMTYPE_DDR3SDRAM0x0b 0x0b
90#define SPDMEM_MEMTYPE_DDR4SDRAM0x0c 0x0c
91 /* 0xd reserved */
92#define SPDMEM_MEMTYPE_DDR4ESDRAM0x0e 0x0e
93#define SPDMEM_MEMTYPE_LPDDR3SDRAM0x0f 0x0f
94#define SPDMEM_MEMTYPE_LPDDR4SDRAM0x10 0x10
95#define SPDMEM_MEMTYPE_LPDDR4XSDRAM0x11 0x11
96#define SPDMEM_MEMTYPE_DDR5SDRAM0x12 0x12
97#define SPDMEM_MEMTYPE_LPDDR5SDRAM0x13 0x13
98
99#define SPDMEM_MEMTYPE_NONE0xff 0xff
100
101#define SPDMEM_MEMTYPE_DIRECT_RAMBUS0x01 0x01
102#define SPDMEM_MEMTYPE_RAMBUS0x11 0x11
103
104/* possible values for the supply voltage */
105#define SPDMEM_VOLTAGE_TTL_5V0x00 0x00
106#define SPDMEM_VOLTAGE_TTL_LV0x01 0x01
107#define SPDMEM_VOLTAGE_HSTTL_1_5V0x02 0x02
108#define SPDMEM_VOLTAGE_SSTL_3_3V0x03 0x03
109#define SPDMEM_VOLTAGE_SSTL_2_5V0x04 0x04
110#define SPDMEM_VOLTAGE_SSTL_1_8V0x05 0x05
111
112/* possible values for module configuration */
113#define SPDMEM_MODCONFIG_PARITY0x01 0x01
114#define SPDMEM_MODCONFIG_ECC0x02 0x02
115
116/* for DDR2, module configuration is a bit-mask field */
117#define SPDMEM_MODCONFIG_HAS_DATA_PARITY0x01 0x01
118#define SPDMEM_MODCONFIG_HAS_DATA_ECC0x02 0x02
119#define SPDMEM_MODCONFIG_HAS_ADDR_CMD_PARITY0x04 0x04
120
121/* possible values for the refresh field */
122#define SPDMEM_REFRESH_STD0x00 0x00
123#define SPDMEM_REFRESH_QUARTER0x01 0x01
124#define SPDMEM_REFRESH_HALF0x02 0x02
125#define SPDMEM_REFRESH_TWOX0x03 0x03
126#define SPDMEM_REFRESH_FOURX0x04 0x04
127#define SPDMEM_REFRESH_EIGHTX0x05 0x05
128#define SPDMEM_REFRESH_SELFREFRESH0x80 0x80
129
130/* superset types */
131#define SPDMEM_SUPERSET_ESDRAM0x01 0x01
132#define SPDMEM_SUPERSET_DDR_ESDRAM0x02 0x02
133#define SPDMEM_SUPERSET_EDO_PEM0x03 0x03
134#define SPDMEM_SUPERSET_SDR_PEM0x04 0x04
135
136/* FPM and EDO DIMMS */
137#define SPDMEM_FPM_ROWS0x00 0x00
138#define SPDMEM_FPM_COLS0x01 0x01
139#define SPDMEM_FPM_BANKS0x02 0x02
140#define SPDMEM_FPM_CONFIG0x08 0x08
141#define SPDMEM_FPM_REFRESH0x09 0x09
142#define SPDMEM_FPM_SUPERSET0x0c 0x0c
143
144/* PC66/PC100/PC133 SDRAM */
145#define SPDMEM_SDR_ROWS0x00 0x00
146#define SPDMEM_SDR_COLS0x01 0x01
147#define SPDMEM_SDR_BANKS0x02 0x02
148#define SPDMEM_SDR_CYCLE0x06 0x06
149#define SPDMEM_SDR_BANKS_PER_CHIP0x0e 0x0e
150#define SPDMEM_SDR_MOD_ATTRIB0x12 0x12
151#define SPDMEM_SDR_SUPERSET0x1d 0x1d
152
153#define SPDMEM_SDR_FREQUENCY126 126
154#define SPDMEM_SDR_CAS127 127
155#define SPDMEM_SDR_FREQ_660x66 0x66
156#define SPDMEM_SDR_FREQ_1000x64 0x64
157#define SPDMEM_SDR_FREQ_1330x85 0x85
158#define SPDMEM_SDR_CAS2(1 << 1) (1 << 1)
159#define SPDMEM_SDR_CAS3(1 << 2) (1 << 2)
160
161/* Rambus Direct DRAM */
162#define SPDMEM_RDR_MODULE_TYPE0x00 0x00
163#define SPDMEM_RDR_ROWS_COLS0x01 0x01
164#define SPDMEM_RDR_BANK0x02 0x02
165
166#define SPDMEM_RDR_TYPE_RIMM1 1
167#define SPDMEM_RDR_TYPE_SORIMM2 2
168#define SPDMEM_RDR_TYPE_EMBED3 3
169#define SPDMEM_RDR_TYPE_RIMM324 4
170
171/* Dual Data Rate SDRAM */
172#define SPDMEM_DDR_ROWS0x00 0x00
173#define SPDMEM_DDR_COLS0x01 0x01
174#define SPDMEM_DDR_RANKS0x02 0x02
175#define SPDMEM_DDR_DATAWIDTH0x03 0x03
176#define SPDMEM_DDR_VOLTAGE0x05 0x05
177#define SPDMEM_DDR_CYCLE0x06 0x06
178#define SPDMEM_DDR_REFRESH0x09 0x09
179#define SPDMEM_DDR_BANKS_PER_CHIP0x0e 0x0e
180#define SPDMEM_DDR_CAS0x0f 0x0f
181#define SPDMEM_DDR_MOD_ATTRIB0x12 0x12
182#define SPDMEM_DDR_SUPERSET0x1d 0x1d
183
184#define SPDMEM_DDR_ATTRIB_REG(1 << 1) (1 << 1)
185
186/* Dual Data Rate 2 SDRAM */
187#define SPDMEM_DDR2_ROWS0x00 0x00
188#define SPDMEM_DDR2_COLS0x01 0x01
189#define SPDMEM_DDR2_RANKS0x02 0x02
190#define SPDMEM_DDR2_DATAWIDTH0x03 0x03
191#define SPDMEM_DDR2_VOLTAGE0x05 0x05
192#define SPDMEM_DDR2_CYCLE0x06 0x06
193#define SPDMEM_DDR2_DIMMTYPE0x11 0x11
194#define SPDMEM_DDR2_RANK_DENSITY0x1c 0x1c
195
196#define SPDMEM_DDR2_TYPE_REGMASK((1 << 4) | (1 << 0)) ((1 << 4) | (1 << 0))
197#define SPDMEM_DDR2_SODIMM(1 << 2) (1 << 2)
198#define SPDMEM_DDR2_MICRO_DIMM(1 << 3) (1 << 3)
199#define SPDMEM_DDR2_MINI_RDIMM(1 << 4) (1 << 4)
200#define SPDMEM_DDR2_MINI_UDIMM(1 << 5) (1 << 5)
201
202/* DDR2 FB-DIMM SDRAM */
203#define SPDMEM_FBDIMM_ADDR0x01 0x01
204#define SPDMEM_FBDIMM_RANKS0x04 0x04
205#define SPDMEM_FBDIMM_MTB_DIVIDEND0x06 0x06
206#define SPDMEM_FBDIMM_MTB_DIVISOR0x07 0x07
207#define SPDMEM_FBDIMM_PROTO0x4e 0x4e
208
209#define SPDMEM_FBDIMM_RANKS_WIDTH0x07 0x07
210#define SPDMEM_FBDIMM_ADDR_BANKS0x02 0x02
211#define SPDMEM_FBDIMM_ADDR_COL0x0c 0x0c
212#define SPDMEM_FBDIMM_ADDR_COL_SHIFT2 2
213#define SPDMEM_FBDIMM_ADDR_ROW0xe0 0xe0
214#define SPDMEM_FBDIMM_ADDR_ROW_SHIFT5 5
215#define SPDMEM_FBDIMM_PROTO_ECC(1 << 1) (1 << 1)
216
217
218/* Dual Data Rate 3 SDRAM */
219#define SPDMEM_DDR3_MODTYPE0x00 0x00
220#define SPDMEM_DDR3_DENSITY0x01 0x01
221#define SPDMEM_DDR3_MOD_ORG0x04 0x04
222#define SPDMEM_DDR3_DATAWIDTH0x05 0x05
223#define SPDMEM_DDR3_MTB_DIVIDEND0x07 0x07
224#define SPDMEM_DDR3_MTB_DIVISOR0x08 0x08
225#define SPDMEM_DDR3_TCKMIN0x09 0x09
226#define SPDMEM_DDR3_THERMAL0x1d 0x1d
227
228#define SPDMEM_DDR3_DENSITY_CAPMASK0x0f 0x0f
229#define SPDMEM_DDR3_MOD_ORG_CHIPWIDTH_MASK0x07 0x07
230#define SPDMEM_DDR3_MOD_ORG_BANKS_SHIFT3 3
231#define SPDMEM_DDR3_MOD_ORG_BANKS_MASK0x07 0x07
232#define SPDMEM_DDR3_DATAWIDTH_ECCMASK(1 << 3) (1 << 3)
233#define SPDMEM_DDR3_DATAWIDTH_PRIMASK0x07 0x07
234#define SPDMEM_DDR3_THERMAL_PRESENT(1 << 7) (1 << 7)
235
236#define SPDMEM_DDR3_RDIMM0x01 0x01
237#define SPDMEM_DDR3_UDIMM0x02 0x02
238#define SPDMEM_DDR3_SODIMM0x03 0x03
239#define SPDMEM_DDR3_MICRO_DIMM0x04 0x04
240#define SPDMEM_DDR3_MINI_RDIMM0x05 0x05
241#define SPDMEM_DDR3_MINI_UDIMM0x06 0x06
242
243/* Dual Data Rate 4 SDRAM */
244#define SPDMEM_DDR4_MODTYPE0x00 0x00
245#define SPDMEM_DDR4_DENSITY0x01 0x01
246#define SPDMEM_DDR4_PACK_TYPE0x03 0x03
247#define SPDMEM_DDR4_MOD_ORG0x09 0x09
248#define SPDMEM_DDR4_DATAWIDTH0x0a 0x0a
249#define SPDMEM_DDR4_THERMAL0x0b 0x0b
250#define SPDMEM_DDR4_TCKMIN_MTB0x0f 0x0f
251#define SPDMEM_DDR4_TCKMIN_FTB0x7d 0x7d /* not offset by 3 */
252
253#define SPDMEM_DDR4_DENSITY_CAPMASK0x0f 0x0f
254#define SPDMEM_DDR4_PACK_TYPE_SIG_LOAD_MASK0x03 0x03
255#define SPDMEM_DDR4_PACK_TYPE_SIG_SINGLE_LOAD0x02 0x02
256#define SPDMEM_DDR4_PACK_TYPE_DIE_COUNT_SHIFT4 4
257#define SPDMEM_DDR4_PACK_TYPE_DIE_COUNT_MASK0x07 0x07
258#define SPDMEM_DDR4_MOD_ORG_CHIPWIDTH_MASK0x07 0x07
259#define SPDMEM_DDR4_MOD_ORG_BANKS_SHIFT3 3
260#define SPDMEM_DDR4_MOD_ORG_BANKS_MASK0x07 0x07
261#define SPDMEM_DDR4_DATAWIDTH_ECCMASK(1 << 3) (1 << 3)
262#define SPDMEM_DDR4_DATAWIDTH_PRIMASK0x07 0x07
263#define SPDMEM_DDR4_THERMAL_PRESENT(1 << 7) (1 << 7)
264
265#define SPDMEM_DDR4_RDIMM0x01 0x01
266#define SPDMEM_DDR4_UDIMM0x02 0x02
267#define SPDMEM_DDR4_SODIMM0x03 0x03
268#define SPDMEM_DDR4_LRDIMM0x04 0x04
269#define SPDMEM_DDR4_MINI_RDIMM0x05 0x05
270#define SPDMEM_DDR4_MINI_UDIMM0x06 0x06
271#define SPDMEM_DDR4_LP_DIMM0x07 0x07
272#define SPDMEM_DDR4_72B_SO_RDIMM0x08 0x08
273#define SPDMEM_DDR4_72B_SO_UDIMM0x09 0x09
274#define SPDMEM_DDR4_16B_SO_DIMM0x0c 0x0c
275#define SPDMEM_DDR4_32B_SO_DIMM0x0d 0x0d
276#define SPDMEM_DDR4_NON_DIMM0x0e 0x0e
277#define SPDMEM_DDR4_MODTYPE_MASK0x0f 0x0f
278#define SPDMEM_DDR4_MODTYPE_HYBRID0x80 0x80
279
280static const uint8_t ddr2_cycle_tenths[] = {
281 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 25, 33, 66, 75, 0, 0
282};
283
284#define SPDMEM_TYPE_MAXLEN16 16
285
286uint16_t spdmem_crc16(struct spdmem_softc *, int);
287static inline
288uint8_t spdmem_read(struct spdmem_softc *, uint8_t);
289void spdmem_sdram_decode(struct spdmem_softc *, struct spdmem *);
290void spdmem_rdr_decode(struct spdmem_softc *, struct spdmem *);
291void spdmem_ddr_decode(struct spdmem_softc *, struct spdmem *);
292void spdmem_ddr2_decode(struct spdmem_softc *, struct spdmem *);
293void spdmem_fbdimm_decode(struct spdmem_softc *, struct spdmem *);
294void spdmem_ddr3_decode(struct spdmem_softc *, struct spdmem *);
295
296struct cfdriver spdmem_cd = {
297 NULL((void *)0), "spdmem", DV_DULL
298};
299
300#define IS_RAMBUS_TYPE(s->sm_len < 4) (s->sm_len < 4)
301
302static const char *spdmem_basic_types[] = {
303 "unknown",
304 "FPM",
305 "EDO",
306 "Pipelined Nibble",
307 "SDRAM",
308 "ROM",
309 "DDR SGRAM",
310 "DDR SDRAM",
311 "DDR2 SDRAM",
312 "DDR2 SDRAM FB-DIMM",
313 "DDR2 SDRAM FB-DIMM Probe",
314 "DDR3 SDRAM",
315 "DDR4 SDRAM",
316 "unknown",
317 "DDR4E SDRAM",
318 "LPDDR3 SDRAM",
319 "LPDDR4 SDRAM",
320 "LPDDR4X SDRAM",
321 "DDR5 SDRAM",
322 "LPDDR5 SDRAM"
323};
324
325static const char *spdmem_superset_types[] = {
326 "unknown",
327 "ESDRAM",
328 "DDR ESDRAM",
329 "PEM EDO",
330 "PEM SDRAM"
331};
332
333static const char *spdmem_parity_types[] = {
334 "non-parity",
335 "data parity",
336 "ECC",
337 "data parity and ECC",
338 "cmd/addr parity",
339 "cmd/addr/data parity",
340 "cmd/addr parity, data ECC",
341 "cmd/addr/data parity, data ECC"
342};
343
344static inline uint8_t
345spdmem_read(struct spdmem_softc *sc, uint8_t reg)
346{
347 return (*sc->sc_read)(sc, reg);
348}
349
350/* CRC functions used for certain memory types */
351uint16_t
352spdmem_crc16(struct spdmem_softc *sc, int count)
353{
354 uint16_t crc;
355 int i, j;
356 uint8_t val;
357 crc = 0;
358 for (j = 0; j <= count; j++) {
359 val = spdmem_read(sc, j);
360 crc = crc ^ val << 8;
361 for (i = 0; i < 8; ++i)
362 if (crc & 0x8000)
363 crc = crc << 1 ^ 0x1021;
364 else
365 crc = crc << 1;
366 }
367 return (crc & 0xFFFF);
368}
369
370void
371spdmem_sdram_decode(struct spdmem_softc *sc, struct spdmem *s)
372{
373 const char *type;
374 int dimm_size, p_clk;
375 int num_banks, per_chip;
376 uint8_t rows, cols;
377
378 type = spdmem_basic_types[s->sm_type];
379
380 if (s->sm_data[SPDMEM_SDR_SUPERSET0x1d] == SPDMEM_SUPERSET_SDR_PEM0x04)
381 type = spdmem_superset_types[SPDMEM_SUPERSET_SDR_PEM0x04];
382 if (s->sm_data[SPDMEM_SDR_SUPERSET0x1d] == SPDMEM_SUPERSET_ESDRAM0x01)
383 type = spdmem_superset_types[SPDMEM_SUPERSET_ESDRAM0x01];
384
385 num_banks = s->sm_data[SPDMEM_SDR_BANKS0x02];
386 per_chip = s->sm_data[SPDMEM_SDR_BANKS_PER_CHIP0x0e];
387 rows = s->sm_data[SPDMEM_SDR_ROWS0x00] & 0x0f;
388 cols = s->sm_data[SPDMEM_SDR_COLS0x01] & 0x0f;
389 dimm_size = (1 << (rows + cols - 17)) * num_banks * per_chip;
390
391 if (dimm_size > 0) {
392 if (dimm_size < 1024)
393 printf(" %dMB", dimm_size);
394 else
395 printf(" %dGB", dimm_size / 1024);
396 }
397
398 printf(" %s", type);
399
400 if (s->sm_data[SPDMEM_DDR_MOD_ATTRIB0x12] & SPDMEM_DDR_ATTRIB_REG(1 << 1))
401 printf(" registered");
402
403 if (s->sm_data[SPDMEM_FPM_CONFIG0x08] < 8)
404 printf(" %s",
405 spdmem_parity_types[s->sm_data[SPDMEM_FPM_CONFIG0x08]]);
406
407 p_clk = 66;
408 if (s->sm_len >= 128) {
409 switch (spdmem_read(sc, SPDMEM_SDR_FREQUENCY126)) {
410 case SPDMEM_SDR_FREQ_1000x64:
411 case SPDMEM_SDR_FREQ_1330x85:
412 /* We need to check ns to decide here */
413 if (s->sm_data[SPDMEM_SDR_CYCLE0x06] < 0x80)
414 p_clk = 133;
415 else
416 p_clk = 100;
417 break;
418 case SPDMEM_SDR_FREQ_660x66:
419 default:
420 p_clk = 66;
421 break;
422 }
423 }
424 printf(" PC%d", p_clk);
425
426 /* Print CAS latency */
427 if (s->sm_len < 128)
428 return;
429 if (spdmem_read(sc, SPDMEM_SDR_CAS127) & SPDMEM_SDR_CAS2(1 << 1))
430 printf("CL2");
431 else if (spdmem_read(sc, SPDMEM_SDR_CAS127) & SPDMEM_SDR_CAS3(1 << 2))
432 printf("CL3");
433}
434
435void
436spdmem_rdr_decode(struct spdmem_softc *sc, struct spdmem *s)
437{
438 int rimm_size;
439 uint8_t row_bits, col_bits, bank_bits;
440
441 row_bits = s->sm_data[SPDMEM_RDR_ROWS_COLS0x01] >> 4;
442 col_bits = s->sm_data[SPDMEM_RDR_ROWS_COLS0x01] & 0x0f;
443 bank_bits = s->sm_data[SPDMEM_RDR_BANK0x02] & 0x07;
444
445 /* subtracting 13 here is a cheaper way of dividing by 8k later */
446 rimm_size = 1 << (row_bits + col_bits + bank_bits - 13);
447
448 if (rimm_size < 1024)
449 printf(" %dMB ", rimm_size);
450 else
451 printf(" %dGB ", rimm_size / 1024);
452
453 switch(s->sm_data[SPDMEM_RDR_MODULE_TYPE0x00]) {
454 case SPDMEM_RDR_TYPE_RIMM1:
455 printf("RIMM");
456 break;
457 case SPDMEM_RDR_TYPE_SORIMM2:
458 printf("SO-RIMM");
459 break;
460 case SPDMEM_RDR_TYPE_EMBED3:
461 printf("Embedded Rambus");
462 break;
463 case SPDMEM_RDR_TYPE_RIMM324:
464 printf("RIMM32");
465 break;
466 }
467}
468
469void
470spdmem_ddr_decode(struct spdmem_softc *sc, struct spdmem *s)
471{
472 const char *type;
473 int dimm_size, cycle_time, d_clk, p_clk, bits;
474 int i, num_banks, per_chip;
475 uint8_t config, rows, cols, cl;
476
477 type = spdmem_basic_types[s->sm_type];
478
479 if (s->sm_data[SPDMEM_DDR_SUPERSET0x1d] == SPDMEM_SUPERSET_DDR_ESDRAM0x02)
480 type = spdmem_superset_types[SPDMEM_SUPERSET_DDR_ESDRAM0x02];
481
482 num_banks = s->sm_data[SPDMEM_SDR_BANKS0x02];
483 per_chip = s->sm_data[SPDMEM_SDR_BANKS_PER_CHIP0x0e];
484 rows = s->sm_data[SPDMEM_SDR_ROWS0x00] & 0x0f;
485 cols = s->sm_data[SPDMEM_SDR_COLS0x01] & 0x0f;
486 dimm_size = (1 << (rows + cols - 17)) * num_banks * per_chip;
487
488 if (dimm_size > 0) {
489 if (dimm_size < 1024)
490 printf(" %dMB", dimm_size);
491 else
492 printf(" %dGB", dimm_size / 1024);
493 }
494
495 printf(" %s", type);
496
497 if (s->sm_data[SPDMEM_DDR_MOD_ATTRIB0x12] & SPDMEM_DDR_ATTRIB_REG(1 << 1))
498 printf(" registered");
499
500 if (s->sm_data[SPDMEM_FPM_CONFIG0x08] < 8)
501 printf(" %s",
502 spdmem_parity_types[s->sm_data[SPDMEM_FPM_CONFIG0x08]]);
503
504 /* cycle_time is expressed in units of 0.01 ns */
505 cycle_time = (s->sm_data[SPDMEM_DDR_CYCLE0x06] >> 4) * 100 +
506 (s->sm_data[SPDMEM_DDR_CYCLE0x06] & 0x0f) * 10;
507
508 if (cycle_time != 0) {
509 /*
510 * cycle time is scaled by a factor of 100 to avoid using
511 * floating point. Calculate memory speed as the number
512 * of cycles per microsecond.
513 * DDR uses dual-pumped clock
514 */
515 d_clk = 100 * 1000 * 2;
516 config = s->sm_data[SPDMEM_FPM_CONFIG0x08];
517 bits = s->sm_data[SPDMEM_DDR_DATAWIDTH0x03] |
518 (s->sm_data[SPDMEM_DDR_DATAWIDTH0x03 + 1] << 8);
519 if (config == 1 || config == 2)
520 bits -= 8;
521
522 d_clk /= cycle_time;
523 p_clk = d_clk * bits / 8;
524 if ((p_clk % 100) >= 50)
525 p_clk += 50;
526 p_clk -= p_clk % 100;
527 printf(" PC%d", p_clk);
528 }
529
530 /* Print CAS latency */
531 for (i = 6; i >= 0; i--) {
532 if (s->sm_data[SPDMEM_DDR_CAS0x0f] & (1 << i)) {
533 cl = ((i * 10) / 2) + 10;
534 printf("CL%d.%d", cl / 10, cl % 10);
535 break;
536 }
537 }
538}
539
540void
541spdmem_ddr2_decode(struct spdmem_softc *sc, struct spdmem *s)
542{
543 const char *type;
544 int dimm_size, cycle_time, d_clk, p_clk, bits;
545 int i, num_ranks, density;
546 uint8_t config;
547
548 type = spdmem_basic_types[s->sm_type];
549
550 num_ranks = (s->sm_data[SPDMEM_DDR2_RANKS0x02] & 0x7) + 1;
551 density = (s->sm_data[SPDMEM_DDR2_RANK_DENSITY0x1c] & 0xf0) |
552 ((s->sm_data[SPDMEM_DDR2_RANK_DENSITY0x1c] & 0x0f) << 8);
553 dimm_size = num_ranks * density * 4;
554
555 if (dimm_size > 0) {
556 if (dimm_size < 1024)
557 printf(" %dMB", dimm_size);
558 else
559 printf(" %dGB", dimm_size / 1024);
560 }
561
562 printf(" %s", type);
563
564 if (s->sm_data[SPDMEM_DDR2_DIMMTYPE0x11] & SPDMEM_DDR2_TYPE_REGMASK((1 << 4) | (1 << 0)))
565 printf(" registered");
566
567 if (s->sm_data[SPDMEM_FPM_CONFIG0x08] < 8)
568 printf(" %s",
569 spdmem_parity_types[s->sm_data[SPDMEM_FPM_CONFIG0x08]]);
570
571 /* cycle_time is expressed in units of 0.01 ns */
572 cycle_time = (s->sm_data[SPDMEM_DDR2_CYCLE0x06] >> 4) * 100 +
573 ddr2_cycle_tenths[(s->sm_data[SPDMEM_DDR2_CYCLE0x06] & 0x0f)];
574
575 if (cycle_time != 0) {
576 /*
577 * cycle time is scaled by a factor of 100 to avoid using
578 * floating point. Calculate memory speed as the number
579 * of cycles per microsecond.
580 * DDR2 uses quad-pumped clock
581 */
582 d_clk = 100 * 1000 * 4;
583 config = s->sm_data[SPDMEM_FPM_CONFIG0x08];
584 bits = s->sm_data[SPDMEM_DDR2_DATAWIDTH0x03];
585 if ((config & 0x03) != 0)
586 bits -= 8;
587 d_clk /= cycle_time;
588 d_clk = (d_clk + 1) / 2;
589 p_clk = d_clk * bits / 8;
590 p_clk -= p_clk % 100;
591 printf(" PC2-%d", p_clk);
592 }
593
594 /* Print CAS latency */
595 for (i = 7; i >= 2; i--) {
596 if (s->sm_data[SPDMEM_DDR_CAS0x0f] & (1 << i)) {
597 printf("CL%d", i);
598 break;
599 }
600 }
601
602 switch (s->sm_data[SPDMEM_DDR2_DIMMTYPE0x11]) {
603 case SPDMEM_DDR2_SODIMM(1 << 2):
604 printf(" SO-DIMM");
605 break;
606 case SPDMEM_DDR2_MICRO_DIMM(1 << 3):
607 printf(" Micro-DIMM");
608 break;
609 case SPDMEM_DDR2_MINI_RDIMM(1 << 4):
610 case SPDMEM_DDR2_MINI_UDIMM(1 << 5):
611 printf(" Mini-DIMM");
612 break;
613 }
614}
615
616void
617spdmem_fbdimm_decode(struct spdmem_softc *sc, struct spdmem *s)
618{
619 int dimm_size, cycle_time, d_clk, p_clk, bits;
620 uint8_t rows, cols, dividend, divisor;
621 /*
622 * FB-DIMM is very much like DDR3
623 */
624
625 cols = (s->sm_data[SPDMEM_FBDIMM_ADDR0x01] & SPDMEM_FBDIMM_ADDR_COL0x0c) >>
626 SPDMEM_FBDIMM_ADDR_COL_SHIFT2;
627 rows = (s->sm_data[SPDMEM_FBDIMM_ADDR0x01] & SPDMEM_FBDIMM_ADDR_ROW0xe0) >>
628 SPDMEM_FBDIMM_ADDR_ROW_SHIFT5;
629 dimm_size = rows + 12 + cols + 9 - 20 - 3;
630
631 if (dimm_size < 1024)
632 printf(" %dMB", dimm_size);
633 else
634 printf(" %dGB", dimm_size / 1024);
635
636 dividend = s->sm_data[SPDMEM_FBDIMM_MTB_DIVIDEND0x06];
637 divisor = s->sm_data[SPDMEM_FBDIMM_MTB_DIVISOR0x07];
638
639 cycle_time = (1000 * dividend + (divisor / 2)) / divisor;
640
641 if (cycle_time != 0) {
642 /*
643 * cycle time is scaled by a factor of 1000 to avoid using
644 * floating point. Calculate memory speed as the number
645 * of cycles per microsecond.
646 */
647 d_clk = 1000 * 1000;
648
649 /* DDR2 FB-DIMM uses a dual-pumped clock */
650 d_clk *= 2;
651 bits = 1 << ((s->sm_data[SPDMEM_FBDIMM_RANKS0x04] &
652 SPDMEM_FBDIMM_RANKS_WIDTH0x07) + 2);
653
654 p_clk = (d_clk * bits) / 8 / cycle_time;
655 p_clk -= p_clk % 100;
656 printf(" PC2-%d", p_clk);
657 }
658}
659
660void
661spdmem_ddr3_decode(struct spdmem_softc *sc, struct spdmem *s)
662{
663 const char *type;
664 int dimm_size, cycle_time, d_clk, p_clk, bits;
665 uint8_t mtype, chipsize, dividend, divisor;
666 uint8_t datawidth, chipwidth, physbanks;
667
668 type = spdmem_basic_types[s->sm_type];
669
670 chipsize = s->sm_data[SPDMEM_DDR3_DENSITY0x01] &
671 SPDMEM_DDR3_DENSITY_CAPMASK0x0f;
672 datawidth = s->sm_data[SPDMEM_DDR3_DATAWIDTH0x05] &
673 SPDMEM_DDR3_DATAWIDTH_PRIMASK0x07;
674 chipwidth = s->sm_data[SPDMEM_DDR3_MOD_ORG0x04] &
675 SPDMEM_DDR3_MOD_ORG_CHIPWIDTH_MASK0x07;
676 physbanks = (s->sm_data[SPDMEM_DDR3_MOD_ORG0x04] >>
677 SPDMEM_DDR3_MOD_ORG_BANKS_SHIFT3) & SPDMEM_DDR3_MOD_ORG_BANKS_MASK0x07;
678
679 dimm_size = (chipsize + 28 - 20) - 3 + (datawidth + 3) -
680 (chipwidth + 2);
681 dimm_size = (1 << dimm_size) * (physbanks + 1);
682
683 if (dimm_size < 1024)
684 printf(" %dMB", dimm_size);
685 else
686 printf(" %dGB", dimm_size / 1024);
687
688 printf(" %s", type);
689
690 mtype = s->sm_data[SPDMEM_DDR3_MODTYPE0x00];
691 if (mtype == SPDMEM_DDR3_RDIMM0x01 || mtype == SPDMEM_DDR3_MINI_RDIMM0x05)
692 printf(" registered");
693
694 if (s->sm_data[SPDMEM_DDR3_DATAWIDTH0x05] & SPDMEM_DDR3_DATAWIDTH_ECCMASK(1 << 3))
695 printf(" ECC");
696
697 dividend = s->sm_data[SPDMEM_DDR3_MTB_DIVIDEND0x07];
698 divisor = s->sm_data[SPDMEM_DDR3_MTB_DIVISOR0x08];
699 cycle_time = (1000 * dividend + (divisor / 2)) / divisor;
700 cycle_time *= s->sm_data[SPDMEM_DDR3_TCKMIN0x09];
701
702 if (cycle_time != 0) {
703 /*
704 * cycle time is scaled by a factor of 1000 to avoid using
705 * floating point. Calculate memory speed as the number
706 * of cycles per microsecond.
707 * DDR3 uses a dual-pumped clock
708 */
709 d_clk = 1000 * 1000;
710 d_clk *= 2;
711 bits = 1 << ((s->sm_data[SPDMEM_DDR3_DATAWIDTH0x05] &
712 SPDMEM_DDR3_DATAWIDTH_PRIMASK0x07) + 3);
713 /*
714 * Calculate p_clk first, since for DDR3 we need maximum
715 * significance. DDR3 rating is not rounded to a multiple
716 * of 100. This results in cycle_time of 1.5ns displayed
717 * as p_clk PC3-10666 (d_clk DDR3-1333)
718 */
719 p_clk = (d_clk * bits) / 8 / cycle_time;
720 p_clk -= (p_clk % 100);
721 d_clk = ((d_clk + cycle_time / 2) ) / cycle_time;
Value stored to 'd_clk' is never read
722 printf(" PC3-%d", p_clk);
723 }
724
725 switch (s->sm_data[SPDMEM_DDR3_MODTYPE0x00]) {
726 case SPDMEM_DDR3_SODIMM0x03:
727 printf(" SO-DIMM");
728 break;
729 case SPDMEM_DDR3_MICRO_DIMM0x04:
730 printf(" Micro-DIMM");
731 break;
732 case SPDMEM_DDR3_MINI_RDIMM0x05:
733 case SPDMEM_DDR3_MINI_UDIMM0x06:
734 printf(" Mini-DIMM");
735 break;
736 }
737
738 if (s->sm_data[SPDMEM_DDR3_THERMAL0x1d] & SPDMEM_DDR3_THERMAL_PRESENT(1 << 7))
739 printf(" with thermal sensor");
740}
741
742void
743spdmem_ddr4_decode(struct spdmem_softc *sc, struct spdmem *s)
744{
745 static const int ddr4_chipsize[16] = { 256, 512, 1024, 2048, 4096,
746 8 * 1024, 16 * 1024, 32 * 1024, 12 * 1024, 24 * 1024,
747 3 * 1024, 6 * 1024, 18 * 1024 };
748 const char *type;
749 int dimm_size, cycle_time, d_clk, p_clk, bits;
750 uint8_t mtype, chipsize, mtb;
751 int8_t ftb;
752 uint8_t datawidth, chipwidth, physbanks, diecount = 0;
753
754 type = spdmem_basic_types[s->sm_type];
755
756 chipsize = s->sm_data[SPDMEM_DDR4_DENSITY0x01] &
757 SPDMEM_DDR4_DENSITY_CAPMASK0x0f;
758 datawidth = s->sm_data[SPDMEM_DDR4_DATAWIDTH0x0a] &
759 SPDMEM_DDR4_DATAWIDTH_PRIMASK0x07;
760 chipwidth = s->sm_data[SPDMEM_DDR4_MOD_ORG0x09] &
761 SPDMEM_DDR4_MOD_ORG_CHIPWIDTH_MASK0x07;
762 physbanks = (s->sm_data[SPDMEM_DDR4_MOD_ORG0x09] >>
763 SPDMEM_DDR4_MOD_ORG_BANKS_SHIFT3) & SPDMEM_DDR4_MOD_ORG_BANKS_MASK0x07;
764
765 if ((s->sm_data[SPDMEM_DDR4_PACK_TYPE0x03] &
766 SPDMEM_DDR4_PACK_TYPE_SIG_LOAD_MASK0x03) ==
767 SPDMEM_DDR4_PACK_TYPE_SIG_SINGLE_LOAD0x02) {
768 diecount = (s->sm_data[SPDMEM_DDR4_PACK_TYPE0x03] >>
769 SPDMEM_DDR4_PACK_TYPE_DIE_COUNT_SHIFT4) &
770 SPDMEM_DDR4_PACK_TYPE_DIE_COUNT_MASK0x07;
771 }
772
773 dimm_size = (datawidth + 3) - (chipwidth + 2);
774 dimm_size = (ddr4_chipsize[chipsize] / 8) * (1 << dimm_size) *
775 (physbanks + 1) * (diecount + 1);
776
777 if (dimm_size < 1024)
778 printf(" %dMB", dimm_size);
779 else
780 printf(" %dGB", dimm_size / 1024);
781
782 printf(" %s", type);
783
784 mtype = s->sm_data[SPDMEM_DDR4_MODTYPE0x00];
785 if (mtype & SPDMEM_DDR4_MODTYPE_HYBRID0x80)
786 printf(" hybrid");
787 mtype &= SPDMEM_DDR4_MODTYPE_MASK0x0f;
788 if (mtype == SPDMEM_DDR4_RDIMM0x01 || mtype == SPDMEM_DDR4_MINI_RDIMM0x05 ||
789 mtype == SPDMEM_DDR4_72B_SO_RDIMM0x08)
790 printf(" registered");
791 if (mtype == SPDMEM_DDR4_72B_SO_UDIMM0x09 ||
792 mtype == SPDMEM_DDR4_72B_SO_RDIMM0x08)
793 printf(" 72-bit");
794 if (mtype == SPDMEM_DDR4_32B_SO_DIMM0x0d)
795 printf(" 32-bit");
796 if (mtype == SPDMEM_DDR4_16B_SO_DIMM0x0c)
797 printf(" 16-bit");
798
799 if (s->sm_data[SPDMEM_DDR4_DATAWIDTH0x0a] & SPDMEM_DDR4_DATAWIDTH_ECCMASK(1 << 3))
800 printf(" ECC");
801
802 mtb = s->sm_data[SPDMEM_DDR4_TCKMIN_MTB0x0f];
803 /* SPDMEM_DDR4_TCKMIN_FTB (addr 125) is outside of s->sm_data */
804 ftb = spdmem_read(sc, SPDMEM_DDR4_TCKMIN_FTB0x7d);
805 cycle_time = mtb * 125 + ftb; /* in ps */
806
807 if (cycle_time != 0) {
808 /*
809 * cycle time is scaled by a factor of 1000 to avoid using
810 * floating point. Calculate memory speed as the number
811 * of cycles per microsecond.
812 * DDR4 uses a dual-pumped clock
813 */
814 d_clk = 1000 * 1000;
815 d_clk *= 2;
816 bits = 1 << ((s->sm_data[SPDMEM_DDR4_DATAWIDTH0x0a] &
817 SPDMEM_DDR4_DATAWIDTH_PRIMASK0x07) + 3);
818
819 p_clk = (d_clk * bits) / 8 / cycle_time;
820 p_clk -= (p_clk % 100);
821 printf(" PC4-%d", p_clk);
822 }
823
824 switch (s->sm_data[SPDMEM_DDR4_MODTYPE0x00] & SPDMEM_DDR4_MODTYPE_MASK0x0f) {
825 case SPDMEM_DDR4_SODIMM0x03:
826 case SPDMEM_DDR4_72B_SO_RDIMM0x08:
827 case SPDMEM_DDR4_72B_SO_UDIMM0x09:
828 case SPDMEM_DDR4_16B_SO_DIMM0x0c:
829 case SPDMEM_DDR4_32B_SO_DIMM0x0d:
830 printf(" SO-DIMM");
831 break;
832 case SPDMEM_DDR4_LRDIMM0x04:
833 printf(" LR-DIMM");
834 break;
835 case SPDMEM_DDR4_MINI_RDIMM0x05:
836 case SPDMEM_DDR4_MINI_UDIMM0x06:
837 printf(" Mini-DIMM");
838 break;
839 case SPDMEM_DDR4_LP_DIMM0x07:
840 printf(" LP-DIMM");
841 break;
842 case SPDMEM_DDR4_NON_DIMM0x0e:
843 printf(" non-DIMM solution");
844 break;
845 }
846
847 if (s->sm_data[SPDMEM_DDR4_THERMAL0x0b] & SPDMEM_DDR4_THERMAL_PRESENT(1 << 7))
848 printf(" with thermal sensor");
849}
850
851int
852spdmem_probe(struct spdmem_softc *sc)
853{
854 uint8_t i, val, type;
855 int cksum = 0;
856 int spd_len, spd_crc_cover;
857 uint16_t crc_calc, crc_spd;
858
859 type = spdmem_read(sc, 2);
860 /* For older memory types, validate the checksum over 1st 63 bytes */
861 if (type <= SPDMEM_MEMTYPE_DDR2SDRAM0x08) {
862 for (i = 0; i < 63; i++)
863 cksum += spdmem_read(sc, i);
864
865 val = spdmem_read(sc, 63);
866
867 if (cksum == 0 || (cksum & 0xff) != val) {
868 return 0;
869 } else
870 return 1;
871 }
872
873 /* For DDR3 and FBDIMM, verify the CRC */
874 else if (type <= SPDMEM_MEMTYPE_DDR3SDRAM0x0b) {
875 spd_len = spdmem_read(sc, 0);
876 if (spd_len & SPDMEM_SPDCRC_1160x80)
877 spd_crc_cover = 116;
878 else
879 spd_crc_cover = 125;
880 switch (spd_len & SPDMEM_SPDLEN_MASK0x70) {
881 case SPDMEM_SPDLEN_1280x00:
882 spd_len = 128;
883 break;
884 case SPDMEM_SPDLEN_1760x10:
885 spd_len = 176;
886 break;
887 case SPDMEM_SPDLEN_2560x20:
888 spd_len = 256;
889 break;
890 default:
891 return 0;
892 }
893calc_crc:
894 if (spd_crc_cover > spd_len)
895 return 0;
896 crc_calc = spdmem_crc16(sc, spd_crc_cover);
897 crc_spd = spdmem_read(sc, 127) << 8;
898 crc_spd |= spdmem_read(sc, 126);
899 if (crc_calc != crc_spd) {
900 return 0;
901 }
902 return 1;
903 } else if (type <= SPDMEM_MEMTYPE_LPDDR4SDRAM0x10) {
904 spd_len = spdmem_read(sc, 0);
905 spd_crc_cover = 125;
906 switch (spd_len & SPDMEM_DDR4_SPDLEN_MASK0x0f) {
907 case SPDMEM_DDR4_SPDLEN_1280x01:
908 spd_len = 128;
909 break;
910 case SPDMEM_DDR4_SPDLEN_2560x02:
911 spd_len = 256;
912 break;
913 case SPDMEM_DDR4_SPDLEN_3840x03:
914 spd_len = 384;
915 break;
916 case SPDMEM_DDR4_SPDLEN_5120x04:
917 spd_len = 512;
918 break;
919 default:
920 return 0;
921 }
922 goto calc_crc;
923 }
924
925 return 0;
926}
927
928void
929spdmem_attach_common(struct spdmem_softc *sc)
930{
931 struct spdmem *s = &(sc->sc_spd_data);
932 int i;
933
934 /* All SPD have at least 64 bytes of data including checksum */
935 for (i = 0; i < 64; i++) {
936 ((uint8_t *)s)[i] = spdmem_read(sc, i);
937 }
938
939 /*
940 * Decode and print SPD contents
941 */
942 if (s->sm_len < 4) {
943 if (s->sm_type == SPDMEM_MEMTYPE_DIRECT_RAMBUS0x01)
944 spdmem_rdr_decode(sc, s);
945 else
946 printf(" no decode method for Rambus memory");
947 } else {
948 switch(s->sm_type) {
949 case SPDMEM_MEMTYPE_EDO0x02:
950 case SPDMEM_MEMTYPE_SDRAM0x04:
951 spdmem_sdram_decode(sc, s);
952 break;
953 case SPDMEM_MEMTYPE_DDRSDRAM0x07:
954 spdmem_ddr_decode(sc, s);
955 break;
956 case SPDMEM_MEMTYPE_DDR2SDRAM0x08:
957 spdmem_ddr2_decode(sc, s);
958 break;
959 case SPDMEM_MEMTYPE_FBDIMM0x09:
960 case SPDMEM_MEMTYPE_FBDIMM_PROBE0x0a:
961 spdmem_fbdimm_decode(sc, s);
962 break;
963 case SPDMEM_MEMTYPE_DDR3SDRAM0x0b:
964 spdmem_ddr3_decode(sc, s);
965 break;
966 case SPDMEM_MEMTYPE_DDR4SDRAM0x0c:
967 case SPDMEM_MEMTYPE_DDR4ESDRAM0x0e:
968 case SPDMEM_MEMTYPE_LPDDR3SDRAM0x0f:
969 case SPDMEM_MEMTYPE_LPDDR4SDRAM0x10:
970 spdmem_ddr4_decode(sc, s);
971 break;
972 case SPDMEM_MEMTYPE_NONE0xff:
973 printf(" no EEPROM found");
974 break;
975 default:
976 if (s->sm_type <= SPDMEM_MEMTYPE_LPDDR5SDRAM0x13)
977 printf(" no decode method for %s memory",
978 spdmem_basic_types[s->sm_type]);
979 else
980 printf(" unknown memory type %d", s->sm_type);
981 break;
982 }
983 }
984
985 printf("\n");
986}