]> git.sur5r.net Git - u-boot/blobdiff - arch/powerpc/cpu/mpc8xxx/ddr/interactive.c
Merge branch 'u-boot/master' into u-boot-arm/master
[u-boot] / arch / powerpc / cpu / mpc8xxx / ddr / interactive.c
index 4d1cf3c59309bebaff54f0107735550de04bdd73..1ed6c77150d7323f583158cff4f35cc03183649d 100644 (file)
@@ -1,9 +1,7 @@
 /*
  * Copyright 2010-2012 Freescale Semiconductor, Inc.
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * Version 2 or any later versionas published by the Free Software Foundation.
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 /*
@@ -1390,9 +1388,10 @@ static unsigned int fsl_ddr_parse_interactive_cmd(
 
        unsigned int i, j;
        unsigned int error = 0;
-       unsigned int matched = 0;
 
        for (i = 1; i < argc; i++) {
+               unsigned int matched = 0;
+
                for (j = 0; j < n_opts; j++) {
                        if (strcmp(options[j].data_name, argv[i]) != 0)
                                continue;
@@ -1429,11 +1428,23 @@ static unsigned int fsl_ddr_parse_interactive_cmd(
        return error;
 }
 
-unsigned long long fsl_ddr_interactive(fsl_ddr_info_t *pinfo)
+int fsl_ddr_interactive_env_var_exists(void)
+{
+       char buffer[CONFIG_SYS_CBSIZE];
+
+       if (getenv_f("ddr_interactive", buffer, CONFIG_SYS_CBSIZE) >= 0)
+               return 1;
+
+       return 0;
+}
+
+unsigned long long fsl_ddr_interactive(fsl_ddr_info_t *pinfo, int var_is_set)
 {
        unsigned long long ddrsize;
        const char *prompt = "FSL DDR>";
        char buffer[CONFIG_SYS_CBSIZE];
+       char buffer2[CONFIG_SYS_CBSIZE];
+       char *p = NULL;
        char *argv[CONFIG_SYS_MAXARGS + 1];     /* NULL terminated */
        int argc;
        unsigned int next_step = STEP_GET_SPD;
@@ -1444,21 +1455,45 @@ unsigned long long fsl_ddr_interactive(fsl_ddr_info_t *pinfo)
                "recompute  reload SPD and options to default and recompute regs\n"
                "edit       modify spd, parameter, or option\n"
                "compute    recompute registers from current next_step to end\n"
+               "copy       copy parameters\n"
                "next_step  shows current next_step\n"
                "help       this message\n"
                "go         program the memory controller and continue with u-boot\n"
        };
 
+       if (var_is_set) {
+               if (getenv_f("ddr_interactive", buffer2, CONFIG_SYS_CBSIZE) > 0) {
+                       p = buffer2;
+               } else {
+                       var_is_set = 0;
+               }
+       }
+
        /*
         * The strategy for next_step is that it points to the next
         * step in the computation process that needs to be done.
         */
        while (1) {
-               /*
-                * No need to worry for buffer overflow here in
-                * this function;  readline() maxes out at CFG_CBSIZE
-                */
-               readline_into_buffer(prompt, buffer, 0);
+               if (var_is_set) {
+                       char *pend = strchr(p, ';');
+                       if (pend) {
+                               /* found command separator, copy sub-command */
+                               *pend = '\0';
+                               strcpy(buffer, p);
+                               p = pend + 1;
+                       } else {
+                               /* separator not found, copy whole string */
+                               strcpy(buffer, p);
+                               p = NULL;
+                               var_is_set = 0;
+                       }
+               } else {
+                       /*
+                        * No need to worry for buffer overflow here in
+                        * this function;  readline() maxes out at CFG_CBSIZE
+                        */
+                       readline_into_buffer(prompt, buffer, 0);
+               }
                argc = parse_line(buffer, argv);
                if (argc == 0)
                        continue;
@@ -1476,6 +1511,132 @@ unsigned long long fsl_ddr_interactive(fsl_ddr_info_t *pinfo)
                        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) {
                        unsigned int error = 0;
                        unsigned int step_mask = 0;