Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
arm
mach-omap2
clkt2xxx_virt_prcm_set.c
Go to the documentation of this file.
1
/*
2
* OMAP2xxx DVFS virtual clock functions
3
*
4
* Copyright (C) 2005-2008 Texas Instruments, Inc.
5
* Copyright (C) 2004-2010 Nokia Corporation
6
*
7
* Contacts:
8
* Richard Woodruff <
[email protected]
>
9
* Paul Walmsley
10
*
11
* Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
12
* Gordon McNutt and RidgeRun, Inc.
13
*
14
* This program is free software; you can redistribute it and/or modify
15
* it under the terms of the GNU General Public License version 2 as
16
* published by the Free Software Foundation.
17
*
18
* XXX Some of this code should be replaceable by the upcoming OPP layer
19
* code. However, some notion of "rate set" is probably still necessary
20
* for OMAP2xxx at least. Rate sets should be generalized so they can be
21
* used for any OMAP chip, not just OMAP2xxx. In particular, Richard Woodruff
22
* has in the past expressed a preference to use rate sets for OPP changes,
23
* rather than dynamically recalculating the clock tree, so if someone wants
24
* this badly enough to write the code to handle it, we should support it
25
* as an option.
26
*/
27
#undef DEBUG
28
29
#include <linux/kernel.h>
30
#include <linux/errno.h>
31
#include <
linux/clk.h
>
32
#include <
linux/io.h
>
33
#include <
linux/cpufreq.h
>
34
#include <linux/slab.h>
35
36
#include <plat/clock.h>
37
#include <
plat/sram.h
>
38
#include <
plat/sdrc.h
>
39
40
#include "
soc.h
"
41
#include "
clock.h
"
42
#include "
clock2xxx.h
"
43
#include "
opp2xxx.h
"
44
#include "
cm2xxx_3xxx.h
"
45
#include "
cm-regbits-24xx.h
"
46
47
const
struct
prcm_config
*
curr_prcm_set
;
48
const
struct
prcm_config
*
rate_table
;
49
56
unsigned
long
omap2_table_mpu_recalc
(
struct
clk
*
clk
)
57
{
58
return
curr_prcm_set->
mpu_speed
;
59
}
60
61
/*
62
* Look for a rate equal or less than the target rate given a configuration set.
63
*
64
* What's not entirely clear is "which" field represents the key field.
65
* Some might argue L3-DDR, others ARM, others IVA. This code is simple and
66
* just uses the ARM rates.
67
*/
68
long
omap2_round_to_table_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
69
{
70
const
struct
prcm_config
*
ptr
;
71
long
highest_rate, sys_clk_rate;
72
73
highest_rate = -
EINVAL
;
74
sys_clk_rate =
__clk_get_rate
(
sclk
);
75
76
for
(ptr = rate_table; ptr->
mpu_speed
; ptr++) {
77
if
(!(ptr->
flags
&
cpu_mask
))
78
continue
;
79
if
(ptr->
xtal_speed
!= sys_clk_rate)
80
continue
;
81
82
highest_rate = ptr->
mpu_speed
;
83
84
/* Can check only after xtal frequency check */
85
if
(ptr->
mpu_speed
<= rate)
86
break
;
87
}
88
return
highest_rate;
89
}
90
91
/* Sets basic clocks based on the specified rate */
92
int
omap2_select_table_rate
(
struct
clk
*
clk
,
unsigned
long
rate
)
93
{
94
u32
cur_rate, done_rate,
bypass
= 0,
tmp
;
95
const
struct
prcm_config
*prcm;
96
unsigned
long
found_speed = 0;
97
unsigned
long
flags
;
98
long
sys_clk_rate;
99
100
sys_clk_rate =
__clk_get_rate
(
sclk
);
101
102
for
(prcm = rate_table; prcm->
mpu_speed
; prcm++) {
103
if
(!(prcm->
flags
&
cpu_mask
))
104
continue
;
105
106
if
(prcm->
xtal_speed
!= sys_clk_rate)
107
continue
;
108
109
if
(prcm->
mpu_speed
<= rate) {
110
found_speed = prcm->
mpu_speed
;
111
break
;
112
}
113
}
114
115
if
(!found_speed) {
116
printk
(
KERN_INFO
"Could not set MPU rate to %luMHz\n"
,
117
rate / 1000000);
118
return
-
EINVAL
;
119
}
120
121
curr_prcm_set = prcm;
122
cur_rate =
omap2xxx_clk_get_core_rate
(
dclk
);
123
124
if
(prcm->
dpll_speed
== cur_rate / 2) {
125
omap2xxx_sdrc_reprogram
(
CORE_CLK_SRC_DPLL
, 1);
126
}
else
if
(prcm->
dpll_speed
== cur_rate * 2) {
127
omap2xxx_sdrc_reprogram
(
CORE_CLK_SRC_DPLL_X2
, 1);
128
}
else
if
(prcm->
dpll_speed
!= cur_rate) {
129
local_irq_save
(flags);
130
131
if
(prcm->
dpll_speed
== prcm->
xtal_speed
)
132
bypass = 1;
133
134
if
((prcm->
cm_clksel2_pll
&
OMAP24XX_CORE_CLK_SRC_MASK
) ==
135
CORE_CLK_SRC_DPLL_X2
)
136
done_rate =
CORE_CLK_SRC_DPLL_X2
;
137
else
138
done_rate =
CORE_CLK_SRC_DPLL
;
139
140
/* MPU divider */
141
omap2_cm_write_mod_reg
(prcm->
cm_clksel_mpu
,
MPU_MOD
,
CM_CLKSEL
);
142
143
/* dsp + iva1 div(2420), iva2.1(2430) */
144
omap2_cm_write_mod_reg
(prcm->
cm_clksel_dsp
,
145
OMAP24XX_DSP_MOD
,
CM_CLKSEL
);
146
147
omap2_cm_write_mod_reg
(prcm->
cm_clksel_gfx
,
GFX_MOD
,
CM_CLKSEL
);
148
149
/* Major subsystem dividers */
150
tmp
=
omap2_cm_read_mod_reg
(
CORE_MOD
,
CM_CLKSEL1
) &
OMAP24XX_CLKSEL_DSS2_MASK
;
151
omap2_cm_write_mod_reg
(prcm->
cm_clksel1_core
|
tmp
,
CORE_MOD
,
152
CM_CLKSEL1
);
153
154
if
(
cpu_is_omap2430
())
155
omap2_cm_write_mod_reg
(prcm->
cm_clksel_mdm
,
156
OMAP2430_MDM_MOD
,
CM_CLKSEL
);
157
158
/* x2 to enter omap2xxx_sdrc_init_params() */
159
omap2xxx_sdrc_reprogram
(
CORE_CLK_SRC_DPLL_X2
, 1);
160
161
omap2_set_prcm
(prcm->
cm_clksel1_pll
, prcm->
base_sdrc_rfr
,
162
bypass);
163
164
omap2xxx_sdrc_init_params
(
omap2xxx_sdrc_dll_is_unlocked
());
165
omap2xxx_sdrc_reprogram
(done_rate, 0);
166
167
local_irq_restore
(flags);
168
}
169
170
return
0;
171
}
Generated on Thu Jan 10 2013 13:00:25 for Linux Kernel by
1.8.2