Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/mips/kernel/cpufreq/loongson2_clock.c
10820 views
1
/*
2
* Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology
3
* Author: Yanhua, [email protected]
4
*
5
* This file is subject to the terms and conditions of the GNU General Public
6
* License. See the file "COPYING" in the main directory of this archive
7
* for more details.
8
*/
9
10
#include <linux/cpufreq.h>
11
#include <linux/platform_device.h>
12
13
#include <asm/clock.h>
14
15
#include <loongson.h>
16
17
static LIST_HEAD(clock_list);
18
static DEFINE_SPINLOCK(clock_lock);
19
static DEFINE_MUTEX(clock_list_sem);
20
21
/* Minimum CLK support */
22
enum {
23
DC_ZERO, DC_25PT = 2, DC_37PT, DC_50PT, DC_62PT, DC_75PT,
24
DC_87PT, DC_DISABLE, DC_RESV
25
};
26
27
struct cpufreq_frequency_table loongson2_clockmod_table[] = {
28
{DC_RESV, CPUFREQ_ENTRY_INVALID},
29
{DC_ZERO, CPUFREQ_ENTRY_INVALID},
30
{DC_25PT, 0},
31
{DC_37PT, 0},
32
{DC_50PT, 0},
33
{DC_62PT, 0},
34
{DC_75PT, 0},
35
{DC_87PT, 0},
36
{DC_DISABLE, 0},
37
{DC_RESV, CPUFREQ_TABLE_END},
38
};
39
EXPORT_SYMBOL_GPL(loongson2_clockmod_table);
40
41
static struct clk cpu_clk = {
42
.name = "cpu_clk",
43
.flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES,
44
.rate = 800000000,
45
};
46
47
struct clk *clk_get(struct device *dev, const char *id)
48
{
49
return &cpu_clk;
50
}
51
EXPORT_SYMBOL(clk_get);
52
53
static void propagate_rate(struct clk *clk)
54
{
55
struct clk *clkp;
56
57
list_for_each_entry(clkp, &clock_list, node) {
58
if (likely(clkp->parent != clk))
59
continue;
60
if (likely(clkp->ops && clkp->ops->recalc))
61
clkp->ops->recalc(clkp);
62
if (unlikely(clkp->flags & CLK_RATE_PROPAGATES))
63
propagate_rate(clkp);
64
}
65
}
66
67
int clk_enable(struct clk *clk)
68
{
69
return 0;
70
}
71
EXPORT_SYMBOL(clk_enable);
72
73
void clk_disable(struct clk *clk)
74
{
75
}
76
EXPORT_SYMBOL(clk_disable);
77
78
unsigned long clk_get_rate(struct clk *clk)
79
{
80
return (unsigned long)clk->rate;
81
}
82
EXPORT_SYMBOL(clk_get_rate);
83
84
void clk_put(struct clk *clk)
85
{
86
}
87
EXPORT_SYMBOL(clk_put);
88
89
int clk_set_rate(struct clk *clk, unsigned long rate)
90
{
91
return clk_set_rate_ex(clk, rate, 0);
92
}
93
EXPORT_SYMBOL_GPL(clk_set_rate);
94
95
int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id)
96
{
97
int ret = 0;
98
int regval;
99
int i;
100
101
if (likely(clk->ops && clk->ops->set_rate)) {
102
unsigned long flags;
103
104
spin_lock_irqsave(&clock_lock, flags);
105
ret = clk->ops->set_rate(clk, rate, algo_id);
106
spin_unlock_irqrestore(&clock_lock, flags);
107
}
108
109
if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
110
propagate_rate(clk);
111
112
for (i = 0; loongson2_clockmod_table[i].frequency != CPUFREQ_TABLE_END;
113
i++) {
114
if (loongson2_clockmod_table[i].frequency ==
115
CPUFREQ_ENTRY_INVALID)
116
continue;
117
if (rate == loongson2_clockmod_table[i].frequency)
118
break;
119
}
120
if (rate != loongson2_clockmod_table[i].frequency)
121
return -ENOTSUPP;
122
123
clk->rate = rate;
124
125
regval = LOONGSON_CHIPCFG0;
126
regval = (regval & ~0x7) | (loongson2_clockmod_table[i].index - 1);
127
LOONGSON_CHIPCFG0 = regval;
128
129
return ret;
130
}
131
EXPORT_SYMBOL_GPL(clk_set_rate_ex);
132
133
long clk_round_rate(struct clk *clk, unsigned long rate)
134
{
135
if (likely(clk->ops && clk->ops->round_rate)) {
136
unsigned long flags, rounded;
137
138
spin_lock_irqsave(&clock_lock, flags);
139
rounded = clk->ops->round_rate(clk, rate);
140
spin_unlock_irqrestore(&clock_lock, flags);
141
142
return rounded;
143
}
144
145
return rate;
146
}
147
EXPORT_SYMBOL_GPL(clk_round_rate);
148
149
/*
150
* This is the simple version of Loongson-2 wait, Maybe we need do this in
151
* interrupt disabled content
152
*/
153
154
DEFINE_SPINLOCK(loongson2_wait_lock);
155
void loongson2_cpu_wait(void)
156
{
157
u32 cpu_freq;
158
unsigned long flags;
159
160
spin_lock_irqsave(&loongson2_wait_lock, flags);
161
cpu_freq = LOONGSON_CHIPCFG0;
162
LOONGSON_CHIPCFG0 &= ~0x7; /* Put CPU into wait mode */
163
LOONGSON_CHIPCFG0 = cpu_freq; /* Restore CPU state */
164
spin_unlock_irqrestore(&loongson2_wait_lock, flags);
165
}
166
EXPORT_SYMBOL_GPL(loongson2_cpu_wait);
167
168
MODULE_AUTHOR("Yanhua <[email protected]>");
169
MODULE_DESCRIPTION("cpufreq driver for Loongson 2F");
170
MODULE_LICENSE("GPL");
171
172