OSDN Git Service

4916cccf378fdd1d446f6ed23420828133e73563
[uclinux-h8/linux.git] / arch / mips / lantiq / clk.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *
4  * Copyright (C) 2010 Thomas Langer <thomas.langer@lantiq.com>
5  * Copyright (C) 2010 John Crispin <john@phrozen.org>
6  */
7 #include <linux/io.h>
8 #include <linux/export.h>
9 #include <linux/init.h>
10 #include <linux/kernel.h>
11 #include <linux/types.h>
12 #include <linux/clk.h>
13 #include <linux/clkdev.h>
14 #include <linux/err.h>
15 #include <linux/list.h>
16
17 #include <asm/time.h>
18 #include <asm/irq.h>
19 #include <asm/div64.h>
20
21 #include <lantiq_soc.h>
22
23 #include "clk.h"
24 #include "prom.h"
25
26 /* lantiq socs have 3 static clocks */
27 static struct clk cpu_clk_generic[4];
28
29 void clkdev_add_static(unsigned long cpu, unsigned long fpi,
30                         unsigned long io, unsigned long ppe)
31 {
32         cpu_clk_generic[0].rate = cpu;
33         cpu_clk_generic[1].rate = fpi;
34         cpu_clk_generic[2].rate = io;
35         cpu_clk_generic[3].rate = ppe;
36 }
37
38 struct clk *clk_get_cpu(void)
39 {
40         return &cpu_clk_generic[0];
41 }
42
43 struct clk *clk_get_fpi(void)
44 {
45         return &cpu_clk_generic[1];
46 }
47 EXPORT_SYMBOL_GPL(clk_get_fpi);
48
49 struct clk *clk_get_io(void)
50 {
51         return &cpu_clk_generic[2];
52 }
53
54 struct clk *clk_get_ppe(void)
55 {
56         return &cpu_clk_generic[3];
57 }
58 EXPORT_SYMBOL_GPL(clk_get_ppe);
59
60 static inline int clk_good(struct clk *clk)
61 {
62         return clk && !IS_ERR(clk);
63 }
64
65 unsigned long clk_get_rate(struct clk *clk)
66 {
67         if (unlikely(!clk_good(clk)))
68                 return 0;
69
70         if (clk->rate != 0)
71                 return clk->rate;
72
73         if (clk->get_rate != NULL)
74                 return clk->get_rate();
75
76         return 0;
77 }
78 EXPORT_SYMBOL(clk_get_rate);
79
80 int clk_set_rate(struct clk *clk, unsigned long rate)
81 {
82         if (unlikely(!clk_good(clk)))
83                 return 0;
84         if (clk->rates && *clk->rates) {
85                 unsigned long *r = clk->rates;
86
87                 while (*r && (*r != rate))
88                         r++;
89                 if (!*r) {
90                         pr_err("clk %s.%s: trying to set invalid rate %ld\n",
91                                 clk->cl.dev_id, clk->cl.con_id, rate);
92                         return -1;
93                 }
94         }
95         clk->rate = rate;
96         return 0;
97 }
98 EXPORT_SYMBOL(clk_set_rate);
99
100 long clk_round_rate(struct clk *clk, unsigned long rate)
101 {
102         if (unlikely(!clk_good(clk)))
103                 return 0;
104         if (clk->rates && *clk->rates) {
105                 unsigned long *r = clk->rates;
106
107                 while (*r && (*r != rate))
108                         r++;
109                 if (!*r) {
110                         return clk->rate;
111                 }
112         }
113         return rate;
114 }
115 EXPORT_SYMBOL(clk_round_rate);
116
117 int clk_enable(struct clk *clk)
118 {
119         if (unlikely(!clk_good(clk)))
120                 return -1;
121
122         if (clk->enable)
123                 return clk->enable(clk);
124
125         return -1;
126 }
127 EXPORT_SYMBOL(clk_enable);
128
129 void clk_disable(struct clk *clk)
130 {
131         if (unlikely(!clk_good(clk)))
132                 return;
133
134         if (clk->disable)
135                 clk->disable(clk);
136 }
137 EXPORT_SYMBOL(clk_disable);
138
139 int clk_activate(struct clk *clk)
140 {
141         if (unlikely(!clk_good(clk)))
142                 return -1;
143
144         if (clk->activate)
145                 return clk->activate(clk);
146
147         return -1;
148 }
149 EXPORT_SYMBOL(clk_activate);
150
151 void clk_deactivate(struct clk *clk)
152 {
153         if (unlikely(!clk_good(clk)))
154                 return;
155
156         if (clk->deactivate)
157                 clk->deactivate(clk);
158 }
159 EXPORT_SYMBOL(clk_deactivate);
160
161 struct clk *clk_get_parent(struct clk *clk)
162 {
163         return NULL;
164 }
165 EXPORT_SYMBOL(clk_get_parent);
166
167 static inline u32 get_counter_resolution(void)
168 {
169         u32 res;
170
171         __asm__ __volatile__(
172                 ".set   push\n"
173                 ".set   mips32r2\n"
174                 "rdhwr  %0, $3\n"
175                 ".set pop\n"
176                 : "=&r" (res)
177                 : /* no input */
178                 : "memory");
179
180         return res;
181 }
182
183 void __init plat_time_init(void)
184 {
185         struct clk *clk;
186
187         ltq_soc_init();
188
189         clk = clk_get_cpu();
190         mips_hpt_frequency = clk_get_rate(clk) / get_counter_resolution();
191         write_c0_compare(read_c0_count());
192         pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
193         clk_put(clk);
194 }