|
@@ -1445,6 +1445,7 @@ unsigned long long fsl_ddr_interactive(fsl_ddr_info_t *pinfo)
|
|
"recompute reload SPD and options to default and recompute regs\n"
|
|
"recompute reload SPD and options to default and recompute regs\n"
|
|
"edit modify spd, parameter, or option\n"
|
|
"edit modify spd, parameter, or option\n"
|
|
"compute recompute registers from current next_step to end\n"
|
|
"compute recompute registers from current next_step to end\n"
|
|
|
|
+ "copy copy parameters\n"
|
|
"next_step shows current next_step\n"
|
|
"next_step shows current next_step\n"
|
|
"help this message\n"
|
|
"help this message\n"
|
|
"go program the memory controller and continue with u-boot\n"
|
|
"go program the memory controller and continue with u-boot\n"
|
|
@@ -1477,6 +1478,132 @@ unsigned long long fsl_ddr_interactive(fsl_ddr_info_t *pinfo)
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (strcmp(argv[0], "copy") == 0) {
|
|
|
|
+ unsigned int error = 0;
|
|
|
|
+ unsigned int step_mask = 0;
|
|
|
|
+ unsigned int src_ctlr_mask = 0;
|
|
|
|
+ unsigned int src_dimm_mask = 0;
|
|
|
|
+ unsigned int dimm_number_required = 0;
|
|
|
|
+ unsigned int src_ctlr_num = 0;
|
|
|
|
+ unsigned int src_dimm_num = 0;
|
|
|
|
+ unsigned int dst_ctlr_num = -1;
|
|
|
|
+ unsigned int dst_dimm_num = -1;
|
|
|
|
+ unsigned int i, num_dest_parms;
|
|
|
|
+
|
|
|
|
+ if (argc == 1) {
|
|
|
|
+ printf("copy <src c#> <src d#> <spd|dimmparms|commonparms|opts|addresses|regs> <dst c#> <dst d#>\n");
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ error = fsl_ddr_parse_interactive_cmd(
|
|
|
|
+ argv, argc,
|
|
|
|
+ &step_mask,
|
|
|
|
+ &src_ctlr_mask,
|
|
|
|
+ &src_dimm_mask,
|
|
|
|
+ &dimm_number_required
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ /* XXX: only dimm_number_required and step_mask will
|
|
|
|
+ be used by this function. Parse the controller and
|
|
|
|
+ DIMM number separately because it is easier. */
|
|
|
|
+
|
|
|
|
+ if (error)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ /* parse source destination controller / DIMM */
|
|
|
|
+
|
|
|
|
+ num_dest_parms = dimm_number_required ? 2 : 1;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < argc; i++) {
|
|
|
|
+ if (argv[i][0] == 'c') {
|
|
|
|
+ char c = argv[i][1];
|
|
|
|
+ if (isdigit(c)) {
|
|
|
|
+ src_ctlr_num = (c - '0');
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < argc; i++) {
|
|
|
|
+ if (argv[i][0] == 'd') {
|
|
|
|
+ char c = argv[i][1];
|
|
|
|
+ if (isdigit(c)) {
|
|
|
|
+ src_dimm_num = (c - '0');
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* parse destination controller / DIMM */
|
|
|
|
+
|
|
|
|
+ for (i = argc - 1; i >= argc - num_dest_parms; i--) {
|
|
|
|
+ if (argv[i][0] == 'c') {
|
|
|
|
+ char c = argv[i][1];
|
|
|
|
+ if (isdigit(c)) {
|
|
|
|
+ dst_ctlr_num = (c - '0');
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (i = argc - 1; i >= argc - num_dest_parms; i--) {
|
|
|
|
+ if (argv[i][0] == 'd') {
|
|
|
|
+ char c = argv[i][1];
|
|
|
|
+ if (isdigit(c)) {
|
|
|
|
+ dst_dimm_num = (c - '0');
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* TODO: validate inputs */
|
|
|
|
+
|
|
|
|
+ debug("src_ctlr_num = %u, src_dimm_num = %u, dst_ctlr_num = %u, dst_dimm_num = %u, step_mask = %x\n",
|
|
|
|
+ src_ctlr_num, src_dimm_num, dst_ctlr_num, dst_dimm_num, step_mask);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ switch (step_mask) {
|
|
|
|
+
|
|
|
|
+ case STEP_GET_SPD:
|
|
|
|
+ memcpy(&(pinfo->spd_installed_dimms[dst_ctlr_num][dst_dimm_num]),
|
|
|
|
+ &(pinfo->spd_installed_dimms[src_ctlr_num][src_dimm_num]),
|
|
|
|
+ sizeof(pinfo->spd_installed_dimms[0][0]));
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case STEP_COMPUTE_DIMM_PARMS:
|
|
|
|
+ memcpy(&(pinfo->dimm_params[dst_ctlr_num][dst_dimm_num]),
|
|
|
|
+ &(pinfo->dimm_params[src_ctlr_num][src_dimm_num]),
|
|
|
|
+ sizeof(pinfo->dimm_params[0][0]));
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case STEP_COMPUTE_COMMON_PARMS:
|
|
|
|
+ memcpy(&(pinfo->common_timing_params[dst_ctlr_num]),
|
|
|
|
+ &(pinfo->common_timing_params[src_ctlr_num]),
|
|
|
|
+ sizeof(pinfo->common_timing_params[0]));
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case STEP_GATHER_OPTS:
|
|
|
|
+ memcpy(&(pinfo->memctl_opts[dst_ctlr_num]),
|
|
|
|
+ &(pinfo->memctl_opts[src_ctlr_num]),
|
|
|
|
+ sizeof(pinfo->memctl_opts[0]));
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ /* someday be able to have addresses to copy addresses... */
|
|
|
|
+
|
|
|
|
+ case STEP_COMPUTE_REGS:
|
|
|
|
+ memcpy(&(pinfo->fsl_ddr_config_reg[dst_ctlr_num]),
|
|
|
|
+ &(pinfo->fsl_ddr_config_reg[src_ctlr_num]),
|
|
|
|
+ sizeof(pinfo->memctl_opts[0]));
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ default:
|
|
|
|
+ printf("unexpected step_mask value\n");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
if (strcmp(argv[0], "edit") == 0) {
|
|
if (strcmp(argv[0], "edit") == 0) {
|
|
unsigned int error = 0;
|
|
unsigned int error = 0;
|
|
unsigned int step_mask = 0;
|
|
unsigned int step_mask = 0;
|