diff options
Diffstat (limited to 'arch/arm/mach-s3c2440/clock.c')
-rw-r--r-- | arch/arm/mach-s3c2440/clock.c | 44 |
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 | ||
112 | static 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 | |||
138 | static 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 | |||
146 | static 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 | |||
110 | static int s3c2440_clk_add(struct device *dev) | 152 | static 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); |