blob: 49d93efc191107aec23fdd04aeefb54ed13b57c3 [file] [log] [blame]
Paul Walmsley02e19a92008-03-18 15:09:51 +02001/*
2 * OMAP3-specific clock framework functions
3 *
Paul Walmsley542313c2008-07-03 12:24:45 +03004 * Copyright (C) 2007-2008 Texas Instruments, Inc.
Paul Walmsleyda4d2902010-01-26 20:13:10 -07005 * Copyright (C) 2007-2010 Nokia Corporation
Paul Walmsley02e19a92008-03-18 15:09:51 +02006 *
Paul Walmsleyda4d2902010-01-26 20:13:10 -07007 * Paul Walmsley
8 * Jouni Högander
Paul Walmsley02e19a92008-03-18 15:09:51 +02009 *
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
Paul Walmsley02e19a92008-03-18 15:09:51 +020019#include <linux/kernel.h>
Paul Walmsley02e19a92008-03-18 15:09:51 +020020#include <linux/errno.h>
21#include <linux/delay.h>
22#include <linux/clk.h>
23#include <linux/io.h>
24
Tony Lindgrence491cf2009-10-20 09:40:47 -070025#include <plat/cpu.h>
26#include <plat/clock.h>
Paul Walmsley02e19a92008-03-18 15:09:51 +020027
Paul Walmsley02e19a92008-03-18 15:09:51 +020028#include "clock.h"
Paul Walmsley82e9bd52009-12-08 16:18:47 -070029#include "clock34xx.h"
Paul Walmsley02e19a92008-03-18 15:09:51 +020030#include "prm.h"
31#include "prm-regbits-34xx.h"
32#include "cm.h"
33#include "cm-regbits-34xx.h"
34
Rajendra Nayak7a66a392009-10-05 13:31:44 -070035/*
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
Paul Walmsley82e9bd52009-12-08 16:18:47 -070042/* needed by omap3_core_dpll_m2_set_rate() */
43struct clk *sdrc_ick_p, *arm_fck_p;
44
Paul Walmsley02e19a92008-03-18 15:09:51 +020045/**
Paul Walmsley3c82e222009-07-24 19:44:06 -060046 * 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
Ranjith Lohithakshan419cc972010-02-24 12:05:54 -070050 * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
Paul Walmsley3c82e222009-07-24 19:44:06 -060051 *
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,
Ranjith Lohithakshan419cc972010-02-24 12:05:54 -070058 u8 *idlest_bit,
59 u8 *idlest_val)
Paul Walmsley3c82e222009-07-24 19:44:06 -060060{
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;
Ranjith Lohithakshan419cc972010-02-24 12:05:54 -070066 *idlest_val = OMAP34XX_CM_IDLEST_VAL;
Paul Walmsley3c82e222009-07-24 19:44:06 -060067}
68
Paul Walmsley82e9bd52009-12-08 16:18:47 -070069const 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
Paul Walmsley3c82e222009-07-24 19:44:06 -060076/**
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
Ranjith Lohithakshan419cc972010-02-24 12:05:54 -070081 * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
Paul Walmsley3c82e222009-07-24 19:44:06 -060082 *
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,
Ranjith Lohithakshan419cc972010-02-24 12:05:54 -070092 u8 *idlest_bit,
93 u8 *idlest_val)
Paul Walmsley3c82e222009-07-24 19:44:06 -060094{
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;
Ranjith Lohithakshan419cc972010-02-24 12:05:54 -0700101 *idlest_val = OMAP34XX_CM_IDLEST_VAL;
Paul Walmsley3c82e222009-07-24 19:44:06 -0600102}
103
Paul Walmsley82e9bd52009-12-08 16:18:47 -0700104const 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
Paul Walmsley3c82e222009-07-24 19:44:06 -0600111/**
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
Ranjith Lohithakshan419cc972010-02-24 12:05:54 -0700116 * @idlest_val: pointer to a u8 to store the CM_IDLEST indicator
Paul Walmsley3c82e222009-07-24 19:44:06 -0600117 *
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,
Ranjith Lohithakshan419cc972010-02-24 12:05:54 -0700124 u8 *idlest_bit,
125 u8 *idlest_val)
Paul Walmsley3c82e222009-07-24 19:44:06 -0600126{
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;
Ranjith Lohithakshan419cc972010-02-24 12:05:54 -0700132 *idlest_val = OMAP34XX_CM_IDLEST_VAL;
Paul Walmsley3c82e222009-07-24 19:44:06 -0600133}
134
Paul Walmsley82e9bd52009-12-08 16:18:47 -0700135const 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
Tony Lindgren47512272010-02-15 09:27:25 -0800142const struct clkops omap3_clkops_noncore_dpll_ops = {
Paul Walmsley82e9bd52009-12-08 16:18:47 -0700143 .enable = omap3_noncore_dpll_enable,
144 .disable = omap3_noncore_dpll_disable,
145};
Paul Walmsley16c90f02009-01-27 19:12:47 -0700146
Paul Walmsley82e9bd52009-12-08 16:18:47 -0700147int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
Paul Walmsley16c90f02009-01-27 19:12:47 -0700148{
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
Paul Walmsleye80a9722010-01-26 20:13:12 -0700162void __init omap3_clk_lock_dpll5(void)
Rajendra Nayak7a66a392009-10-05 13:31:44 -0700163{
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
Paul Walmsleyfeec1272010-01-26 20:13:11 -0700184/* Common clock code */
185
Paul Walmsley02e19a92008-03-18 15:09:51 +0200186/* 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 */
Paul Walmsley4680c292010-01-26 20:13:09 -0700192static int __init omap3xxx_clk_arch_init(void)
Paul Walmsley02e19a92008-03-18 15:09:51 +0200193{
Paul Walmsley82e9bd52009-12-08 16:18:47 -0700194 struct clk *osc_sys_ck, *dpll1_ck, *arm_fck, *core_ck;
195 unsigned long osc_sys_rate;
196
Paul Walmsley4680c292010-01-26 20:13:09 -0700197 if (!cpu_is_omap34xx())
198 return 0;
199
Paul Walmsley02e19a92008-03-18 15:09:51 +0200200 if (!mpurate)
201 return -EINVAL;
202
Paul Walmsley82e9bd52009-12-08 16:18:47 -0700203 /* 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
Paul Walmsley02e19a92008-03-18 15:09:51 +0200209 /* REVISIT: not yet ready for 343x */
Paul Walmsley82e9bd52009-12-08 16:18:47 -0700210 if (clk_set_rate(dpll1_ck, mpurate))
Sanjeev Premi11b66382009-09-03 20:13:58 +0300211 printk(KERN_ERR "*** Unable to set MPU rate\n");
Paul Walmsley02e19a92008-03-18 15:09:51 +0200212
213 recalculate_root_clocks();
214
Paul Walmsley82e9bd52009-12-08 16:18:47 -0700215 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));
Sanjeev Premi11b66382009-09-03 20:13:58 +0300223
224 calibrate_delay();
Paul Walmsley02e19a92008-03-18 15:09:51 +0200225
226 return 0;
227}
Paul Walmsley4680c292010-01-26 20:13:09 -0700228arch_initcall(omap3xxx_clk_arch_init);
Paul Walmsley82e9bd52009-12-08 16:18:47 -0700229
230