OMAP2/3 clock: Extend find_idlest() to pass back idle state value
[deliverable/linux.git] / arch / arm / mach-omap2 / clock34xx.c
CommitLineData
02e19a96
PW
1/*
2 * OMAP3-specific clock framework functions
3 *
542313cc 4 * Copyright (C) 2007-2008 Texas Instruments, Inc.
da4d2904 5 * Copyright (C) 2007-2010 Nokia Corporation
02e19a96 6 *
da4d2904
PW
7 * Paul Walmsley
8 * Jouni Högander
02e19a96
PW
9 *
10 * Parts of this code are based on code written by
11 * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2 as
15 * published by the Free Software Foundation.
16 */
17#undef DEBUG
18
02e19a96 19#include <linux/kernel.h>
02e19a96
PW
20#include <linux/errno.h>
21#include <linux/delay.h>
22#include <linux/clk.h>
23#include <linux/io.h>
24
ce491cf8
TL
25#include <plat/cpu.h>
26#include <plat/clock.h>
02e19a96 27
02e19a96 28#include "clock.h"
82e9bd58 29#include "clock34xx.h"
02e19a96
PW
30#include "prm.h"
31#include "prm-regbits-34xx.h"
32#include "cm.h"
33#include "cm-regbits-34xx.h"
34
7a66a39b
RN
35/*
36 * DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
37 * that are sourced by DPLL5, and both of these require this clock
38 * to be at 120 MHz for proper operation.
39 */
40#define DPLL5_FREQ_FOR_USBHOST 120000000
41
82e9bd58
PW
42/* needed by omap3_core_dpll_m2_set_rate() */
43struct clk *sdrc_ick_p, *arm_fck_p;
44
3c82e229
PW
45/**
46 * omap3430es2_clk_ssi_find_idlest - return CM_IDLEST info for SSI
47 * @clk: struct clk * being enabled
48 * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
49 * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
419cc97d 50 * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
3c82e229
PW
51 *
52 * The OMAP3430ES2 SSI target CM_IDLEST bit is at a different shift
53 * from the CM_{I,F}CLKEN bit. Pass back the correct info via
54 * @idlest_reg and @idlest_bit. No return value.
55 */
56static void omap3430es2_clk_ssi_find_idlest(struct clk *clk,
57 void __iomem **idlest_reg,
419cc97d
RL
58 u8 *idlest_bit,
59 u8 *idlest_val)
3c82e229
PW
60{
61 u32 r;
62
63 r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
64 *idlest_reg = (__force void __iomem *)r;
65 *idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT;
419cc97d 66 *idlest_val = OMAP34XX_CM_IDLEST_VAL;
3c82e229
PW
67}
68
82e9bd58
PW
69const struct clkops clkops_omap3430es2_ssi_wait = {
70 .enable = omap2_dflt_clk_enable,
71 .disable = omap2_dflt_clk_disable,
72 .find_idlest = omap3430es2_clk_ssi_find_idlest,
73 .find_companion = omap2_clk_dflt_find_companion,
74};
75
3c82e229
PW
76/**
77 * omap3430es2_clk_dss_usbhost_find_idlest - CM_IDLEST info for DSS, USBHOST
78 * @clk: struct clk * being enabled
79 * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
80 * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
419cc97d 81 * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
3c82e229
PW
82 *
83 * Some OMAP modules on OMAP3 ES2+ chips have both initiator and
84 * target IDLEST bits. For our purposes, we are concerned with the
85 * target IDLEST bits, which exist at a different bit position than
86 * the *CLKEN bit position for these modules (DSS and USBHOST) (The
87 * default find_idlest code assumes that they are at the same
88 * position.) No return value.
89 */
90static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk *clk,
91 void __iomem **idlest_reg,
419cc97d
RL
92 u8 *idlest_bit,
93 u8 *idlest_val)
3c82e229
PW
94{
95 u32 r;
96
97 r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
98 *idlest_reg = (__force void __iomem *)r;
99 /* USBHOST_IDLE has same shift */
100 *idlest_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT;
419cc97d 101 *idlest_val = OMAP34XX_CM_IDLEST_VAL;
3c82e229
PW
102}
103
82e9bd58
PW
104const struct clkops clkops_omap3430es2_dss_usbhost_wait = {
105 .enable = omap2_dflt_clk_enable,
106 .disable = omap2_dflt_clk_disable,
107 .find_idlest = omap3430es2_clk_dss_usbhost_find_idlest,
108 .find_companion = omap2_clk_dflt_find_companion,
109};
110
3c82e229
PW
111/**
112 * omap3430es2_clk_hsotgusb_find_idlest - return CM_IDLEST info for HSOTGUSB
113 * @clk: struct clk * being enabled
114 * @idlest_reg: void __iomem ** to store CM_IDLEST reg address into
115 * @idlest_bit: pointer to a u8 to store the CM_IDLEST bit shift into
419cc97d 116 * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
3c82e229
PW
117 *
118 * The OMAP3430ES2 HSOTGUSB target CM_IDLEST bit is at a different
119 * shift from the CM_{I,F}CLKEN bit. Pass back the correct info via
120 * @idlest_reg and @idlest_bit. No return value.
121 */
122static void omap3430es2_clk_hsotgusb_find_idlest(struct clk *clk,
123 void __iomem **idlest_reg,
419cc97d
RL
124 u8 *idlest_bit,
125 u8 *idlest_val)
3c82e229
PW
126{
127 u32 r;
128
129 r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
130 *idlest_reg = (__force void __iomem *)r;
131 *idlest_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT;
419cc97d 132 *idlest_val = OMAP34XX_CM_IDLEST_VAL;
3c82e229
PW
133}
134
82e9bd58
PW
135const struct clkops clkops_omap3430es2_hsotgusb_wait = {
136 .enable = omap2_dflt_clk_enable,
137 .disable = omap2_dflt_clk_disable,
138 .find_idlest = omap3430es2_clk_hsotgusb_find_idlest,
139 .find_companion = omap2_clk_dflt_find_companion,
140};
141
4751227d 142const struct clkops omap3_clkops_noncore_dpll_ops = {
82e9bd58
PW
143 .enable = omap3_noncore_dpll_enable,
144 .disable = omap3_noncore_dpll_disable,
145};
16c90f02 146
82e9bd58 147int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
16c90f02
PW
148{
149 /*
150 * According to the 12-5 CDP code from TI, "Limitation 2.5"
151 * on 3430ES1 prevents us from changing DPLL multipliers or dividers
152 * on DPLL4.
153 */
154 if (omap_rev() == OMAP3430_REV_ES1_0) {
155 printk(KERN_ERR "clock: DPLL4 cannot change rate due to "
156 "silicon 'Limitation 2.5' on 3430ES1.\n");
157 return -EINVAL;
158 }
159 return omap3_noncore_dpll_set_rate(clk, rate);
160}
161
e80a9729 162void __init omap3_clk_lock_dpll5(void)
7a66a39b
RN
163{
164 struct clk *dpll5_clk;
165 struct clk *dpll5_m2_clk;
166
167 dpll5_clk = clk_get(NULL, "dpll5_ck");
168 clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
169 clk_enable(dpll5_clk);
170
171 /* Enable autoidle to allow it to enter low power bypass */
172 omap3_dpll_allow_idle(dpll5_clk);
173
174 /* Program dpll5_m2_clk divider for no division */
175 dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
176 clk_enable(dpll5_m2_clk);
177 clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST);
178
179 clk_disable(dpll5_m2_clk);
180 clk_disable(dpll5_clk);
181 return;
182}
183
feec1277
PW
184/* Common clock code */
185
02e19a96
PW
186/* REVISIT: Move this init stuff out into clock.c */
187
188/*
189 * Switch the MPU rate if specified on cmdline.
190 * We cannot do this early until cmdline is parsed.
191 */
4680c29f 192static int __init omap3xxx_clk_arch_init(void)
02e19a96 193{
82e9bd58
PW
194 struct clk *osc_sys_ck, *dpll1_ck, *arm_fck, *core_ck;
195 unsigned long osc_sys_rate;
196
4680c29f
PW
197 if (!cpu_is_omap34xx())
198 return 0;
199
02e19a96
PW
200 if (!mpurate)
201 return -EINVAL;
202
82e9bd58
PW
203 /* XXX test these for success */
204 dpll1_ck = clk_get(NULL, "dpll1_ck");
205 arm_fck = clk_get(NULL, "arm_fck");
206 core_ck = clk_get(NULL, "core_ck");
207 osc_sys_ck = clk_get(NULL, "osc_sys_ck");
208
02e19a96 209 /* REVISIT: not yet ready for 343x */
82e9bd58 210 if (clk_set_rate(dpll1_ck, mpurate))
11b66383 211 printk(KERN_ERR "*** Unable to set MPU rate\n");
02e19a96
PW
212
213 recalculate_root_clocks();
214
82e9bd58
PW
215 osc_sys_rate = clk_get_rate(osc_sys_ck);
216
217 pr_info("Switched to new clocking rate (Crystal/Core/MPU): "
218 "%ld.%01ld/%ld/%ld MHz\n",
219 (osc_sys_rate / 1000000),
220 ((osc_sys_rate / 100000) % 10),
221 (clk_get_rate(core_ck) / 1000000),
222 (clk_get_rate(arm_fck) / 1000000));
11b66383
SP
223
224 calibrate_delay();
02e19a96
PW
225
226 return 0;
227}
4680c29f 228arch_initcall(omap3xxx_clk_arch_init);
02e19a96 229
02e19a96 230
This page took 0.156487 seconds and 5 git commands to generate.