LCOV - code coverage report
Current view: top level - dev - spdmem.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 258 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 10 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: spdmem.c,v 1.5 2015/01/25 11:38:49 jsg 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_MASK             0x0F    /* SPD EEPROM Size   */
      62             : 
      63             : #define SPDMEM_SPDLEN_128               0x00    /* SPD EEPROM Sizes  */
      64             : #define SPDMEM_SPDLEN_176               0x10
      65             : #define SPDMEM_SPDLEN_256               0x20
      66             : #define SPDMEM_SPDLEN_MASK              0x70    /* Bits 4 - 6        */
      67             : 
      68             : #define SPDMEM_SPDCRC_116               0x80    /* CRC Bytes covered */
      69             : #define SPDMEM_SPDCRC_125               0x00
      70             : #define SPDMEM_SPDCRC_MASK              0x80    /* Bit 7             */
      71             : 
      72             : 
      73             : /* possible values for the memory type */
      74             : #define SPDMEM_MEMTYPE_FPM              0x01
      75             : #define SPDMEM_MEMTYPE_EDO              0x02
      76             : #define SPDMEM_MEMTYPE_PIPE_NIBBLE      0x03
      77             : #define SPDMEM_MEMTYPE_SDRAM            0x04
      78             : #define SPDMEM_MEMTYPE_ROM              0x05
      79             : #define SPDMEM_MEMTYPE_DDRSGRAM         0x06
      80             : #define SPDMEM_MEMTYPE_DDRSDRAM         0x07
      81             : #define SPDMEM_MEMTYPE_DDR2SDRAM        0x08
      82             : #define SPDMEM_MEMTYPE_FBDIMM           0x09
      83             : #define SPDMEM_MEMTYPE_FBDIMM_PROBE     0x0a
      84             : #define SPDMEM_MEMTYPE_DDR3SDRAM        0x0b
      85             : #define SPDMEM_MEMTYPE_NONE             0xff
      86             : 
      87             : #define SPDMEM_MEMTYPE_DIRECT_RAMBUS    0x01
      88             : #define SPDMEM_MEMTYPE_RAMBUS           0x11
      89             : 
      90             : /* possible values for the supply voltage */
      91             : #define SPDMEM_VOLTAGE_TTL_5V           0x00
      92             : #define SPDMEM_VOLTAGE_TTL_LV           0x01
      93             : #define SPDMEM_VOLTAGE_HSTTL_1_5V       0x02
      94             : #define SPDMEM_VOLTAGE_SSTL_3_3V        0x03
      95             : #define SPDMEM_VOLTAGE_SSTL_2_5V        0x04
      96             : #define SPDMEM_VOLTAGE_SSTL_1_8V        0x05
      97             : 
      98             : /* possible values for module configuration */
      99             : #define SPDMEM_MODCONFIG_PARITY         0x01
     100             : #define SPDMEM_MODCONFIG_ECC            0x02
     101             : 
     102             : /* for DDR2, module configuration is a bit-mask field */
     103             : #define SPDMEM_MODCONFIG_HAS_DATA_PARITY        0x01
     104             : #define SPDMEM_MODCONFIG_HAS_DATA_ECC           0x02
     105             : #define SPDMEM_MODCONFIG_HAS_ADDR_CMD_PARITY    0x04
     106             : 
     107             : /* possible values for the refresh field */
     108             : #define SPDMEM_REFRESH_STD              0x00
     109             : #define SPDMEM_REFRESH_QUARTER          0x01
     110             : #define SPDMEM_REFRESH_HALF             0x02
     111             : #define SPDMEM_REFRESH_TWOX             0x03
     112             : #define SPDMEM_REFRESH_FOURX            0x04
     113             : #define SPDMEM_REFRESH_EIGHTX           0x05
     114             : #define SPDMEM_REFRESH_SELFREFRESH      0x80
     115             : 
     116             : /* superset types */
     117             : #define SPDMEM_SUPERSET_ESDRAM          0x01
     118             : #define SPDMEM_SUPERSET_DDR_ESDRAM      0x02
     119             : #define SPDMEM_SUPERSET_EDO_PEM         0x03
     120             : #define SPDMEM_SUPERSET_SDR_PEM         0x04
     121             : 
     122             : /* FPM and EDO DIMMS */
     123             : #define SPDMEM_FPM_ROWS                 0x00
     124             : #define SPDMEM_FPM_COLS                 0x01
     125             : #define SPDMEM_FPM_BANKS                0x02
     126             : #define SPDMEM_FPM_CONFIG               0x08
     127             : #define SPDMEM_FPM_REFRESH              0x09
     128             : #define SPDMEM_FPM_SUPERSET             0x0c
     129             : 
     130             : /* PC66/PC100/PC133 SDRAM */
     131             : #define SPDMEM_SDR_ROWS                 0x00
     132             : #define SPDMEM_SDR_COLS                 0x01
     133             : #define SPDMEM_SDR_BANKS                0x02
     134             : #define SPDMEM_SDR_CYCLE                0x06
     135             : #define SPDMEM_SDR_BANKS_PER_CHIP       0x0e
     136             : #define SPDMEM_SDR_MOD_ATTRIB           0x12
     137             : #define SPDMEM_SDR_SUPERSET             0x1d
     138             : 
     139             : #define SPDMEM_SDR_FREQUENCY            126
     140             : #define SPDMEM_SDR_CAS                  127
     141             : #define SPDMEM_SDR_FREQ_66              0x66
     142             : #define SPDMEM_SDR_FREQ_100             0x64
     143             : #define SPDMEM_SDR_FREQ_133             0x85
     144             : #define SPDMEM_SDR_CAS2                 (1 << 1)
     145             : #define SPDMEM_SDR_CAS3                 (1 << 2)
     146             : 
     147             : /* Rambus Direct DRAM */
     148             : #define SPDMEM_RDR_MODULE_TYPE          0x00
     149             : #define SPDMEM_RDR_ROWS_COLS            0x01
     150             : #define SPDMEM_RDR_BANK                 0x02
     151             : 
     152             : #define SPDMEM_RDR_TYPE_RIMM            1
     153             : #define SPDMEM_RDR_TYPE_SORIMM          2
     154             : #define SPDMEM_RDR_TYPE_EMBED           3
     155             : #define SPDMEM_RDR_TYPE_RIMM32          4
     156             : 
     157             : /* Dual Data Rate SDRAM */
     158             : #define SPDMEM_DDR_ROWS                 0x00
     159             : #define SPDMEM_DDR_COLS                 0x01
     160             : #define SPDMEM_DDR_RANKS                0x02
     161             : #define SPDMEM_DDR_DATAWIDTH            0x03
     162             : #define SPDMEM_DDR_VOLTAGE              0x05
     163             : #define SPDMEM_DDR_CYCLE                0x06
     164             : #define SPDMEM_DDR_REFRESH              0x09
     165             : #define SPDMEM_DDR_BANKS_PER_CHIP       0x0e
     166             : #define SPDMEM_DDR_CAS                  0x0f
     167             : #define SPDMEM_DDR_MOD_ATTRIB           0x12
     168             : #define SPDMEM_DDR_SUPERSET             0x1d
     169             : 
     170             : #define SPDMEM_DDR_ATTRIB_REG           (1 << 1)
     171             : 
     172             : /* Dual Data Rate 2 SDRAM */
     173             : #define SPDMEM_DDR2_ROWS                0x00
     174             : #define SPDMEM_DDR2_COLS                0x01
     175             : #define SPDMEM_DDR2_RANKS               0x02
     176             : #define SPDMEM_DDR2_DATAWIDTH           0x03
     177             : #define SPDMEM_DDR2_VOLTAGE             0x05
     178             : #define SPDMEM_DDR2_CYCLE               0x06
     179             : #define SPDMEM_DDR2_DIMMTYPE            0x11
     180             : #define SPDMEM_DDR2_RANK_DENSITY        0x1c
     181             : 
     182             : #define SPDMEM_DDR2_TYPE_REGMASK        ((1 << 4) | (1 << 0))
     183             : #define SPDMEM_DDR2_SODIMM              (1 << 2)
     184             : #define SPDMEM_DDR2_MICRO_DIMM          (1 << 3)
     185             : #define SPDMEM_DDR2_MINI_RDIMM          (1 << 4)
     186             : #define SPDMEM_DDR2_MINI_UDIMM          (1 << 5)
     187             : 
     188             : /* DDR2 FB-DIMM SDRAM */
     189             : #define SPDMEM_FBDIMM_ADDR              0x01
     190             : #define SPDMEM_FBDIMM_RANKS             0x04
     191             : #define SPDMEM_FBDIMM_MTB_DIVIDEND      0x06
     192             : #define SPDMEM_FBDIMM_MTB_DIVISOR       0x07
     193             : #define SPDMEM_FBDIMM_PROTO             0x4e
     194             : 
     195             : #define SPDMEM_FBDIMM_RANKS_WIDTH               0x07
     196             : #define SPDMEM_FBDIMM_ADDR_BANKS                0x02
     197             : #define SPDMEM_FBDIMM_ADDR_COL                  0x0c
     198             : #define SPDMEM_FBDIMM_ADDR_COL_SHIFT            2
     199             : #define SPDMEM_FBDIMM_ADDR_ROW                  0xe0
     200             : #define SPDMEM_FBDIMM_ADDR_ROW_SHIFT            5
     201             : #define SPDMEM_FBDIMM_PROTO_ECC                 (1 << 1)
     202             : 
     203             : 
     204             : /* Dual Data Rate 3 SDRAM */
     205             : #define SPDMEM_DDR3_MODTYPE             0x00
     206             : #define SPDMEM_DDR3_DENSITY             0x01
     207             : #define SPDMEM_DDR3_MOD_ORG             0x04
     208             : #define SPDMEM_DDR3_DATAWIDTH           0x05
     209             : #define SPDMEM_DDR3_MTB_DIVIDEND        0x07
     210             : #define SPDMEM_DDR3_MTB_DIVISOR         0x08
     211             : #define SPDMEM_DDR3_TCKMIN              0x09
     212             : #define SPDMEM_DDR3_THERMAL             0x1d
     213             : 
     214             : #define SPDMEM_DDR3_DENSITY_CAPMASK             0x0f
     215             : #define SPDMEM_DDR3_MOD_ORG_CHIPWIDTH_MASK      0x07
     216             : #define SPDMEM_DDR3_MOD_ORG_BANKS_SHIFT         3
     217             : #define SPDMEM_DDR3_MOD_ORG_BANKS_MASK          0x07
     218             : #define SPDMEM_DDR3_DATAWIDTH_ECCMASK           (1 << 3)
     219             : #define SPDMEM_DDR3_DATAWIDTH_PRIMASK           0x07
     220             : #define SPDMEM_DDR3_THERMAL_PRESENT             (1 << 7)
     221             : 
     222             : #define SPDMEM_DDR3_RDIMM               0x01
     223             : #define SPDMEM_DDR3_UDIMM               0x02
     224             : #define SPDMEM_DDR3_SODIMM              0x03
     225             : #define SPDMEM_DDR3_MICRO_DIMM          0x04
     226             : #define SPDMEM_DDR3_MINI_RDIMM          0x05
     227             : #define SPDMEM_DDR3_MINI_UDIMM          0x06
     228             : 
     229             : static const uint8_t ddr2_cycle_tenths[] = {
     230             :         0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 25, 33, 66, 75, 0, 0
     231             : };
     232             : 
     233             : #define SPDMEM_TYPE_MAXLEN 16
     234             : 
     235             : uint16_t        spdmem_crc16(struct spdmem_softc *, int);
     236             : static inline
     237             : uint8_t         spdmem_read(struct spdmem_softc *, uint8_t);
     238             : void            spdmem_sdram_decode(struct spdmem_softc *, struct spdmem *);
     239             : void            spdmem_rdr_decode(struct spdmem_softc *, struct spdmem *);
     240             : void            spdmem_ddr_decode(struct spdmem_softc *, struct spdmem *);
     241             : void            spdmem_ddr2_decode(struct spdmem_softc *, struct spdmem *);
     242             : void            spdmem_fbdimm_decode(struct spdmem_softc *, struct spdmem *);
     243             : void            spdmem_ddr3_decode(struct spdmem_softc *, struct spdmem *);
     244             : 
     245             : struct cfdriver spdmem_cd = {
     246             :         NULL, "spdmem", DV_DULL
     247             : };
     248             : 
     249             : #define IS_RAMBUS_TYPE (s->sm_len < 4)
     250             : 
     251             : static const char *spdmem_basic_types[] = {
     252             :         "unknown",
     253             :         "FPM",
     254             :         "EDO",
     255             :         "Pipelined Nibble",
     256             :         "SDRAM",
     257             :         "ROM",
     258             :         "DDR SGRAM",
     259             :         "DDR SDRAM",
     260             :         "DDR2 SDRAM",
     261             :         "DDR2 SDRAM FB-DIMM",
     262             :         "DDR2 SDRAM FB-DIMM Probe",
     263             :         "DDR3 SDRAM"
     264             : };
     265             : 
     266             : static const char *spdmem_superset_types[] = {
     267             :         "unknown",
     268             :         "ESDRAM",
     269             :         "DDR ESDRAM",
     270             :         "PEM EDO",
     271             :         "PEM SDRAM"
     272             : };
     273             : 
     274             : static const char *spdmem_parity_types[] = {
     275             :         "non-parity",
     276             :         "data parity",
     277             :         "ECC",
     278             :         "data parity and ECC",
     279             :         "cmd/addr parity",
     280             :         "cmd/addr/data parity",
     281             :         "cmd/addr parity, data ECC",
     282             :         "cmd/addr/data parity, data ECC"
     283             : };
     284             : 
     285             : static inline uint8_t
     286           0 : spdmem_read(struct spdmem_softc *sc, uint8_t reg)
     287             : {
     288           0 :         return (*sc->sc_read)(sc, reg);
     289             : }
     290             : 
     291             : /* CRC functions used for certain memory types */
     292             : uint16_t
     293           0 : spdmem_crc16(struct spdmem_softc *sc, int count)
     294             : {
     295             :         uint16_t crc;
     296             :         int i, j;
     297             :         uint8_t val;
     298             :         crc = 0;
     299           0 :         for (j = 0; j <= count; j++) {
     300           0 :                 val = spdmem_read(sc, j);
     301           0 :                 crc = crc ^ val << 8;
     302           0 :                 for (i = 0; i < 8; ++i)
     303           0 :                         if (crc & 0x8000)
     304           0 :                                 crc = crc << 1 ^ 0x1021;
     305             :                         else
     306           0 :                                 crc = crc << 1;
     307             :         }
     308           0 :         return (crc & 0xFFFF);
     309             : }
     310             : 
     311             : void
     312           0 : spdmem_sdram_decode(struct spdmem_softc *sc, struct spdmem *s)
     313             : {
     314             :         const char *type;
     315             :         int dimm_size, p_clk;
     316             :         int num_banks, per_chip;
     317             :         uint8_t rows, cols;
     318             : 
     319           0 :         type = spdmem_basic_types[s->sm_type];
     320             : 
     321           0 :         if (s->sm_data[SPDMEM_SDR_SUPERSET] == SPDMEM_SUPERSET_SDR_PEM)
     322           0 :                 type = spdmem_superset_types[SPDMEM_SUPERSET_SDR_PEM];
     323           0 :         if (s->sm_data[SPDMEM_SDR_SUPERSET] == SPDMEM_SUPERSET_ESDRAM)
     324           0 :                 type = spdmem_superset_types[SPDMEM_SUPERSET_ESDRAM];
     325             : 
     326           0 :         num_banks = s->sm_data[SPDMEM_SDR_BANKS];
     327           0 :         per_chip = s->sm_data[SPDMEM_SDR_BANKS_PER_CHIP];
     328           0 :         rows = s->sm_data[SPDMEM_SDR_ROWS] & 0x0f;
     329           0 :         cols = s->sm_data[SPDMEM_SDR_COLS] & 0x0f;
     330           0 :         dimm_size = (1 << (rows + cols - 17)) * num_banks * per_chip;
     331             : 
     332           0 :         if (dimm_size > 0) {
     333           0 :                 if (dimm_size < 1024)
     334           0 :                         printf(" %dMB", dimm_size);
     335             :                 else
     336           0 :                         printf(" %dGB", dimm_size / 1024);
     337             :         }
     338             : 
     339           0 :         printf(" %s", type);
     340             : 
     341           0 :         if (s->sm_data[SPDMEM_DDR_MOD_ATTRIB] & SPDMEM_DDR_ATTRIB_REG)
     342           0 :                 printf(" registered");
     343             : 
     344           0 :         if (s->sm_data[SPDMEM_FPM_CONFIG] < 8)
     345           0 :                 printf(" %s",
     346           0 :                     spdmem_parity_types[s->sm_data[SPDMEM_FPM_CONFIG]]);
     347             : 
     348             :         p_clk = 66;
     349           0 :         if (s->sm_len >= 128) {
     350           0 :                 switch (spdmem_read(sc, SPDMEM_SDR_FREQUENCY)) {
     351             :                 case SPDMEM_SDR_FREQ_100:
     352             :                 case SPDMEM_SDR_FREQ_133:
     353             :                         /* We need to check ns to decide here */
     354           0 :                         if (s->sm_data[SPDMEM_SDR_CYCLE] < 0x80)
     355           0 :                                 p_clk = 133;
     356             :                         else
     357             :                                 p_clk = 100;
     358             :                         break;
     359             :                 case SPDMEM_SDR_FREQ_66:
     360             :                 default:
     361             :                         p_clk = 66;
     362           0 :                         break;
     363             :                 }
     364             :         }
     365           0 :         printf(" PC%d", p_clk);
     366             : 
     367             :         /* Print CAS latency */
     368           0 :         if (s->sm_len < 128)
     369           0 :                 return;
     370           0 :         if (spdmem_read(sc, SPDMEM_SDR_CAS) & SPDMEM_SDR_CAS2)
     371           0 :                 printf("CL2");
     372           0 :         else if (spdmem_read(sc, SPDMEM_SDR_CAS) & SPDMEM_SDR_CAS3)
     373           0 :                 printf("CL3");
     374           0 : }
     375             : 
     376             : void
     377           0 : spdmem_rdr_decode(struct spdmem_softc *sc, struct spdmem *s)
     378             : {
     379             :         int rimm_size;
     380             :         uint8_t row_bits, col_bits, bank_bits;
     381             : 
     382           0 :         row_bits = s->sm_data[SPDMEM_RDR_ROWS_COLS] >> 4;
     383           0 :         col_bits = s->sm_data[SPDMEM_RDR_ROWS_COLS] & 0x0f;
     384           0 :         bank_bits = s->sm_data[SPDMEM_RDR_BANK] & 0x07;
     385             : 
     386             :         /* subtracting 13 here is a cheaper way of dividing by 8k later */
     387           0 :         rimm_size = 1 << (row_bits + col_bits + bank_bits - 13);
     388             : 
     389           0 :         if (rimm_size < 1024)
     390           0 :                 printf(" %dMB ", rimm_size);
     391             :         else
     392           0 :                 printf(" %dGB ", rimm_size / 1024);
     393             : 
     394           0 :         switch(s->sm_data[SPDMEM_RDR_MODULE_TYPE]) {
     395             :         case SPDMEM_RDR_TYPE_RIMM:
     396           0 :                 printf("RIMM");
     397           0 :                 break;
     398             :         case SPDMEM_RDR_TYPE_SORIMM:
     399           0 :                 printf("SO-RIMM");
     400           0 :                 break;
     401             :         case SPDMEM_RDR_TYPE_EMBED:
     402           0 :                 printf("Embedded Rambus");
     403           0 :                 break;
     404             :         case SPDMEM_RDR_TYPE_RIMM32:
     405           0 :                 printf("RIMM32");
     406           0 :                 break;
     407             :         }
     408           0 : }
     409             : 
     410             : void
     411           0 : spdmem_ddr_decode(struct spdmem_softc *sc, struct spdmem *s)
     412             : {
     413             :         const char *type;
     414             :         int dimm_size, cycle_time, d_clk, p_clk, bits;
     415             :         int i, num_banks, per_chip;
     416             :         uint8_t config, rows, cols, cl;
     417             : 
     418           0 :         type = spdmem_basic_types[s->sm_type];
     419             : 
     420           0 :         if (s->sm_data[SPDMEM_DDR_SUPERSET] == SPDMEM_SUPERSET_DDR_ESDRAM)
     421           0 :                 type = spdmem_superset_types[SPDMEM_SUPERSET_DDR_ESDRAM];
     422             : 
     423           0 :         num_banks = s->sm_data[SPDMEM_SDR_BANKS];
     424           0 :         per_chip = s->sm_data[SPDMEM_SDR_BANKS_PER_CHIP];
     425           0 :         rows = s->sm_data[SPDMEM_SDR_ROWS] & 0x0f;
     426           0 :         cols = s->sm_data[SPDMEM_SDR_COLS] & 0x0f;
     427           0 :         dimm_size = (1 << (rows + cols - 17)) * num_banks * per_chip;
     428             : 
     429           0 :         if (dimm_size > 0) {
     430           0 :                 if (dimm_size < 1024)
     431           0 :                         printf(" %dMB", dimm_size);
     432             :                 else
     433           0 :                         printf(" %dGB", dimm_size / 1024);
     434             :         }
     435             : 
     436           0 :         printf(" %s", type);
     437             : 
     438           0 :         if (s->sm_data[SPDMEM_DDR_MOD_ATTRIB] & SPDMEM_DDR_ATTRIB_REG)
     439           0 :                 printf(" registered");
     440             : 
     441           0 :         if (s->sm_data[SPDMEM_FPM_CONFIG] < 8)
     442           0 :                 printf(" %s",
     443           0 :                     spdmem_parity_types[s->sm_data[SPDMEM_FPM_CONFIG]]);
     444             : 
     445             :         /* cycle_time is expressed in units of 0.01 ns */
     446           0 :         cycle_time = (s->sm_data[SPDMEM_DDR_CYCLE] >> 4) * 100 +
     447           0 :             (s->sm_data[SPDMEM_DDR_CYCLE] & 0x0f) * 10;
     448             : 
     449           0 :         if (cycle_time != 0) {
     450             :                 /*
     451             :                  * cycle time is scaled by a factor of 100 to avoid using
     452             :                  * floating point.  Calculate memory speed as the number
     453             :                  * of cycles per microsecond.
     454             :                  * DDR uses dual-pumped clock
     455             :                  */
     456             :                 d_clk = 100 * 1000 * 2;
     457           0 :                 config = s->sm_data[SPDMEM_FPM_CONFIG];
     458           0 :                 bits = s->sm_data[SPDMEM_DDR_DATAWIDTH] |
     459           0 :                     (s->sm_data[SPDMEM_DDR_DATAWIDTH + 1] << 8);
     460           0 :                 if (config == 1 || config == 2)
     461           0 :                         bits -= 8;
     462             : 
     463           0 :                 d_clk /= cycle_time;
     464           0 :                 p_clk = d_clk * bits / 8;
     465           0 :                 if ((p_clk % 100) >= 50)
     466           0 :                         p_clk += 50;
     467           0 :                 p_clk -= p_clk % 100;
     468           0 :                 printf(" PC%d", p_clk);
     469           0 :         }
     470             : 
     471             :         /* Print CAS latency */
     472           0 :         for (i = 6; i >= 0; i--) {
     473           0 :                 if (s->sm_data[SPDMEM_DDR_CAS] & (1 << i)) {
     474           0 :                         cl = ((i * 10) / 2) + 10;
     475           0 :                         printf("CL%d.%d", cl / 10, cl % 10);
     476           0 :                         break;
     477             :                 }
     478             :         }
     479           0 : }
     480             : 
     481             : void
     482           0 : spdmem_ddr2_decode(struct spdmem_softc *sc, struct spdmem *s)
     483             : {
     484             :         const char *type;
     485             :         int dimm_size, cycle_time, d_clk, p_clk, bits;
     486             :         int i, num_ranks, density;
     487             :         uint8_t config;
     488             : 
     489           0 :         type = spdmem_basic_types[s->sm_type];
     490             : 
     491           0 :         num_ranks = (s->sm_data[SPDMEM_DDR2_RANKS] & 0x7) + 1;
     492           0 :         density = (s->sm_data[SPDMEM_DDR2_RANK_DENSITY] & 0xf0) |
     493           0 :             ((s->sm_data[SPDMEM_DDR2_RANK_DENSITY] & 0x0f) << 8);
     494           0 :         dimm_size = num_ranks * density * 4;
     495             : 
     496           0 :         if (dimm_size > 0) {
     497           0 :                 if (dimm_size < 1024)
     498           0 :                         printf(" %dMB", dimm_size);
     499             :                 else
     500           0 :                         printf(" %dGB", dimm_size / 1024);
     501             :         }
     502             : 
     503           0 :         printf(" %s", type);
     504             : 
     505           0 :         if (s->sm_data[SPDMEM_DDR2_DIMMTYPE] & SPDMEM_DDR2_TYPE_REGMASK)
     506           0 :                 printf(" registered");
     507             : 
     508           0 :         if (s->sm_data[SPDMEM_FPM_CONFIG] < 8)
     509           0 :                 printf(" %s",
     510           0 :                     spdmem_parity_types[s->sm_data[SPDMEM_FPM_CONFIG]]);
     511             : 
     512             :         /* cycle_time is expressed in units of 0.01 ns */
     513           0 :         cycle_time = (s->sm_data[SPDMEM_DDR2_CYCLE] >> 4) * 100 +
     514           0 :             ddr2_cycle_tenths[(s->sm_data[SPDMEM_DDR2_CYCLE] & 0x0f)];
     515             : 
     516           0 :         if (cycle_time != 0) {
     517             :                 /*
     518             :                  * cycle time is scaled by a factor of 100 to avoid using
     519             :                  * floating point.  Calculate memory speed as the number
     520             :                  * of cycles per microsecond.
     521             :                  * DDR2 uses quad-pumped clock
     522             :                  */
     523             :                 d_clk = 100 * 1000 * 4;
     524           0 :                 config = s->sm_data[SPDMEM_FPM_CONFIG];
     525           0 :                 bits = s->sm_data[SPDMEM_DDR2_DATAWIDTH];
     526           0 :                 if ((config & 0x03) != 0)
     527           0 :                         bits -= 8;
     528           0 :                 d_clk /= cycle_time;
     529           0 :                 d_clk = (d_clk + 1) / 2;
     530           0 :                 p_clk = d_clk * bits / 8;
     531           0 :                 p_clk -= p_clk % 100;
     532           0 :                 printf(" PC2-%d", p_clk);
     533           0 :         }
     534             : 
     535             :         /* Print CAS latency */
     536           0 :         for (i = 7; i >= 2; i--) {
     537           0 :                 if (s->sm_data[SPDMEM_DDR_CAS] & (1 << i)) {
     538           0 :                         printf("CL%d", i);
     539           0 :                         break;
     540             :                 }
     541             :         }
     542             : 
     543           0 :         switch (s->sm_data[SPDMEM_DDR2_DIMMTYPE]) {
     544             :         case SPDMEM_DDR2_SODIMM:
     545           0 :                 printf(" SO-DIMM");
     546           0 :                 break;
     547             :         case SPDMEM_DDR2_MICRO_DIMM:
     548           0 :                 printf(" Micro-DIMM");
     549           0 :                 break;
     550             :         case SPDMEM_DDR2_MINI_RDIMM:
     551             :         case SPDMEM_DDR2_MINI_UDIMM:
     552           0 :                 printf(" Mini-DIMM");
     553           0 :                 break;
     554             :         }
     555           0 : }
     556             : 
     557             : void
     558           0 : spdmem_fbdimm_decode(struct spdmem_softc *sc, struct spdmem *s)
     559             : {
     560             :         int dimm_size, cycle_time, d_clk, p_clk, bits;
     561             :         uint8_t rows, cols, dividend, divisor;
     562             :         /*
     563             :          * FB-DIMM is very much like DDR3
     564             :          */
     565             : 
     566           0 :         cols = (s->sm_data[SPDMEM_FBDIMM_ADDR] & SPDMEM_FBDIMM_ADDR_COL) >>
     567             :             SPDMEM_FBDIMM_ADDR_COL_SHIFT;
     568           0 :         rows = (s->sm_data[SPDMEM_FBDIMM_ADDR] & SPDMEM_FBDIMM_ADDR_ROW) >>
     569             :             SPDMEM_FBDIMM_ADDR_ROW_SHIFT;
     570           0 :         dimm_size = rows + 12 + cols +  9 - 20 - 3;
     571             : 
     572           0 :         if (dimm_size < 1024)
     573           0 :                 printf(" %dMB", dimm_size);
     574             :         else
     575           0 :                 printf(" %dGB", dimm_size / 1024);
     576             : 
     577           0 :         dividend = s->sm_data[SPDMEM_FBDIMM_MTB_DIVIDEND];
     578           0 :         divisor = s->sm_data[SPDMEM_FBDIMM_MTB_DIVISOR];
     579             : 
     580           0 :         cycle_time = (1000 * dividend + (divisor / 2)) / divisor;
     581             : 
     582           0 :         if (cycle_time != 0) {
     583             :                 /*
     584             :                  * cycle time is scaled by a factor of 1000 to avoid using
     585             :                  * floating point.  Calculate memory speed as the number
     586             :                  * of cycles per microsecond.
     587             :                  */
     588             :                 d_clk = 1000 * 1000;
     589             : 
     590             :                 /* DDR2 FB-DIMM uses a dual-pumped clock */
     591             :                 d_clk *= 2;
     592           0 :                 bits = 1 << ((s->sm_data[SPDMEM_FBDIMM_RANKS] &
     593           0 :                     SPDMEM_FBDIMM_RANKS_WIDTH) + 2);
     594             : 
     595           0 :                 p_clk = (d_clk * bits) / 8 / cycle_time;
     596           0 :                 p_clk -= p_clk % 100;
     597           0 :                 printf(" PC2-%d", p_clk);
     598           0 :         }
     599           0 : }
     600             : 
     601             : void
     602           0 : spdmem_ddr3_decode(struct spdmem_softc *sc, struct spdmem *s)
     603             : {
     604             :         const char *type;
     605             :         int dimm_size, cycle_time, d_clk, p_clk, bits;
     606             :         uint8_t mtype, chipsize, dividend, divisor;
     607             :         uint8_t datawidth, chipwidth, physbanks;
     608             : 
     609           0 :         type = spdmem_basic_types[s->sm_type];
     610             : 
     611           0 :         chipsize = s->sm_data[SPDMEM_DDR3_DENSITY] &
     612             :             SPDMEM_DDR3_DENSITY_CAPMASK;
     613           0 :         datawidth = s->sm_data[SPDMEM_DDR3_DATAWIDTH] &
     614             :             SPDMEM_DDR3_DATAWIDTH_PRIMASK;
     615           0 :         chipwidth = s->sm_data[SPDMEM_DDR3_MOD_ORG] &
     616             :             SPDMEM_DDR3_MOD_ORG_CHIPWIDTH_MASK;
     617           0 :         physbanks = (s->sm_data[SPDMEM_DDR3_MOD_ORG] >> 
     618           0 :             SPDMEM_DDR3_MOD_ORG_BANKS_SHIFT) & SPDMEM_DDR3_MOD_ORG_BANKS_MASK;
     619             : 
     620           0 :         dimm_size = (chipsize + 28 - 20) - 3 + (datawidth + 3) -
     621           0 :             (chipwidth + 2);
     622           0 :         dimm_size = (1 << dimm_size) * (physbanks + 1);
     623             : 
     624           0 :         if (dimm_size < 1024)
     625           0 :                 printf(" %dMB", dimm_size);
     626             :         else
     627           0 :                 printf(" %dGB", dimm_size / 1024);
     628             : 
     629           0 :         printf(" %s", type);
     630             : 
     631           0 :         mtype = s->sm_data[SPDMEM_DDR3_MODTYPE];
     632           0 :         if (mtype == SPDMEM_DDR3_RDIMM || mtype == SPDMEM_DDR3_MINI_RDIMM)
     633           0 :                 printf(" registered");
     634             : 
     635           0 :         if (s->sm_data[SPDMEM_DDR3_DATAWIDTH] & SPDMEM_DDR3_DATAWIDTH_ECCMASK) 
     636           0 :                 printf(" ECC");
     637             : 
     638           0 :         dividend = s->sm_data[SPDMEM_DDR3_MTB_DIVIDEND];
     639           0 :         divisor = s->sm_data[SPDMEM_DDR3_MTB_DIVISOR];
     640           0 :         cycle_time = (1000 * dividend +  (divisor / 2)) / divisor;
     641           0 :         cycle_time *= s->sm_data[SPDMEM_DDR3_TCKMIN];
     642             : 
     643           0 :         if (cycle_time != 0) {
     644             :                 /*
     645             :                  * cycle time is scaled by a factor of 1000 to avoid using
     646             :                  * floating point.  Calculate memory speed as the number
     647             :                  * of cycles per microsecond.
     648             :                  * DDR3 uses a dual-pumped clock
     649             :                  */
     650             :                 d_clk = 1000 * 1000;
     651             :                 d_clk *= 2;
     652           0 :                 bits = 1 << ((s->sm_data[SPDMEM_DDR3_DATAWIDTH] &
     653           0 :                     SPDMEM_DDR3_DATAWIDTH_PRIMASK) + 3);
     654             :                 /*
     655             :                  * Calculate p_clk first, since for DDR3 we need maximum
     656             :                  * significance.  DDR3 rating is not rounded to a multiple
     657             :                  * of 100.  This results in cycle_time of 1.5ns displayed
     658             :                  * as p_clk PC3-10666 (d_clk DDR3-1333)
     659             :                  */
     660           0 :                 p_clk = (d_clk * bits) / 8 / cycle_time;
     661           0 :                 p_clk -= (p_clk % 100);
     662           0 :                 d_clk = ((d_clk + cycle_time / 2) ) / cycle_time;
     663           0 :                 printf(" PC3-%d", p_clk);
     664           0 :         }
     665             : 
     666           0 :         switch (s->sm_data[SPDMEM_DDR3_MODTYPE]) {
     667             :         case SPDMEM_DDR3_SODIMM:
     668           0 :                 printf(" SO-DIMM");
     669           0 :                 break;
     670             :         case SPDMEM_DDR3_MICRO_DIMM:
     671           0 :                 printf(" Micro-DIMM");
     672           0 :                 break;
     673             :         case SPDMEM_DDR3_MINI_RDIMM:
     674             :         case SPDMEM_DDR3_MINI_UDIMM:
     675           0 :                 printf(" Mini-DIMM");
     676           0 :                 break;
     677             :         }
     678             : 
     679           0 :         if (s->sm_data[SPDMEM_DDR3_THERMAL] & SPDMEM_DDR3_THERMAL_PRESENT)
     680           0 :                 printf(" with thermal sensor");
     681           0 : }
     682             : 
     683             : int
     684           0 : spdmem_probe(struct spdmem_softc *sc)
     685             : {
     686             :         uint8_t i, val, type;
     687             :         int cksum = 0;
     688             :         int spd_len, spd_crc_cover;
     689             :         uint16_t crc_calc, crc_spd;
     690             : 
     691           0 :         type = spdmem_read(sc, 2);
     692             :         /* For older memory types, validate the checksum over 1st 63 bytes */
     693           0 :         if (type <= SPDMEM_MEMTYPE_DDR2SDRAM) {
     694           0 :                 for (i = 0; i < 63; i++)
     695           0 :                         cksum += spdmem_read(sc, i);
     696             : 
     697           0 :                 val = spdmem_read(sc, 63);
     698             : 
     699           0 :                 if (cksum == 0 || (cksum & 0xff) != val) {
     700           0 :                         return 0;
     701             :                 } else
     702           0 :                         return 1;
     703             :         }
     704             : 
     705             :         /* For DDR3 and FBDIMM, verify the CRC */
     706           0 :         else if (type <= SPDMEM_MEMTYPE_DDR3SDRAM) {
     707           0 :                 spd_len = spdmem_read(sc, 0);
     708           0 :                 if (spd_len & SPDMEM_SPDCRC_116)
     709           0 :                         spd_crc_cover = 116;
     710             :                 else
     711             :                         spd_crc_cover = 125;
     712           0 :                 switch (spd_len & SPDMEM_SPDLEN_MASK) {
     713             :                 case SPDMEM_SPDLEN_128:
     714             :                         spd_len = 128;
     715           0 :                         break;
     716             :                 case SPDMEM_SPDLEN_176:
     717             :                         spd_len = 176;
     718           0 :                         break;
     719             :                 case SPDMEM_SPDLEN_256:
     720             :                         spd_len = 256;
     721           0 :                         break;
     722             :                 default:
     723           0 :                         return 0;
     724             :                 }
     725           0 :                 if (spd_crc_cover > spd_len)
     726           0 :                         return 0;
     727           0 :                 crc_calc = spdmem_crc16(sc, spd_crc_cover);
     728           0 :                 crc_spd = spdmem_read(sc, 127) << 8;
     729           0 :                 crc_spd |= spdmem_read(sc, 126);
     730           0 :                 if (crc_calc != crc_spd) {
     731           0 :                         return 0;
     732             :                 }
     733           0 :                 return 1;
     734             :         }
     735             : 
     736           0 :         return 0;
     737           0 : }
     738             : 
     739             : void
     740           0 : spdmem_attach_common(struct spdmem_softc *sc)
     741             : {
     742           0 :         struct spdmem *s = &(sc->sc_spd_data);
     743             :         int i;
     744             : 
     745             :         /* All SPD have at least 64 bytes of data including checksum */
     746           0 :         for (i = 0; i < 64; i++) {
     747           0 :                 ((uint8_t *)s)[i] = spdmem_read(sc, i);
     748             :         }
     749             : 
     750             :         /*
     751             :          * Decode and print SPD contents
     752             :          */
     753           0 :         if (s->sm_len < 4) {
     754           0 :                 if (s->sm_type == SPDMEM_MEMTYPE_DIRECT_RAMBUS)
     755           0 :                         spdmem_rdr_decode(sc, s);
     756             :                 else
     757           0 :                         printf(" no decode method for Rambus memory");
     758             :         } else {
     759           0 :                 switch(s->sm_type) {
     760             :                 case SPDMEM_MEMTYPE_EDO:
     761             :                 case SPDMEM_MEMTYPE_SDRAM:
     762           0 :                         spdmem_sdram_decode(sc, s);
     763           0 :                         break;
     764             :                 case SPDMEM_MEMTYPE_DDRSDRAM:
     765           0 :                         spdmem_ddr_decode(sc, s);
     766           0 :                         break;
     767             :                 case SPDMEM_MEMTYPE_DDR2SDRAM:
     768           0 :                         spdmem_ddr2_decode(sc, s);
     769           0 :                         break;
     770             :                 case SPDMEM_MEMTYPE_FBDIMM:
     771             :                 case SPDMEM_MEMTYPE_FBDIMM_PROBE:
     772           0 :                         spdmem_fbdimm_decode(sc, s);
     773           0 :                         break;
     774             :                 case SPDMEM_MEMTYPE_DDR3SDRAM:
     775           0 :                         spdmem_ddr3_decode(sc, s);
     776           0 :                         break;
     777             :                 case SPDMEM_MEMTYPE_NONE:
     778           0 :                         printf(" no EEPROM found");
     779           0 :                         break;
     780             :                 default:
     781           0 :                         if (s->sm_type <= 10)
     782           0 :                                 printf(" no decode method for %s memory",
     783           0 :                                     spdmem_basic_types[s->sm_type]);
     784             :                         else
     785           0 :                                 printf(" unknown memory type %d", s->sm_type);
     786             :                         break;
     787             :                 }
     788             :         }
     789             : 
     790           0 :         printf("\n");
     791           0 : }

Generated by: LCOV version 1.13