From 046c217c65a7670b4ee1aecdb9854284e32b2d6c Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 24 Oct 2011 11:47:40 +0200 Subject: ARM: S3C2440: move handling of fclk/n clock to platform code s3c2440 uses fclk/n (fclk divided by n) clock as one of the possible clocks used to generate the baud rate clock. The divider 'n' in this case can be logically represented outside of the uart controller. This patch creates a new clock by name "fclk_n" for s3c2440 based platforms to represent the fclk/n clock in the platform code. This clock provides a get_rate callback that checks the UCON0/1/2 registers to determine the clock rate. The samsung uart driver would receive the "fclk_n" clock name as one of the possible baud rate clock options and the driver need not determine clock rate of fclk/n. Cc: Ben Dooks Cc: Vasily Khoruzhick Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c2440/clock.c | 37 +++++++++++++++++++++++++++++++++++++ arch/arm/mach-s3c2440/mach-rx1950.c | 4 ++-- arch/arm/mach-s3c2440/mach-rx3715.c | 4 ++-- 3 files changed, 41 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-s3c2440/clock.c b/arch/arm/mach-s3c2440/clock.c index f9e6bdaf41d..f85853c5d5e 100644 --- a/arch/arm/mach-s3c2440/clock.c +++ b/arch/arm/mach-s3c2440/clock.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -43,6 +44,7 @@ #include #include +#include /* S3C2440 extended clock support */ @@ -108,6 +110,40 @@ static struct clk s3c2440_clk_ac97 = { .ctrlbit = S3C2440_CLKCON_CAMERA, }; +static unsigned long s3c2440_fclk_n_getrate(struct clk *clk) +{ + unsigned long ucon0, ucon1, ucon2, divisor; + + /* the fun of calculating the uart divisors on the s3c2440 */ + ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON); + ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON); + ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON); + + ucon0 &= S3C2440_UCON0_DIVMASK; + ucon1 &= S3C2440_UCON1_DIVMASK; + ucon2 &= S3C2440_UCON2_DIVMASK; + + if (ucon0 != 0) + divisor = (ucon0 >> S3C2440_UCON_DIVSHIFT) + 6; + else if (ucon1 != 0) + divisor = (ucon1 >> S3C2440_UCON_DIVSHIFT) + 21; + else if (ucon2 != 0) + divisor = (ucon2 >> S3C2440_UCON_DIVSHIFT) + 36; + else + /* manual calims 44, seems to be 9 */ + divisor = 9; + + return clk_get_rate(clk->parent) / divisor; +} + +static struct clk s3c2440_clk_fclk_n = { + .name = "fclk_n", + .parent = &clk_f, + .ops = &(struct clk_ops) { + .get_rate = s3c2440_fclk_n_getrate, + }, +}; + static int s3c2440_clk_add(struct sys_device *sysdev) { struct clk *clock_upll; @@ -126,6 +162,7 @@ static int s3c2440_clk_add(struct sys_device *sysdev) s3c2440_clk_cam.parent = clock_h; s3c2440_clk_ac97.parent = clock_p; s3c2440_clk_cam_upll.parent = clock_upll; + s3c24xx_register_clock(&s3c2440_clk_fclk_n); s3c24xx_register_clock(&s3c2440_clk_ac97); s3c24xx_register_clock(&s3c2440_clk_cam); diff --git a/arch/arm/mach-s3c2440/mach-rx1950.c b/arch/arm/mach-s3c2440/mach-rx1950.c index 0d3453bf567..094c4bff7fe 100644 --- a/arch/arm/mach-s3c2440/mach-rx1950.c +++ b/arch/arm/mach-s3c2440/mach-rx1950.c @@ -70,8 +70,8 @@ static struct map_desc rx1950_iodesc[] __initdata = { static struct s3c24xx_uart_clksrc rx1950_serial_clocks[] = { [0] = { - .name = "fclk", - .divisor = 0x0a, + .name = "fclk_n", + .divisor = 1, .min_baud = 0, .max_baud = 0, }, diff --git a/arch/arm/mach-s3c2440/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c index e19499c2f90..f934f5b88a4 100644 --- a/arch/arm/mach-s3c2440/mach-rx3715.c +++ b/arch/arm/mach-s3c2440/mach-rx3715.c @@ -70,8 +70,8 @@ static struct map_desc rx3715_iodesc[] __initdata = { static struct s3c24xx_uart_clksrc rx3715_serial_clocks[] = { [0] = { - .name = "fclk", - .divisor = 0, + .name = "fclk_n", + .divisor = 1, .min_baud = 0, .max_baud = 0, } -- cgit v1.2.3-70-g09d2