Home | History | Annotate | Line # | Download | only in ic
spdmem.c revision 1.1.2.2
      1  1.1.2.2  uebayasi /* $NetBSD: spdmem.c,v 1.1.2.2 2010/04/30 14:43:23 uebayasi Exp $ */
      2  1.1.2.2  uebayasi 
      3  1.1.2.2  uebayasi /*
      4  1.1.2.2  uebayasi  * Copyright (c) 2007 Nicolas Joly
      5  1.1.2.2  uebayasi  * Copyright (c) 2007 Paul Goyette
      6  1.1.2.2  uebayasi  * Copyright (c) 2007 Tobias Nygren
      7  1.1.2.2  uebayasi  * All rights reserved.
      8  1.1.2.2  uebayasi  *
      9  1.1.2.2  uebayasi  * Redistribution and use in source and binary forms, with or without
     10  1.1.2.2  uebayasi  * modification, are permitted provided that the following conditions
     11  1.1.2.2  uebayasi  * are met:
     12  1.1.2.2  uebayasi  * 1. Redistributions of source code must retain the above copyright
     13  1.1.2.2  uebayasi  *    notice, this list of conditions and the following disclaimer.
     14  1.1.2.2  uebayasi  * 2. Redistributions in binary form must reproduce the above copyright
     15  1.1.2.2  uebayasi  *    notice, this list of conditions and the following disclaimer in the
     16  1.1.2.2  uebayasi  *    documentation and/or other materials provided with the distribution.
     17  1.1.2.2  uebayasi  * 3. The name of the author may not be used to endorse or promote products
     18  1.1.2.2  uebayasi  *    derived from this software without specific prior written permission.
     19  1.1.2.2  uebayasi  *
     20  1.1.2.2  uebayasi  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS
     21  1.1.2.2  uebayasi  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  1.1.2.2  uebayasi  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  1.1.2.2  uebayasi  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24  1.1.2.2  uebayasi  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25  1.1.2.2  uebayasi  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26  1.1.2.2  uebayasi  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27  1.1.2.2  uebayasi  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28  1.1.2.2  uebayasi  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29  1.1.2.2  uebayasi  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30  1.1.2.2  uebayasi  * POSSIBILITY OF SUCH DAMAGE.
     31  1.1.2.2  uebayasi  */
     32  1.1.2.2  uebayasi 
     33  1.1.2.2  uebayasi /*
     34  1.1.2.2  uebayasi  * Serial Presence Detect (SPD) memory identification
     35  1.1.2.2  uebayasi  */
     36  1.1.2.2  uebayasi 
     37  1.1.2.2  uebayasi #include <sys/cdefs.h>
     38  1.1.2.2  uebayasi __KERNEL_RCSID(0, "$NetBSD: spdmem.c,v 1.1.2.2 2010/04/30 14:43:23 uebayasi Exp $");
     39  1.1.2.2  uebayasi 
     40  1.1.2.2  uebayasi #include <sys/param.h>
     41  1.1.2.2  uebayasi #include <sys/device.h>
     42  1.1.2.2  uebayasi #include <sys/endian.h>
     43  1.1.2.2  uebayasi #include <sys/sysctl.h>
     44  1.1.2.2  uebayasi #include <machine/bswap.h>
     45  1.1.2.2  uebayasi 
     46  1.1.2.2  uebayasi #include <dev/i2c/i2cvar.h>
     47  1.1.2.2  uebayasi #include <dev/ic/spdmemreg.h>
     48  1.1.2.2  uebayasi #include <dev/ic/spdmemvar.h>
     49  1.1.2.2  uebayasi 
     50  1.1.2.2  uebayasi SYSCTL_SETUP_PROTO(sysctl_spdmem_setup);
     51  1.1.2.2  uebayasi 
     52  1.1.2.2  uebayasi /* Routines for decoding spd data */
     53  1.1.2.2  uebayasi static void decode_edofpm(const struct sysctlnode *, device_t, struct spdmem *);
     54  1.1.2.2  uebayasi static void decode_rom(const struct sysctlnode *, device_t, struct spdmem *);
     55  1.1.2.2  uebayasi static void decode_sdram(const struct sysctlnode *, device_t, struct spdmem *,
     56  1.1.2.2  uebayasi 	int);
     57  1.1.2.2  uebayasi static void decode_ddr(const struct sysctlnode *, device_t, struct spdmem *);
     58  1.1.2.2  uebayasi static void decode_ddr2(const struct sysctlnode *, device_t, struct spdmem *);
     59  1.1.2.2  uebayasi static void decode_ddr3(const struct sysctlnode *, device_t, struct spdmem *);
     60  1.1.2.2  uebayasi static void decode_fbdimm(const struct sysctlnode *, device_t, struct spdmem *);
     61  1.1.2.2  uebayasi 
     62  1.1.2.2  uebayasi static void decode_size_speed(const struct sysctlnode *, int, int, int, int,
     63  1.1.2.2  uebayasi 			      bool, const char *, int);
     64  1.1.2.2  uebayasi static void decode_voltage_refresh(device_t, struct spdmem *);
     65  1.1.2.2  uebayasi 
     66  1.1.2.2  uebayasi #define IS_RAMBUS_TYPE (s->sm_len < 4)
     67  1.1.2.2  uebayasi 
     68  1.1.2.2  uebayasi static const char* spdmem_basic_types[] = {
     69  1.1.2.2  uebayasi 	"unknown",
     70  1.1.2.2  uebayasi 	"FPM",
     71  1.1.2.2  uebayasi 	"EDO",
     72  1.1.2.2  uebayasi 	"Pipelined Nibble",
     73  1.1.2.2  uebayasi 	"SDRAM",
     74  1.1.2.2  uebayasi 	"ROM",
     75  1.1.2.2  uebayasi 	"DDR SGRAM",
     76  1.1.2.2  uebayasi 	"DDR SDRAM",
     77  1.1.2.2  uebayasi 	"DDR2 SDRAM",
     78  1.1.2.2  uebayasi 	"DDR2 SDRAM FB",
     79  1.1.2.2  uebayasi 	"DDR2 SDRAM FB Probe",
     80  1.1.2.2  uebayasi 	"DDR3 SDRAM"
     81  1.1.2.2  uebayasi };
     82  1.1.2.2  uebayasi 
     83  1.1.2.2  uebayasi static const char* spdmem_superset_types[] = {
     84  1.1.2.2  uebayasi 	"unknown",
     85  1.1.2.2  uebayasi 	"ESDRAM",
     86  1.1.2.2  uebayasi 	"DDR ESDRAM",
     87  1.1.2.2  uebayasi 	"PEM EDO",
     88  1.1.2.2  uebayasi 	"PEM SDRAM"
     89  1.1.2.2  uebayasi };
     90  1.1.2.2  uebayasi 
     91  1.1.2.2  uebayasi static const char* spdmem_voltage_types[] = {
     92  1.1.2.2  uebayasi 	"TTL (5V tolerant)",
     93  1.1.2.2  uebayasi 	"LvTTL (not 5V tolerant)",
     94  1.1.2.2  uebayasi 	"HSTL 1.5V",
     95  1.1.2.2  uebayasi 	"SSTL 3.3V",
     96  1.1.2.2  uebayasi 	"SSTL 2.5V",
     97  1.1.2.2  uebayasi 	"SSTL 1.8V"
     98  1.1.2.2  uebayasi };
     99  1.1.2.2  uebayasi 
    100  1.1.2.2  uebayasi static const char* spdmem_refresh_types[] = {
    101  1.1.2.2  uebayasi 	"15.625us",
    102  1.1.2.2  uebayasi 	"3.9us",
    103  1.1.2.2  uebayasi 	"7.8us",
    104  1.1.2.2  uebayasi 	"31.3us",
    105  1.1.2.2  uebayasi 	"62.5us",
    106  1.1.2.2  uebayasi 	"125us"
    107  1.1.2.2  uebayasi };
    108  1.1.2.2  uebayasi 
    109  1.1.2.2  uebayasi static const char* spdmem_parity_types[] = {
    110  1.1.2.2  uebayasi 	"no parity or ECC",
    111  1.1.2.2  uebayasi 	"data parity",
    112  1.1.2.2  uebayasi 	"data ECC",
    113  1.1.2.2  uebayasi 	"data parity and ECC",
    114  1.1.2.2  uebayasi 	"cmd/addr parity",
    115  1.1.2.2  uebayasi 	"cmd/addr/data parity",
    116  1.1.2.2  uebayasi 	"cmd/addr parity, data ECC",
    117  1.1.2.2  uebayasi 	"cmd/addr/data parity, data ECC"
    118  1.1.2.2  uebayasi };
    119  1.1.2.2  uebayasi 
    120  1.1.2.2  uebayasi /* Cycle time fractional values (units of .001 ns) for DDR2 SDRAM */
    121  1.1.2.2  uebayasi static const uint16_t spdmem_cycle_frac[] = {
    122  1.1.2.2  uebayasi 	0, 100, 200, 300, 400, 500, 600, 700, 800, 900,
    123  1.1.2.2  uebayasi 	250, 333, 667, 750, 999, 999
    124  1.1.2.2  uebayasi };
    125  1.1.2.2  uebayasi 
    126  1.1.2.2  uebayasi /* Format string for timing info */
    127  1.1.2.2  uebayasi static const char* latency="tAA-tRCD-tRP-tRAS: %d-%d-%d-%d\n";
    128  1.1.2.2  uebayasi 
    129  1.1.2.2  uebayasi /* sysctl stuff */
    130  1.1.2.2  uebayasi static int hw_node = CTL_EOL;
    131  1.1.2.2  uebayasi 
    132  1.1.2.2  uebayasi /* CRC functions used for certain memory types */
    133  1.1.2.2  uebayasi 
    134  1.1.2.2  uebayasi static uint16_t spdcrc16 (struct spdmem_softc *sc, int count)
    135  1.1.2.2  uebayasi {
    136  1.1.2.2  uebayasi 	uint16_t crc;
    137  1.1.2.2  uebayasi 	int i, j;
    138  1.1.2.2  uebayasi 	uint8_t val;
    139  1.1.2.2  uebayasi 	crc = 0;
    140  1.1.2.2  uebayasi 	for (j = 0; j <= count; j++) {
    141  1.1.2.2  uebayasi 		val = (sc->sc_read)(sc, j);
    142  1.1.2.2  uebayasi 		crc = crc ^ val << 8;
    143  1.1.2.2  uebayasi 		for (i = 0; i < 8; ++i)
    144  1.1.2.2  uebayasi 			if (crc & 0x8000)
    145  1.1.2.2  uebayasi 				crc = crc << 1 ^ 0x1021;
    146  1.1.2.2  uebayasi 			else
    147  1.1.2.2  uebayasi 				crc = crc << 1;
    148  1.1.2.2  uebayasi 	}
    149  1.1.2.2  uebayasi 	return (crc & 0xFFFF);
    150  1.1.2.2  uebayasi }
    151  1.1.2.2  uebayasi 
    152  1.1.2.2  uebayasi int
    153  1.1.2.2  uebayasi spdmem_common_probe(struct spdmem_softc *sc)
    154  1.1.2.2  uebayasi {
    155  1.1.2.2  uebayasi 	int cksum = 0;
    156  1.1.2.2  uebayasi 	uint8_t i, val, spd_type;
    157  1.1.2.2  uebayasi 	int spd_len, spd_crc_cover;
    158  1.1.2.2  uebayasi 	uint16_t crc_calc, crc_spd;
    159  1.1.2.2  uebayasi 
    160  1.1.2.2  uebayasi 	spd_type = (sc->sc_read)(sc, 2);
    161  1.1.2.2  uebayasi 
    162  1.1.2.2  uebayasi 	/* For older memory types, validate the checksum over 1st 63 bytes */
    163  1.1.2.2  uebayasi 	if (spd_type <= SPDMEM_MEMTYPE_DDR2SDRAM) {
    164  1.1.2.2  uebayasi 		for (i = 0; i < 63; i++)
    165  1.1.2.2  uebayasi 			cksum += (sc->sc_read)(sc, i);
    166  1.1.2.2  uebayasi 
    167  1.1.2.2  uebayasi 		val = (sc->sc_read)(sc, 63);
    168  1.1.2.2  uebayasi 
    169  1.1.2.2  uebayasi 		if (cksum == 0 || (cksum & 0xff) != val) {
    170  1.1.2.2  uebayasi 			aprint_debug("spd checksum failed, calc = 0x%02x, "
    171  1.1.2.2  uebayasi 				     "spd = 0x%02x\n", cksum, val);
    172  1.1.2.2  uebayasi 			return 0;
    173  1.1.2.2  uebayasi 		} else
    174  1.1.2.2  uebayasi 			return 1;
    175  1.1.2.2  uebayasi 	}
    176  1.1.2.2  uebayasi 
    177  1.1.2.2  uebayasi 	/* For DDR3 and FBDIMM, verify the CRC */
    178  1.1.2.2  uebayasi 	else if (spd_type <= SPDMEM_MEMTYPE_DDR3SDRAM) {
    179  1.1.2.2  uebayasi 		spd_len = (sc->sc_read)(sc, 0);
    180  1.1.2.2  uebayasi 		if (spd_len && SPDMEM_SPDCRC_116)
    181  1.1.2.2  uebayasi 			spd_crc_cover = 116;
    182  1.1.2.2  uebayasi 		else
    183  1.1.2.2  uebayasi 			spd_crc_cover = 125;
    184  1.1.2.2  uebayasi 		switch (spd_len & SPDMEM_SPDLEN_MASK) {
    185  1.1.2.2  uebayasi 		case SPDMEM_SPDLEN_128:
    186  1.1.2.2  uebayasi 			spd_len = 128;
    187  1.1.2.2  uebayasi 			break;
    188  1.1.2.2  uebayasi 		case SPDMEM_SPDLEN_176:
    189  1.1.2.2  uebayasi 			spd_len = 176;
    190  1.1.2.2  uebayasi 			break;
    191  1.1.2.2  uebayasi 		case SPDMEM_SPDLEN_256:
    192  1.1.2.2  uebayasi 			spd_len = 256;
    193  1.1.2.2  uebayasi 			break;
    194  1.1.2.2  uebayasi 		default:
    195  1.1.2.2  uebayasi 			return 0;
    196  1.1.2.2  uebayasi 		}
    197  1.1.2.2  uebayasi 		if (spd_crc_cover > spd_len)
    198  1.1.2.2  uebayasi 			return 0;
    199  1.1.2.2  uebayasi 		crc_calc = spdcrc16(sc, spd_crc_cover);
    200  1.1.2.2  uebayasi 		crc_spd = (sc->sc_read)(sc, 127) << 8;
    201  1.1.2.2  uebayasi 		crc_spd |= (sc->sc_read)(sc, 126);
    202  1.1.2.2  uebayasi 		if (crc_calc != crc_spd) {
    203  1.1.2.2  uebayasi 			aprint_debug("crc16 failed, covers %d bytes, "
    204  1.1.2.2  uebayasi 				     "calc = 0x%04x, spd = 0x%04x\n",
    205  1.1.2.2  uebayasi 				     spd_crc_cover, crc_calc, crc_spd);
    206  1.1.2.2  uebayasi 			return 0;
    207  1.1.2.2  uebayasi 		}
    208  1.1.2.2  uebayasi 		return 1;
    209  1.1.2.2  uebayasi 	}
    210  1.1.2.2  uebayasi 
    211  1.1.2.2  uebayasi 	/* For unrecognized memory types, don't match at all */
    212  1.1.2.2  uebayasi 	return 0;
    213  1.1.2.2  uebayasi }
    214  1.1.2.2  uebayasi 
    215  1.1.2.2  uebayasi void
    216  1.1.2.2  uebayasi spdmem_common_attach(struct spdmem_softc *sc, device_t self)
    217  1.1.2.2  uebayasi {
    218  1.1.2.2  uebayasi 	struct spdmem *s = &(sc->sc_spd_data);
    219  1.1.2.2  uebayasi 	const char *type;
    220  1.1.2.2  uebayasi 	const char *rambus_rev = "Reserved";
    221  1.1.2.2  uebayasi 	int dimm_size;
    222  1.1.2.2  uebayasi 	int i;
    223  1.1.2.2  uebayasi 	unsigned int spd_len, spd_size;
    224  1.1.2.2  uebayasi 	const struct sysctlnode *node = NULL;
    225  1.1.2.2  uebayasi 
    226  1.1.2.2  uebayasi 	/*
    227  1.1.2.2  uebayasi 	 * FBDIMM and DDR3 (and probably all newer) have a different
    228  1.1.2.2  uebayasi 	 * encoding of the SPD EEPROM used/total sizes
    229  1.1.2.2  uebayasi 	 */
    230  1.1.2.2  uebayasi 	s->sm_len = (sc->sc_read)(sc, 0);
    231  1.1.2.2  uebayasi 	s->sm_size = (sc->sc_read)(sc, 1);
    232  1.1.2.2  uebayasi 	s->sm_type = (sc->sc_read)(sc, 2);
    233  1.1.2.2  uebayasi 
    234  1.1.2.2  uebayasi 	if (s->sm_type >= SPDMEM_MEMTYPE_FBDIMM) {
    235  1.1.2.2  uebayasi 		spd_size = 64 << (s->sm_len & SPDMEM_SPDSIZE_MASK);
    236  1.1.2.2  uebayasi 		switch (s->sm_len & SPDMEM_SPDLEN_MASK) {
    237  1.1.2.2  uebayasi 		case SPDMEM_SPDLEN_128:
    238  1.1.2.2  uebayasi 			spd_len = 128;
    239  1.1.2.2  uebayasi 			break;
    240  1.1.2.2  uebayasi 		case SPDMEM_SPDLEN_176:
    241  1.1.2.2  uebayasi 			spd_len = 176;
    242  1.1.2.2  uebayasi 			break;
    243  1.1.2.2  uebayasi 		case SPDMEM_SPDLEN_256:
    244  1.1.2.2  uebayasi 			spd_len = 256;
    245  1.1.2.2  uebayasi 			break;
    246  1.1.2.2  uebayasi 		default:
    247  1.1.2.2  uebayasi 			spd_len = 64;
    248  1.1.2.2  uebayasi 			break;
    249  1.1.2.2  uebayasi 		}
    250  1.1.2.2  uebayasi 	} else {
    251  1.1.2.2  uebayasi 		spd_size = 1 << s->sm_size;
    252  1.1.2.2  uebayasi 		spd_len = s->sm_len;
    253  1.1.2.2  uebayasi 		if (spd_len < 64)
    254  1.1.2.2  uebayasi 			spd_len = 64;
    255  1.1.2.2  uebayasi 	}
    256  1.1.2.2  uebayasi 	if (spd_len > spd_size)
    257  1.1.2.2  uebayasi 		spd_len = spd_size;
    258  1.1.2.2  uebayasi 	if (spd_len > sizeof(struct spdmem))
    259  1.1.2.2  uebayasi 		spd_len = sizeof(struct spdmem);
    260  1.1.2.2  uebayasi 	for (i = 3; i < spd_len; i++)
    261  1.1.2.2  uebayasi 		((uint8_t *)s)[i] = (sc->sc_read)(sc, i);
    262  1.1.2.2  uebayasi 
    263  1.1.2.2  uebayasi #ifdef DEBUG
    264  1.1.2.2  uebayasi 	for (i = 0; i < spd_len;  i += 16) {
    265  1.1.2.2  uebayasi 		int j, k;
    266  1.1.2.2  uebayasi 		aprint_debug("\n");
    267  1.1.2.2  uebayasi 		aprint_debug_dev(self, "0x%02x:", i);
    268  1.1.2.2  uebayasi 		k = (spd_len > i + 16) ? spd_len : i + 16;
    269  1.1.2.2  uebayasi 		for (j = i; j < k; j++)
    270  1.1.2.2  uebayasi 			aprint_debug(" %02x", ((uint8_t *)s)[j]);
    271  1.1.2.2  uebayasi 	}
    272  1.1.2.2  uebayasi 	aprint_debug("\n");
    273  1.1.2.2  uebayasi 	aprint_debug_dev(self, "");
    274  1.1.2.2  uebayasi #endif
    275  1.1.2.2  uebayasi 
    276  1.1.2.2  uebayasi 	/*
    277  1.1.2.2  uebayasi 	 * Setup our sysctl subtree, hw.spdmemN
    278  1.1.2.2  uebayasi 	 */
    279  1.1.2.2  uebayasi 	if (hw_node != CTL_EOL)
    280  1.1.2.2  uebayasi 		sysctl_createv(NULL, 0, NULL, &node,
    281  1.1.2.2  uebayasi 		    0, CTLTYPE_NODE,
    282  1.1.2.2  uebayasi 		    device_xname(self), NULL, NULL, 0, NULL, 0,
    283  1.1.2.2  uebayasi 		    CTL_HW, CTL_CREATE, CTL_EOL);
    284  1.1.2.2  uebayasi 	if (node != NULL && spd_len != 0)
    285  1.1.2.2  uebayasi                 sysctl_createv(NULL, 0, NULL, NULL,
    286  1.1.2.2  uebayasi                     0,
    287  1.1.2.2  uebayasi                     CTLTYPE_STRUCT, "spd_data",
    288  1.1.2.2  uebayasi 		    SYSCTL_DESCR("raw spd data"), NULL,
    289  1.1.2.2  uebayasi                     0, s, spd_len,
    290  1.1.2.2  uebayasi                     CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL);
    291  1.1.2.2  uebayasi 
    292  1.1.2.2  uebayasi 	/*
    293  1.1.2.2  uebayasi 	 * Decode and print key SPD contents
    294  1.1.2.2  uebayasi 	 */
    295  1.1.2.2  uebayasi 	if (IS_RAMBUS_TYPE) {
    296  1.1.2.2  uebayasi 		if (s->sm_type == SPDMEM_MEMTYPE_RAMBUS)
    297  1.1.2.2  uebayasi 			type = "Rambus";
    298  1.1.2.2  uebayasi 		else if (s->sm_type == SPDMEM_MEMTYPE_DIRECTRAMBUS)
    299  1.1.2.2  uebayasi 			type = "Direct Rambus";
    300  1.1.2.2  uebayasi 		else
    301  1.1.2.2  uebayasi 			type = "Rambus (unknown)";
    302  1.1.2.2  uebayasi 
    303  1.1.2.2  uebayasi 		switch (s->sm_len) {
    304  1.1.2.2  uebayasi 		case 0:
    305  1.1.2.2  uebayasi 			rambus_rev = "Invalid";
    306  1.1.2.2  uebayasi 			break;
    307  1.1.2.2  uebayasi 		case 1:
    308  1.1.2.2  uebayasi 			rambus_rev = "0.7";
    309  1.1.2.2  uebayasi 			break;
    310  1.1.2.2  uebayasi 		case 2:
    311  1.1.2.2  uebayasi 			rambus_rev = "1.0";
    312  1.1.2.2  uebayasi 			break;
    313  1.1.2.2  uebayasi 		default:
    314  1.1.2.2  uebayasi 			rambus_rev = "Reserved";
    315  1.1.2.2  uebayasi 			break;
    316  1.1.2.2  uebayasi 		}
    317  1.1.2.2  uebayasi 	} else {
    318  1.1.2.2  uebayasi 		if (s->sm_type < __arraycount(spdmem_basic_types))
    319  1.1.2.2  uebayasi 			type = spdmem_basic_types[s->sm_type];
    320  1.1.2.2  uebayasi 		else
    321  1.1.2.2  uebayasi 			type = "unknown memory type";
    322  1.1.2.2  uebayasi 
    323  1.1.2.2  uebayasi 		if (s->sm_type == SPDMEM_MEMTYPE_EDO &&
    324  1.1.2.2  uebayasi 		    s->sm_fpm.fpm_superset == SPDMEM_SUPERSET_EDO_PEM)
    325  1.1.2.2  uebayasi 			type = spdmem_superset_types[SPDMEM_SUPERSET_EDO_PEM];
    326  1.1.2.2  uebayasi 		if (s->sm_type == SPDMEM_MEMTYPE_SDRAM &&
    327  1.1.2.2  uebayasi 		    s->sm_sdr.sdr_superset == SPDMEM_SUPERSET_SDRAM_PEM)
    328  1.1.2.2  uebayasi 			type = spdmem_superset_types[SPDMEM_SUPERSET_SDRAM_PEM];
    329  1.1.2.2  uebayasi 		if (s->sm_type == SPDMEM_MEMTYPE_DDRSDRAM &&
    330  1.1.2.2  uebayasi 		    s->sm_ddr.ddr_superset == SPDMEM_SUPERSET_DDR_ESDRAM)
    331  1.1.2.2  uebayasi 			type =
    332  1.1.2.2  uebayasi 			    spdmem_superset_types[SPDMEM_SUPERSET_DDR_ESDRAM];
    333  1.1.2.2  uebayasi 		if (s->sm_type == SPDMEM_MEMTYPE_SDRAM &&
    334  1.1.2.2  uebayasi 		    s->sm_sdr.sdr_superset == SPDMEM_SUPERSET_ESDRAM) {
    335  1.1.2.2  uebayasi 			type = spdmem_superset_types[SPDMEM_SUPERSET_ESDRAM];
    336  1.1.2.2  uebayasi 		}
    337  1.1.2.2  uebayasi 	}
    338  1.1.2.2  uebayasi 
    339  1.1.2.2  uebayasi 	aprint_naive("\n");
    340  1.1.2.2  uebayasi 	aprint_normal("\n");
    341  1.1.2.2  uebayasi 	aprint_normal_dev(self, "%s", type);
    342  1.1.2.2  uebayasi 	strlcpy(sc->sc_type, type, SPDMEM_TYPE_MAXLEN);
    343  1.1.2.2  uebayasi 	if (node != NULL)
    344  1.1.2.2  uebayasi 		sysctl_createv(NULL, 0, NULL, NULL,
    345  1.1.2.2  uebayasi 		    0,
    346  1.1.2.2  uebayasi 		    CTLTYPE_STRING, "mem_type",
    347  1.1.2.2  uebayasi 		    SYSCTL_DESCR("memory module type"), NULL,
    348  1.1.2.2  uebayasi 		    0, sc->sc_type, 0,
    349  1.1.2.2  uebayasi 		    CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL);
    350  1.1.2.2  uebayasi 
    351  1.1.2.2  uebayasi 	if (IS_RAMBUS_TYPE) {
    352  1.1.2.2  uebayasi 		aprint_normal(", SPD Revision %s", rambus_rev);
    353  1.1.2.2  uebayasi 		dimm_size = 1 << (s->sm_rdr.rdr_rows + s->sm_rdr.rdr_cols - 13);
    354  1.1.2.2  uebayasi 		if (dimm_size >= 1024)
    355  1.1.2.2  uebayasi 			aprint_normal(", %dGB\n", dimm_size / 1024);
    356  1.1.2.2  uebayasi 		else
    357  1.1.2.2  uebayasi 			aprint_normal(", %dMB\n", dimm_size);
    358  1.1.2.2  uebayasi 
    359  1.1.2.2  uebayasi 		/* No further decode for RAMBUS memory */
    360  1.1.2.2  uebayasi 		return;
    361  1.1.2.2  uebayasi 	}
    362  1.1.2.2  uebayasi 	switch (s->sm_type) {
    363  1.1.2.2  uebayasi 	case SPDMEM_MEMTYPE_EDO:
    364  1.1.2.2  uebayasi 	case SPDMEM_MEMTYPE_FPM:
    365  1.1.2.2  uebayasi 		decode_edofpm(node, self, s);
    366  1.1.2.2  uebayasi 		break;
    367  1.1.2.2  uebayasi 	case SPDMEM_MEMTYPE_ROM:
    368  1.1.2.2  uebayasi 		decode_rom(node, self, s);
    369  1.1.2.2  uebayasi 		break;
    370  1.1.2.2  uebayasi 	case SPDMEM_MEMTYPE_SDRAM:
    371  1.1.2.2  uebayasi 		decode_sdram(node, self, s, spd_len);
    372  1.1.2.2  uebayasi 		break;
    373  1.1.2.2  uebayasi 	case SPDMEM_MEMTYPE_DDRSDRAM:
    374  1.1.2.2  uebayasi 		decode_ddr(node, self, s);
    375  1.1.2.2  uebayasi 		break;
    376  1.1.2.2  uebayasi 	case SPDMEM_MEMTYPE_DDR2SDRAM:
    377  1.1.2.2  uebayasi 		decode_ddr2(node, self, s);
    378  1.1.2.2  uebayasi 		break;
    379  1.1.2.2  uebayasi 	case SPDMEM_MEMTYPE_DDR3SDRAM:
    380  1.1.2.2  uebayasi 		decode_ddr3(node, self, s);
    381  1.1.2.2  uebayasi 		break;
    382  1.1.2.2  uebayasi 	case SPDMEM_MEMTYPE_FBDIMM:
    383  1.1.2.2  uebayasi 	case SPDMEM_MEMTYPE_FBDIMM_PROBE:
    384  1.1.2.2  uebayasi 		decode_fbdimm(node, self, s);
    385  1.1.2.2  uebayasi 		break;
    386  1.1.2.2  uebayasi 	}
    387  1.1.2.2  uebayasi }
    388  1.1.2.2  uebayasi 
    389  1.1.2.2  uebayasi SYSCTL_SETUP(sysctl_spdmem_setup, "sysctl hw.spdmem subtree setup")
    390  1.1.2.2  uebayasi {
    391  1.1.2.2  uebayasi 	const struct sysctlnode *node;
    392  1.1.2.2  uebayasi 
    393  1.1.2.2  uebayasi 	if (sysctl_createv(clog, 0, NULL, &node,
    394  1.1.2.2  uebayasi 	    CTLFLAG_PERMANENT,
    395  1.1.2.2  uebayasi 	    CTLTYPE_NODE, "hw", NULL,
    396  1.1.2.2  uebayasi 	    NULL, 0, NULL, 0,
    397  1.1.2.2  uebayasi 	    CTL_HW, CTL_EOL) != 0)
    398  1.1.2.2  uebayasi 		return;
    399  1.1.2.2  uebayasi 
    400  1.1.2.2  uebayasi 	hw_node = node->sysctl_num;
    401  1.1.2.2  uebayasi }
    402  1.1.2.2  uebayasi 
    403  1.1.2.2  uebayasi static void
    404  1.1.2.2  uebayasi decode_size_speed(const struct sysctlnode *node, int dimm_size, int cycle_time,
    405  1.1.2.2  uebayasi 		  int d_clk, int bits, bool round, const char *ddr_type_string,
    406  1.1.2.2  uebayasi 		  int speed)
    407  1.1.2.2  uebayasi {
    408  1.1.2.2  uebayasi 	int p_clk;
    409  1.1.2.2  uebayasi 
    410  1.1.2.2  uebayasi 	if (dimm_size < 1024)
    411  1.1.2.2  uebayasi 		aprint_normal("%dMB", dimm_size);
    412  1.1.2.2  uebayasi 	else
    413  1.1.2.2  uebayasi 		aprint_normal("%dGB", dimm_size / 1024);
    414  1.1.2.2  uebayasi 	if (node != NULL)
    415  1.1.2.2  uebayasi 		sysctl_createv(NULL, 0, NULL, NULL,
    416  1.1.2.2  uebayasi 		    CTLFLAG_IMMEDIATE,
    417  1.1.2.2  uebayasi 		    CTLTYPE_INT, "size",
    418  1.1.2.2  uebayasi 		    SYSCTL_DESCR("module size in MB"), NULL,
    419  1.1.2.2  uebayasi 		    dimm_size, NULL, 0,
    420  1.1.2.2  uebayasi 		    CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL);
    421  1.1.2.2  uebayasi 
    422  1.1.2.2  uebayasi 	if (cycle_time == 0) {
    423  1.1.2.2  uebayasi 		aprint_normal("\n");
    424  1.1.2.2  uebayasi 		return;
    425  1.1.2.2  uebayasi 	}
    426  1.1.2.2  uebayasi 
    427  1.1.2.2  uebayasi 	/*
    428  1.1.2.2  uebayasi 	 * Calculate p_clk first, since for DDR3 we need maximum significance.
    429  1.1.2.2  uebayasi 	 * DDR3 rating is not rounded to a multiple of 100.  This results in
    430  1.1.2.2  uebayasi 	 * cycle_time of 1.5ns displayed as PC3-10666.
    431  1.1.2.2  uebayasi 	 *
    432  1.1.2.2  uebayasi 	 * For SDRAM, the speed is provided by the caller so we use it.
    433  1.1.2.2  uebayasi 	 */
    434  1.1.2.2  uebayasi 	d_clk *= 1000 * 1000;
    435  1.1.2.2  uebayasi 	if (speed)
    436  1.1.2.2  uebayasi 		p_clk = speed;
    437  1.1.2.2  uebayasi 	else
    438  1.1.2.2  uebayasi 		p_clk = (d_clk * bits) / 8 / cycle_time;
    439  1.1.2.2  uebayasi 	d_clk = ((d_clk + cycle_time / 2) ) / cycle_time;
    440  1.1.2.2  uebayasi 	if (round) {
    441  1.1.2.2  uebayasi 		if ((p_clk % 100) >= 50)
    442  1.1.2.2  uebayasi 			p_clk += 50;
    443  1.1.2.2  uebayasi 		p_clk -= p_clk % 100;
    444  1.1.2.2  uebayasi 	}
    445  1.1.2.2  uebayasi 	aprint_normal(", %dMHz (%s-%d)\n",
    446  1.1.2.2  uebayasi 		      d_clk, ddr_type_string, p_clk);
    447  1.1.2.2  uebayasi 	if (node != NULL)
    448  1.1.2.2  uebayasi 		sysctl_createv(NULL, 0, NULL, NULL,
    449  1.1.2.2  uebayasi 			       CTLFLAG_IMMEDIATE,
    450  1.1.2.2  uebayasi 			       CTLTYPE_INT, "speed",
    451  1.1.2.2  uebayasi 			       SYSCTL_DESCR("memory speed in MHz"),
    452  1.1.2.2  uebayasi 			       NULL, d_clk, NULL, 0,
    453  1.1.2.2  uebayasi 			       CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL);
    454  1.1.2.2  uebayasi }
    455  1.1.2.2  uebayasi 
    456  1.1.2.2  uebayasi static void
    457  1.1.2.2  uebayasi decode_voltage_refresh(device_t self, struct spdmem *s)
    458  1.1.2.2  uebayasi {
    459  1.1.2.2  uebayasi 	const char *voltage, *refresh;
    460  1.1.2.2  uebayasi 
    461  1.1.2.2  uebayasi 	if (s->sm_voltage < __arraycount(spdmem_voltage_types))
    462  1.1.2.2  uebayasi 		voltage = spdmem_voltage_types[s->sm_voltage];
    463  1.1.2.2  uebayasi 	else
    464  1.1.2.2  uebayasi 		voltage = "unknown";
    465  1.1.2.2  uebayasi 
    466  1.1.2.2  uebayasi 	if (s->sm_refresh < __arraycount(spdmem_refresh_types))
    467  1.1.2.2  uebayasi 		refresh = spdmem_refresh_types[s->sm_refresh];
    468  1.1.2.2  uebayasi 	else
    469  1.1.2.2  uebayasi 		refresh = "unknown";
    470  1.1.2.2  uebayasi 
    471  1.1.2.2  uebayasi 	aprint_verbose_dev(self, "voltage %s, refresh time %s%s\n",
    472  1.1.2.2  uebayasi 			voltage, refresh,
    473  1.1.2.2  uebayasi 			s->sm_selfrefresh?" (self-refreshing)":"");
    474  1.1.2.2  uebayasi }
    475  1.1.2.2  uebayasi 
    476  1.1.2.2  uebayasi static void
    477  1.1.2.2  uebayasi decode_edofpm(const struct sysctlnode *node, device_t self, struct spdmem *s) {
    478  1.1.2.2  uebayasi 	aprint_normal("\n");
    479  1.1.2.2  uebayasi 	aprint_verbose_dev(self,
    480  1.1.2.2  uebayasi 	    "%d rows, %d cols, %d banks, %dns tRAC, %dns tCAC\n",
    481  1.1.2.2  uebayasi 	    s->sm_fpm.fpm_rows, s->sm_fpm.fpm_cols, s->sm_fpm.fpm_banks,
    482  1.1.2.2  uebayasi 	    s->sm_fpm.fpm_tRAC, s->sm_fpm.fpm_tCAC);
    483  1.1.2.2  uebayasi }
    484  1.1.2.2  uebayasi 
    485  1.1.2.2  uebayasi static void
    486  1.1.2.2  uebayasi decode_rom(const struct sysctlnode *node, device_t self, struct spdmem *s) {
    487  1.1.2.2  uebayasi 	aprint_normal("\n");
    488  1.1.2.2  uebayasi 	aprint_verbose_dev(self, "%d rows, %d cols, %d banks\n",
    489  1.1.2.2  uebayasi 	    s->sm_rom.rom_rows, s->sm_rom.rom_cols, s->sm_rom.rom_banks);
    490  1.1.2.2  uebayasi }
    491  1.1.2.2  uebayasi 
    492  1.1.2.2  uebayasi static void
    493  1.1.2.2  uebayasi decode_sdram(const struct sysctlnode *node, device_t self, struct spdmem *s,
    494  1.1.2.2  uebayasi 	     int spd_len) {
    495  1.1.2.2  uebayasi 	int dimm_size, cycle_time, bits, tAA, i, speed, freq;
    496  1.1.2.2  uebayasi 
    497  1.1.2.2  uebayasi 	aprint_normal("%s, %s, ",
    498  1.1.2.2  uebayasi 		(s->sm_sdr.sdr_mod_attrs & SPDMEM_SDR_MASK_REG)?
    499  1.1.2.2  uebayasi 			" (registered)":"",
    500  1.1.2.2  uebayasi 		(s->sm_config < __arraycount(spdmem_parity_types))?
    501  1.1.2.2  uebayasi 			spdmem_parity_types[s->sm_config]:"invalid parity");
    502  1.1.2.2  uebayasi 
    503  1.1.2.2  uebayasi 	dimm_size = 1 << (s->sm_sdr.sdr_rows + s->sm_sdr.sdr_cols - 17);
    504  1.1.2.2  uebayasi 	dimm_size *= s->sm_sdr.sdr_banks * s->sm_sdr.sdr_banks_per_chip;
    505  1.1.2.2  uebayasi 
    506  1.1.2.2  uebayasi 	cycle_time = s->sm_sdr.sdr_cycle_whole * 1000 +
    507  1.1.2.2  uebayasi 		     s->sm_sdr.sdr_cycle_tenths * 100;
    508  1.1.2.2  uebayasi 	bits = le16toh(s->sm_sdr.sdr_datawidth);
    509  1.1.2.2  uebayasi 	if (s->sm_config == 1 || s->sm_config == 2)
    510  1.1.2.2  uebayasi 		bits -= 8;
    511  1.1.2.2  uebayasi 
    512  1.1.2.2  uebayasi 	/* Calculate speed here - from OpenBSD */
    513  1.1.2.2  uebayasi 	if (spd_len >= 128)
    514  1.1.2.2  uebayasi 		freq = ((uint8_t *)s)[126];
    515  1.1.2.2  uebayasi 	else
    516  1.1.2.2  uebayasi 		freq = 0;
    517  1.1.2.2  uebayasi 	switch (freq) {
    518  1.1.2.2  uebayasi 		/*
    519  1.1.2.2  uebayasi 		 * Must check cycle time since some PC-133 DIMMs
    520  1.1.2.2  uebayasi 		 * actually report PC-100
    521  1.1.2.2  uebayasi 		 */
    522  1.1.2.2  uebayasi 	    case 100:
    523  1.1.2.2  uebayasi 	    case 133:
    524  1.1.2.2  uebayasi 		if (cycle_time < 8000)
    525  1.1.2.2  uebayasi 			speed = 133;
    526  1.1.2.2  uebayasi 		else
    527  1.1.2.2  uebayasi 			speed = 100;
    528  1.1.2.2  uebayasi 		break;
    529  1.1.2.2  uebayasi 	    case 0x66:		/* Legacy DIMMs use _hex_ 66! */
    530  1.1.2.2  uebayasi 	    default:
    531  1.1.2.2  uebayasi 		speed = 66;
    532  1.1.2.2  uebayasi 	}
    533  1.1.2.2  uebayasi 	decode_size_speed(node, dimm_size, cycle_time, 1, bits, FALSE, "PC",
    534  1.1.2.2  uebayasi 			  speed);
    535  1.1.2.2  uebayasi 
    536  1.1.2.2  uebayasi 	aprint_verbose_dev(self,
    537  1.1.2.2  uebayasi 	    "%d rows, %d cols, %d banks, %d banks/chip, %d.%dns cycle time\n",
    538  1.1.2.2  uebayasi 	    s->sm_sdr.sdr_rows, s->sm_sdr.sdr_cols, s->sm_sdr.sdr_banks,
    539  1.1.2.2  uebayasi 	    s->sm_sdr.sdr_banks_per_chip, cycle_time/1000,
    540  1.1.2.2  uebayasi 	    (cycle_time % 1000) / 100);
    541  1.1.2.2  uebayasi 
    542  1.1.2.2  uebayasi 	tAA  = 0;
    543  1.1.2.2  uebayasi 	for (i = 0; i < 8; i++)
    544  1.1.2.2  uebayasi 		if (s->sm_sdr.sdr_tCAS & (1 << i))
    545  1.1.2.2  uebayasi 			tAA = i;
    546  1.1.2.2  uebayasi 	tAA++;
    547  1.1.2.2  uebayasi 	aprint_verbose_dev(self, latency, tAA, s->sm_sdr.sdr_tRCD,
    548  1.1.2.2  uebayasi 	    s->sm_sdr.sdr_tRP, s->sm_sdr.sdr_tRAS);
    549  1.1.2.2  uebayasi 
    550  1.1.2.2  uebayasi 	decode_voltage_refresh(self, s);
    551  1.1.2.2  uebayasi }
    552  1.1.2.2  uebayasi 
    553  1.1.2.2  uebayasi static void
    554  1.1.2.2  uebayasi decode_ddr(const struct sysctlnode *node, device_t self, struct spdmem *s) {
    555  1.1.2.2  uebayasi 	int dimm_size, cycle_time, bits, tAA, i;
    556  1.1.2.2  uebayasi 
    557  1.1.2.2  uebayasi 	aprint_normal("%s, %s, ",
    558  1.1.2.2  uebayasi 		(s->sm_ddr.ddr_mod_attrs & SPDMEM_DDR_MASK_REG)?
    559  1.1.2.2  uebayasi 			" (registered)":"",
    560  1.1.2.2  uebayasi 		(s->sm_config < __arraycount(spdmem_parity_types))?
    561  1.1.2.2  uebayasi 			spdmem_parity_types[s->sm_config]:"invalid parity");
    562  1.1.2.2  uebayasi 
    563  1.1.2.2  uebayasi 	dimm_size = 1 << (s->sm_ddr.ddr_rows + s->sm_ddr.ddr_cols - 17);
    564  1.1.2.2  uebayasi 	dimm_size *= s->sm_ddr.ddr_ranks * s->sm_ddr.ddr_banks_per_chip;
    565  1.1.2.2  uebayasi 
    566  1.1.2.2  uebayasi 	cycle_time = s->sm_ddr.ddr_cycle_whole * 1000 +
    567  1.1.2.2  uebayasi 		  spdmem_cycle_frac[s->sm_ddr.ddr_cycle_tenths];
    568  1.1.2.2  uebayasi 	bits = le16toh(s->sm_ddr.ddr_datawidth);
    569  1.1.2.2  uebayasi 	if (s->sm_config == 1 || s->sm_config == 2)
    570  1.1.2.2  uebayasi 		bits -= 8;
    571  1.1.2.2  uebayasi 	decode_size_speed(node, dimm_size, cycle_time, 2, bits, TRUE, "PC", 0);
    572  1.1.2.2  uebayasi 
    573  1.1.2.2  uebayasi 	aprint_verbose_dev(self,
    574  1.1.2.2  uebayasi 	    "%d rows, %d cols, %d ranks, %d banks/chip, %d.%dns cycle time\n",
    575  1.1.2.2  uebayasi 	    s->sm_ddr.ddr_rows, s->sm_ddr.ddr_cols, s->sm_ddr.ddr_ranks,
    576  1.1.2.2  uebayasi 	    s->sm_ddr.ddr_banks_per_chip, cycle_time/1000,
    577  1.1.2.2  uebayasi 	    (cycle_time % 1000 + 50) / 100);
    578  1.1.2.2  uebayasi 
    579  1.1.2.2  uebayasi 	tAA  = 0;
    580  1.1.2.2  uebayasi 	for (i = 2; i < 8; i++)
    581  1.1.2.2  uebayasi 		if (s->sm_ddr.ddr_tCAS & (1 << i))
    582  1.1.2.2  uebayasi 			tAA = i;
    583  1.1.2.2  uebayasi 	tAA /= 2;
    584  1.1.2.2  uebayasi 
    585  1.1.2.2  uebayasi #define __DDR_ROUND(scale, field)	\
    586  1.1.2.2  uebayasi 		((scale * s->sm_ddr.field + cycle_time - 1) / cycle_time)
    587  1.1.2.2  uebayasi 
    588  1.1.2.2  uebayasi 	aprint_verbose_dev(self, latency, tAA, __DDR_ROUND(250, ddr_tRCD),
    589  1.1.2.2  uebayasi 		__DDR_ROUND(250, ddr_tRP), __DDR_ROUND(1000, ddr_tRAS));
    590  1.1.2.2  uebayasi 
    591  1.1.2.2  uebayasi #undef	__DDR_ROUND
    592  1.1.2.2  uebayasi 
    593  1.1.2.2  uebayasi 	decode_voltage_refresh(self, s);
    594  1.1.2.2  uebayasi }
    595  1.1.2.2  uebayasi 
    596  1.1.2.2  uebayasi static void
    597  1.1.2.2  uebayasi decode_ddr2(const struct sysctlnode *node, device_t self, struct spdmem *s) {
    598  1.1.2.2  uebayasi 	int dimm_size, cycle_time, bits, tAA, i;
    599  1.1.2.2  uebayasi 
    600  1.1.2.2  uebayasi 	aprint_normal("%s, %s, ",
    601  1.1.2.2  uebayasi 		(s->sm_ddr2.ddr2_mod_attrs & SPDMEM_DDR2_MASK_REG)?
    602  1.1.2.2  uebayasi 			" (registered)":"",
    603  1.1.2.2  uebayasi 		(s->sm_config < __arraycount(spdmem_parity_types))?
    604  1.1.2.2  uebayasi 			spdmem_parity_types[s->sm_config]:"invalid parity");
    605  1.1.2.2  uebayasi 
    606  1.1.2.2  uebayasi 	dimm_size = 1 << (s->sm_ddr2.ddr2_rows + s->sm_ddr2.ddr2_cols - 17);
    607  1.1.2.2  uebayasi 	dimm_size *= (s->sm_ddr2.ddr2_ranks + 1) *
    608  1.1.2.2  uebayasi 		     s->sm_ddr2.ddr2_banks_per_chip;
    609  1.1.2.2  uebayasi 
    610  1.1.2.2  uebayasi 	cycle_time = s->sm_ddr2.ddr2_cycle_whole * 1000 +
    611  1.1.2.2  uebayasi 		 spdmem_cycle_frac[s->sm_ddr2.ddr2_cycle_frac];
    612  1.1.2.2  uebayasi 	bits = s->sm_ddr2.ddr2_datawidth;
    613  1.1.2.2  uebayasi 	if ((s->sm_config & 0x03) != 0)
    614  1.1.2.2  uebayasi 		bits -= 8;
    615  1.1.2.2  uebayasi 	decode_size_speed(node, dimm_size, cycle_time, 2, bits, TRUE, "PC2", 0);
    616  1.1.2.2  uebayasi 
    617  1.1.2.2  uebayasi 	aprint_verbose_dev(self,
    618  1.1.2.2  uebayasi 	    "%d rows, %d cols, %d ranks, %d banks/chip, %d.%02dns cycle time\n",
    619  1.1.2.2  uebayasi 	    s->sm_ddr2.ddr2_rows, s->sm_ddr2.ddr2_cols,
    620  1.1.2.2  uebayasi 	    s->sm_ddr2.ddr2_ranks + 1, s->sm_ddr2.ddr2_banks_per_chip,
    621  1.1.2.2  uebayasi 	    cycle_time / 1000, (cycle_time % 1000 + 5) /10 );
    622  1.1.2.2  uebayasi 
    623  1.1.2.2  uebayasi 	tAA  = 0;
    624  1.1.2.2  uebayasi 	for (i = 2; i < 8; i++)
    625  1.1.2.2  uebayasi 		if (s->sm_ddr2.ddr2_tCAS & (1 << i))
    626  1.1.2.2  uebayasi 			tAA = i;
    627  1.1.2.2  uebayasi 
    628  1.1.2.2  uebayasi #define __DDR2_ROUND(scale, field)	\
    629  1.1.2.2  uebayasi 		((scale * s->sm_ddr2.field + cycle_time - 1) / cycle_time)
    630  1.1.2.2  uebayasi 
    631  1.1.2.2  uebayasi 	aprint_verbose_dev(self, latency, tAA, __DDR2_ROUND(250, ddr2_tRCD),
    632  1.1.2.2  uebayasi 		__DDR2_ROUND(250, ddr2_tRP), __DDR2_ROUND(1000, ddr2_tRAS));
    633  1.1.2.2  uebayasi 
    634  1.1.2.2  uebayasi #undef	__DDR_ROUND
    635  1.1.2.2  uebayasi 
    636  1.1.2.2  uebayasi 	decode_voltage_refresh(self, s);
    637  1.1.2.2  uebayasi }
    638  1.1.2.2  uebayasi 
    639  1.1.2.2  uebayasi static void
    640  1.1.2.2  uebayasi decode_ddr3(const struct sysctlnode *node, device_t self, struct spdmem *s) {
    641  1.1.2.2  uebayasi 	int dimm_size, cycle_time, bits;
    642  1.1.2.2  uebayasi 
    643  1.1.2.2  uebayasi 	if (s->sm_ddr3.ddr3_mod_type ==
    644  1.1.2.2  uebayasi 		SPDMEM_DDR3_TYPE_MINI_RDIMM ||
    645  1.1.2.2  uebayasi 	    s->sm_ddr3.ddr3_mod_type == SPDMEM_DDR3_TYPE_RDIMM)
    646  1.1.2.2  uebayasi 		aprint_normal(" (registered)");
    647  1.1.2.2  uebayasi 	aprint_normal(", %sECC, %stemp-sensor, ",
    648  1.1.2.2  uebayasi 		(s->sm_ddr3.ddr3_hasECC)?"":"no ",
    649  1.1.2.2  uebayasi 		(s->sm_ddr3.ddr3_has_therm_sensor)?"":"no ");
    650  1.1.2.2  uebayasi 
    651  1.1.2.2  uebayasi 	/*
    652  1.1.2.2  uebayasi 	 * DDR3 size specification is quite different from others
    653  1.1.2.2  uebayasi 	 *
    654  1.1.2.2  uebayasi 	 * Module capacity is defined as
    655  1.1.2.2  uebayasi 	 *	Chip_Capacity_in_bits / 8bits-per-byte *
    656  1.1.2.2  uebayasi 	 *	external_bus_width / internal_bus_width
    657  1.1.2.2  uebayasi 	 * We further divide by 2**20 to get our answer in MB
    658  1.1.2.2  uebayasi 	 */
    659  1.1.2.2  uebayasi 	dimm_size = (s->sm_ddr3.ddr3_chipsize + 28 - 20) - 3 +
    660  1.1.2.2  uebayasi 		    (s->sm_ddr3.ddr3_datawidth + 3) -
    661  1.1.2.2  uebayasi 		    (s->sm_ddr3.ddr3_chipwidth + 2);
    662  1.1.2.2  uebayasi 	dimm_size = (1 << dimm_size) * (s->sm_ddr3.ddr3_physbanks + 1);
    663  1.1.2.2  uebayasi 
    664  1.1.2.2  uebayasi 	cycle_time = (1000 * s->sm_ddr3.ddr3_mtb_dividend +
    665  1.1.2.2  uebayasi 			    (s->sm_ddr3.ddr3_mtb_divisor / 2)) /
    666  1.1.2.2  uebayasi 		     s->sm_ddr3.ddr3_mtb_divisor;
    667  1.1.2.2  uebayasi 	cycle_time *= s->sm_ddr3.ddr3_tCKmin;
    668  1.1.2.2  uebayasi 	bits = 1 << (s->sm_ddr3.ddr3_datawidth + 3);
    669  1.1.2.2  uebayasi 	decode_size_speed(node, dimm_size, cycle_time, 2, bits, FALSE, "PC3", 0);
    670  1.1.2.2  uebayasi 
    671  1.1.2.2  uebayasi 	aprint_verbose_dev(self,
    672  1.1.2.2  uebayasi 	    "%d rows, %d cols, %d log. banks, %d phys. banks, "
    673  1.1.2.2  uebayasi 	    "%d.%03dns cycle time\n",
    674  1.1.2.2  uebayasi 	    s->sm_ddr3.ddr3_rows + 9, s->sm_ddr3.ddr3_cols + 12,
    675  1.1.2.2  uebayasi 	    1 << (s->sm_ddr3.ddr3_logbanks + 3),
    676  1.1.2.2  uebayasi 	    s->sm_ddr3.ddr3_physbanks + 1,
    677  1.1.2.2  uebayasi 	    cycle_time/1000, cycle_time % 1000);
    678  1.1.2.2  uebayasi 
    679  1.1.2.2  uebayasi #define	__DDR3_CYCLES(field) (s->sm_ddr3.field / s->sm_ddr3.ddr3_tCKmin)
    680  1.1.2.2  uebayasi 
    681  1.1.2.2  uebayasi 	aprint_verbose_dev(self, latency, __DDR3_CYCLES(ddr3_tAAmin),
    682  1.1.2.2  uebayasi 		__DDR3_CYCLES(ddr3_tRCDmin), __DDR3_CYCLES(ddr3_tRPmin),
    683  1.1.2.2  uebayasi 		(s->sm_ddr3.ddr3_tRAS_msb * 256 + s->sm_ddr3.ddr3_tRAS_lsb) /
    684  1.1.2.2  uebayasi 		    s->sm_ddr3.ddr3_tCKmin);
    685  1.1.2.2  uebayasi 
    686  1.1.2.2  uebayasi #undef	__DDR3_CYCLES
    687  1.1.2.2  uebayasi }
    688  1.1.2.2  uebayasi 
    689  1.1.2.2  uebayasi static void
    690  1.1.2.2  uebayasi decode_fbdimm(const struct sysctlnode *node, device_t self, struct spdmem *s) {
    691  1.1.2.2  uebayasi 	int dimm_size, cycle_time, bits;
    692  1.1.2.2  uebayasi 
    693  1.1.2.2  uebayasi 	/*
    694  1.1.2.2  uebayasi 	 * FB-DIMM module size calculation is very much like DDR3
    695  1.1.2.2  uebayasi 	 */
    696  1.1.2.2  uebayasi 	dimm_size = s->sm_fbd.fbdimm_rows + 12 +
    697  1.1.2.2  uebayasi 		    s->sm_fbd.fbdimm_cols +  9 - 20 - 3;
    698  1.1.2.2  uebayasi 	dimm_size = (1 << dimm_size) * (1 << (s->sm_fbd.fbdimm_banks + 2));
    699  1.1.2.2  uebayasi 
    700  1.1.2.2  uebayasi 	cycle_time = (1000 * s->sm_fbd.fbdimm_mtb_dividend +
    701  1.1.2.2  uebayasi 			    (s->sm_fbd.fbdimm_mtb_divisor / 2)) /
    702  1.1.2.2  uebayasi 		     s->sm_fbd.fbdimm_mtb_divisor;
    703  1.1.2.2  uebayasi 	bits = 1 << (s->sm_fbd.fbdimm_dev_width + 2);
    704  1.1.2.2  uebayasi 	decode_size_speed(node, dimm_size, cycle_time, 2, bits, TRUE, "PC2", 0);
    705  1.1.2.2  uebayasi 
    706  1.1.2.2  uebayasi 	aprint_verbose_dev(self,
    707  1.1.2.2  uebayasi 	    "%d rows, %d cols, %d banks, %d.%02dns cycle time\n",
    708  1.1.2.2  uebayasi 	    s->sm_fbd.fbdimm_rows, s->sm_fbd.fbdimm_cols,
    709  1.1.2.2  uebayasi 	    1 << (s->sm_fbd.fbdimm_banks + 2),
    710  1.1.2.2  uebayasi 	    cycle_time / 1000, (cycle_time % 1000 + 5) /10 );
    711  1.1.2.2  uebayasi 
    712  1.1.2.2  uebayasi #define	__FBDIMM_CYCLES(field) (s->sm_fbd.field / s->sm_fbd.fbdimm_tCKmin)
    713  1.1.2.2  uebayasi 
    714  1.1.2.2  uebayasi 	aprint_verbose_dev(self, latency, __FBDIMM_CYCLES(fbdimm_tAAmin),
    715  1.1.2.2  uebayasi 		__FBDIMM_CYCLES(fbdimm_tRCDmin), __FBDIMM_CYCLES(fbdimm_tRPmin),
    716  1.1.2.2  uebayasi 		(s->sm_fbd.fbdimm_tRAS_msb * 256 +
    717  1.1.2.2  uebayasi 			s->sm_fbd.fbdimm_tRAS_lsb) /
    718  1.1.2.2  uebayasi 		    s->sm_fbd.fbdimm_tCKmin);
    719  1.1.2.2  uebayasi 
    720  1.1.2.2  uebayasi #undef	__FBDIMM_CYCLES
    721  1.1.2.2  uebayasi 
    722  1.1.2.2  uebayasi 	decode_voltage_refresh(self, s);
    723  1.1.2.2  uebayasi }
    724