New 'setclocks' command
authorPiotr Dymacz <pepe2k@gmail.com>
Tue, 14 Jan 2014 19:05:22 +0000 (20:05 +0100)
committerPiotr Dymacz <pepe2k@gmail.com>
Tue, 14 Jan 2014 19:05:22 +0000 (20:05 +0100)
u-boot/common/cmd_custom.c

index a4ef2eeb21aceaa9912e20a261138957d880e6ab..c80fe822b3f55ea6335c0492ab5841333ce789a5 100755 (executable)
@@ -314,6 +314,430 @@ U_BOOT_CMD(printclocks, 1, 1, do_print_clocks, "print CPU, RAM, AHB, SPI and REF
 #endif /* #if defined(CONFIG_MACH_HORNET) */
 
 #if defined(PLL_IN_FLASH_MAGIC_OFFSET)
+
+typedef struct {
+       // Clocks in MHz
+       unsigned short cpu_clock;
+       unsigned short ram_clock;
+       unsigned short ahb_clock;
+       unsigned short spi_clock;
+
+       // Registers values
+       // (more info in includes/configs/ap121.h)
+       unsigned int cpu_clk_control;
+       unsigned int cpu_pll_config;
+       unsigned int spi_control;
+} ar9331_clock_profile;
+
+static const ar9331_clock_profile oc_profiles[] = {
+       {
+        200, 200, 100, 25,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+#if defined(CONFIG_40MHZ_XTAL_SUPPORT)
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(20, 1, 0, 2),
+#else
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(32, 1, 0, 2),
+#endif
+        MAKE_AR9331_SPI_CONTROL_VAL(4)
+       },
+
+       {
+        200, 200, 200, 33,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 1),
+#if defined(CONFIG_40MHZ_XTAL_SUPPORT)
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(20, 1, 0, 2),
+#else
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(32, 1, 0, 2),
+#endif
+        MAKE_AR9331_SPI_CONTROL_VAL(6)
+       },
+
+#if !defined(CONFIG_40MHZ_XTAL_SUPPORT)
+       {
+        225, 225, 112, 28,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(36, 1, 0, 2),
+        MAKE_AR9331_SPI_CONTROL_VAL(4)
+       },
+
+       {
+        225, 225, 225, 28,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 1),
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(36, 1, 0, 2),
+        MAKE_AR9331_SPI_CONTROL_VAL(8)
+       },
+#endif
+
+       {
+        250, 250, 125, 31,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+#if defined(CONFIG_40MHZ_XTAL_SUPPORT)
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(25, 1, 0, 2),
+#else
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(20, 1, 0, 1),
+#endif
+        MAKE_AR9331_SPI_CONTROL_VAL(4)
+       },
+
+       {
+        250, 250, 250, 31,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 1),
+#if defined(CONFIG_40MHZ_XTAL_SUPPORT)
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(25, 1, 0, 2),
+#else
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(20, 1, 0, 1),
+#endif
+        MAKE_AR9331_SPI_CONTROL_VAL(8)
+       },
+
+       {
+        300, 300, 150, 25,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+#if defined(CONFIG_40MHZ_XTAL_SUPPORT)
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(15, 1, 0, 1),
+#else
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(24, 1, 0, 1),
+#endif
+        MAKE_AR9331_SPI_CONTROL_VAL(6)
+       },
+
+#if !defined(CONFIG_40MHZ_XTAL_SUPPORT)
+       {
+        325, 325, 162, 27,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(26, 1, 0, 1),
+        MAKE_AR9331_SPI_CONTROL_VAL(6)
+       },
+
+       {
+        350, 350, 175, 29,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(28, 1, 0, 1),
+        MAKE_AR9331_SPI_CONTROL_VAL(6)
+       },
+#endif
+
+       {
+        360, 360, 180, 30,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+#if defined(CONFIG_40MHZ_XTAL_SUPPORT)
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(18, 1, 0, 1),
+#else
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(29, 1, 0, 1),
+#endif
+        MAKE_AR9331_SPI_CONTROL_VAL(6)
+       },
+
+#if defined(CONFIG_40MHZ_XTAL_SUPPORT)
+       {
+        380, 380, 190, 32,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(19, 1, 0, 1),
+        MAKE_AR9331_SPI_CONTROL_VAL(6)
+       },
+#endif
+
+       {
+        400, 400, 200, 33,
+        CPU_CLK_CONTROL_VAL_DEFAULT,
+        CPU_PLL_CONFIG_VAL_DEFAULT,
+        AR7240_SPI_CONTROL_DEFAULT
+       },
+
+#if !defined(CONFIG_40MHZ_XTAL_SUPPORT)
+       {
+        412, 412, 206, 34,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(33, 1, 0, 1),
+        MAKE_AR9331_SPI_CONTROL_VAL(6)
+       },
+#endif
+
+#if defined(CONFIG_40MHZ_XTAL_SUPPORT)
+       {
+        420, 420, 210, 35,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(21, 1, 0, 1),
+        MAKE_AR9331_SPI_CONTROL_VAL(6)
+       },
+#endif
+
+#if !defined(CONFIG_40MHZ_XTAL_SUPPORT)
+       {
+        425, 425, 212, 35,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(34, 1, 0, 1),
+        MAKE_AR9331_SPI_CONTROL_VAL(6)
+       },
+
+       {
+        437, 437, 218, 27,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(35, 1, 0, 1),
+        MAKE_AR9331_SPI_CONTROL_VAL(8)
+       },
+#endif
+
+#if defined(CONFIG_40MHZ_XTAL_SUPPORT)
+       {
+        440, 440, 220, 27,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(22, 1, 0, 1),
+        MAKE_AR9331_SPI_CONTROL_VAL(8)
+       },
+#endif
+
+#if !defined(CONFIG_40MHZ_XTAL_SUPPORT)
+       {
+        450, 450, 225, 28,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(36, 1, 0, 1),
+        MAKE_AR9331_SPI_CONTROL_VAL(8)
+       },
+#endif
+
+       {
+        460, 460, 230, 29,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+#if defined(CONFIG_40MHZ_XTAL_SUPPORT)
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(23, 1, 0, 1),
+#else
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(37, 1, 0, 1),
+#endif
+        MAKE_AR9331_SPI_CONTROL_VAL(8)
+       },
+
+#if !defined(CONFIG_40MHZ_XTAL_SUPPORT)
+       {
+        475, 475, 237, 30,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(38, 1, 0, 1),
+        MAKE_AR9331_SPI_CONTROL_VAL(8)
+       },
+#endif
+
+#if defined(CONFIG_40MHZ_XTAL_SUPPORT)
+       {
+        480, 480, 240, 30,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(24, 1, 0, 1),
+        MAKE_AR9331_SPI_CONTROL_VAL(8)
+       },
+#endif
+
+#if !defined(CONFIG_40MHZ_XTAL_SUPPORT)
+       {
+        487, 487, 243, 30,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(39, 1, 0, 1),
+        MAKE_AR9331_SPI_CONTROL_VAL(8)
+       },
+#endif
+
+       {
+        500, 500, 250, 31,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+#if defined(CONFIG_40MHZ_XTAL_SUPPORT)
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(25, 1, 0, 1),
+#else
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(40, 1, 0, 1),
+#endif
+        MAKE_AR9331_SPI_CONTROL_VAL(8)
+       },
+
+       {
+        500, 250, 250, 31,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 2, 2),
+#if defined(CONFIG_40MHZ_XTAL_SUPPORT)
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(25, 1, 0, 1),
+#else
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(40, 1, 0, 1),
+#endif
+        MAKE_AR9331_SPI_CONTROL_VAL(8)
+       },
+
+#if defined(CONFIG_40MHZ_XTAL_SUPPORT)
+       {
+        520, 520, 260, 32,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 1, 2),
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(26, 1, 0, 1),
+        MAKE_AR9331_SPI_CONTROL_VAL(8)
+       },
+#endif
+
+#if !defined(CONFIG_40MHZ_XTAL_SUPPORT)
+       {
+        525, 262, 131, 33,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 2, 4),
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(42, 1, 0, 1),
+        MAKE_AR9331_SPI_CONTROL_VAL(4)
+       },
+#endif
+
+       {
+        560, 280, 140, 35,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 2, 4),
+#if defined(CONFIG_40MHZ_XTAL_SUPPORT)
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(28, 1, 0, 1),
+#else
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(45, 1, 0, 1),
+#endif
+        MAKE_AR9331_SPI_CONTROL_VAL(4)
+       },
+
+#if defined(CONFIG_40MHZ_XTAL_SUPPORT)
+       {
+        580, 290, 145, 36,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 2, 4),
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(29, 1, 0, 1),
+        MAKE_AR9331_SPI_CONTROL_VAL(4)
+       },
+#endif
+
+       {
+        600, 300, 200, 33,
+        MAKE_AR9331_CPU_CLK_CONTROL_VAL(1, 2, 3),
+#if CONFIG_40MHZ_XTAL_SUPPORT
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(30, 1, 0, 1),
+#else
+        MAKE_AR9331_CPU_PLL_CONFIG_VAL(48, 1, 0, 1),
+#endif
+        MAKE_AR9331_SPI_CONTROL_VAL(6)
+       },
+};
+
+/*
+ * Set and store PLL configuration in FLASH
+ */
+int do_set_clocks(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){
+       unsigned int cpu_pll_config_flash, cpu_clock_control_flash, spi_control_flash, reg;
+       unsigned int ahb_freq, ddr_freq, cpu_freq, spi_freq;
+       unsigned int *data_pointer;
+       int i, index, profiles_count;
+       char buf[128];
+
+       profiles_count = sizeof(oc_profiles) / sizeof(ar9331_clock_profile);
+
+       // print all available profiles and current settings
+       if(argc == 1){
+
+               // read clocks
+               ar7240_sys_frequency(&cpu_freq, &ddr_freq, &ahb_freq);
+
+               // calculate SPI clock (we need to set bit 0 to 1 in SPI_FUNC_SELECT to access SPI registers)
+               ar7240_reg_wr(AR7240_SPI_FS, 0x01);
+               spi_freq = ahb_freq / (((ar7240_reg_rd(AR7240_SPI_CLOCK) & 0x3F) + 1) * 2);
+               ar7240_reg_wr(AR7240_SPI_FS, 0x0);
+
+               // make MHz from Hz
+               cpu_freq /= 1000000;
+               ddr_freq /= 1000000;
+               ahb_freq /= 1000000;
+               spi_freq /= 1000000;
+
+               printf("Current clocks (approximated):\n- CPU: %3d MHz\n", cpu_freq);
+               printf("- RAM: %3d MHz\n", ddr_freq);
+               printf("- AHB: %3d MHz\n", ahb_freq);
+               printf("- SPI: %3d MHz\n", spi_freq);
+
+               // reference clock
+               if(ar7240_reg_rd(HORNET_BOOTSTRAP_STATUS) & HORNET_BOOTSTRAP_SEL_25M_40M_MASK){
+                       puts("- REF:  40 MHz\n\n");
+               } else {
+                       puts("- REF:  25 MHz\n\n");
+               }
+
+               // do we have PLL_MAGIC in FLASH?
+               reg = ar7240_reg_rd(CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET + PLL_IN_FLASH_MAGIC_OFFSET);
+
+               // read all register values stored in FLASH
+               cpu_pll_config_flash = ar7240_reg_rd(CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET + PLL_IN_FLASH_MAGIC_OFFSET + 4);
+               cpu_clock_control_flash = ar7240_reg_rd(CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET + PLL_IN_FLASH_MAGIC_OFFSET + 8);
+               spi_control_flash = ar7240_reg_rd(CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET + PLL_IN_FLASH_MAGIC_OFFSET + 12);
+
+               printf("Available PLL and clocks configurations: %d\n\n", profiles_count);
+
+               puts("      | CPU | RAM | AHB | SPI | [ ]\n  ---------------------------------\n");
+
+               for(i = 0; i <  profiles_count; i++){
+                       printf("%4d. |%4d |%4d |%4d |%4d | ", i + 1,
+                                                                                                 oc_profiles[i].cpu_clock,
+                                                                                                 oc_profiles[i].ram_clock,
+                                                                                                 oc_profiles[i].ahb_clock,
+                                                                                                 oc_profiles[i].spi_clock);
+
+                       if(reg == PLL_IN_FLASH_MAGIC &&
+                          oc_profiles[i].cpu_pll_config == cpu_pll_config_flash &&
+                          oc_profiles[i].cpu_clk_control == cpu_clock_control_flash &&
+                          oc_profiles[i].spi_control == spi_control_flash){
+                               puts("[*]\n");
+                       } else {
+                               puts("[ ]\n");
+                       }
+               }
+
+               puts("\n[*] = currently selected profile (stored in FLASH).\nAll clocks in MHz, run 'setclocks X' to choose one.\n\n");
+               puts("** Notice:\n   you should always make a backup of your device\n   entire FLASH content before making any changes\n\n");
+
+               return(0);
+       } else {
+               // selected index
+               index = simple_strtoul(argv[1], NULL, 10);
+
+               if(index > profiles_count || index < 1){
+                       printf("## Error: selected index should be in range 1..%d!\n", profiles_count);
+                       return(1);
+               }
+
+               printf("You have selected profile: %d.\n\n", index);
+
+               // array is zero-based indexing
+               index--;
+
+               // backup entire block in which we store PLL/CLK settings
+               data_pointer = (unsigned int *)WEBFAILSAFE_UPLOAD_RAM_ADDRESS;
+
+               if(!data_pointer){
+                       puts("## Error: couldn't allocate RAM for data block backup!\n");
+                       return(1);
+               }
+
+               memcpy((void *)data_pointer, (void *)(CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET), PLL_IN_FLASH_DATA_BLOCK_LENGTH);
+
+               // save PLL_IN_FLASH_MAGIC and PLL/clocks registers values
+               data_pointer = (unsigned int *)(WEBFAILSAFE_UPLOAD_RAM_ADDRESS + PLL_IN_FLASH_MAGIC_OFFSET);
+               *data_pointer = PLL_IN_FLASH_MAGIC;
+
+               data_pointer++;
+               *data_pointer = oc_profiles[index].cpu_pll_config;
+
+               data_pointer++;
+               *data_pointer = oc_profiles[index].cpu_clk_control;
+
+               data_pointer++;
+               *data_pointer = oc_profiles[index].spi_control;
+
+               // erase FLASH, copy data from RAM
+               sprintf(buf,
+                               "erase 0x%lX +0x%lX; cp.b 0x%lX 0x%lX 0x%lX",
+                               CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET,
+                               PLL_IN_FLASH_DATA_BLOCK_LENGTH,
+                               WEBFAILSAFE_UPLOAD_RAM_ADDRESS,
+                               CFG_FLASH_BASE + PLL_IN_FLASH_DATA_BLOCK_OFFSET,
+                               PLL_IN_FLASH_DATA_BLOCK_LENGTH);
+
+               printf("Executing: %s\n\n", buf);
+
+               return(run_command(buf, 0));
+       }
+}
+
+U_BOOT_CMD(setclocks, 2, 0, do_set_clocks, "select clocks configuration from predefined list\n",
+               "index\n"
+               "\t- save 'index' configuration in FLASH\n"
+               "setclocks\n"
+               "\t- prints available clocks configurations and current settings");
+
 /*
  * Remove (clear) PLL and clock settings in FLASH
  */