Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/mips/ath79/clock.c
10818 views
1
/*
2
* Atheros AR71XX/AR724X/AR913X common routines
3
*
4
* Copyright (C) 2011 Gabor Juhos <[email protected]>
5
*
6
* This program is free software; you can redistribute it and/or modify it
7
* under the terms of the GNU General Public License version 2 as published
8
* by the Free Software Foundation.
9
*/
10
11
#include <linux/kernel.h>
12
#include <linux/module.h>
13
#include <linux/init.h>
14
#include <linux/err.h>
15
#include <linux/clk.h>
16
17
#include <asm/mach-ath79/ath79.h>
18
#include <asm/mach-ath79/ar71xx_regs.h>
19
#include "common.h"
20
21
#define AR71XX_BASE_FREQ 40000000
22
#define AR724X_BASE_FREQ 5000000
23
#define AR913X_BASE_FREQ 5000000
24
25
struct clk {
26
unsigned long rate;
27
};
28
29
static struct clk ath79_ref_clk;
30
static struct clk ath79_cpu_clk;
31
static struct clk ath79_ddr_clk;
32
static struct clk ath79_ahb_clk;
33
static struct clk ath79_wdt_clk;
34
static struct clk ath79_uart_clk;
35
36
static void __init ar71xx_clocks_init(void)
37
{
38
u32 pll;
39
u32 freq;
40
u32 div;
41
42
ath79_ref_clk.rate = AR71XX_BASE_FREQ;
43
44
pll = ath79_pll_rr(AR71XX_PLL_REG_CPU_CONFIG);
45
46
div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1;
47
freq = div * ath79_ref_clk.rate;
48
49
div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1;
50
ath79_cpu_clk.rate = freq / div;
51
52
div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1;
53
ath79_ddr_clk.rate = freq / div;
54
55
div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2;
56
ath79_ahb_clk.rate = ath79_cpu_clk.rate / div;
57
58
ath79_wdt_clk.rate = ath79_ahb_clk.rate;
59
ath79_uart_clk.rate = ath79_ahb_clk.rate;
60
}
61
62
static void __init ar724x_clocks_init(void)
63
{
64
u32 pll;
65
u32 freq;
66
u32 div;
67
68
ath79_ref_clk.rate = AR724X_BASE_FREQ;
69
pll = ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG);
70
71
div = ((pll >> AR724X_PLL_DIV_SHIFT) & AR724X_PLL_DIV_MASK);
72
freq = div * ath79_ref_clk.rate;
73
74
div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK);
75
freq *= div;
76
77
ath79_cpu_clk.rate = freq;
78
79
div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1;
80
ath79_ddr_clk.rate = freq / div;
81
82
div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2;
83
ath79_ahb_clk.rate = ath79_cpu_clk.rate / div;
84
85
ath79_wdt_clk.rate = ath79_ahb_clk.rate;
86
ath79_uart_clk.rate = ath79_ahb_clk.rate;
87
}
88
89
static void __init ar913x_clocks_init(void)
90
{
91
u32 pll;
92
u32 freq;
93
u32 div;
94
95
ath79_ref_clk.rate = AR913X_BASE_FREQ;
96
pll = ath79_pll_rr(AR913X_PLL_REG_CPU_CONFIG);
97
98
div = ((pll >> AR913X_PLL_DIV_SHIFT) & AR913X_PLL_DIV_MASK);
99
freq = div * ath79_ref_clk.rate;
100
101
ath79_cpu_clk.rate = freq;
102
103
div = ((pll >> AR913X_DDR_DIV_SHIFT) & AR913X_DDR_DIV_MASK) + 1;
104
ath79_ddr_clk.rate = freq / div;
105
106
div = (((pll >> AR913X_AHB_DIV_SHIFT) & AR913X_AHB_DIV_MASK) + 1) * 2;
107
ath79_ahb_clk.rate = ath79_cpu_clk.rate / div;
108
109
ath79_wdt_clk.rate = ath79_ahb_clk.rate;
110
ath79_uart_clk.rate = ath79_ahb_clk.rate;
111
}
112
113
void __init ath79_clocks_init(void)
114
{
115
if (soc_is_ar71xx())
116
ar71xx_clocks_init();
117
else if (soc_is_ar724x())
118
ar724x_clocks_init();
119
else if (soc_is_ar913x())
120
ar913x_clocks_init();
121
else
122
BUG();
123
124
pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, "
125
"Ref:%lu.%03luMHz",
126
ath79_cpu_clk.rate / 1000000,
127
(ath79_cpu_clk.rate / 1000) % 1000,
128
ath79_ddr_clk.rate / 1000000,
129
(ath79_ddr_clk.rate / 1000) % 1000,
130
ath79_ahb_clk.rate / 1000000,
131
(ath79_ahb_clk.rate / 1000) % 1000,
132
ath79_ref_clk.rate / 1000000,
133
(ath79_ref_clk.rate / 1000) % 1000);
134
}
135
136
/*
137
* Linux clock API
138
*/
139
struct clk *clk_get(struct device *dev, const char *id)
140
{
141
if (!strcmp(id, "ref"))
142
return &ath79_ref_clk;
143
144
if (!strcmp(id, "cpu"))
145
return &ath79_cpu_clk;
146
147
if (!strcmp(id, "ddr"))
148
return &ath79_ddr_clk;
149
150
if (!strcmp(id, "ahb"))
151
return &ath79_ahb_clk;
152
153
if (!strcmp(id, "wdt"))
154
return &ath79_wdt_clk;
155
156
if (!strcmp(id, "uart"))
157
return &ath79_uart_clk;
158
159
return ERR_PTR(-ENOENT);
160
}
161
EXPORT_SYMBOL(clk_get);
162
163
int clk_enable(struct clk *clk)
164
{
165
return 0;
166
}
167
EXPORT_SYMBOL(clk_enable);
168
169
void clk_disable(struct clk *clk)
170
{
171
}
172
EXPORT_SYMBOL(clk_disable);
173
174
unsigned long clk_get_rate(struct clk *clk)
175
{
176
return clk->rate;
177
}
178
EXPORT_SYMBOL(clk_get_rate);
179
180
void clk_put(struct clk *clk)
181
{
182
}
183
EXPORT_SYMBOL(clk_put);
184
185