From cd34a9d142fbeb0e622ee7f47861df2f1df65ee6 Mon Sep 17 00:00:00 2001 From: Piotr Dymacz Date: Tue, 14 Jan 2014 20:05:22 +0100 Subject: [PATCH] New 'setclocks' command --- u-boot/common/cmd_custom.c | 424 +++++++++++++++++++++++++++++++++++++ 1 file changed, 424 insertions(+) diff --git a/u-boot/common/cmd_custom.c b/u-boot/common/cmd_custom.c index a4ef2ee..c80fe82 100755 --- a/u-boot/common/cmd_custom.c +++ b/u-boot/common/cmd_custom.c @@ -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 */ -- 2.25.1