aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-s3c2440/clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-s3c2440/clock.c')
-rw-r--r--arch/arm/mach-s3c2440/clock.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/arch/arm/mach-s3c2440/clock.c b/arch/arm/mach-s3c2440/clock.c
index d8957592fdc4..bedbc87a3426 100644
--- a/arch/arm/mach-s3c2440/clock.c
+++ b/arch/arm/mach-s3c2440/clock.c
@@ -33,6 +33,7 @@
33#include <linux/mutex.h> 33#include <linux/mutex.h>
34#include <linux/clk.h> 34#include <linux/clk.h>
35#include <linux/io.h> 35#include <linux/io.h>
36#include <linux/serial_core.h>
36 37
37#include <mach/hardware.h> 38#include <mach/hardware.h>
38#include <linux/atomic.h> 39#include <linux/atomic.h>
@@ -42,6 +43,7 @@
42 43
43#include <plat/clock.h> 44#include <plat/clock.h>
44#include <plat/cpu.h> 45#include <plat/cpu.h>
46#include <plat/regs-serial.h>
45 47
46/* S3C2440 extended clock support */ 48/* S3C2440 extended clock support */
47 49
@@ -107,6 +109,46 @@ static struct clk s3c2440_clk_ac97 = {
107 .ctrlbit = S3C2440_CLKCON_CAMERA, 109 .ctrlbit = S3C2440_CLKCON_CAMERA,
108}; 110};
109 111
112static unsigned long s3c2440_fclk_n_getrate(struct clk *clk)
113{
114 unsigned long ucon0, ucon1, ucon2, divisor;
115
116 /* the fun of calculating the uart divisors on the s3c2440 */
117 ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON);
118 ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON);
119 ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON);
120
121 ucon0 &= S3C2440_UCON0_DIVMASK;
122 ucon1 &= S3C2440_UCON1_DIVMASK;
123 ucon2 &= S3C2440_UCON2_DIVMASK;
124
125 if (ucon0 != 0)
126 divisor = (ucon0 >> S3C2440_UCON_DIVSHIFT) + 6;
127 else if (ucon1 != 0)
128 divisor = (ucon1 >> S3C2440_UCON_DIVSHIFT) + 21;
129 else if (ucon2 != 0)
130 divisor = (ucon2 >> S3C2440_UCON_DIVSHIFT) + 36;
131 else
132 /* manual calims 44, seems to be 9 */
133 divisor = 9;
134
135 return clk_get_rate(clk->parent) / divisor;
136}
137
138static struct clk s3c2440_clk_fclk_n = {
139 .name = "fclk_n",
140 .parent = &clk_f,
141 .ops = &(struct clk_ops) {
142 .get_rate = s3c2440_fclk_n_getrate,
143 },
144};
145
146static struct clk_lookup s3c2440_clk_lookup[] = {
147 CLKDEV_INIT(NULL, "clk_uart_baud1", &s3c24xx_uclk),
148 CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
149 CLKDEV_INIT(NULL, "clk_uart_baud3", &s3c2440_clk_fclk_n),
150};
151
110static int s3c2440_clk_add(struct device *dev) 152static int s3c2440_clk_add(struct device *dev)
111{ 153{
112 struct clk *clock_upll; 154 struct clk *clock_upll;
@@ -125,10 +167,12 @@ static int s3c2440_clk_add(struct device *dev)
125 s3c2440_clk_cam.parent = clock_h; 167 s3c2440_clk_cam.parent = clock_h;
126 s3c2440_clk_ac97.parent = clock_p; 168 s3c2440_clk_ac97.parent = clock_p;
127 s3c2440_clk_cam_upll.parent = clock_upll; 169 s3c2440_clk_cam_upll.parent = clock_upll;
170 s3c24xx_register_clock(&s3c2440_clk_fclk_n);
128 171
129 s3c24xx_register_clock(&s3c2440_clk_ac97); 172 s3c24xx_register_clock(&s3c2440_clk_ac97);
130 s3c24xx_register_clock(&s3c2440_clk_cam); 173 s3c24xx_register_clock(&s3c2440_clk_cam);
131 s3c24xx_register_clock(&s3c2440_clk_cam_upll); 174 s3c24xx_register_clock(&s3c2440_clk_cam_upll);
175 clkdev_add_table(s3c2440_clk_lookup, ARRAY_SIZE(s3c2440_clk_lookup));
132 176
133 clk_disable(&s3c2440_clk_ac97); 177 clk_disable(&s3c2440_clk_ac97);
134 clk_disable(&s3c2440_clk_cam); 178 clk_disable(&s3c2440_clk_cam);