1
2
3
4
5
6
7
8
9
10#include <linux/module.h>
11#include <linux/list.h>
12#include <linux/mutex.h>
13#include <linux/clk.h>
14#include <linux/err.h>
15#include <asm/clock.h>
16#include <asm/time.h>
17
18#include <loongson1.h>
19
20static LIST_HEAD(clocks);
21static DEFINE_MUTEX(clocks_mutex);
22
23struct clk *clk_get(struct device *dev, const char *name)
24{
25 struct clk *c;
26 struct clk *ret = NULL;
27
28 mutex_lock(&clocks_mutex);
29 list_for_each_entry(c, &clocks, node) {
30 if (!strcmp(c->name, name)) {
31 ret = c;
32 break;
33 }
34 }
35 mutex_unlock(&clocks_mutex);
36
37 return ret;
38}
39EXPORT_SYMBOL(clk_get);
40
41int clk_enable(struct clk *clk)
42{
43 return 0;
44}
45EXPORT_SYMBOL(clk_enable);
46
47void clk_disable(struct clk *clk)
48{
49}
50EXPORT_SYMBOL(clk_disable);
51
52unsigned long clk_get_rate(struct clk *clk)
53{
54 return clk->rate;
55}
56EXPORT_SYMBOL(clk_get_rate);
57
58void clk_put(struct clk *clk)
59{
60}
61EXPORT_SYMBOL(clk_put);
62
63static void pll_clk_init(struct clk *clk)
64{
65 u32 pll;
66
67 pll = __raw_readl(LS1X_CLK_PLL_FREQ);
68 clk->rate = (12 + (pll & 0x3f)) * 33 / 2
69 + ((pll >> 8) & 0x3ff) * 33 / 1024 / 2;
70 clk->rate *= 1000000;
71}
72
73static void cpu_clk_init(struct clk *clk)
74{
75 u32 pll, ctrl;
76
77 pll = clk_get_rate(clk->parent);
78 ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_CPU;
79 clk->rate = pll / (ctrl >> DIV_CPU_SHIFT);
80}
81
82static void ddr_clk_init(struct clk *clk)
83{
84 u32 pll, ctrl;
85
86 pll = clk_get_rate(clk->parent);
87 ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_DDR;
88 clk->rate = pll / (ctrl >> DIV_DDR_SHIFT);
89}
90
91static void dc_clk_init(struct clk *clk)
92{
93 u32 pll, ctrl;
94
95 pll = clk_get_rate(clk->parent);
96 ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_DC;
97 clk->rate = pll / (ctrl >> DIV_DC_SHIFT);
98}
99
100static struct clk_ops pll_clk_ops = {
101 .init = pll_clk_init,
102};
103
104static struct clk_ops cpu_clk_ops = {
105 .init = cpu_clk_init,
106};
107
108static struct clk_ops ddr_clk_ops = {
109 .init = ddr_clk_init,
110};
111
112static struct clk_ops dc_clk_ops = {
113 .init = dc_clk_init,
114};
115
116static struct clk pll_clk = {
117 .name = "pll",
118 .ops = &pll_clk_ops,
119};
120
121static struct clk cpu_clk = {
122 .name = "cpu",
123 .parent = &pll_clk,
124 .ops = &cpu_clk_ops,
125};
126
127static struct clk ddr_clk = {
128 .name = "ddr",
129 .parent = &pll_clk,
130 .ops = &ddr_clk_ops,
131};
132
133static struct clk dc_clk = {
134 .name = "dc",
135 .parent = &pll_clk,
136 .ops = &dc_clk_ops,
137};
138
139int clk_register(struct clk *clk)
140{
141 mutex_lock(&clocks_mutex);
142 list_add(&clk->node, &clocks);
143 if (clk->ops->init)
144 clk->ops->init(clk);
145 mutex_unlock(&clocks_mutex);
146
147 return 0;
148}
149EXPORT_SYMBOL(clk_register);
150
151static struct clk *ls1x_clks[] = {
152 &pll_clk,
153 &cpu_clk,
154 &ddr_clk,
155 &dc_clk,
156};
157
158int __init ls1x_clock_init(void)
159{
160 int i;
161
162 for (i = 0; i < ARRAY_SIZE(ls1x_clks); i++)
163 clk_register(ls1x_clks[i]);
164
165 return 0;
166}
167
168void __init plat_time_init(void)
169{
170 struct clk *clk;
171
172
173 ls1x_clock_init();
174
175
176 clk = clk_get(NULL, "cpu");
177 if (IS_ERR(clk))
178 panic("unable to get dc clock, err=%ld", PTR_ERR(clk));
179
180 mips_hpt_frequency = clk_get_rate(clk) / 2;
181}
182