This patch adds a new 's3c2410' command which currently supports 's3c2410 speed {set,get,list} and thus allows dynamic change of the CPU clock. Signed-off-by: Harald Welte Index: u-boot/cpu/arm920t/s3c24x0/Makefile =================================================================== --- u-boot.orig/cpu/arm920t/s3c24x0/Makefile 2007-02-24 15:14:00.000000000 +0100 +++ u-boot/cpu/arm920t/s3c24x0/Makefile 2007-02-24 15:21:02.000000000 +0100 @@ -26,7 +26,7 @@ LIB = $(obj)lib$(SOC).a COBJS = i2c.o interrupts.o serial.o speed.o \ - usb_ohci.o nand_read.o nand.o + usb_ohci.o nand_read.o nand.o cmd_s3c2410.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) Index: u-boot/cpu/arm920t/s3c24x0/cmd_s3c2410.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ u-boot/cpu/arm920t/s3c24x0/cmd_s3c2410.c 2007-02-24 15:22:17.000000000 +0100 @@ -0,0 +1,152 @@ +/* + * (C) Copyright 2006 by OpenMoko, Inc. + * Author: Harald Welte + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Boot support + */ +#include +#include +#include /* for print_IPaddr */ +#include + +DECLARE_GLOBAL_DATA_PTR; + +#if (CONFIG_COMMANDS & CFG_CMD_BDI) + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#define MHZ 1000000 + +static void print_cpu_speed(void) +{ + printf("FCLK = %u MHz, HCLK = %u MHz, PCLK = %u MHz\n", + get_FCLK()/MHZ, get_HCLK()/MHZ, get_PCLK()/MHZ); +} + +struct s3c2410_pll_speed { + u_int16_t mhz; + u_int32_t mpllcon; + u_int32_t clkdivn; +}; + +#define CLKDIVN_1_1_1 0x00 +#define CLKDIVN_1_2_2 0x02 +#define CLKDIVN_1_2_4 0x03 +#define CLKDIVN_1_4_4 0x04 + +static const struct s3c2410_pll_speed pll_configs[] = { + { + .mhz = 50, + .mpllcon = ((0x5c << 12) + (0x4 << 4) + 0x2), + .clkdivn = CLKDIVN_1_1_1, + }, + { + .mhz = 101, + .mpllcon = ((0x7f << 12) + (0x2 << 4) + 0x2), + .clkdivn = CLKDIVN_1_2_2, + }, + { + .mhz = 202, + .mpllcon = ((0x90 << 12) + (0x7 << 4) + 0x0), + .clkdivn = CLKDIVN_1_2_4, + }, + { + .mhz = 266, + .mpllcon = ((0x7d << 12) + (0x1 << 4) + 0x1), + .clkdivn = CLKDIVN_1_2_4, + }, +}; + +static void list_cpu_speeds(void) +{ + int i; + for (i = 0; i < ARRAY_SIZE(pll_configs); i++) + printf("%u MHz\n", pll_configs[i].mhz); +} + +static int reconfig_mpll(u_int16_t mhz) +{ + S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); + int i; + + for (i = 0; i < ARRAY_SIZE(pll_configs); i++) { + if (pll_configs[i].mhz == mhz) { + /* to reduce PLL lock time, adjust the LOCKTIME register */ + clk_power->LOCKTIME = 0xFFFFFF; + + /* configure MPLL */ + clk_power->MPLLCON = pll_configs[i].mpllcon; + clk_power->UPLLCON = ((0x78 << 12) + (0x2 << 4) + 0x3), + clk_power->CLKDIVN = pll_configs[i].clkdivn; + + /* If we changed the speed, we need to re-configure + * the serial baud rate generator */ + serial_setbrg(); + return 0; + } + } + return -1; +} + +int do_s3c2410 ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + if (!strcmp(argv[1], "speed")) { + if (argc < 2) + goto out_help; + if (!strcmp(argv[2], "get")) + print_cpu_speed(); + else if (!strcmp(argv[2], "list")) + list_cpu_speeds(); + else if (!strcmp(argv[2], "set")) { + unsigned long mhz; + if (argc < 3) + goto out_help; + + mhz = simple_strtoul(argv[3], NULL, 10); + + if (reconfig_mpll(mhz) < 0) + printf("error, speed %uMHz unknown\n", mhz); + else + print_cpu_speed(); + } else + goto out_help; + } else { +out_help: + printf("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + return 0; +} + +/* -------------------------------------------------------------------- */ + + +U_BOOT_CMD( + s3c2410, 4, 1, do_s3c2410, + "s3c2410 - SoC specific commands\n", + "speed get - display current PLL speed config\n" + "s3c2410 speed list - display supporte PLL speed configs\n" + "s3c2410 speed set - set PLL speed\n" +); + +#endif