GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / cfe / cfe / hosttools / memconfig.c
blobcba39f2b6d2de254c71401bb7b0b93f5b01d2071
1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * Memory Config Utility File: memconfig.c
5 *
6 * Author: Mitch Lichtenberg (mpl@broadcom.com)
7 *
8 * This host tool lets you enter DRAM parameters and run CFE's
9 * standard memory configuration to calculate the relevant timing
10 * parameters. It's a good way to see what CFE would have done,
11 * to find bogus timing calculations.
13 *********************************************************************
15 * Copyright 2000,2001,2002,2003
16 * Broadcom Corporation. All rights reserved.
18 * This software is furnished under license and may be used and
19 * copied only in accordance with the following terms and
20 * conditions. Subject to these conditions, you may download,
21 * copy, install, use, modify and distribute modified or unmodified
22 * copies of this software in source and/or binary form. No title
23 * or ownership is transferred hereby.
25 * 1) Any source code used, modified or distributed must reproduce
26 * and retain this copyright notice and list of conditions
27 * as they appear in the source file.
29 * 2) No right is granted to use any trade name, trademark, or
30 * logo of Broadcom Corporation. The "Broadcom Corporation"
31 * name may not be used to endorse or promote products derived
32 * from this software without the prior written permission of
33 * Broadcom Corporation.
35 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
36 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
37 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
38 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
39 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
40 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
41 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
43 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
44 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
45 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
46 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
47 * THE POSSIBILITY OF SUCH DAMAGE.
48 ********************************************************************* */
50 #include <stdio.h>
51 #include <string.h>
53 /* *********************************************************************
54 * Basic types
55 ********************************************************************* */
57 typedef unsigned char uint8_t;
58 typedef unsigned short uint16_t;
59 typedef unsigned long uint32_t;
60 typedef unsigned long long uint64_t;
62 /* *********************************************************************
63 * SB1250 stuff
64 ********************************************************************* */
66 #include "sb1250_defs.h"
67 #include "sb1250_mc.h"
68 #include "sb1250_draminit.h"
69 #include "sb1250_regs.h"
70 #include "sb1250_scd.h"
72 /* *********************************************************************
73 * BCD macros
74 ********************************************************************* */
76 #define DECTO10THS(x) ((((x) >> 4)*10)+((x) & 0x0F))
78 /* *********************************************************************
79 * Global defaults
80 ********************************************************************* */
82 #define MIN_tMEMCLK DRT10(8,0)
83 #define tROUNDTRIP DRT10(2,5)
85 /* *********************************************************************
86 * Types
87 ********************************************************************* */
89 typedef struct encvalue_s {
90 char *name;
91 uint8_t val;
92 } encvalue_t;
94 typedef struct spdbyte_s {
95 char *name;
96 uint8_t *data;
97 int decimal;
98 encvalue_t *values;
99 char *units;
100 char *description;
101 char *deflt;
102 } spdbyte_t;
104 #define SPD_DEC_BCD 1
105 #define SPD_DEC_QTR 2
106 #define SPD_ENCODED 3
107 #define SPD_ENCODED2 4
109 /* *********************************************************************
110 * Globals
111 ********************************************************************* */
114 uint8_t spd[64] = {0}; /* SPD data */
115 uint8_t mintmemclk = MIN_tMEMCLK; /* Default value: 8.0ns */
116 uint8_t roundtrip = tROUNDTRIP; /* Default value: 2.5ns */
117 uint8_t dramtype = JEDEC; /* Regular DDR SDRAMs */
118 uint8_t plldiv = 10; /* 500 MHz using 100Mhz refclk */
119 uint8_t refclk = 100; /* 100Mhz reference clock */
120 uint8_t portintlv = 0; /* no port interleaving */
122 uint8_t addrskew = 0x8;
123 uint8_t dqoskew = 0x8;
124 uint8_t dqiskew = 0x8;
125 uint8_t addrdrive = 0xF;
126 uint8_t datadrive = 0xF;
127 uint8_t clkdrive = 0xF;
129 uint64_t mc0_mclkcfg; /* Value programmed by draminit */
130 uint64_t mc0_timing1; /* Value programmed by draminit */
131 uint64_t smbus0_start = 0; /* Rememberd SMBus register value */
132 uint64_t smbus0_cmd = 0; /* Rememberd SMBus register value */
134 extern int sb1250_refclk; /* from draminit - reference clock */
135 extern int dram_cas_latency; /* from draminit - calc'd cas latency */
136 extern int dram_tMemClk; /* from draminit - calc'd tMemClk */
138 draminittab_t inittab[16]; /* our init tab */
140 int debug = 0;
142 /* *********************************************************************
143 * Parameter and value tables
144 ********************************************************************* */
146 encvalue_t caslatencies[] = {
147 {"3.5",JEDEC_CASLAT_35},
148 {"3.0",JEDEC_CASLAT_30},
149 {"2.5",JEDEC_CASLAT_25},
150 {"2.0",JEDEC_CASLAT_20},
151 {"1.5",JEDEC_CASLAT_15},
152 {"1.0",JEDEC_CASLAT_10},
153 {NULL,0}};
155 encvalue_t refreshrates[] = {
156 {"64",JEDEC_RFSH_64khz},
157 {"256",JEDEC_RFSH_256khz},
158 {"128",JEDEC_RFSH_128khz},
159 {"32",JEDEC_RFSH_32khz},
160 {"16",JEDEC_RFSH_16khz},
161 {"8",JEDEC_RFSH_8khz},
162 {NULL,0}};
164 encvalue_t modattribs[] = {
165 {"none",0},
166 {"reg",JEDEC_ATTRIB_REG},
167 {"diffclk",0x20},
168 {NULL,0}};
170 encvalue_t dramtypes[] = {
171 {"jedec",JEDEC},
172 {"fcram",FCRAM},
173 {"sgram",SGRAM},
174 {NULL,0}};
176 spdbyte_t spdfields[] = {
177 {"mintmemclk",&mintmemclk,SPD_DEC_BCD,NULL,"ns","Minimum value for tMEMCLK","8.0"},
178 {"roundtrip", &roundtrip, SPD_DEC_BCD,NULL,"ns","Round trip time from CLK to returned DQS","2.5"},
179 {"plldiv", &plldiv, 0,NULL,"","PLL Ratio (System Config Register)","10"},
180 {"refclk", &refclk, 0,NULL,"Mhz","Reference clock, usually 100Mhz","100"},
181 // {"portintlv", &portintlv, 0,NULL,"","Port interleave (1=on)","0"},
182 {"memtype", &dramtype, SPD_ENCODED,dramtypes,"","Memory type (jedec, fcram, sgram)","jedec"},
183 {"rows", &spd[JEDEC_SPD_ROWS],0,NULL,"","[3 ] Number of row bits","13"},
184 {"cols", &spd[JEDEC_SPD_COLS],0,NULL,"","[4 ] Number of column bits","9"},
185 {"banks", &spd[JEDEC_SPD_BANKS],0,NULL,"","[17] Number of banks","4"},
186 {"tCK25", &spd[JEDEC_SPD_tCK25],SPD_DEC_BCD,NULL,"ns","[9 ] tCK value for CAS Latency 2.5","7.5"},
187 {"tCK20", &spd[JEDEC_SPD_tCK20],SPD_DEC_BCD,NULL,"ns","[23] tCK value for CAS Latency 2.0","0"},
188 {"tCK10", &spd[JEDEC_SPD_tCK10],SPD_DEC_BCD,NULL,"ns","[25] tCK value for CAS Latency 1.0","0"},
189 {"rfsh", &spd[JEDEC_SPD_RFSH],SPD_ENCODED,refreshrates,"","[12] Refresh rate (KHz)","8"},
190 {"caslat", &spd[JEDEC_SPD_CASLATENCIES],SPD_ENCODED2,caslatencies,"","[18] CAS Latencies supported","2.5"},
191 {"attrib", &spd[JEDEC_SPD_ATTRIBUTES],SPD_ENCODED,modattribs,"","[21] Module attributes","none"},
192 {"tRAS", &spd[JEDEC_SPD_tRAS],0,NULL,"ns","[30]","45"},
193 {"tRP", &spd[JEDEC_SPD_tRP],SPD_DEC_QTR,NULL,"ns","[27]","20.0"},
194 {"tRRD", &spd[JEDEC_SPD_tRRD],SPD_DEC_QTR,NULL,"ns","[28]","15.0"},
195 {"tRCD", &spd[JEDEC_SPD_tRCD],SPD_DEC_QTR,NULL,"ns","[29]","20.0"},
196 {"tRFC", &spd[JEDEC_SPD_tRFC],0,NULL,"ns","[42]","0"},
197 {"tRC", &spd[JEDEC_SPD_tRC],0,NULL,"ns","[41]","0"},
199 {"addrskew", &addrskew, 0, NULL, "","Address Skew","0x0F"},
200 {"dqoskew", &dqoskew, 0, NULL, "","DQO Skew","0x08"},
201 {"dqikew", &dqiskew, 0, NULL, "","DQI Skew","0x08"},
202 {"addrdrive", &addrdrive, 0, NULL, "","Address Drive","0x0F"},
203 {"datadrive", &datadrive, 0, NULL, "","Data Drive","0x0F"},
204 {"clkdrive", &clkdrive, 0, NULL, "","Clock Drive","0"},
205 {NULL,0,0,NULL,NULL,NULL,NULL}};
207 char *lookupstr(encvalue_t *ev,uint8_t val)
209 while (ev->name) {
210 if (ev->val == val) return ev->name;
211 ev++;
213 return "unknown";
216 uint64_t sbreadcsr(uint64_t reg)
218 uint64_t val = 0;
220 if (debug) printf("READ %08X\n",(uint32_t) reg);
222 switch ((uint32_t) reg) {
223 case A_SCD_SYSTEM_REVISION:
224 val = V_SYS_PART(0x1250) | V_SYS_WID(0) | V_SYS_REVISION(1) | 0xFF;
225 break;
226 case A_SCD_SYSTEM_CFG:
227 val = V_SYS_PLL_DIV(plldiv);
228 break;
229 case A_SMB_STATUS_0:
230 val = 0;
231 break;
232 case A_SMB_CMD_0:
233 val = smbus0_cmd;
234 break;
235 case A_SMB_START_0:
236 val = smbus0_start;
237 break;
238 case A_SMB_DATA_0:
239 val = spd[smbus0_cmd & 0x3F];
240 break;
242 return val;
245 void sbwritecsr(uint64_t reg,uint64_t val)
247 if (debug) printf("WRITE %08X %016llX\n",(uint32_t) reg,val);
249 switch ((uint32_t) reg) {
250 case A_MC_REGISTER(0,R_MC_MCLK_CFG):
251 mc0_mclkcfg = val;
252 break;
253 case A_MC_REGISTER(0,R_MC_TIMING1):
254 mc0_timing1 = val;
255 break;
256 case A_SMB_CMD_0:
257 smbus0_cmd = val;
258 break;
259 case A_SMB_START_0:
260 smbus0_start = val;
261 break;
266 int procfield(char *txt)
268 int num = 0;
269 int a,b;
270 spdbyte_t *sf;
271 encvalue_t *ev;
272 char *x;
273 char *tok;
275 x = strchr(txt,'=');
276 if (!x) {
277 printf("Fields must be specified as 'name=value'\n");
278 exit(1);
280 *x++ = '\0';
282 sf = spdfields;
283 while (sf->name) {
284 if (strcmp(sf->name,txt) == 0) break;
285 sf++;
288 if (sf->name == NULL) {
289 printf("Invalid field name: %s\n",txt);
290 return -1;
293 if (memcmp(x,"0x",2) == 0) {
294 sscanf(x+2,"%x",&num);
296 else {
297 if (strchr(x,'.')) {
298 if (sscanf(x,"%d.%d",&a,&b) != 2) {
299 printf("%s: invalid number: %s\n",sf->name,x);
300 return -1;
303 else {
304 a = atoi(x);
305 b = 0;
308 switch (sf->decimal) {
309 case SPD_DEC_BCD:
310 if ((b < 0) || (b > 9)) {
311 printf("%s: Invalid BCD number: %s\n",sf->name,x);
312 return -1;
314 num = (a*16)+b;
315 break;
316 case SPD_DEC_QTR:
317 if ((b != 0) && (b != 25) && (b != 50) && (b != 75)) {
318 printf("%s: Invalid 2-bit fraction number: %s\n",sf->name,x);
319 printf("(number after decimal should be 0,25,50,75)\n");
320 exit(1);
322 num = (a*4)+(b/25);
323 break;
324 case SPD_ENCODED:
325 ev = sf->values;
326 while (ev->name) {
327 if (strcmp(ev->name,x) == 0) break;
328 ev++;
330 if (!ev->name) {
331 printf("%s: Invalid value. Valid values are: ",x);
332 ev = sf->values;
333 while (ev->name) { printf("%s ",ev->name); ev++; }
334 printf("\n");
335 return -1;
337 num = ev->val;
338 break;
339 case SPD_ENCODED2:
340 tok = strtok(x," ,");
341 num = 0;
342 while (tok) {
343 ev = sf->values;
344 while (ev->name) {
345 if (strcmp(ev->name,tok) == 0) break;
346 ev++;
348 if (!ev->name) {
349 printf("%s: Invalid value. Valid values are: ",tok);
350 ev = sf->values;
351 while (ev->name) { printf("%s ",ev->name); ev++; }
352 printf("\n");
353 return -1;
355 num |= ev->val;
356 tok = strtok(NULL," ,");
358 break;
359 default:
360 num = a;
361 break;
365 *(sf->data) = num;
367 return 0;
370 void interactive(void)
372 spdbyte_t *sf;
373 char field[100];
374 char ask[100];
375 char prompt[100];
376 char *x;
378 sf = spdfields;
380 printf("%-65.65s: Value\n","Parameter");
381 printf("%-65.65s: -----\n","-----------------------------------------------------------------");
383 while (sf->name) {
384 for (;;) {
385 x = prompt;
386 x += sprintf(x,"%s (%s", sf->name,sf->description);
387 if (sf->units && sf->units[0]) {
388 if (sf->description && sf->description[0]) x += sprintf(x,", ");
389 x += sprintf(x,"%s",sf->units);
391 x += sprintf(x,"): [%s]", sf->deflt);
392 printf("%-65.65s: ",prompt);
394 fgets(ask,sizeof(ask),stdin);
395 if ((x = strchr(ask,'\n'))) *x = '\0';
396 if (ask[0] == 0) strcpy(ask,sf->deflt);
397 sprintf(field,"%s=%s",sf->name,ask);
398 if (procfield(field) < 0) continue;
399 break;
401 sf++;
404 printf("\n\n");
407 int swcnt = 0;
408 char *swnames[32];
410 int proc_args(int argc,char *argv[])
412 int inidx,outidx;
414 outidx = 1;
416 for (inidx = 1; inidx < argc; inidx++) {
417 if (argv[inidx][0] != '-') {
418 argv[outidx++] = argv[inidx];
420 else {
421 swnames[swcnt] = argv[inidx];
422 swcnt++;
426 return outidx;
429 int swisset(char *x)
431 int idx;
433 for (idx = 0; idx < swcnt; idx++) {
434 if (strcmp(x,swnames[idx]) == 0) return 1;
436 return 0;
439 void dumpmclkcfg(uint64_t val)
441 printf("clk_ratio = %d\n",G_MC_CLK_RATIO(val));
442 printf("ref_rate = %d\n",G_MC_REF_RATE(val));
446 void dumptiming1(uint64_t val)
448 printf("w2rIdle = %d\n",(val & M_MC_w2rIDLE_TWOCYCLES) ? 1 : 0);
449 printf("r2rIdle = %d\n",(val & M_MC_r2rIDLE_TWOCYCLES) ? 1 : 0);
450 printf("r2wIdle = %d\n",(val & M_MC_r2wIDLE_TWOCYCLES) ? 1 : 0);
451 printf("tCrD = %d\n",(int)G_MC_tCrD(val));
452 printf("tCrDh = %d\n",(val & M_MC_tCrDh) ? 1 : 0);
453 printf("tFIFO = %d\n",(int)G_MC_tFIFO(val));
454 printf("tCwD = %d\n",(int)G_MC_tCwD(val));
456 printf("tRP = %d\n",(int)G_MC_tRP(val));
457 printf("tRRD = %d\n",(int)G_MC_tRRD(val));
458 printf("tRCD = %d\n",(int)G_MC_tRCD(val));
460 printf("tRFC = %d\n",(int)G_MC_tRFC(val));
461 printf("tRCw = %d\n",(int)G_MC_tRCw(val));
462 printf("tRCr = %d\n",(int)G_MC_tRCr(val));
463 printf("tCwCr = %d\n",(int)G_MC_tCwCr(val));
466 int main(int argc,char *argv[])
468 spdbyte_t *sf;
469 uint8_t t;
470 int idx;
471 int mclk;
472 draminittab_t *init;
474 spd[JEDEC_SPD_MEMTYPE] = JEDEC_MEMTYPE_DDRSDRAM2;
475 spd[JEDEC_SPD_ROWS] = 13;
476 spd[JEDEC_SPD_COLS] = 9;
477 spd[JEDEC_SPD_BANKS] = 2;
478 spd[JEDEC_SPD_SIDES] = 1;
479 spd[JEDEC_SPD_WIDTH] = 72;
481 argc = proc_args(argc,argv);
483 if ((argc == 1) && !swisset("-i")) {
484 printf("usage: memconfig name=value name=value ...\n");
485 printf("\n");
486 printf("Available fields: ");
487 sf = spdfields;
488 while (sf->name) {
489 printf("%s ",sf->name);
490 sf++;
492 printf("\n");
493 exit(1);
496 if (swisset("-i")) {
497 interactive();
499 else {
500 for (idx = 1; idx < argc; idx++) {
501 if (procfield(argv[idx]) < 0) exit(1);
505 debug = swisset("-d");
507 printf("-------Memory Parameters---------\n");
509 sf = spdfields;
510 while (sf->name) {
511 char buffer[64];
512 char *p = buffer;
514 t = *(sf->data);
515 printf("%-10.10s = 0x%02X ",sf->name,t);
516 switch (sf->decimal) {
517 case SPD_DEC_BCD:
518 p += sprintf(p,"(%d.%d)",
519 t >> 4, t & 0x0F);
520 break;
521 case SPD_DEC_QTR:
522 p += sprintf(p,"(%d.%02d)",
523 t/4,(t&3)*25);
524 break;
525 case SPD_ENCODED:
526 p += sprintf(p,"(%s)",lookupstr(sf->values,t));
527 break;
528 default:
529 p += sprintf(p,"(%d)",t);
530 break;
533 p += sprintf(p," %s",sf->units);
534 printf("%-16.16s %s\n",buffer,sf->description);
535 sf++;
538 printf("\n");
540 init = &inittab[0];
541 memset(inittab,0,sizeof(inittab));
543 init->gbl.gbl_type = MCR_GLOBALS;
544 init->gbl.gbl_intlv_ch = portintlv;
545 init++;
547 init->cfg.cfg_type = MCR_CHCFG;
548 init->cfg.cfg_chan = 0;
549 init->cfg.cfg_mintmemclk = mintmemclk;
550 init->cfg.cfg_dramtype = dramtype;
551 init->cfg.cfg_pagepolicy = CASCHECK;
552 init->cfg.cfg_blksize = BLKSIZE32;
553 init->cfg.cfg_intlv_cs = NOCSINTLV;
554 init->cfg.cfg_ecc = 0;
555 init->cfg.cfg_roundtrip = roundtrip;
556 init++;
558 init->clk.clk_type = MCR_CLKCFG;
559 init->clk.clk_addrskew = addrskew;
560 init->clk.clk_dqoskew = dqoskew;
561 init->clk.clk_dqiskew = dqiskew;
562 init->clk.clk_addrdrive = addrdrive;
563 init->clk.clk_datadrive = datadrive;
564 init->clk.clk_clkdrive = clkdrive;
565 init++;
567 init->geom.geom_type = MCR_GEOM;
568 init->geom.geom_csel = 0;
569 init->geom.geom_rows = spd[JEDEC_SPD_ROWS];
570 init->geom.geom_cols = spd[JEDEC_SPD_COLS];
571 init->geom.geom_banks = spd[JEDEC_SPD_BANKS];
572 init++;
574 init->spd.spd_type = MCR_SPD;
575 init->spd.spd_csel = 0;
576 init->spd.spd_flags = 0;
577 init->spd.spd_smbuschan = 0;
578 init->spd.spd_smbusdev = 0x50;
579 init++;
581 init->mcr.mcr_type = MCR_EOT;
584 sb1250_refclk = (int) refclk;
586 sb1250_dram_init(inittab);
589 printf("-----Memory Timing Register Values-----\n");
590 printf("System Clock %dMHz\n",plldiv*refclk/2);
591 printf("CAS latency %d.%d\n",dram_cas_latency>>1,(dram_cas_latency&1)?5:0);
592 printf("tMemClk %d.%d ns\n",dram_tMemClk/10,dram_tMemClk%10);
593 mclk = (plldiv*refclk)*10/2/((int)G_MC_CLK_RATIO(mc0_mclkcfg));
594 printf("MCLK Freq %d.%dMHz\n",mclk/10,mclk%10);
595 printf("\n");
596 printf("MC_TIMING1 = %016llX\n",mc0_timing1);
597 printf("MCLK_CONFIG = %016llX\n",mc0_mclkcfg);
598 printf("\n");
600 printf("-----Memory Timing Register Fields-----\n");
601 dumptiming1(mc0_timing1);
603 printf("-----Memory Clock Config Register Fields-----\n");
604 dumpmclkcfg(mc0_mclkcfg);
606 printf("---Done!---\n");
608 printf("%s ",argv[0]);
609 sf = spdfields;
610 while (sf->name) {
611 char buffer[64];
612 char *p = buffer;
614 t = *(sf->data);
616 p += sprintf(p,"%s=",sf->name);
617 switch (sf->decimal) {
618 case SPD_DEC_BCD:
619 p += sprintf(p,"%d.%d",
620 t >> 4, t & 0x0F);
621 break;
622 case SPD_DEC_QTR:
623 p += sprintf(p,"%d.%02d",
624 t/4,(t&3)*25);
625 break;
626 case SPD_ENCODED:
627 default:
628 p += sprintf(p,"0x%02X",t);
629 break;
632 printf("%s ",buffer);
633 sf++;
636 printf("\n");
638 return 0;