Statistics
| Branch: | Revision:

ddr4s / fw / Pi / spd_prog_both.c @ 32:cadb9025f1e0

History | View | Annotate | Download (13.6 KB)

1
/******************************************************************************
2
 * $Id$
3
 * $Project maintainers$
4
 * $Revision$
5
 * $Tree$
6
 *
7
 * SPD Programming tool for DDR4s adapter + Raspberry Pi Model B
8
 * Supported memory modules: DDR3 DIMM, DDR4 DIMM, I2C header
9
 * 
10
 * Supported I2C chips:
11
 * - Generic 24C02 EEPROM (256 bytes)
12
 * - TSE 34C02 EEPROM (512 bytes)
13
 *
14
 * Provided as is.
15
 * Debian Linux | GCC
16
 */
17

    
18
#include <stdio.h>
19
#include <stdint.h>
20
#include <stdlib.h>
21
#include <string.h>
22
#include <time.h>
23
#include <wiringPi.h>
24
#include <wiringPiI2C.h>
25

    
26
static int infoSPD (void); /* Parse information from SPD */
27
static void info (const char *buffer); /* Info function */
28

    
29
int main()
30
{
31
    int choice = 0;
32
    printf ("\033[22;34m\033[34;1m/********************** :) DDR4s Project ************************/\n DDR3/DDR4 SPD read/write tool | (C) Planet, TiN \n Usage: ./spd_prog | $Revision$\n/***********************************************************************/\033[0m\n");
33
    printf(" 1: Write DDR3 SPD | 2: Verify DDR3 SPD | 3: Read DDR3 SPD \n 4: Write DDR4 SPD | 5: Verify DDR4 SPD | 6: Read DDR4 SPD with info \n 7. SPD Info \n");
34
    printf("\033[22;35mPlease make a selection: \033[0m\n");
35
    scanf("%d", &choice);
36
    
37
    switch (choice) {
38
        case 1: writeSPD_t(); break;
39
        case 2: verifySPD_t();break;
40
        case 3: readSPD_t();  break;
41
        case 4: writeSPD_f(); break;
42
        case 5: verifySPD_f();break;
43
        case 6: readSPD_f();  break;
44
        case 7: infoSPD();    break;
45
    }
46
    return 0;
47
}
48

    
49
int infoSPD(void) {
50
    //int i = 0, j = 0, count = 0;
51
    //int addr = wiringPiI2CSetup(0x50);
52
    //int upper = wiringPiI2CSetup(0x37);
53
    //int lower = wiringPiI2CSetup(0x36);
54
    int temp_val;
55
    int remainder;
56
    int fine_corr;
57
    int tckavg[2]; // Minimum SDRAM Cycle Time in MTB units
58

    
59
    unsigned char buffer[512];
60
    char filename[25];
61
    FILE *ptr;
62

    
63
    printf("Enter filename: ");
64
    scanf("%s",filename);
65
    printf("\033[22;29mParsing file...\033[0m\n");
66

    
67
    /* Function to read dump from filesystem */
68
    ptr = fopen(filename,"rb");
69
    fread(buffer,sizeof(buffer),1,ptr);
70
    if(!ptr) {
71
       printf("Unable to open file");
72
       return 1;
73
    }
74
    fclose(ptr);
75

    
76
    info(buffer);
77
}
78
    
79
int writeSPD_t() {
80
    int i = 0;
81
    int addr = wiringPiI2CSetup(0x50);
82
    unsigned char buffer[256];
83
    char filename[25];
84
    FILE *ptr;
85
    
86
    printf("Enter filename: ");
87
    scanf("%s",filename);
88
    printf("\033[22;31mSPD Write in progress...\033[0m\n");
89
    
90
      ptr = fopen(filename,"rb");
91
      fread(buffer,sizeof(buffer),1,ptr);
92
      if(!ptr)
93
      {
94
       printf("\033[22;31mUnable to open file\033[0m");
95
       return 1;
96
      }
97
     fclose(ptr);
98
     
99
     wiringPiI2CWrite(addr,0x00);
100
     while(i<256)
101
      {
102
       wiringPiI2CWriteReg8(addr,i,buffer[i]);
103
       nanosleep((struct timespec[]){{0,5000000}}, NULL);
104
       ++i;
105
      }
106
    printf("\033[22;35mWrite complete\033[0m \n");
107
    return 0;
108
}
109
int verifySPD_t() {
110
     int i = 0, verify = 0;
111
    int addr = wiringPiI2CSetup(0x50);
112
    unsigned char buffer[256];
113
    char filename[25];
114
    FILE *ptr;
115
    
116
    printf("Enter filename: ");
117
    scanf("%s",filename);
118
    printf("\033[22;29mVerification in progress...\033[0m\n");
119
    
120
      ptr = fopen(filename,"rb");
121
      fread(buffer,sizeof(buffer),1,ptr);
122
      if(!ptr)
123
      {
124
       printf("Unable to open file");
125
       return 1;
126
      }
127
     fclose(ptr);
128
     
129
     wiringPiI2CWrite(addr,0x00);
130
     while(i<256)
131
      {
132
       int spd = wiringPiI2CReadReg8(addr,i);
133
       nanosleep((struct timespec[]){{0,5000000}}, NULL);
134
       if(spd != buffer[i])
135
       {
136
        printf("\033[22;31mSPD does not match file!\033[0m\n");
137
        verify = 1;
138
        return -1;
139
       }
140
       
141
       ++i;
142
      }
143
     if(verify == 0)
144
     {
145
     printf("\033[22;32mSPD matches File\033[0m\n");
146
     }
147
     return 0;
148
 }
149

    
150
/*****************************************************************************
151
** Function name:    readSPD_t
152
** Descriptions:    Read 256-bit EEPROM (DDR3)
153
** Returned value:    true or false, return true if errors detected
154
*****************************************************************************/
155
int readSPD_t()
156
{
157
    int i = 0, count = 1;
158
    int addr = wiringPiI2CSetup(0x50);
159
    char filename[25];
160
    unsigned char buffer[256];
161
    FILE *ptr;
162
    
163
    printf("Enter filename to save dump: ");
164
    scanf("%s",filename);
165
    if (!(filename == NULL)) {
166
        ptr = fopen(filename,"w");
167
    }
168

    
169
    while(i<256) {
170
        int byte = wiringPiI2CReadReg8(addr,i);
171
    buffer[i] = byte;
172
    printf("\033[22;32m%02x\033[0m ",byte);
173
    nanosleep((struct timespec[]){{0,5000000}}, NULL);
174
        if(0==count%16) {
175
        printf("\n");
176
    }
177
    ++count;
178
    ++i;
179
    }
180

    
181
    if (!(filename == NULL)) {
182
        fwrite(buffer,sizeof(buffer),1,ptr);
183
        if(!ptr) {
184
        printf("Unable to save file");
185
            return 1;
186
        }
187
        fclose(ptr);
188
    }
189
    
190
    return 0;
191
}
192

    
193
/*****************************************************************************
194
** Function name:    writeSPD_f
195
** Descriptions:    Write TSE 512-bit EEPROM (DDR4)
196
** Returned value:    true or false, return true if errors detected
197
*****************************************************************************/
198
int writeSPD_f() {
199
    int i = 0,j=0;
200
    int a = wiringPiI2CSetup(0x50);
201
    int c = wiringPiI2CSetup(0x36);
202
    int d = wiringPiI2CSetup(0x37);
203
    unsigned char buffer[512];
204
    char filename[25];
205
    char verify = 0;
206
    FILE *ptr;
207

    
208
    printf("Enter filename: ");
209
    scanf("%s",filename);
210
    ptr = fopen(filename,"rb");
211
    fread(buffer,sizeof(buffer),1,ptr);
212
    if(!ptr) {
213
        printf("Unable to open file");
214
        return 1;
215
    }
216
    fclose(ptr);
217
    printf("\033[22;31mSPD Write in progress...\033[0m\n");
218

    
219
    while(i < 256) {
220
        if(i == 0) {
221
            wiringPiI2CWrite(c,0x00);
222
            nanosleep((struct timespec[]){{0,5000000}}, NULL);
223
        }
224
    
225
        int b = wiringPiI2CWriteReg8(a,i,buffer[i]);
226
        nanosleep((struct timespec[]){{0,5000000}}, NULL);
227
        verify = wiringPiI2CReadReg8(a,i);
228
        nanosleep((struct timespec[]){{0,5000000}}, NULL);
229
        if (verify != buffer[i]) {
230
            printf("\033[22;31mByte %d write fail!\033[0m\n",i);
231
        }
232
        ++i; 
233
    }
234
    
235
    while(j < 256)
236
    {
237
        if(j == 0) {
238
            wiringPiI2CWrite(d,0x00);
239
            nanosleep((struct timespec[]){{0,5000000}}, NULL);
240
        }
241
        int b = wiringPiI2CWriteReg8(a,j,buffer[i]);
242
        nanosleep((struct timespec[]){{0,5000000}}, NULL);
243
        verify = wiringPiI2CReadReg8(a,j);
244
        nanosleep((struct timespec[]){{0,5000000}}, NULL);
245
        if (verify != buffer[j+256]) {
246
            printf("\033[22;31mByte %d write fail, chip %X | file %X \033[0m\n",j+256, verify, buffer[j+256]);
247
        }
248
        ++i;
249
        ++j;
250
    }
251
    
252
    wiringPiI2CWrite(c,0x00);
253
    nanosleep((struct timespec[]){{0,50000000}}, NULL);
254
    printf("\033[22;35mWrite complete!\033[0m\n");
255
    return 0;
256
}
257

    
258

    
259
/*****************************************************************************
260
** Function name:     readSPD_f
261
** Descriptions:      Read TSE 512-bit EEPROM (DDR4)
262
** Returned value:    true or false, return true if errors detected
263
*****************************************************************************/
264
int readSPD_f()
265
{
266
    int i = 0, j = 0, count = 0;
267
    int addr = wiringPiI2CSetup(0x50);
268
    int upper = wiringPiI2CSetup(0x37);
269
    int lower = wiringPiI2CSetup(0x36);
270
    char filename[25];
271
    unsigned char buffer[512];
272
    int byte;
273
    FILE *ptr;
274
    
275
    printf("Enter filename to save 512b dump: ");
276
    scanf("%s",filename);
277
    ptr = fopen(filename,"w");
278

    
279
    /* Switch lower page */
280
    wiringPiI2CWrite(lower,0x00);
281
    nanosleep((struct timespec[]){{0,500000}}, NULL);
282
        
283
    while(count < 256) {
284
        byte = wiringPiI2CReadReg8(addr, i);
285
        buffer[count] = byte;
286
        printf("\033[22;32m%02x\033[0m ",byte);
287
        nanosleep((struct timespec[]){{0,500000}}, NULL);
288
        if(0 == (count + 1)%16) {
289
            printf("\n");
290
        }
291
        
292
        ++count;
293
        ++i;
294
    }
295

    
296
    /* Switch upper page */
297
    wiringPiI2CWrite(upper,0x00);
298
    nanosleep((struct timespec[]){{0,500000}}, NULL);
299
    
300
    while(count < 512) {
301
        byte = wiringPiI2CReadReg8(addr, j);
302
        buffer[count] = byte;
303
        printf("\033[22;32m%02x\033[0m ",byte);
304
        nanosleep((struct timespec[]){{0,500000}}, NULL);
305
        if(0 == (count + 1)%16) {
306
            printf("\n");
307
        }
308
        ++count;
309
        ++j;
310
    }
311
    
312
    info(buffer);
313

    
314
    fwrite(buffer,sizeof(buffer),1,ptr);
315
    if(!ptr) {
316
    printf("\033[22;31mUnable to save file\033[0m\n");
317
        return 1;
318
    }
319
    fclose(ptr);
320
    return 0;
321
}
322

    
323
/*****************************************************************************
324
** Function name:     VerifySPD_f
325
** Descriptions:      Read and verify TSE 512-bit EEPROM (DDR4)
326
** Returned value:    true or false, return true if errors detected
327
*****************************************************************************/
328
int verifySPD_f() {
329
    int verify = 1, i = 0, j = 0, count = 0;
330
    int addr = wiringPiI2CSetup(0x50);
331
    int upper = wiringPiI2CSetup(0x37);
332
    int lower = wiringPiI2CSetup(0x36);
333
    unsigned char buffer[512];
334
    char filename[25];
335
    int byte;
336
    FILE *ptr;
337

    
338
    printf("Enter filename: ");
339
    scanf("%s",filename);
340
    printf("\033[22;29mVerification in progress...\033[0m\n");
341

    
342
    ptr = fopen(filename,"rb");
343
    fread(buffer,sizeof(buffer),1,ptr);
344
    if(!ptr) {
345
        printf("Unable to open file");
346
        return 1; 
347
    }
348
    fclose(ptr);
349

    
350
    info(buffer);
351
    
352
    /* Switch lower page */
353
    wiringPiI2CWrite(lower,0x00);
354
    nanosleep((struct timespec[]){{0,500000}}, NULL);
355

    
356
    while(count < 256) {
357
        byte = wiringPiI2CReadReg8(addr,i);
358
        if (byte != buffer[i]) {
359
            printf("\033[22;31mMismatch in byte %d, chip : %X, file %X\033[0m \n",i, byte, buffer[i]);
360
            verify = 0;
361
            if (byte == 0xFFFFFFFF) {
362
                printf ("\033[21;31m I2C Error, missing device\033[0m\n");
363
                return 100;
364
            }
365
        }
366

    
367
        nanosleep((struct timespec[]){{0,500000}}, NULL);
368
        ++count;
369
        ++i;
370
    }
371

    
372
    /* Switch upper page */
373
    wiringPiI2CWrite(upper,0x00);
374
    nanosleep((struct timespec[]){{0,500000}}, NULL);
375

    
376
    while(count < 512) {
377
        byte = wiringPiI2CReadReg8(addr,j);
378
        if (byte != buffer[count]) {
379
            printf("\033[22;31mMismatch in byte %d, chip : %X, file %X\033[0m \n",j + 256, byte, buffer[j + 256]);
380
            verify = 0;
381
            if (byte == 0xFFFFFFFF) {
382
                printf ("\033[21;31m I2C Error, missing device\033[0m\n");
383
                return 100;
384
            }
385

    
386
        }
387

    
388
        nanosleep((struct timespec[]){{0,500000}}, NULL);
389
        ++count;
390
        ++j;
391
    }
392

    
393
    if(verify == 1) {
394
       printf("\033[22;32m\nSPD matches File\033[0m\n");
395
    }
396

    
397

    
398
    return 0;
399
}
400

    
401
#define MTB                                125 // Medium time base in ps
402
#define FTB                                  1 // Fine time base in ps
403

    
404
void info (const char *buffer) {
405

    
406
    int temp_val;
407
    int remainder;
408
    int mfgid;
409
    int fine_corr;
410
    float xmpp1, xmpp2;
411
    int tckavg[2]; // Minimum SDRAM Cycle Time in MTB units
412

    
413
    printf("\n\033[22;44m*** Dump information ***\033[0m\n");
414

    
415
    printf("Key Byte / Module Type : ");
416
    if ((buffer[3] >> 4)) {
417
        printf("Incorrect type / bad SPD");
418
    } else {
419
        switch (buffer[3] & 0x0F) {
420
        case 0x00: printf("Extended module type, see byte 15 (0x00F)");break;
421
        case 0x01: printf("Registered DIMM");break;
422
        case 0x02: printf("Unbuffered DIMM");break;
423
        case 0x03: printf("Unbuffered SO-DIMM");break;
424
        case 0x04: printf("Load Reduced DIMM (LRDIMM)");break;
425
        case 0x05: printf("Mini RDIMM");break;
426
        case 0x06: printf("Mini UDIMM");break;
427
        case 0x08: printf("72-bit SO-RDIMM");break;
428
        case 0x09: printf("72-bit SO-UDIMM");break;
429
        case 0x0C: printf("16-bit SODIMM");break;
430
        case 0x0D: printf("32-bit SODIMM");break;
431
        }
432
    }
433

    
434
    printf("\033[22;33m\nModule Organization : ");
435
    printf("%d package ranks, ",((buffer[12] & 0x38) >> 3) + 1);
436
    printf("%db width\n",(buffer[12] & 0x03) * 8);
437

    
438
    printf("Module Capacity : %d MB\033[0m\n",(buffer[4] & 0x0F) * 1024 * (((buffer[12] & 0x38) >> 3) + 1));
439

    
440
    /* Check XMP */
441

    
442
    tckavg[0] = buffer[396]; // Profile 1
443
    tckavg[1] = buffer[443]; // Profile 2
444

    
445
    mfgid = (buffer[351] << 8) | buffer[350];
446
    printf("MFG ID: %X - ", mfgid);
447
    switch (mfgid) {
448
        case 0xAD80: printf("SK Hynix");break;
449
        case 0x8980: printf("Intel");break;
450
        case 0x2C80: printf("Micron");break;
451
        case 0xCE80: printf("Samsung");break;
452
        case 0x9801: printf("Kingston");break;
453
        case 0x9E02: printf("Corsair");break;
454
        case 0xCB04: printf("ADATA");break;
455
    }
456
    printf("\n");
457

    
458
    if ((buffer[384] == 0x0C) & (buffer[385] == 0x4A)) {
459
        printf("\033[22;36mIntel DDR4 XMP support present\033[0m\n");
460

    
461
    if (buffer[387] == 0x20) {
462
        printf("\033[22;36mIntel XMP Revision 2.0\033[0m\n");
463
    } else {
464
        printf("\033[22;31mIncorrect XMP Revision number!\033[0m\n");
465
    }
466

    
467
    if (buffer[386] & 0x01) {
468
        xmpp1 = (float)((buffer[396] * MTB) + ((signed char)buffer[431] * FTB)) / 1000;
469
        printf("Intel XMP Profile 1 enabled, VDD voltage level [393 byte] : %d.%d V\n",buffer[393] >> 7,(buffer[393] & 0x7F));
470
        printf("\033[22;37mProfile 1 speed (%X) : %d MHz \n", (int)(2000 / xmpp1) );
471
    }
472

    
473
    if (buffer[386] & 0x02) {
474

    
475
        xmpp2 = (float)((buffer[443] * MTB) + ((signed char)buffer[478] * FTB)) / 1000;
476
        printf("Intel XMP Profile 2 enabled, VDD voltage level [440 byte] : %d.%d V\n",buffer[440] >> 7,(buffer[440] & 0x7F));
477
        printf("\033[22;37mProfile 2 speed (%X) : %d MHz \n", (int)(2000 / xmpp2) );
478
    }
479

    
480
    } else {
481
        printf("\033[22;31mIntel XMP not supported on incorrect ID\033[0m\n");
482
    }
483

    
484
}
485