blob: 7c6f95f291425c5fd3fc3d5c8969d4e9f739201f [file] [log] [blame]
Eric Miao49cbe782009-01-20 14:15:18 +08001/*
2 * linux/arch/arm/mach-mmp/clock.c
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/module.h>
10#include <linux/kernel.h>
11#include <linux/list.h>
12#include <linux/spinlock.h>
13#include <linux/clk.h>
14#include <linux/io.h>
15
16#include <mach/regs-apbc.h>
17#include "clock.h"
18
19static void apbc_clk_enable(struct clk *clk)
20{
21 uint32_t clk_rst;
22
23 clk_rst = APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(clk->fnclksel);
24 __raw_writel(clk_rst, clk->clk_rst);
25}
26
27static void apbc_clk_disable(struct clk *clk)
28{
29 __raw_writel(0, clk->clk_rst);
30}
31
32struct clkops apbc_clk_ops = {
33 .enable = apbc_clk_enable,
34 .disable = apbc_clk_disable,
35};
36
Haojian Zhuang40928552009-09-10 14:01:22 +080037static void apmu_clk_enable(struct clk *clk)
38{
39 __raw_writel(clk->enable_val, clk->clk_rst);
40}
41
42static void apmu_clk_disable(struct clk *clk)
43{
44 __raw_writel(0, clk->clk_rst);
45}
46
47struct clkops apmu_clk_ops = {
48 .enable = apmu_clk_enable,
49 .disable = apmu_clk_disable,
50};
51
Eric Miao49cbe782009-01-20 14:15:18 +080052static DEFINE_SPINLOCK(clocks_lock);
53
54int clk_enable(struct clk *clk)
55{
56 unsigned long flags;
57
58 spin_lock_irqsave(&clocks_lock, flags);
59 if (clk->enabled++ == 0)
60 clk->ops->enable(clk);
61 spin_unlock_irqrestore(&clocks_lock, flags);
62 return 0;
63}
64EXPORT_SYMBOL(clk_enable);
65
66void clk_disable(struct clk *clk)
67{
68 unsigned long flags;
69
70 WARN_ON(clk->enabled == 0);
71
72 spin_lock_irqsave(&clocks_lock, flags);
73 if (--clk->enabled == 0)
74 clk->ops->disable(clk);
75 spin_unlock_irqrestore(&clocks_lock, flags);
76}
77EXPORT_SYMBOL(clk_disable);
78
79unsigned long clk_get_rate(struct clk *clk)
80{
81 unsigned long rate;
82
83 if (clk->ops->getrate)
84 rate = clk->ops->getrate(clk);
85 else
86 rate = clk->rate;
87
88 return rate;
89}
90EXPORT_SYMBOL(clk_get_rate);
Haojian Zhuang52585cc2011-04-08 20:15:38 +080091
92int clk_set_rate(struct clk *clk, unsigned long rate)
93{
94 unsigned long flags;
95 int ret = -EINVAL;
96
97 if (clk->ops->setrate) {
98 spin_lock_irqsave(&clocks_lock, flags);
99 ret = clk->ops->setrate(clk, rate);
100 spin_unlock_irqrestore(&clocks_lock, flags);
101 }
102
103 return ret;
104}
105EXPORT_SYMBOL(clk_set_rate);