ddr.c (14965B)
1 2 /* 3 * 4 * 5 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 6 * 7 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 8 */ 9 10 #include <appl/diag/system.h> 11 #include <appl/diag/parse.h> 12 #include <bcm/error.h> 13 #include <sal/appl/sal.h> 14 #include <sal/appl/config.h> 15 #include <shared/bsl.h> 16 #ifdef BCM_DDR3_SUPPORT 17 #include <soc/shmoo_ddr40.h> 18 #include <soc/phy/ddr40.h> 19 #include <soc/shmoo_and28.h> 20 #include <soc/phy/ddr34.h> 21 #include <soc/saber2.h> 22 23 char cmd_ddr_mem_write_usage[] = "\n" 24 " DDRMemWrite ci<n> range=0xstart-[0xend] data=0xdata\n" 25 " DDRMemWrite ci0,ci1 range=0x0\n" 26 " DDRMemWrite ci2 range=0x0-0x100" 27 "\n"; 28 29 cmd_result_t 30 cmd_ddr_mem_write(int unit, args_t *a) 31 { 32 uint32 data_wr[8] = {0}; 33 uint32 data = 0; 34 int ci = 0; 35 int addr = 0; 36 int bank = 0; 37 int row = 0; 38 int col = 0; 39 int rv_stat = CMD_OK; 40 cmd_result_t ret_code; 41 char *c = NULL; 42 char *range = NULL; 43 char *lo = NULL; 44 char *hi = NULL; 45 soc_pbmp_t ci_pbm; 46 parse_table_t pt; 47 int start_addr; 48 int end_addr; 49 int i; 50 int rv; 51 int inc; 52 53 if (((c = ARG_GET(a)) == NULL) || (parse_pbmp(unit, c, &ci_pbm) < 0)) { 54 return CMD_USAGE; 55 } 56 57 if((lo = range = ARG_GET(a)) != NULL) { 58 if((hi = sal_strchr(range, '-')) != NULL) { 59 hi++; 60 } else { 61 hi = lo; 62 } 63 } else { 64 return CMD_USAGE; 65 } 66 67 if (ARG_CNT(a)) { 68 parse_table_init(0,&pt); 69 parse_table_add(&pt,"data",PQ_INT, 70 0, &data, NULL); 71 parse_table_add(&pt,"inc",PQ_INT, 72 0, &inc, NULL); 73 if (!parseEndOk(a,&pt,&ret_code)) { 74 return ret_code; 75 } 76 } else { 77 return CMD_USAGE; 78 } 79 80 if (diag_parse_range(lo,hi,&start_addr,&end_addr,0,1<<22)) { 81 cli_out("Invalid range. Valid range is : 0 - 0x%x\n",(1<<22)); 82 return CMD_FAIL; 83 } 84 85 /* for now 32B of data will be same */ 86 for(i=0;i<8;i++) { 87 if (inc) { 88 data_wr[i] = data+i; 89 } else { 90 data_wr[i] = data; 91 } 92 } 93 94 SOC_PBMP_ITER(ci_pbm,ci) { 95 cli_out("Writing ci%d DDR %s ..\n",ci,lo); 96 for (addr=start_addr; addr <= end_addr; addr++) { 97 bank = (addr & 0x7); 98 col = (addr >> 3) & 0x3f; 99 row = (addr >> 9) & 0x7fff; 100 /* for debug */ 101 cli_out("Writing to ci%d,bank[%d],row[0x%04x],cols[0x%03x - 0x%03x] 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", 102 ci,bank,row,col,col+0xf,data_wr[0],data_wr[1],data_wr[2],data_wr[3],data_wr[4],data_wr[5],data_wr[6],data_wr[7]); 103 104 rv = soc_ddr40_write(unit, ci, addr, 105 data_wr[0],data_wr[1],data_wr[2], 106 data_wr[3],data_wr[4],data_wr[5], 107 data_wr[6],data_wr[7]); 108 if (rv != BCM_E_NONE) { 109 rv_stat = CMD_FAIL; 110 } 111 } 112 } 113 114 return rv_stat; 115 } 116 117 char cmd_ddr_mem_read_usage[] = "\n" 118 " DDRMemRead ci<n> range=0xstart-[0xend]\n" 119 " DDRMemRead ci0,ci1 range=0x0\n" 120 " DDRMemRead ci2 range=0x0-0x100" 121 "\n"; 122 123 cmd_result_t 124 cmd_ddr_mem_read(int unit, args_t *a) 125 { 126 uint32 data_rd[8] = {0}; 127 int ci = 0; 128 int addr = 0; 129 int bank = 0; 130 int row = 0; 131 int col = 0; 132 int rv_stat = CMD_OK; 133 char *c = NULL; 134 char *range = NULL; 135 char *lo = NULL; 136 char *hi = NULL; 137 soc_pbmp_t ci_pbm; 138 int start_addr; 139 int end_addr; 140 int rv; 141 142 if (((c = ARG_GET(a)) == NULL) || (parse_pbmp(unit, c, &ci_pbm) < 0)) { 143 return CMD_USAGE; 144 } 145 146 if((lo = range = ARG_GET(a)) != NULL) { 147 if((hi = sal_strchr(range, '-')) != NULL) { 148 hi++; 149 } else { 150 hi = lo; 151 } 152 } else { 153 return CMD_USAGE; 154 } 155 156 if (diag_parse_range(lo,hi,&start_addr,&end_addr,0,1<<22)) { 157 cli_out("Invalid range. Valid range is : 0 - 0x%x\n",(1<<22)); 158 return CMD_FAIL; 159 } 160 161 SOC_PBMP_ITER(ci_pbm,ci) { 162 cli_out("Reading ci%d DDR %s ..\n",ci,lo); 163 for (addr=start_addr; addr <= end_addr; addr++) { 164 rv = soc_ddr40_read(unit, ci, addr, 165 &data_rd[0],&data_rd[1],&data_rd[2], 166 &data_rd[3],&data_rd[4],&data_rd[5], 167 &data_rd[6],&data_rd[7]); 168 169 if (rv == BCM_E_NONE) { 170 /* convert the dram addr to pla_addr, to show bank,row,col */ 171 bank = (addr & 0x7); 172 col = (addr >> 3) & 0x3f; 173 row = (addr >> 9) & 0x7fff; 174 cli_out("ci%d,bank[%d],row[%d],col[0x%03x - 0x%03x] = 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", 175 ci,bank,row,col,col+0xf,data_rd[0],data_rd[1],data_rd[2],data_rd[3], 176 data_rd[4],data_rd[5],data_rd[6],data_rd[7]); 177 } else { 178 rv_stat = CMD_FAIL; 179 } 180 } 181 } 182 return rv_stat; 183 } 184 185 char cmd_ddr_phy_read_usage[] = "\n" 186 " DDRPhyRead ci<n> [addr=<0xaddr>]\n" 187 " eg. DDRPhyRead ci0\n" 188 " DDRPhyRead ci0,ci1 addr=0x0\n"; 189 190 191 cmd_result_t 192 cmd_ddr_phy_read(int unit, args_t *a) 193 { 194 uint32 data[4] = {0}; 195 int addr,address = -1; 196 int reg = 0; 197 int ci = 0; 198 char *c = NULL; 199 soc_pbmp_t ci_pbm; 200 parse_table_t pt; 201 cmd_result_t rv; 202 203 if (((c = ARG_GET(a)) == NULL) || (parse_pbmp(unit, c, &ci_pbm) < 0)) { 204 return CMD_USAGE; 205 } 206 207 if (ARG_CNT(a) > 0) { 208 parse_table_init(0,&pt); 209 parse_table_add(&pt,"addr",PQ_INT, 210 (void *) (0), &address, NULL); 211 if (!parseEndOk(a,&pt,&rv)) { 212 return rv; 213 } 214 } 215 216 SOC_PBMP_ITER(ci_pbm,ci) { 217 addr = address; 218 if (addr == -1) { 219 #if defined(BCM_SABER2_SUPPORT) 220 if(SOC_IS_SABER2(unit)) { 221 cli_out("CI%d ( Address not valid )\n",ci); 222 return CMD_USAGE; 223 } 224 #endif 225 /* ADDR_CTL */ 226 cli_out("CI%d ( DDR40_PHY_ADDR_CTL )\n",ci); 227 for (addr=DDR40_PHY_ADDR_CTL_MIN; addr <= DDR40_PHY_ADDR_CTL_MAX;) { 228 for (reg=0;reg<4 && addr <= DDR40_PHY_ADDR_CTL_MAX;reg++) { 229 if(soc_ddr40_phy_reg_ci_read(unit, ci, addr, &data[reg])) { 230 cli_out("failed to read phy register 0x%04x\n", addr); 231 } 232 cli_out(" 0x%04x: 0x%08x ",addr,data[reg]); 233 addr += 4; 234 } 235 cli_out("\n"); 236 } 237 238 /* BYTE_LANE0 */ 239 cli_out("CI%d ( DDR40_PHY_BYTE_LANE0 )\n",ci); 240 for (addr=DDR40_PHY_BYTE_LANE0_ADDR_MIN; addr <= DDR40_PHY_BYTE_LANE0_ADDR_MAX;) { 241 for (reg=0;reg<4 && addr <= DDR40_PHY_BYTE_LANE0_ADDR_MAX;reg++) { 242 if(soc_ddr40_phy_reg_ci_read(unit, ci, addr, &data[reg])) { 243 cli_out("failed to read phy register 0x%04x\n", addr); 244 } 245 cli_out(" 0x%04x: 0x%08x ",addr,data[reg]); 246 addr += 4; 247 } 248 cli_out("\n"); 249 } 250 251 /* BYTE_LANE1 */ 252 cli_out("CI%d ( DDR40_PHY_BYTE_LANE1 )\n",ci); 253 for (addr=DDR40_PHY_BYTE_LANE1_ADDR_MIN; addr <= DDR40_PHY_BYTE_LANE1_ADDR_MAX;) { 254 for (reg=0;reg<4 && addr <= DDR40_PHY_BYTE_LANE1_ADDR_MAX;reg++) { 255 if(soc_ddr40_phy_reg_ci_read(unit, ci, addr, &data[reg])) { 256 cli_out("failed to read phy register 0x%04x\n", addr); 257 } 258 cli_out(" 0x%04x: 0x%08x ",addr,data[reg]); 259 addr += 4; 260 } 261 cli_out("\n"); 262 } 263 } else { 264 #if defined(BCM_SABER2_SUPPORT) 265 if(SOC_IS_SABER2(unit)) { 266 if(soc_and28_phy_reg_read(unit, ci, addr, &data[0])) { 267 cli_out("failed to read phy register 0x%04x\n", addr); 268 return CMD_FAIL; 269 } 270 cli_out(" 0x%04x: 0x%08x\n",addr,data[0]); 271 } else 272 #endif 273 if(soc_ddr40_phy_reg_ci_read(unit, ci, addr, &data[0])) { 274 cli_out("failed to read phy register 0x%04x\n", addr); 275 } 276 cli_out(" 0x%04x: 0x%08x\n",addr,data[0]); 277 } 278 } 279 return CMD_OK; 280 } 281 282 char cmd_ddr_phy_write_usage[] = "\n" 283 " DDRPhyWrite ci<n> addr=<0xaddr> data=<0xdata>\n" 284 " eg. DDRPhyWrite ci addr=0x0 data=0x55\n" 285 " DDRPhyWrite ci0,ci2 addr=0x240 data=0xaa\n"; 286 287 288 cmd_result_t 289 cmd_ddr_phy_write(int unit, args_t *a) 290 { 291 uint32 data = 0; 292 int ci = 0; 293 int addr = 0; 294 parse_table_t pt; 295 cmd_result_t rv; 296 char *c = NULL; 297 soc_pbmp_t ci_pbm; 298 299 if (((c = ARG_GET(a)) == NULL) || (parse_pbmp(unit, c, &ci_pbm) < 0)) { 300 return CMD_USAGE; 301 } 302 303 if (ARG_CNT(a) == 2) { 304 parse_table_init(0,&pt); 305 parse_table_add(&pt,"addr",PQ_INT, 306 (void *) (0), &addr, NULL); 307 parse_table_add(&pt,"data",PQ_INT, 308 (void *) (0), &data, NULL); 309 if (!parseEndOk(a,&pt,&rv)) { 310 return rv; 311 } 312 } else { 313 cli_out("Invalid number of args.\n"); 314 return CMD_USAGE; 315 } 316 317 SOC_PBMP_ITER(ci_pbm,ci) { 318 #if defined(BCM_SABER2_SUPPORT) 319 if(SOC_IS_SABER2(unit)) { 320 if(soc_and28_phy_reg_write(unit, ci, addr, data)) { 321 cli_out("Writing 0x%08x to ci:%d addr=0x%08x failed.\n", 322 data,ci,addr); 323 return CMD_FAIL; 324 } 325 } else 326 #endif 327 if(soc_ddr40_phy_reg_ci_write(unit, ci, addr, data)) { 328 cli_out("Writing 0x%08x to ci:%d addr=0x%08x failed.\n", 329 data,ci,addr); 330 return CMD_FAIL; 331 } 332 } 333 return CMD_OK; 334 } 335 336 char cmd_ddr_phy_tune_usage[] = "\n" 337 " DDRPhyTune ci<n> \n" 338 " eg. DDRPhyTune ci \n" 339 " DDRPhyTune ci0,ci2\n"; 340 341 cmd_result_t 342 cmd_ddr_phy_tune(int unit, args_t *a) 343 { 344 parse_table_t pt; 345 cmd_result_t rv; 346 char *c = NULL; 347 soc_pbmp_t ci_pbm; 348 349 int ci = 0; 350 int phyType = 0; 351 int ctlType = 1; 352 int stat = 0; 353 int plot = 0; 354 int save = 0; 355 int restore = 0; 356 #if defined(BCM_SABER2_SUPPORT) 357 int done = 0; 358 #endif 359 360 SOC_PBMP_CLEAR(ci_pbm); 361 362 if (((c = ARG_GET(a)) == NULL) || (parse_pbmp(unit, c, &ci_pbm) < 0)) { 363 return CMD_USAGE; 364 } 365 366 if (ARG_CNT(a) > 0) { 367 parse_table_init(0,&pt); 368 parse_table_add(&pt,"CtlType",PQ_INT, 369 (void *) (1), &ctlType, NULL); 370 parse_table_add(&pt,"PhyType",PQ_INT, 371 (void *) (0), &phyType, NULL); 372 parse_table_add(&pt,"Stat",PQ_INT, 373 (void *) (0), &stat, NULL); 374 parse_table_add(&pt, "Plot", PQ_BOOL|PQ_DFL, 375 0, &plot, NULL); 376 parse_table_add(&pt, "SaveCfg", PQ_BOOL|PQ_DFL, 377 0, &save, NULL); 378 parse_table_add(&pt, "RestoreCfg", PQ_BOOL|PQ_DFL, 379 0, &restore, NULL); 380 if (!parseEndOk(a,&pt,&rv)) { 381 return rv; 382 } 383 } 384 385 SOC_PBMP_ITER(ci_pbm,ci) { 386 if (restore) { 387 #if defined(BCM_SABER2_SUPPORT) 388 if(SOC_IS_SABER2(unit)) { 389 and28_shmoo_config_param_t config_param; 390 sal_memset(&config_param, 0, sizeof(config_param)); 391 392 /* Saber2 has one PHY 32 bit(CI0 16 bit and CI1 16 bit) 393 * shmoo code is written per PHY not per CI */ 394 if (ci != 0){ 395 cli_out(" Saber2 has 32 bit PHY hence shmoo is running on ci0\n"); 396 } 397 if (done == 0) { 398 if (SOC_E_NONE == (soc_sb2_and28_dram_restorecfg(unit, &config_param))) { 399 if (soc_and28_shmoo_ctl(unit, 0, -1, 0, 400 SHMOO_AND28_ACTION_RESTORE, &config_param)) { 401 cli_out(" RestoreCfg ci:%d failed\n", ci); 402 return CMD_FAIL; 403 } 404 }else 405 { 406 cli_out(" RestoreCfg ci:%d failed\n", ci); 407 return CMD_FAIL; 408 } 409 done++; 410 } 411 } else 412 #endif 413 { 414 if (soc_ddr40_shmoo_restorecfg(unit, ci)) { 415 cli_out(" RestoreCfg ci:%d failed\n", ci); 416 return CMD_FAIL; 417 } 418 } 419 } else { 420 #if defined(BCM_SABER2_SUPPORT) 421 if(SOC_IS_SABER2(unit)) { 422 and28_shmoo_config_param_t config_param; 423 sal_memset(&config_param, 0, sizeof(config_param)); 424 425 /* Saber2 has one PHY 32 bit(CI0 16 bit and CI1 16 bit) 426 * shmoo code is written per PHY not per CI */ 427 if (ci != 0){ 428 cli_out(" Saber2 has 32 bit PHY hence shmoo is running on ci0\n"); 429 } 430 if (done == 0) { 431 if (save) { 432 if (SOC_E_NONE == (soc_and28_shmoo_ctl(unit, 0, -1, 0, 433 SHMOO_AND28_ACTION_RUN_AND_SAVE, &config_param))){ 434 if (soc_sb2_and28_dram_savecfg(unit, &config_param)) { 435 cli_out(" SaveCfg ci:%d failed\n", ci); 436 return CMD_FAIL; 437 } 438 }else 439 { 440 cli_out(" SaveCfg ci:%d failed\n", ci); 441 return CMD_FAIL; 442 } 443 }else 444 { 445 446 if ((soc_and28_shmoo_ctl(unit, 0, -1, 0, 447 SHMOO_AND28_ACTION_RUN, &config_param))){ 448 cli_out(" ci:%d failed\n", ci); 449 return CMD_FAIL; 450 } 451 } 452 done++; 453 } 454 } else 455 #endif 456 { 457 if(soc_ddr40_shmoo_ctl(unit, ci, phyType, ctlType, stat , plot)) { 458 cli_out(" ci:%d failed\n", ci); 459 return CMD_FAIL; 460 } 461 if (save) { 462 if (soc_ddr40_shmoo_savecfg(unit, ci)) { 463 cli_out(" SaveCfg ci:%d failed\n", ci); 464 } 465 } 466 } 467 } 468 } 469 return CMD_OK; 470 } 471 472 cmd_result_t 473 cmd_ddr_phy_init(int unit, args_t *a) 474 { 475 #ifdef BCM_SABER2_SUPPORT 476 if (SOC_IS_SABER2(unit) && SOC_DDR3_NUM_MEMORIES(unit)) { 477 return soc_sb2_and28_dram_init_reset(unit); 478 } 479 #endif 480 return CMD_NOTIMPL; 481 } 482 #endif 483