1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * SPD (memory serial presence detect) File: ui_spdcmds.c
6 * Commands to display contents of memory SPD ROMs
8 * Author: Mitch Lichtenberg (mpl@broadcom.com)
10 *********************************************************************
12 * Copyright 2000,2001,2002,2003
13 * Broadcom Corporation. All rights reserved.
15 * This software is furnished under license and may be used and
16 * copied only in accordance with the following terms and
17 * conditions. Subject to these conditions, you may download,
18 * copy, install, use, modify and distribute modified or unmodified
19 * copies of this software in source and/or binary form. No title
20 * or ownership is transferred hereby.
22 * 1) Any source code used, modified or distributed must reproduce
23 * and retain this copyright notice and list of conditions
24 * as they appear in the source file.
26 * 2) No right is granted to use any trade name, trademark, or
27 * logo of Broadcom Corporation. The "Broadcom Corporation"
28 * name may not be used to endorse or promote products derived
29 * from this software without the prior written permission of
30 * Broadcom Corporation.
32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44 * THE POSSIBILITY OF SUCH DAMAGE.
45 ********************************************************************* */
48 #include "lib_types.h"
49 #include "lib_string.h"
50 #include "lib_queue.h"
51 #include "lib_malloc.h"
52 #include "lib_printf.h"
54 #include "cfe_error.h"
55 #include "cfe_timer.h"
57 #include "ui_command.h"
60 #include "bsp_config.h"
63 #include "sb1250_regs.h"
64 #include "sb1250_smbus.h"
65 #include "sb1250_draminit.h"
67 /*#define _PROGRAM_SPD_*/
69 /* *********************************************************************
71 ********************************************************************* */
74 /* *********************************************************************
76 ********************************************************************* */
78 int ui_init_spdcmds(void);
79 static int ui_cmd_showspd(ui_cmdline_t
*cmd
,int argc
,char *argv
[]);
82 static int ui_cmd_programspd(ui_cmdline_t
*cmd
,int argc
,char *argv
[]);
85 /* *********************************************************************
87 ********************************************************************* */
93 #define SPD_ENCODED2 4
95 typedef struct spdbyte_s
{
102 static spdbyte_t spdinfo
[] = {
103 {"memtype",JEDEC_SPD_MEMTYPE
, 0,"[2 ] Memory type"},
104 {"rows", JEDEC_SPD_ROWS
, 0,"[3 ] Number of row bits"},
105 {"cols", JEDEC_SPD_COLS
, 0,"[4 ] Number of column bits"},
106 {"sides", JEDEC_SPD_SIDES
, 0,"[5 ] Number of sides"},
107 {"width", JEDEC_SPD_WIDTH
, 0,"[6 ] Module width"},
108 {"banks", JEDEC_SPD_BANKS
, 0,"[17] Number of banks"},
109 {"tCK25", JEDEC_SPD_tCK25
, SPD_DEC_BCD
,"[9 ] tCK value for CAS Latency 2.5"},
110 {"tCK20", JEDEC_SPD_tCK20
, SPD_DEC_BCD
,"[23] tCK value for CAS Latency 2.0"},
111 {"tCK10", JEDEC_SPD_tCK10
, SPD_DEC_BCD
,"[25] tCK value for CAS Latency 1.0"},
112 {"rfsh", JEDEC_SPD_RFSH
, SPD_ENCODED
,"[12] Refresh rate (KHz)"},
113 {"caslat",JEDEC_SPD_CASLATENCIES
,SPD_ENCODED
,"[18] CAS Latencies supported"},
114 {"attrib",JEDEC_SPD_ATTRIBUTES
, SPD_ENCODED
,"[21] Module attributes"},
115 {"tRAS", JEDEC_SPD_tRAS
, 0,"[30]"},
116 {"tRP", JEDEC_SPD_tRP
, SPD_DEC_QTR
,"[27]"},
117 {"tRRD", JEDEC_SPD_tRRD
, SPD_DEC_QTR
,"[28]"},
118 {"tRCD", JEDEC_SPD_tRCD
, SPD_DEC_QTR
,"[29]"},
119 {"tRFC", JEDEC_SPD_tRFC
, 0,"[42]"},
120 {"tRC", JEDEC_SPD_tRC
, 0,"[41]"},
124 /* *********************************************************************
127 * Add SPD-specific commands to the command table
134 ********************************************************************* */
136 int ui_init_spdcmds(void)
139 cmd_addcmd("show spd",
142 "Display contents of memory SPD",
143 "show spd chan device",
144 "-v;Display entire SPD content in hex");
147 cmd_addcmd("program spd",
150 "DANGER Program SPD with memory parameters DANGER",
151 "program spd chan device [ {-offset=* -byte=*} | [MEMORY_PARAMETERS] ]\n\n"
152 "This commands first reads from SPD, then change only the specified parameter.",
153 "-offset=*;Dev addr within SPD(deflt=0)|"
154 "-byte=*;Byte value if -offset used|"
155 "-memtype=*;Memory type|"
156 "-rows=*;Number of row bits|"
157 "-cols=*;Number of column bits|"
158 "-sides=*;Number of sides|"
159 "-width=*;Module width|"
160 "-banks=*;Number of banks|"
161 "-tck25=*;tCK value for CAS Latency 2.5|"
162 "-tck20=*;tCK value for CAS Latency 2.0|"
163 "-tck10=*;tCK value for CAS Latency 1.0|"
164 "-rfsh=*;Refresh rate setting|"
165 "-caslat=*;CAS Latencies supported|"
166 "-attrib=*;Module Attributes|"
174 #endif // _PROGRAM_SPD_
180 /* *********************************************************************
181 * spd_smbus_init(chan)
183 * Initialize the specified SMBus channel for the temp sensor
186 * chan - channel # (0 or 1)
190 ********************************************************************* */
192 static void spd_smbus_init(int chan
)
196 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_FREQ
));
198 SBWRITECSR(reg
,K_SMB_FREQ_100KHZ
); /* 100Khz clock */
200 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_CONTROL
));
202 SBWRITECSR(reg
,0); /* not in direct mode, no interrupts, will poll */
206 /* *********************************************************************
207 * spd_smbus_waitready(chan)
209 * Wait until the SMBus channel is ready. We simply poll
210 * the busy bit until it clears.
213 * chan - channel (0 or 1)
217 ********************************************************************* */
218 static int spd_smbus_waitready(int chan
)
223 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_STATUS
));
226 status
= SBREADCSR(reg
);
227 if (status
& M_SMB_BUSY
) continue;
231 if (status
& M_SMB_ERROR
) {
232 SBWRITECSR(reg
,(status
& M_SMB_ERROR
));
238 /* *********************************************************************
239 * spd_smbus_read(chan,slaveaddr,devaddr)
241 * Read a byte from the chip
244 * chan - SMBus channel
245 * slaveaddr - SMBus slave address
246 * devaddr - byte with in the sensor device to read
251 ********************************************************************* */
253 static int spd_smbus_read(int chan
,int slaveaddr
,int devaddr
)
259 * Make sure the bus is idle (probably should
263 if (spd_smbus_waitready(chan
) < 0) return -1;
266 * Write the device address to the controller. There are two
267 * parts, the high part goes in the "CMD" field, and the
268 * low part is the data field.
271 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_CMD
));
272 SBWRITECSR(reg
,devaddr
);
278 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_START
));
279 SBWRITECSR(reg
,V_SMB_TT(K_SMB_TT_CMD_RD1BYTE
) | slaveaddr
);
281 err
= spd_smbus_waitready(chan
);
282 if (err
< 0) return err
;
284 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_DATA
));
285 err
= SBREADCSR(reg
);
290 /* *********************************************************************
291 * spd_smbus_write(chan,slaveaddr,devaddr,b)
293 * write a byte to the chip.
296 * chan - SMBus channel
297 * slaveaddr - SMBus slave address
298 * devaddr - byte within the at24c02 device to read
304 ********************************************************************* */
308 static int spd_smbus_write(int chan
,int slaveaddr
,int devaddr
,int b
)
315 * Make sure the bus is idle (probably should
319 if (spd_smbus_waitready(chan
) < 0) return -1;
322 * Write the device address to the controller. There are two
323 * parts, the high part goes in the "CMD" field, and the
324 * low part is the data field.
327 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_CMD
));
328 SBWRITECSR(reg
,devaddr
);
331 * Write the data to the controller
334 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_DATA
));
338 * Start the command. Keep pounding on the device until it
339 * submits or the timer expires, whichever comes first. The
340 * datasheet says writes can take up to 10ms, so we'll give it 500.
343 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_START
));
344 SBWRITECSR(reg
,V_SMB_TT(K_SMB_TT_WR2BYTE
) | slaveaddr
);
347 * Wait till the SMBus interface is done
350 err
= spd_smbus_waitready(chan
);
351 if (err
< 0) return err
;
354 * Pound on the device with a current address read
355 * to poll for the write complete
361 while (!TIMER_EXPIRED(timer
)) {
364 SBWRITECSR(reg
,V_SMB_TT(K_SMB_TT_RD1BYTE
) | slaveaddr
);
366 err
= spd_smbus_waitready(chan
);
373 #endif // _PROGRAM_SPD_
375 /* *********************************************************************
376 * ui_cmd_showspd(cmd,argc,argv)
381 * cmd - command structure
382 * argc,argv - parameters
385 * -1 if error occured.
386 ********************************************************************* */
388 static int ui_cmd_showspd(ui_cmdline_t
*cmd
,int argc
,char *argv
[])
395 x
= cmd_getarg(cmd
,0);
396 if (!x
) return ui_showusage(cmd
);
398 if ((chan
< 0) || (chan
> 1)) return ui_showusage(cmd
);
400 x
= cmd_getarg(cmd
,1);
401 if (!x
) return ui_showusage(cmd
);
404 spd_smbus_init(chan
);
406 if (cmd_sw_isset(cmd
,"-v")) {
407 for (idx
= 0; idx
< 32; idx
++) {
408 b
= spd_smbus_read(chan
,dev
,idx
);
410 printf("Could not read SPD at %d/0x%02X\n",chan
,dev
);
413 printf("SPD[%2d] = %02X\n",idx
,b
);
417 spdbyte_t
*s
= spdinfo
;
421 b
= spd_smbus_read(chan
,dev
,s
->spdidx
);
423 printf("Could not read SPD at %d/0x%02X\n",chan
,dev
);
427 switch (s
->decimal
) {
429 sprintf(buf
,"%02X (%u)",b
,b
);
432 sprintf(buf
,"%d.%d",(b
>> 4), b
& 0x0F);
435 sprintf(buf
,"0x%02X",b
);
438 sprintf(buf
,"%d.%02d",(b
>> 2), (b
& 0x03) *25);;
442 printf("%8s = %15s | %30s\n",s
->name
,buf
,s
->description
);
451 /* *********************************************************************
452 * ui_cmd_programspd(cmd,argc,argv)
454 * Program SPD with memory parameters.
457 * cmd - command structure
458 * argc,argv - parameters
461 * -1 if error occured.
462 ********************************************************************* */
466 static int ui_cmd_programspd(ui_cmdline_t
*cmd
,int argc
,char *argv
[])
470 unsigned char spd
[JEDEC_SPD_MAX
+1];
475 x
= cmd_getarg(cmd
,0);
476 if (!x
) return ui_showusage(cmd
);
478 if ((chan
< 0) || (chan
> 1)) return ui_showusage(cmd
);
480 x
= cmd_getarg(cmd
,1);
481 if (!x
) return ui_showusage(cmd
);
484 spd_smbus_init(chan
);
486 /* Save what's on the SPD */
488 while (idx
<= JEDEC_SPD_MAX
) {
489 res
= spd_smbus_read(chan
,dev
,idx
);
491 printf("Could not read byte %d at %d/0x%02X\n",idx
,chan
,dev
);
498 /* Get user values */
501 cmd_sw_value(cmd
,"-offset",&x
);
502 if (x
!= NULL
) offset
= lib_atoi(x
);
505 cmd_sw_value(cmd
,"-byte",&x
);
506 if (x
!= NULL
) spd
[offset
] = lib_atoi(x
);
509 cmd_sw_value(cmd
,"-memtype",&x
);
510 if (x
!= NULL
) spd
[JEDEC_SPD_MEMTYPE
] = lib_atoi(x
);
513 cmd_sw_value(cmd
,"-rows",&x
);
514 if (x
!= NULL
) spd
[JEDEC_SPD_ROWS
] = lib_atoi(x
);
517 cmd_sw_value(cmd
,"-cols",&x
);
518 if (x
!= NULL
) spd
[JEDEC_SPD_COLS
] = lib_atoi(x
);
521 cmd_sw_value(cmd
,"-sides",&x
);
522 if (x
!= NULL
) spd
[JEDEC_SPD_SIDES
] = lib_atoi(x
);
525 cmd_sw_value(cmd
,"-width",&x
);
526 if (x
!= NULL
) spd
[JEDEC_SPD_WIDTH
] = lib_atoi(x
);
529 cmd_sw_value(cmd
,"-banks",&x
);
530 if (x
!= NULL
) spd
[JEDEC_SPD_BANKS
] = lib_atoi(x
);
533 cmd_sw_value(cmd
,"-tck25",&x
);
534 if (x
!= NULL
) spd
[JEDEC_SPD_tCK25
] = lib_atoi(x
);
537 cmd_sw_value(cmd
,"-tck20",&x
);
538 if (x
!= NULL
) spd
[JEDEC_SPD_tCK20
] = lib_atoi(x
);
541 cmd_sw_value(cmd
,"-tck10",&x
);
542 if (x
!= NULL
) spd
[JEDEC_SPD_tCK10
] = lib_atoi(x
);
545 cmd_sw_value(cmd
,"-rfsh",&x
);
546 if (x
!= NULL
) spd
[JEDEC_SPD_RFSH
] = lib_atoi(x
);
549 cmd_sw_value(cmd
,"-caslat",&x
);
550 if (x
!= NULL
) spd
[JEDEC_SPD_CASLATENCIES
] = lib_atoi(x
);
553 cmd_sw_value(cmd
,"-attrib",&x
);
554 if (x
!= NULL
) spd
[JEDEC_SPD_ATTRIBUTES
] = lib_atoi(x
);
557 cmd_sw_value(cmd
,"-tras",&x
);
558 if (x
!= NULL
) spd
[JEDEC_SPD_tRAS
] = lib_atoi(x
);
561 cmd_sw_value(cmd
,"-trp",&x
);
562 if (x
!= NULL
) spd
[JEDEC_SPD_tRP
] = lib_atoi(x
);
565 cmd_sw_value(cmd
,"-trrd",&x
);
566 if (x
!= NULL
) spd
[JEDEC_SPD_tRRD
] = lib_atoi(x
);
569 cmd_sw_value(cmd
,"-trcd",&x
);
570 if (x
!= NULL
) spd
[JEDEC_SPD_tRCD
] = lib_atoi(x
);
573 cmd_sw_value(cmd
,"-trfc",&x
);
574 if (x
!= NULL
) spd
[JEDEC_SPD_tRFC
] = lib_atoi(x
);
577 cmd_sw_value(cmd
,"-trc",&x
);
578 if (x
!= NULL
) spd
[JEDEC_SPD_tRC
] = lib_atoi(x
);
582 while (idx
<= JEDEC_SPD_MAX
) {
583 res
= spd_smbus_write(chan
,dev
,idx
,spd
[idx
]);
585 printf("Could not write byte %d at %d/0x%02X\n",idx
,chan
,dev
);
594 #endif // _PROGRAM_SPD_