1 /* linux/arch/arm/mach-s3c2410/clock.c
3 * Copyright (c) 2004 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
6 * S3C2410 Clock control support
8 * Based on, and code from linux/arch/arm/mach-versatile/clock.c
10 ** Copyright (C) 2004 ARM Limited.
11 ** Written by Deep Blue Solutions Limited.
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include <linux/init.h>
30 #include <linux/module.h>
31 #include <linux/kernel.h>
32 #include <linux/list.h>
33 #include <linux/errno.h>
34 #include <linux/err.h>
36 #include <linux/interrupt.h>
37 #include <linux/ioport.h>
39 #include <asm/hardware.h>
40 #include <asm/atomic.h>
44 #include <asm/hardware/clock.h>
45 #include <asm/arch/regs-clock.h>
50 static LIST_HEAD(clocks);
51 static DECLARE_MUTEX(clocks_sem);
56 void s3c2410_clk_enable(unsigned int clocks, unsigned int enable)
61 local_irq_save(flags);
63 clkcon = __raw_readl(S3C2410_CLKCON);
69 __raw_writel(clkcon, S3C2410_CLKCON);
71 local_irq_restore(flags);
77 struct clk *clk_get(struct device *dev, const char *id)
80 struct clk *clk = ERR_PTR(-ENOENT);
83 list_for_each_entry(p, &clocks, list) {
84 if (strcmp(id, p->name) == 0 &&
85 try_module_get(p->owner)) {
95 void clk_put(struct clk *clk)
97 module_put(clk->owner);
100 int clk_enable(struct clk *clk)
102 if (clk->ctrlbit != 0)
103 s3c2410_clk_enable(clk->ctrlbit, 1);
108 void clk_disable(struct clk *clk)
110 s3c2410_clk_enable(clk->ctrlbit, 0);
114 int clk_use(struct clk *clk)
116 atomic_inc(&clk->used);
121 void clk_unuse(struct clk *clk)
123 atomic_dec(&clk->used);
126 unsigned long clk_get_rate(struct clk *clk)
128 if (clk->parent != NULL)
129 return clk->parent->rate;
134 long clk_round_rate(struct clk *clk, unsigned long rate)
139 int clk_set_rate(struct clk *clk, unsigned long rate)
144 struct clk *clk_get_parent(struct clk *clk)
149 EXPORT_SYMBOL(clk_get);
150 EXPORT_SYMBOL(clk_put);
151 EXPORT_SYMBOL(clk_enable);
152 EXPORT_SYMBOL(clk_disable);
153 EXPORT_SYMBOL(clk_use);
154 EXPORT_SYMBOL(clk_unuse);
155 EXPORT_SYMBOL(clk_get_rate);
156 EXPORT_SYMBOL(clk_round_rate);
157 EXPORT_SYMBOL(clk_set_rate);
158 EXPORT_SYMBOL(clk_get_parent);
162 static struct clk clk_f = {
169 static struct clk clk_h = {
176 static struct clk clk_p = {
183 /* clock definitions */
185 static struct clk init_clocks[] = {
188 .ctrlbit = S3C2410_CLKCON_NAND
192 .ctrlbit = S3C2410_CLKCON_LCDC
194 { .name = "usb-host",
196 .ctrlbit = S3C2410_CLKCON_USBH
198 { .name = "usb-device",
200 .ctrlbit = S3C2410_CLKCON_USBD
204 .ctrlbit = S3C2410_CLKCON_PWMT
208 .ctrlbit = S3C2410_CLKCON_SDI
212 .ctrlbit = S3C2410_CLKCON_UART0
216 .ctrlbit = S3C2410_CLKCON_UART1
220 .ctrlbit = S3C2410_CLKCON_UART2
224 .ctrlbit = S3C2410_CLKCON_GPIO
228 .ctrlbit = S3C2410_CLKCON_RTC
232 .ctrlbit = S3C2410_CLKCON_ADC
236 .ctrlbit = S3C2410_CLKCON_IIC
240 .ctrlbit = S3C2410_CLKCON_IIS
244 .ctrlbit = S3C2410_CLKCON_SPI
246 { .name = "watchdog",
252 /* initialise the clock system */
254 int s3c2410_register_clock(struct clk *clk)
256 clk->owner = THIS_MODULE;
257 atomic_set(&clk->used, 0);
259 /* add to the list of available clocks */
262 list_add(&clk->list, &clocks);
268 /* initalise all the clocks */
270 static int __init s3c2410_init_clocks(void)
272 struct clk *clkp = init_clocks;
276 printk(KERN_INFO "S3C2410 Clock control, (c) 2004 Simtec Electronics\n");
278 /* initialise the main system clocks */
280 clk_h.rate = s3c2410_hclk;
281 clk_p.rate = s3c2410_pclk;
282 clk_f.rate = s3c2410_fclk;
284 /* set the enabled clocks to a minimal (known) state */
285 __raw_writel(S3C2410_CLKCON_PWMT | S3C2410_CLKCON_UART0 | S3C2410_CLKCON_UART1 | S3C2410_CLKCON_UART2 | S3C2410_CLKCON_GPIO | S3C2410_CLKCON_RTC, S3C2410_CLKCON);
287 /* register our clocks */
289 if (s3c2410_register_clock(&clk_f) < 0)
290 printk(KERN_ERR "failed to register cpu fclk\n");
292 if (s3c2410_register_clock(&clk_h) < 0)
293 printk(KERN_ERR "failed to register cpu hclk\n");
295 if (s3c2410_register_clock(&clk_p) < 0)
296 printk(KERN_ERR "failed to register cpu pclk\n");
298 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
299 ret = s3c2410_register_clock(clkp);
301 printk(KERN_ERR "Failed to register clock %s (%d)\n",
309 arch_initcall(s3c2410_init_clocks);