blob: 9273b0dffc660ccba9b13fe6167f3c04b3c19130 [file] [log] [blame]
Colin Crossd8611962010-01-28 16:40:29 -08001/*
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05302 * arch/arm/mach-tegra/tegra20_clocks.c
Colin Crossd8611962010-01-28 16:40:29 -08003 *
4 * Copyright (C) 2010 Google, Inc.
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05305 * Copyright (c) 2010-2012 NVIDIA CORPORATION. All rights reserved.
Colin Crossd8611962010-01-28 16:40:29 -08006 *
7 * Author:
8 * Colin Cross <ccross@google.com>
9 *
10 * This software is licensed under the terms of the GNU General Public
11 * License version 2, as published by the Free Software Foundation, and
12 * may be copied, distributed, and modified under those terms.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 */
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/list.h>
24#include <linux/spinlock.h>
25#include <linux/delay.h>
26#include <linux/io.h>
Jean-Christop PLAGNIOL-VILLARD6d803ba2010-11-17 10:04:33 +010027#include <linux/clkdev.h>
Colin Cross4729fd72011-02-12 16:43:05 -080028#include <linux/clk.h>
Colin Crossd8611962010-01-28 16:40:29 -080029
30#include <mach/iomap.h>
Colin Cross2ea67fd2010-10-04 08:49:49 -070031#include <mach/suspend.h>
Colin Crossd8611962010-01-28 16:40:29 -080032
33#include "clock.h"
Colin Cross71fc84c2010-06-07 20:49:46 -070034#include "fuse.h"
Colin Cross6d296822010-11-22 18:37:54 -080035#include "tegra2_emc.h"
Joseph Lodab403e2012-08-16 17:31:48 +080036#include "tegra_cpu_car.h"
Colin Crossd8611962010-01-28 16:40:29 -080037
38#define RST_DEVICES 0x004
39#define RST_DEVICES_SET 0x300
40#define RST_DEVICES_CLR 0x304
Colin Cross71fc84c2010-06-07 20:49:46 -070041#define RST_DEVICES_NUM 3
Colin Crossd8611962010-01-28 16:40:29 -080042
43#define CLK_OUT_ENB 0x010
44#define CLK_OUT_ENB_SET 0x320
45#define CLK_OUT_ENB_CLR 0x324
Colin Cross71fc84c2010-06-07 20:49:46 -070046#define CLK_OUT_ENB_NUM 3
47
48#define CLK_MASK_ARM 0x44
49#define MISC_CLK_ENB 0x48
Colin Crossd8611962010-01-28 16:40:29 -080050
51#define OSC_CTRL 0x50
52#define OSC_CTRL_OSC_FREQ_MASK (3<<30)
53#define OSC_CTRL_OSC_FREQ_13MHZ (0<<30)
54#define OSC_CTRL_OSC_FREQ_19_2MHZ (1<<30)
55#define OSC_CTRL_OSC_FREQ_12MHZ (2<<30)
56#define OSC_CTRL_OSC_FREQ_26MHZ (3<<30)
Colin Crosscea62c82010-10-04 11:49:26 -070057#define OSC_CTRL_MASK (0x3f2 | OSC_CTRL_OSC_FREQ_MASK)
Colin Crossd8611962010-01-28 16:40:29 -080058
59#define OSC_FREQ_DET 0x58
60#define OSC_FREQ_DET_TRIG (1<<31)
61
62#define OSC_FREQ_DET_STATUS 0x5C
63#define OSC_FREQ_DET_BUSY (1<<31)
64#define OSC_FREQ_DET_CNT_MASK 0xFFFF
65
Colin Cross71fc84c2010-06-07 20:49:46 -070066#define PERIPH_CLK_SOURCE_I2S1 0x100
67#define PERIPH_CLK_SOURCE_EMC 0x19c
68#define PERIPH_CLK_SOURCE_OSC 0x1fc
69#define PERIPH_CLK_SOURCE_NUM \
70 ((PERIPH_CLK_SOURCE_OSC - PERIPH_CLK_SOURCE_I2S1) / 4)
71
Colin Crossd8611962010-01-28 16:40:29 -080072#define PERIPH_CLK_SOURCE_MASK (3<<30)
73#define PERIPH_CLK_SOURCE_SHIFT 30
Simon Quebb1dccf2011-12-16 20:11:22 +010074#define PERIPH_CLK_SOURCE_PWM_MASK (7<<28)
75#define PERIPH_CLK_SOURCE_PWM_SHIFT 28
Colin Crossd8611962010-01-28 16:40:29 -080076#define PERIPH_CLK_SOURCE_ENABLE (1<<28)
Colin Cross71fc84c2010-06-07 20:49:46 -070077#define PERIPH_CLK_SOURCE_DIVU71_MASK 0xFF
78#define PERIPH_CLK_SOURCE_DIVU16_MASK 0xFFFF
Colin Crossd8611962010-01-28 16:40:29 -080079#define PERIPH_CLK_SOURCE_DIV_SHIFT 0
80
Colin Cross9743b382011-02-12 18:24:32 -080081#define SDMMC_CLK_INT_FB_SEL (1 << 23)
82#define SDMMC_CLK_INT_FB_DLY_SHIFT 16
83#define SDMMC_CLK_INT_FB_DLY_MASK (0xF << SDMMC_CLK_INT_FB_DLY_SHIFT)
84
Colin Crossd8611962010-01-28 16:40:29 -080085#define PLL_BASE 0x0
86#define PLL_BASE_BYPASS (1<<31)
87#define PLL_BASE_ENABLE (1<<30)
88#define PLL_BASE_REF_ENABLE (1<<29)
89#define PLL_BASE_OVERRIDE (1<<28)
Colin Crossd8611962010-01-28 16:40:29 -080090#define PLL_BASE_DIVP_MASK (0x7<<20)
91#define PLL_BASE_DIVP_SHIFT 20
92#define PLL_BASE_DIVN_MASK (0x3FF<<8)
93#define PLL_BASE_DIVN_SHIFT 8
94#define PLL_BASE_DIVM_MASK (0x1F)
95#define PLL_BASE_DIVM_SHIFT 0
96
97#define PLL_OUT_RATIO_MASK (0xFF<<8)
98#define PLL_OUT_RATIO_SHIFT 8
99#define PLL_OUT_OVERRIDE (1<<2)
100#define PLL_OUT_CLKEN (1<<1)
101#define PLL_OUT_RESET_DISABLE (1<<0)
102
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530103#define PLL_MISC(c) (((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc)
Colin Cross71fc84c2010-06-07 20:49:46 -0700104
Colin Crossd8611962010-01-28 16:40:29 -0800105#define PLL_MISC_DCCON_SHIFT 20
Colin Crossd8611962010-01-28 16:40:29 -0800106#define PLL_MISC_CPCON_SHIFT 8
107#define PLL_MISC_CPCON_MASK (0xF<<PLL_MISC_CPCON_SHIFT)
108#define PLL_MISC_LFCON_SHIFT 4
109#define PLL_MISC_LFCON_MASK (0xF<<PLL_MISC_LFCON_SHIFT)
110#define PLL_MISC_VCOCON_SHIFT 0
111#define PLL_MISC_VCOCON_MASK (0xF<<PLL_MISC_VCOCON_SHIFT)
112
Colin Cross71fc84c2010-06-07 20:49:46 -0700113#define PLLU_BASE_POST_DIV (1<<20)
114
Colin Crossd8611962010-01-28 16:40:29 -0800115#define PLLD_MISC_CLKENABLE (1<<30)
116#define PLLD_MISC_DIV_RST (1<<23)
117#define PLLD_MISC_DCCON_SHIFT 12
118
Mike Rapoport8d685bc2010-09-27 11:26:32 +0200119#define PLLE_MISC_READY (1 << 15)
120
Colin Crossf1519612011-02-12 16:05:31 -0800121#define PERIPH_CLK_TO_ENB_REG(c) ((c->u.periph.clk_num / 32) * 4)
122#define PERIPH_CLK_TO_ENB_SET_REG(c) ((c->u.periph.clk_num / 32) * 8)
123#define PERIPH_CLK_TO_ENB_BIT(c) (1 << (c->u.periph.clk_num % 32))
Colin Crossd8611962010-01-28 16:40:29 -0800124
125#define SUPER_CLK_MUX 0x00
126#define SUPER_STATE_SHIFT 28
127#define SUPER_STATE_MASK (0xF << SUPER_STATE_SHIFT)
128#define SUPER_STATE_STANDBY (0x0 << SUPER_STATE_SHIFT)
129#define SUPER_STATE_IDLE (0x1 << SUPER_STATE_SHIFT)
130#define SUPER_STATE_RUN (0x2 << SUPER_STATE_SHIFT)
131#define SUPER_STATE_IRQ (0x3 << SUPER_STATE_SHIFT)
132#define SUPER_STATE_FIQ (0x4 << SUPER_STATE_SHIFT)
133#define SUPER_SOURCE_MASK 0xF
134#define SUPER_FIQ_SOURCE_SHIFT 12
135#define SUPER_IRQ_SOURCE_SHIFT 8
136#define SUPER_RUN_SOURCE_SHIFT 4
137#define SUPER_IDLE_SOURCE_SHIFT 0
138
139#define SUPER_CLK_DIVIDER 0x04
140
141#define BUS_CLK_DISABLE (1<<3)
142#define BUS_CLK_DIV_MASK 0x3
143
Colin Crosscea62c82010-10-04 11:49:26 -0700144#define PMC_CTRL 0x0
145 #define PMC_CTRL_BLINK_ENB (1 << 7)
146
147#define PMC_DPD_PADS_ORIDE 0x1c
148 #define PMC_DPD_PADS_ORIDE_BLINK_ENB (1 << 20)
149
150#define PMC_BLINK_TIMER_DATA_ON_SHIFT 0
151#define PMC_BLINK_TIMER_DATA_ON_MASK 0x7fff
152#define PMC_BLINK_TIMER_ENB (1 << 15)
153#define PMC_BLINK_TIMER_DATA_OFF_SHIFT 16
154#define PMC_BLINK_TIMER_DATA_OFF_MASK 0xffff
155
Joseph Lodab403e2012-08-16 17:31:48 +0800156/* Tegra CPU clock and reset control regs */
157#define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX 0x4c
158#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET 0x340
159#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR 0x344
160
161#define CPU_CLOCK(cpu) (0x1 << (8 + cpu))
162#define CPU_RESET(cpu) (0x1111ul << (cpu))
163
Colin Crossd8611962010-01-28 16:40:29 -0800164static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
Colin Crosscea62c82010-10-04 11:49:26 -0700165static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
Colin Crossd8611962010-01-28 16:40:29 -0800166
Colin Cross4729fd72011-02-12 16:43:05 -0800167/*
168 * Some clocks share a register with other clocks. Any clock op that
169 * non-atomically modifies a register used by another clock must lock
170 * clock_register_lock first.
171 */
172static DEFINE_SPINLOCK(clock_register_lock);
173
Colin Cross78f379b2010-10-20 19:19:58 -0700174/*
175 * Some peripheral clocks share an enable bit, so refcount the enable bits
176 * in registers CLK_ENABLE_L, CLK_ENABLE_H, and CLK_ENABLE_U
177 */
178static int tegra_periph_clk_enable_refcount[3 * 32];
179
Colin Crossd8611962010-01-28 16:40:29 -0800180#define clk_writel(value, reg) \
Olof Johanssond3959352011-09-08 17:56:59 -0700181 __raw_writel(value, reg_clk_base + (reg))
Colin Crossd8611962010-01-28 16:40:29 -0800182#define clk_readl(reg) \
Olof Johanssond3959352011-09-08 17:56:59 -0700183 __raw_readl(reg_clk_base + (reg))
Colin Crosscea62c82010-10-04 11:49:26 -0700184#define pmc_writel(value, reg) \
Olof Johanssond3959352011-09-08 17:56:59 -0700185 __raw_writel(value, reg_pmc_base + (reg))
Colin Crosscea62c82010-10-04 11:49:26 -0700186#define pmc_readl(reg) \
Olof Johanssond3959352011-09-08 17:56:59 -0700187 __raw_readl(reg_pmc_base + (reg))
Colin Crossd8611962010-01-28 16:40:29 -0800188
Peter De Schrijver8e4fab22011-12-14 17:03:16 +0200189static unsigned long clk_measure_input_freq(void)
Colin Crossd8611962010-01-28 16:40:29 -0800190{
191 u32 clock_autodetect;
192 clk_writel(OSC_FREQ_DET_TRIG | 1, OSC_FREQ_DET);
193 do {} while (clk_readl(OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY);
194 clock_autodetect = clk_readl(OSC_FREQ_DET_STATUS);
195 if (clock_autodetect >= 732 - 3 && clock_autodetect <= 732 + 3) {
196 return 12000000;
197 } else if (clock_autodetect >= 794 - 3 && clock_autodetect <= 794 + 3) {
198 return 13000000;
199 } else if (clock_autodetect >= 1172 - 3 && clock_autodetect <= 1172 + 3) {
200 return 19200000;
201 } else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3) {
202 return 26000000;
203 } else {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530204 pr_err("%s: Unexpected clock autodetect value %d",
205 __func__, clock_autodetect);
Colin Crossd8611962010-01-28 16:40:29 -0800206 BUG();
207 return 0;
208 }
209}
210
Colin Cross71fc84c2010-06-07 20:49:46 -0700211static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate)
Colin Crossd8611962010-01-28 16:40:29 -0800212{
Colin Cross71fc84c2010-06-07 20:49:46 -0700213 s64 divider_u71 = parent_rate * 2;
214 divider_u71 += rate - 1;
215 do_div(divider_u71, rate);
Colin Crossd8611962010-01-28 16:40:29 -0800216
Colin Cross71fc84c2010-06-07 20:49:46 -0700217 if (divider_u71 - 2 < 0)
218 return 0;
Colin Crossd8611962010-01-28 16:40:29 -0800219
Colin Cross71fc84c2010-06-07 20:49:46 -0700220 if (divider_u71 - 2 > 255)
Colin Crossd8611962010-01-28 16:40:29 -0800221 return -EINVAL;
222
223 return divider_u71 - 2;
224}
225
Colin Cross71fc84c2010-06-07 20:49:46 -0700226static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate)
Colin Crossd8611962010-01-28 16:40:29 -0800227{
Colin Cross71fc84c2010-06-07 20:49:46 -0700228 s64 divider_u16;
Colin Crossd8611962010-01-28 16:40:29 -0800229
Colin Cross71fc84c2010-06-07 20:49:46 -0700230 divider_u16 = parent_rate;
231 divider_u16 += rate - 1;
232 do_div(divider_u16, rate);
233
234 if (divider_u16 - 1 < 0)
235 return 0;
236
Stephen Warreneb70e1b2012-07-24 15:48:12 -0600237 if (divider_u16 - 1 > 0xFFFF)
Colin Cross71fc84c2010-06-07 20:49:46 -0700238 return -EINVAL;
239
240 return divider_u16 - 1;
Colin Crossd8611962010-01-28 16:40:29 -0800241}
242
Joseph Lob78c0302012-08-17 14:51:21 +0800243static unsigned long tegra_clk_fixed_recalc_rate(struct clk_hw *hw,
244 unsigned long parent_rate)
245{
246 return to_clk_tegra(hw)->fixed_rate;
247}
248
249struct clk_ops tegra_clk_32k_ops = {
250 .recalc_rate = tegra_clk_fixed_recalc_rate,
251};
252
Colin Crossd8611962010-01-28 16:40:29 -0800253/* clk_m functions */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530254static unsigned long tegra20_clk_m_recalc_rate(struct clk_hw *hw,
255 unsigned long prate)
Colin Crossd8611962010-01-28 16:40:29 -0800256{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530257 if (!to_clk_tegra(hw)->fixed_rate)
258 to_clk_tegra(hw)->fixed_rate = clk_measure_input_freq();
259 return to_clk_tegra(hw)->fixed_rate;
260}
Colin Crossd8611962010-01-28 16:40:29 -0800261
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530262static void tegra20_clk_m_init(struct clk_hw *hw)
263{
264 struct clk_tegra *c = to_clk_tegra(hw);
265 u32 osc_ctrl = clk_readl(OSC_CTRL);
266 u32 auto_clock_control = osc_ctrl & ~OSC_CTRL_OSC_FREQ_MASK;
267
268 switch (c->fixed_rate) {
Colin Crossd8611962010-01-28 16:40:29 -0800269 case 12000000:
270 auto_clock_control |= OSC_CTRL_OSC_FREQ_12MHZ;
271 break;
272 case 13000000:
273 auto_clock_control |= OSC_CTRL_OSC_FREQ_13MHZ;
274 break;
275 case 19200000:
276 auto_clock_control |= OSC_CTRL_OSC_FREQ_19_2MHZ;
277 break;
278 case 26000000:
279 auto_clock_control |= OSC_CTRL_OSC_FREQ_26MHZ;
280 break;
281 default:
Colin Crossd8611962010-01-28 16:40:29 -0800282 BUG();
283 }
284 clk_writel(auto_clock_control, OSC_CTRL);
Colin Crossd8611962010-01-28 16:40:29 -0800285}
286
Prashant Gaikwad86edb872012-08-06 11:57:40 +0530287struct clk_ops tegra_clk_m_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530288 .init = tegra20_clk_m_init,
289 .recalc_rate = tegra20_clk_m_recalc_rate,
Colin Crossd8611962010-01-28 16:40:29 -0800290};
291
292/* super clock functions */
293/* "super clocks" on tegra have two-stage muxes and a clock skipping
294 * super divider. We will ignore the clock skipping divider, since we
295 * can't lower the voltage when using the clock skip, but we can if we
296 * lower the PLL frequency.
297 */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530298static int tegra20_super_clk_is_enabled(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800299{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530300 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crossd8611962010-01-28 16:40:29 -0800301 u32 val;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530302
303 val = clk_readl(c->reg + SUPER_CLK_MUX);
304 BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
305 ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
306 c->state = ON;
307 return c->state;
308}
309
310static int tegra20_super_clk_enable(struct clk_hw *hw)
311{
312 struct clk_tegra *c = to_clk_tegra(hw);
313 clk_writel(0, c->reg + SUPER_CLK_DIVIDER);
314 return 0;
315}
316
317static void tegra20_super_clk_disable(struct clk_hw *hw)
318{
319 pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
320
321 /* oops - don't disable the CPU clock! */
322 BUG();
323}
324
325static u8 tegra20_super_clk_get_parent(struct clk_hw *hw)
326{
327 struct clk_tegra *c = to_clk_tegra(hw);
328 int val = clk_readl(c->reg + SUPER_CLK_MUX);
Colin Crossd8611962010-01-28 16:40:29 -0800329 int source;
330 int shift;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530331
Colin Crossd8611962010-01-28 16:40:29 -0800332 BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
333 ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
334 shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
335 SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
336 source = (val >> shift) & SUPER_SOURCE_MASK;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530337 return source;
Colin Crossd8611962010-01-28 16:40:29 -0800338}
339
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530340static int tegra20_super_clk_set_parent(struct clk_hw *hw, u8 index)
Colin Crossd8611962010-01-28 16:40:29 -0800341{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530342 struct clk_tegra *c = to_clk_tegra(hw);
343 u32 val = clk_readl(c->reg + SUPER_CLK_MUX);
Colin Crossd8611962010-01-28 16:40:29 -0800344 int shift;
Colin Cross71fc84c2010-06-07 20:49:46 -0700345
Colin Crossd8611962010-01-28 16:40:29 -0800346 BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
347 ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
348 shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
349 SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530350 val &= ~(SUPER_SOURCE_MASK << shift);
351 val |= index << shift;
Colin Cross71fc84c2010-06-07 20:49:46 -0700352
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530353 clk_writel(val, c->reg);
Colin Cross71fc84c2010-06-07 20:49:46 -0700354
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530355 return 0;
Colin Crossd8611962010-01-28 16:40:29 -0800356}
357
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530358/* FIX ME: Need to switch parents to change the source PLL rate */
359static unsigned long tegra20_super_clk_recalc_rate(struct clk_hw *hw,
360 unsigned long prate)
Colin Cross9c7dc562011-02-12 21:25:23 -0800361{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530362 return prate;
Colin Cross9c7dc562011-02-12 21:25:23 -0800363}
364
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530365static long tegra20_super_clk_round_rate(struct clk_hw *hw, unsigned long rate,
366 unsigned long *prate)
Colin Cross71fc84c2010-06-07 20:49:46 -0700367{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530368 return *prate;
Colin Cross71fc84c2010-06-07 20:49:46 -0700369}
370
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530371static int tegra20_super_clk_set_rate(struct clk_hw *hw, unsigned long rate,
372 unsigned long parent_rate)
Colin Cross71fc84c2010-06-07 20:49:46 -0700373{
374 return 0;
375}
376
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530377struct clk_ops tegra_super_ops = {
378 .is_enabled = tegra20_super_clk_is_enabled,
379 .enable = tegra20_super_clk_enable,
380 .disable = tegra20_super_clk_disable,
381 .set_parent = tegra20_super_clk_set_parent,
382 .get_parent = tegra20_super_clk_get_parent,
383 .set_rate = tegra20_super_clk_set_rate,
384 .round_rate = tegra20_super_clk_round_rate,
385 .recalc_rate = tegra20_super_clk_recalc_rate,
386};
Colin Cross71fc84c2010-06-07 20:49:46 -0700387
Prashant Gaikwadb4350f42012-09-13 15:04:33 +0530388static unsigned long tegra20_twd_clk_recalc_rate(struct clk_hw *hw,
389 unsigned long parent_rate)
390{
391 struct clk_tegra *c = to_clk_tegra(hw);
392 u64 rate = parent_rate;
393
394 if (c->mul != 0 && c->div != 0) {
395 rate *= c->mul;
396 rate += c->div - 1; /* round up */
397 do_div(rate, c->div);
398 }
399
400 return rate;
401}
402
403struct clk_ops tegra_twd_ops = {
404 .recalc_rate = tegra20_twd_clk_recalc_rate,
405};
406
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530407static u8 tegra20_cop_clk_get_parent(struct clk_hw *hw)
408{
409 return 0;
Colin Cross71fc84c2010-06-07 20:49:46 -0700410}
411
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530412struct clk_ops tegra_cop_ops = {
413 .get_parent = tegra20_cop_clk_get_parent,
Colin Crossd8611962010-01-28 16:40:29 -0800414};
415
Colin Cross9c7dc562011-02-12 21:25:23 -0800416/* virtual cop clock functions. Used to acquire the fake 'cop' clock to
417 * reset the COP block (i.e. AVP) */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530418void tegra2_cop_clk_reset(struct clk_hw *hw, bool assert)
Colin Cross9c7dc562011-02-12 21:25:23 -0800419{
420 unsigned long reg = assert ? RST_DEVICES_SET : RST_DEVICES_CLR;
421
422 pr_debug("%s %s\n", __func__, assert ? "assert" : "deassert");
423 clk_writel(1 << 1, reg);
424}
425
Colin Crossd8611962010-01-28 16:40:29 -0800426/* bus clock functions */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530427static int tegra20_bus_clk_is_enabled(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800428{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530429 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crossd8611962010-01-28 16:40:29 -0800430 u32 val = clk_readl(c->reg);
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530431
Colin Crossd8611962010-01-28 16:40:29 -0800432 c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530433 return c->state;
Colin Crossd8611962010-01-28 16:40:29 -0800434}
435
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530436static int tegra20_bus_clk_enable(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800437{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530438 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross4729fd72011-02-12 16:43:05 -0800439 unsigned long flags;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530440 u32 val;
Colin Cross4729fd72011-02-12 16:43:05 -0800441
442 spin_lock_irqsave(&clock_register_lock, flags);
443
444 val = clk_readl(c->reg);
Colin Crossd8611962010-01-28 16:40:29 -0800445 val &= ~(BUS_CLK_DISABLE << c->reg_shift);
446 clk_writel(val, c->reg);
Colin Cross4729fd72011-02-12 16:43:05 -0800447
448 spin_unlock_irqrestore(&clock_register_lock, flags);
449
Colin Crossd8611962010-01-28 16:40:29 -0800450 return 0;
451}
452
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530453static void tegra20_bus_clk_disable(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800454{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530455 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross4729fd72011-02-12 16:43:05 -0800456 unsigned long flags;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530457 u32 val;
Colin Cross4729fd72011-02-12 16:43:05 -0800458
459 spin_lock_irqsave(&clock_register_lock, flags);
460
461 val = clk_readl(c->reg);
Colin Crossd8611962010-01-28 16:40:29 -0800462 val |= BUS_CLK_DISABLE << c->reg_shift;
463 clk_writel(val, c->reg);
Colin Cross4729fd72011-02-12 16:43:05 -0800464
465 spin_unlock_irqrestore(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -0800466}
467
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530468static unsigned long tegra20_bus_clk_recalc_rate(struct clk_hw *hw,
469 unsigned long prate)
Colin Crossd8611962010-01-28 16:40:29 -0800470{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530471 struct clk_tegra *c = to_clk_tegra(hw);
472 u32 val = clk_readl(c->reg);
473 u64 rate = prate;
474
475 c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1;
476 c->mul = 1;
477
478 if (c->mul != 0 && c->div != 0) {
479 rate *= c->mul;
480 rate += c->div - 1; /* round up */
481 do_div(rate, c->div);
482 }
483 return rate;
484}
485
486static int tegra20_bus_clk_set_rate(struct clk_hw *hw, unsigned long rate,
487 unsigned long parent_rate)
488{
489 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross4729fd72011-02-12 16:43:05 -0800490 int ret = -EINVAL;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530491 unsigned long flags;
492 u32 val;
Colin Crossd8611962010-01-28 16:40:29 -0800493 int i;
Colin Cross4729fd72011-02-12 16:43:05 -0800494
495 spin_lock_irqsave(&clock_register_lock, flags);
496
497 val = clk_readl(c->reg);
Colin Crossd8611962010-01-28 16:40:29 -0800498 for (i = 1; i <= 4; i++) {
499 if (rate == parent_rate / i) {
500 val &= ~(BUS_CLK_DIV_MASK << c->reg_shift);
501 val |= (i - 1) << c->reg_shift;
502 clk_writel(val, c->reg);
503 c->div = i;
504 c->mul = 1;
Colin Cross4729fd72011-02-12 16:43:05 -0800505 ret = 0;
506 break;
Colin Crossd8611962010-01-28 16:40:29 -0800507 }
508 }
Colin Cross4729fd72011-02-12 16:43:05 -0800509
510 spin_unlock_irqrestore(&clock_register_lock, flags);
511
512 return ret;
Colin Crossd8611962010-01-28 16:40:29 -0800513}
514
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530515static long tegra20_bus_clk_round_rate(struct clk_hw *hw, unsigned long rate,
516 unsigned long *prate)
517{
518 unsigned long parent_rate = *prate;
519 s64 divider;
520
521 if (rate >= parent_rate)
522 return rate;
523
524 divider = parent_rate;
525 divider += rate - 1;
526 do_div(divider, rate);
527
528 if (divider < 0)
529 return divider;
530
531 if (divider > 4)
532 divider = 4;
533 do_div(parent_rate, divider);
534
535 return parent_rate;
536}
537
Prashant Gaikwad86edb872012-08-06 11:57:40 +0530538struct clk_ops tegra_bus_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530539 .is_enabled = tegra20_bus_clk_is_enabled,
540 .enable = tegra20_bus_clk_enable,
541 .disable = tegra20_bus_clk_disable,
542 .set_rate = tegra20_bus_clk_set_rate,
543 .round_rate = tegra20_bus_clk_round_rate,
544 .recalc_rate = tegra20_bus_clk_recalc_rate,
Colin Crossd8611962010-01-28 16:40:29 -0800545};
546
Colin Crosscea62c82010-10-04 11:49:26 -0700547/* Blink output functions */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530548static int tegra20_blink_clk_is_enabled(struct clk_hw *hw)
Colin Crosscea62c82010-10-04 11:49:26 -0700549{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530550 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crosscea62c82010-10-04 11:49:26 -0700551 u32 val;
552
553 val = pmc_readl(PMC_CTRL);
554 c->state = (val & PMC_CTRL_BLINK_ENB) ? ON : OFF;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530555 return c->state;
556}
557
558static unsigned long tegra20_blink_clk_recalc_rate(struct clk_hw *hw,
559 unsigned long prate)
560{
561 struct clk_tegra *c = to_clk_tegra(hw);
562 u64 rate = prate;
563 u32 val;
564
Colin Crosscea62c82010-10-04 11:49:26 -0700565 c->mul = 1;
566 val = pmc_readl(c->reg);
567
568 if (val & PMC_BLINK_TIMER_ENB) {
569 unsigned int on_off;
570
571 on_off = (val >> PMC_BLINK_TIMER_DATA_ON_SHIFT) &
572 PMC_BLINK_TIMER_DATA_ON_MASK;
573 val >>= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
574 val &= PMC_BLINK_TIMER_DATA_OFF_MASK;
575 on_off += val;
576 /* each tick in the blink timer is 4 32KHz clocks */
577 c->div = on_off * 4;
578 } else {
579 c->div = 1;
580 }
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530581
582 if (c->mul != 0 && c->div != 0) {
583 rate *= c->mul;
584 rate += c->div - 1; /* round up */
585 do_div(rate, c->div);
586 }
587 return rate;
Colin Crosscea62c82010-10-04 11:49:26 -0700588}
589
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530590static int tegra20_blink_clk_enable(struct clk_hw *hw)
Colin Crosscea62c82010-10-04 11:49:26 -0700591{
592 u32 val;
593
594 val = pmc_readl(PMC_DPD_PADS_ORIDE);
595 pmc_writel(val | PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
596
597 val = pmc_readl(PMC_CTRL);
598 pmc_writel(val | PMC_CTRL_BLINK_ENB, PMC_CTRL);
599
600 return 0;
601}
602
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530603static void tegra20_blink_clk_disable(struct clk_hw *hw)
Colin Crosscea62c82010-10-04 11:49:26 -0700604{
605 u32 val;
606
607 val = pmc_readl(PMC_CTRL);
608 pmc_writel(val & ~PMC_CTRL_BLINK_ENB, PMC_CTRL);
609
610 val = pmc_readl(PMC_DPD_PADS_ORIDE);
611 pmc_writel(val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
612}
613
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530614static int tegra20_blink_clk_set_rate(struct clk_hw *hw, unsigned long rate,
615 unsigned long parent_rate)
Colin Crosscea62c82010-10-04 11:49:26 -0700616{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530617 struct clk_tegra *c = to_clk_tegra(hw);
618
Colin Cross4729fd72011-02-12 16:43:05 -0800619 if (rate >= parent_rate) {
Colin Crosscea62c82010-10-04 11:49:26 -0700620 c->div = 1;
621 pmc_writel(0, c->reg);
622 } else {
623 unsigned int on_off;
624 u32 val;
625
Colin Cross4729fd72011-02-12 16:43:05 -0800626 on_off = DIV_ROUND_UP(parent_rate / 8, rate);
Colin Crosscea62c82010-10-04 11:49:26 -0700627 c->div = on_off * 8;
628
629 val = (on_off & PMC_BLINK_TIMER_DATA_ON_MASK) <<
630 PMC_BLINK_TIMER_DATA_ON_SHIFT;
631 on_off &= PMC_BLINK_TIMER_DATA_OFF_MASK;
632 on_off <<= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
633 val |= on_off;
634 val |= PMC_BLINK_TIMER_ENB;
635 pmc_writel(val, c->reg);
636 }
637
638 return 0;
639}
640
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530641static long tegra20_blink_clk_round_rate(struct clk_hw *hw, unsigned long rate,
642 unsigned long *prate)
643{
644 int div;
645 int mul;
646 long round_rate = *prate;
647
648 mul = 1;
649
650 if (rate >= *prate) {
651 div = 1;
652 } else {
653 div = DIV_ROUND_UP(*prate / 8, rate);
654 div *= 8;
655 }
656
657 round_rate *= mul;
658 round_rate += div - 1;
659 do_div(round_rate, div);
660
661 return round_rate;
662}
663
Prashant Gaikwad86edb872012-08-06 11:57:40 +0530664struct clk_ops tegra_blink_clk_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530665 .is_enabled = tegra20_blink_clk_is_enabled,
666 .enable = tegra20_blink_clk_enable,
667 .disable = tegra20_blink_clk_disable,
668 .set_rate = tegra20_blink_clk_set_rate,
669 .round_rate = tegra20_blink_clk_round_rate,
670 .recalc_rate = tegra20_blink_clk_recalc_rate,
Colin Crosscea62c82010-10-04 11:49:26 -0700671};
672
Colin Crossd8611962010-01-28 16:40:29 -0800673/* PLL Functions */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530674static int tegra20_pll_clk_wait_for_lock(struct clk_tegra *c)
Colin Crossd8611962010-01-28 16:40:29 -0800675{
Colin Crossf1519612011-02-12 16:05:31 -0800676 udelay(c->u.pll.lock_delay);
Colin Crossd8611962010-01-28 16:40:29 -0800677 return 0;
678}
679
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530680static int tegra20_pll_clk_is_enabled(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800681{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530682 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crossd8611962010-01-28 16:40:29 -0800683 u32 val = clk_readl(c->reg + PLL_BASE);
684
685 c->state = (val & PLL_BASE_ENABLE) ? ON : OFF;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530686 return c->state;
687}
688
689static unsigned long tegra20_pll_clk_recalc_rate(struct clk_hw *hw,
690 unsigned long prate)
691{
692 struct clk_tegra *c = to_clk_tegra(hw);
693 u32 val = clk_readl(c->reg + PLL_BASE);
694 u64 rate = prate;
Colin Crossd8611962010-01-28 16:40:29 -0800695
696 if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530697 const struct clk_pll_freq_table *sel;
698 for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
699 if (sel->input_rate == prate &&
700 sel->output_rate == c->u.pll.fixed_rate) {
701 c->mul = sel->n;
702 c->div = sel->m * sel->p;
703 break;
704 }
705 }
706 pr_err("Clock %s has unknown fixed frequency\n",
707 __clk_get_name(hw->clk));
708 BUG();
Colin Crossd8611962010-01-28 16:40:29 -0800709 } else if (val & PLL_BASE_BYPASS) {
Colin Cross71fc84c2010-06-07 20:49:46 -0700710 c->mul = 1;
711 c->div = 1;
Colin Crossd8611962010-01-28 16:40:29 -0800712 } else {
Colin Cross71fc84c2010-06-07 20:49:46 -0700713 c->mul = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT;
714 c->div = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT;
715 if (c->flags & PLLU)
716 c->div *= (val & PLLU_BASE_POST_DIV) ? 1 : 2;
717 else
718 c->div *= (val & PLL_BASE_DIVP_MASK) ? 2 : 1;
Colin Crossd8611962010-01-28 16:40:29 -0800719 }
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530720
721 if (c->mul != 0 && c->div != 0) {
722 rate *= c->mul;
723 rate += c->div - 1; /* round up */
724 do_div(rate, c->div);
725 }
726 return rate;
Colin Crossd8611962010-01-28 16:40:29 -0800727}
728
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530729static int tegra20_pll_clk_enable(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800730{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530731 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crossd8611962010-01-28 16:40:29 -0800732 u32 val;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530733 pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
Colin Crossd8611962010-01-28 16:40:29 -0800734
735 val = clk_readl(c->reg + PLL_BASE);
736 val &= ~PLL_BASE_BYPASS;
737 val |= PLL_BASE_ENABLE;
738 clk_writel(val, c->reg + PLL_BASE);
739
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530740 tegra20_pll_clk_wait_for_lock(c);
Colin Crossd8611962010-01-28 16:40:29 -0800741
742 return 0;
743}
744
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530745static void tegra20_pll_clk_disable(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800746{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530747 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crossd8611962010-01-28 16:40:29 -0800748 u32 val;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530749 pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
Colin Crossd8611962010-01-28 16:40:29 -0800750
751 val = clk_readl(c->reg);
752 val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
753 clk_writel(val, c->reg);
754}
755
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530756static int tegra20_pll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
757 unsigned long parent_rate)
Colin Crossd8611962010-01-28 16:40:29 -0800758{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530759 struct clk_tegra *c = to_clk_tegra(hw);
760 unsigned long input_rate = parent_rate;
Colin Crossf1519612011-02-12 16:05:31 -0800761 const struct clk_pll_freq_table *sel;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530762 u32 val;
Colin Crossd8611962010-01-28 16:40:29 -0800763
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530764 pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate);
Colin Crossd8611962010-01-28 16:40:29 -0800765
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530766 if (c->flags & PLL_FIXED) {
767 int ret = 0;
768 if (rate != c->u.pll.fixed_rate) {
769 pr_err("%s: Can not change %s fixed rate %lu to %lu\n",
770 __func__, __clk_get_name(hw->clk),
771 c->u.pll.fixed_rate, rate);
772 ret = -EINVAL;
773 }
774 return ret;
775 }
776
Colin Crossf1519612011-02-12 16:05:31 -0800777 for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
Colin Crossd8611962010-01-28 16:40:29 -0800778 if (sel->input_rate == input_rate && sel->output_rate == rate) {
Colin Cross71fc84c2010-06-07 20:49:46 -0700779 c->mul = sel->n;
780 c->div = sel->m * sel->p;
Colin Crossd8611962010-01-28 16:40:29 -0800781
782 val = clk_readl(c->reg + PLL_BASE);
783 if (c->flags & PLL_FIXED)
784 val |= PLL_BASE_OVERRIDE;
785 val &= ~(PLL_BASE_DIVP_MASK | PLL_BASE_DIVN_MASK |
786 PLL_BASE_DIVM_MASK);
Colin Cross71fc84c2010-06-07 20:49:46 -0700787 val |= (sel->m << PLL_BASE_DIVM_SHIFT) |
788 (sel->n << PLL_BASE_DIVN_SHIFT);
789 BUG_ON(sel->p < 1 || sel->p > 2);
790 if (c->flags & PLLU) {
791 if (sel->p == 1)
792 val |= PLLU_BASE_POST_DIV;
793 } else {
794 if (sel->p == 2)
795 val |= 1 << PLL_BASE_DIVP_SHIFT;
796 }
Colin Crossd8611962010-01-28 16:40:29 -0800797 clk_writel(val, c->reg + PLL_BASE);
798
799 if (c->flags & PLL_HAS_CPCON) {
Colin Cross71fc84c2010-06-07 20:49:46 -0700800 val = clk_readl(c->reg + PLL_MISC(c));
801 val &= ~PLL_MISC_CPCON_MASK;
802 val |= sel->cpcon << PLL_MISC_CPCON_SHIFT;
Colin Crossd8611962010-01-28 16:40:29 -0800803 clk_writel(val, c->reg + PLL_MISC(c));
804 }
805
806 if (c->state == ON)
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530807 tegra20_pll_clk_enable(hw);
Colin Crossd8611962010-01-28 16:40:29 -0800808 return 0;
809 }
810 }
811 return -EINVAL;
812}
813
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530814static long tegra20_pll_clk_round_rate(struct clk_hw *hw, unsigned long rate,
815 unsigned long *prate)
816{
817 struct clk_tegra *c = to_clk_tegra(hw);
818 const struct clk_pll_freq_table *sel;
819 unsigned long input_rate = *prate;
Stephen Warren7a74a442012-09-10 17:02:45 -0600820 u64 output_rate = *prate;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530821 int mul;
822 int div;
823
824 if (c->flags & PLL_FIXED)
825 return c->u.pll.fixed_rate;
826
827 for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++)
828 if (sel->input_rate == input_rate && sel->output_rate == rate) {
829 mul = sel->n;
830 div = sel->m * sel->p;
831 break;
832 }
833
834 if (sel->input_rate == 0)
835 return -EINVAL;
836
837 output_rate *= mul;
838 output_rate += div - 1; /* round up */
839 do_div(output_rate, div);
840
841 return output_rate;
842}
843
Prashant Gaikwad86edb872012-08-06 11:57:40 +0530844struct clk_ops tegra_pll_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530845 .is_enabled = tegra20_pll_clk_is_enabled,
846 .enable = tegra20_pll_clk_enable,
847 .disable = tegra20_pll_clk_disable,
848 .set_rate = tegra20_pll_clk_set_rate,
849 .recalc_rate = tegra20_pll_clk_recalc_rate,
850 .round_rate = tegra20_pll_clk_round_rate,
Colin Cross71fc84c2010-06-07 20:49:46 -0700851};
852
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530853static void tegra20_pllx_clk_init(struct clk_hw *hw)
Colin Cross71fc84c2010-06-07 20:49:46 -0700854{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530855 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross71fc84c2010-06-07 20:49:46 -0700856
Olof Johansson9a1086d2011-10-13 00:31:20 -0700857 if (tegra_sku_id == 7)
Colin Cross71fc84c2010-06-07 20:49:46 -0700858 c->max_rate = 750000000;
859}
860
Prashant Gaikwad86edb872012-08-06 11:57:40 +0530861struct clk_ops tegra_pllx_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530862 .init = tegra20_pllx_clk_init,
863 .is_enabled = tegra20_pll_clk_is_enabled,
864 .enable = tegra20_pll_clk_enable,
865 .disable = tegra20_pll_clk_disable,
866 .set_rate = tegra20_pll_clk_set_rate,
867 .recalc_rate = tegra20_pll_clk_recalc_rate,
868 .round_rate = tegra20_pll_clk_round_rate,
Colin Crossd8611962010-01-28 16:40:29 -0800869};
870
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530871static int tegra20_plle_clk_enable(struct clk_hw *hw)
Mike Rapoport8d685bc2010-09-27 11:26:32 +0200872{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530873 struct clk_tegra *c = to_clk_tegra(hw);
Mike Rapoport8d685bc2010-09-27 11:26:32 +0200874 u32 val;
875
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530876 pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
Mike Rapoport8d685bc2010-09-27 11:26:32 +0200877
878 mdelay(1);
879
880 val = clk_readl(c->reg + PLL_BASE);
881 if (!(val & PLLE_MISC_READY))
882 return -EBUSY;
883
884 val = clk_readl(c->reg + PLL_BASE);
885 val |= PLL_BASE_ENABLE | PLL_BASE_BYPASS;
886 clk_writel(val, c->reg + PLL_BASE);
887
888 return 0;
889}
890
Prashant Gaikwad86edb872012-08-06 11:57:40 +0530891struct clk_ops tegra_plle_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530892 .is_enabled = tegra20_pll_clk_is_enabled,
893 .enable = tegra20_plle_clk_enable,
894 .set_rate = tegra20_pll_clk_set_rate,
895 .recalc_rate = tegra20_pll_clk_recalc_rate,
896 .round_rate = tegra20_pll_clk_round_rate,
Mike Rapoport8d685bc2010-09-27 11:26:32 +0200897};
898
Colin Crossd8611962010-01-28 16:40:29 -0800899/* Clock divider ops */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530900static int tegra20_pll_div_clk_is_enabled(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800901{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530902 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crossd8611962010-01-28 16:40:29 -0800903 u32 val = clk_readl(c->reg);
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530904
Colin Crossd8611962010-01-28 16:40:29 -0800905 val >>= c->reg_shift;
906 c->state = (val & PLL_OUT_CLKEN) ? ON : OFF;
907 if (!(val & PLL_OUT_RESET_DISABLE))
908 c->state = OFF;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530909 return c->state;
910}
911
912static unsigned long tegra20_pll_div_clk_recalc_rate(struct clk_hw *hw,
913 unsigned long prate)
914{
915 struct clk_tegra *c = to_clk_tegra(hw);
916 u64 rate = prate;
917 u32 val = clk_readl(c->reg);
918 u32 divu71;
919
920 val >>= c->reg_shift;
Colin Crossd8611962010-01-28 16:40:29 -0800921
922 if (c->flags & DIV_U71) {
923 divu71 = (val & PLL_OUT_RATIO_MASK) >> PLL_OUT_RATIO_SHIFT;
924 c->div = (divu71 + 2);
925 c->mul = 2;
926 } else if (c->flags & DIV_2) {
927 c->div = 2;
928 c->mul = 1;
929 } else {
930 c->div = 1;
931 c->mul = 1;
932 }
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530933
934 rate *= c->mul;
935 rate += c->div - 1; /* round up */
936 do_div(rate, c->div);
937
938 return rate;
Colin Crossd8611962010-01-28 16:40:29 -0800939}
940
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530941static int tegra20_pll_div_clk_enable(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800942{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530943 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross4729fd72011-02-12 16:43:05 -0800944 unsigned long flags;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530945 u32 new_val;
946 u32 val;
Colin Crossd8611962010-01-28 16:40:29 -0800947
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530948 pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
949
Colin Crossd8611962010-01-28 16:40:29 -0800950 if (c->flags & DIV_U71) {
Colin Cross4729fd72011-02-12 16:43:05 -0800951 spin_lock_irqsave(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -0800952 val = clk_readl(c->reg);
953 new_val = val >> c->reg_shift;
954 new_val &= 0xFFFF;
955
956 new_val |= PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE;
957
958 val &= ~(0xFFFF << c->reg_shift);
959 val |= new_val << c->reg_shift;
960 clk_writel(val, c->reg);
Colin Cross4729fd72011-02-12 16:43:05 -0800961 spin_unlock_irqrestore(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -0800962 return 0;
963 } else if (c->flags & DIV_2) {
964 BUG_ON(!(c->flags & PLLD));
Colin Cross4729fd72011-02-12 16:43:05 -0800965 spin_lock_irqsave(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -0800966 val = clk_readl(c->reg);
967 val &= ~PLLD_MISC_DIV_RST;
968 clk_writel(val, c->reg);
Colin Cross4729fd72011-02-12 16:43:05 -0800969 spin_unlock_irqrestore(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -0800970 return 0;
971 }
972 return -EINVAL;
973}
974
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530975static void tegra20_pll_div_clk_disable(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800976{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530977 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross4729fd72011-02-12 16:43:05 -0800978 unsigned long flags;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530979 u32 new_val;
980 u32 val;
Colin Crossd8611962010-01-28 16:40:29 -0800981
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530982 pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
983
Colin Crossd8611962010-01-28 16:40:29 -0800984 if (c->flags & DIV_U71) {
Colin Cross4729fd72011-02-12 16:43:05 -0800985 spin_lock_irqsave(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -0800986 val = clk_readl(c->reg);
987 new_val = val >> c->reg_shift;
988 new_val &= 0xFFFF;
989
990 new_val &= ~(PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE);
991
992 val &= ~(0xFFFF << c->reg_shift);
993 val |= new_val << c->reg_shift;
994 clk_writel(val, c->reg);
Colin Cross4729fd72011-02-12 16:43:05 -0800995 spin_unlock_irqrestore(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -0800996 } else if (c->flags & DIV_2) {
997 BUG_ON(!(c->flags & PLLD));
Colin Cross4729fd72011-02-12 16:43:05 -0800998 spin_lock_irqsave(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -0800999 val = clk_readl(c->reg);
1000 val |= PLLD_MISC_DIV_RST;
1001 clk_writel(val, c->reg);
Colin Cross4729fd72011-02-12 16:43:05 -08001002 spin_unlock_irqrestore(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -08001003 }
1004}
1005
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301006static int tegra20_pll_div_clk_set_rate(struct clk_hw *hw, unsigned long rate,
1007 unsigned long parent_rate)
Colin Crossd8611962010-01-28 16:40:29 -08001008{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301009 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross4729fd72011-02-12 16:43:05 -08001010 unsigned long flags;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301011 int divider_u71;
1012 u32 new_val;
1013 u32 val;
Colin Cross4729fd72011-02-12 16:43:05 -08001014
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301015 pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate);
1016
Colin Crossd8611962010-01-28 16:40:29 -08001017 if (c->flags & DIV_U71) {
Colin Cross4729fd72011-02-12 16:43:05 -08001018 divider_u71 = clk_div71_get_divider(parent_rate, rate);
Colin Crossd8611962010-01-28 16:40:29 -08001019 if (divider_u71 >= 0) {
Colin Cross4729fd72011-02-12 16:43:05 -08001020 spin_lock_irqsave(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -08001021 val = clk_readl(c->reg);
1022 new_val = val >> c->reg_shift;
1023 new_val &= 0xFFFF;
1024 if (c->flags & DIV_U71_FIXED)
1025 new_val |= PLL_OUT_OVERRIDE;
1026 new_val &= ~PLL_OUT_RATIO_MASK;
1027 new_val |= divider_u71 << PLL_OUT_RATIO_SHIFT;
1028
1029 val &= ~(0xFFFF << c->reg_shift);
1030 val |= new_val << c->reg_shift;
1031 clk_writel(val, c->reg);
1032 c->div = divider_u71 + 2;
1033 c->mul = 2;
Colin Cross4729fd72011-02-12 16:43:05 -08001034 spin_unlock_irqrestore(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -08001035 return 0;
1036 }
1037 } else if (c->flags & DIV_2) {
Colin Cross4729fd72011-02-12 16:43:05 -08001038 if (parent_rate == rate * 2)
Colin Crossd8611962010-01-28 16:40:29 -08001039 return 0;
Colin Crossd8611962010-01-28 16:40:29 -08001040 }
1041 return -EINVAL;
1042}
1043
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301044static long tegra20_pll_div_clk_round_rate(struct clk_hw *hw, unsigned long rate,
1045 unsigned long *prate)
Colin Cross71fc84c2010-06-07 20:49:46 -07001046{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301047 struct clk_tegra *c = to_clk_tegra(hw);
1048 unsigned long parent_rate = *prate;
Colin Cross71fc84c2010-06-07 20:49:46 -07001049 int divider;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301050
1051 pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate);
Colin Cross71fc84c2010-06-07 20:49:46 -07001052
1053 if (c->flags & DIV_U71) {
Colin Cross4729fd72011-02-12 16:43:05 -08001054 divider = clk_div71_get_divider(parent_rate, rate);
Colin Cross71fc84c2010-06-07 20:49:46 -07001055 if (divider < 0)
1056 return divider;
Colin Cross421186e2011-02-12 18:21:47 -08001057 return DIV_ROUND_UP(parent_rate * 2, divider + 2);
Colin Cross71fc84c2010-06-07 20:49:46 -07001058 } else if (c->flags & DIV_2) {
Colin Cross421186e2011-02-12 18:21:47 -08001059 return DIV_ROUND_UP(parent_rate, 2);
Colin Cross71fc84c2010-06-07 20:49:46 -07001060 }
1061 return -EINVAL;
1062}
Colin Crossd8611962010-01-28 16:40:29 -08001063
Prashant Gaikwad86edb872012-08-06 11:57:40 +05301064struct clk_ops tegra_pll_div_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301065 .is_enabled = tegra20_pll_div_clk_is_enabled,
1066 .enable = tegra20_pll_div_clk_enable,
1067 .disable = tegra20_pll_div_clk_disable,
1068 .set_rate = tegra20_pll_div_clk_set_rate,
1069 .round_rate = tegra20_pll_div_clk_round_rate,
1070 .recalc_rate = tegra20_pll_div_clk_recalc_rate,
Colin Crossd8611962010-01-28 16:40:29 -08001071};
1072
1073/* Periph clk ops */
1074
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301075static int tegra20_periph_clk_is_enabled(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -08001076{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301077 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crossd8611962010-01-28 16:40:29 -08001078
1079 c->state = ON;
Colin Cross1be3d052011-02-21 16:44:07 -08001080
1081 if (!c->u.periph.clk_num)
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301082 goto out;
Colin Cross1be3d052011-02-21 16:44:07 -08001083
Colin Crossd8611962010-01-28 16:40:29 -08001084 if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
1085 PERIPH_CLK_TO_ENB_BIT(c)))
1086 c->state = OFF;
Colin Cross1be3d052011-02-21 16:44:07 -08001087
Colin Crossd8611962010-01-28 16:40:29 -08001088 if (!(c->flags & PERIPH_NO_RESET))
1089 if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) &
1090 PERIPH_CLK_TO_ENB_BIT(c))
1091 c->state = OFF;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301092
1093out:
1094 return c->state;
Colin Crossd8611962010-01-28 16:40:29 -08001095}
1096
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301097static int tegra20_periph_clk_enable(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -08001098{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301099 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross78f379b2010-10-20 19:19:58 -07001100 unsigned long flags;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301101 u32 val;
1102
1103 pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
Colin Crossd8611962010-01-28 16:40:29 -08001104
Colin Cross1be3d052011-02-21 16:44:07 -08001105 if (!c->u.periph.clk_num)
1106 return 0;
1107
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301108 tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++;
1109 if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 1)
1110 return 0;
1111
Colin Cross78f379b2010-10-20 19:19:58 -07001112 spin_lock_irqsave(&clock_register_lock, flags);
1113
Colin Crossd8611962010-01-28 16:40:29 -08001114 clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
1115 CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
1116 if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET))
1117 clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
1118 RST_DEVICES_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
1119 if (c->flags & PERIPH_EMC_ENB) {
1120 /* The EMC peripheral clock has 2 extra enable bits */
1121 /* FIXME: Do they need to be disabled? */
1122 val = clk_readl(c->reg);
1123 val |= 0x3 << 24;
1124 clk_writel(val, c->reg);
1125 }
Colin Cross78f379b2010-10-20 19:19:58 -07001126
Colin Cross78f379b2010-10-20 19:19:58 -07001127 spin_unlock_irqrestore(&clock_register_lock, flags);
1128
Colin Crossd8611962010-01-28 16:40:29 -08001129 return 0;
1130}
1131
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301132static void tegra20_periph_clk_disable(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -08001133{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301134 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross78f379b2010-10-20 19:19:58 -07001135 unsigned long flags;
1136
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301137 pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
Colin Crossd8611962010-01-28 16:40:29 -08001138
Colin Cross1be3d052011-02-21 16:44:07 -08001139 if (!c->u.periph.clk_num)
1140 return;
1141
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301142 tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--;
1143
1144 if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 0)
1145 return;
1146
Colin Cross78f379b2010-10-20 19:19:58 -07001147 spin_lock_irqsave(&clock_register_lock, flags);
1148
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301149 clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
1150 CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
Colin Cross78f379b2010-10-20 19:19:58 -07001151
1152 spin_unlock_irqrestore(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -08001153}
1154
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301155void tegra2_periph_clk_reset(struct clk_hw *hw, bool assert)
Colin Crossd8611962010-01-28 16:40:29 -08001156{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301157 struct clk_tegra *c = to_clk_tegra(hw);
Dima Zavin2b84cb4f2010-09-02 19:11:11 -07001158 unsigned long base = assert ? RST_DEVICES_SET : RST_DEVICES_CLR;
1159
1160 pr_debug("%s %s on clock %s\n", __func__,
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301161 assert ? "assert" : "deassert", __clk_get_name(hw->clk));
Colin Cross1be3d052011-02-21 16:44:07 -08001162
1163 BUG_ON(!c->u.periph.clk_num);
1164
Colin Crossd8611962010-01-28 16:40:29 -08001165 if (!(c->flags & PERIPH_NO_RESET))
1166 clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
Dima Zavin2b84cb4f2010-09-02 19:11:11 -07001167 base + PERIPH_CLK_TO_ENB_SET_REG(c));
Colin Crossd8611962010-01-28 16:40:29 -08001168}
1169
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301170static int tegra20_periph_clk_set_parent(struct clk_hw *hw, u8 index)
Colin Crossd8611962010-01-28 16:40:29 -08001171{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301172 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crossd8611962010-01-28 16:40:29 -08001173 u32 val;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301174 u32 mask;
1175 u32 shift;
Simon Quebb1dccf2011-12-16 20:11:22 +01001176
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301177 pr_debug("%s: %s %d\n", __func__, __clk_get_name(hw->clk), index);
Simon Quebb1dccf2011-12-16 20:11:22 +01001178
1179 if (c->flags & MUX_PWM) {
1180 shift = PERIPH_CLK_SOURCE_PWM_SHIFT;
1181 mask = PERIPH_CLK_SOURCE_PWM_MASK;
1182 } else {
1183 shift = PERIPH_CLK_SOURCE_SHIFT;
1184 mask = PERIPH_CLK_SOURCE_MASK;
1185 }
1186
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301187 val = clk_readl(c->reg);
1188 val &= ~mask;
1189 val |= (index) << shift;
Colin Cross71fc84c2010-06-07 20:49:46 -07001190
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301191 clk_writel(val, c->reg);
Colin Cross71fc84c2010-06-07 20:49:46 -07001192
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301193 return 0;
Colin Crossd8611962010-01-28 16:40:29 -08001194}
1195
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301196static u8 tegra20_periph_clk_get_parent(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -08001197{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301198 struct clk_tegra *c = to_clk_tegra(hw);
1199 u32 val = clk_readl(c->reg);
1200 u32 mask;
1201 u32 shift;
1202
1203 if (c->flags & MUX_PWM) {
1204 shift = PERIPH_CLK_SOURCE_PWM_SHIFT;
1205 mask = PERIPH_CLK_SOURCE_PWM_MASK;
1206 } else {
1207 shift = PERIPH_CLK_SOURCE_SHIFT;
1208 mask = PERIPH_CLK_SOURCE_MASK;
1209 }
1210
1211 if (c->flags & MUX)
1212 return (val & mask) >> shift;
1213 else
1214 return 0;
1215}
1216
1217static unsigned long tegra20_periph_clk_recalc_rate(struct clk_hw *hw,
1218 unsigned long prate)
1219{
1220 struct clk_tegra *c = to_clk_tegra(hw);
1221 unsigned long rate = prate;
1222 u32 val = clk_readl(c->reg);
1223
1224 if (c->flags & DIV_U71) {
1225 u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK;
1226 c->div = divu71 + 2;
1227 c->mul = 2;
1228 } else if (c->flags & DIV_U16) {
1229 u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK;
1230 c->div = divu16 + 1;
1231 c->mul = 1;
1232 } else {
1233 c->div = 1;
1234 c->mul = 1;
1235 return rate;
1236 }
1237
1238 if (c->mul != 0 && c->div != 0) {
1239 rate *= c->mul;
1240 rate += c->div - 1; /* round up */
1241 do_div(rate, c->div);
1242 }
1243
1244 return rate;
1245}
1246
1247static int tegra20_periph_clk_set_rate(struct clk_hw *hw, unsigned long rate,
1248 unsigned long parent_rate)
1249{
1250 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crossd8611962010-01-28 16:40:29 -08001251 u32 val;
Colin Cross71fc84c2010-06-07 20:49:46 -07001252 int divider;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301253
1254 val = clk_readl(c->reg);
Colin Cross4729fd72011-02-12 16:43:05 -08001255
Colin Crossd8611962010-01-28 16:40:29 -08001256 if (c->flags & DIV_U71) {
Colin Cross4729fd72011-02-12 16:43:05 -08001257 divider = clk_div71_get_divider(parent_rate, rate);
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301258
Colin Cross71fc84c2010-06-07 20:49:46 -07001259 if (divider >= 0) {
Colin Crossd8611962010-01-28 16:40:29 -08001260 val = clk_readl(c->reg);
Colin Cross71fc84c2010-06-07 20:49:46 -07001261 val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK;
1262 val |= divider;
Colin Crossd8611962010-01-28 16:40:29 -08001263 clk_writel(val, c->reg);
Colin Cross71fc84c2010-06-07 20:49:46 -07001264 c->div = divider + 2;
Colin Crossd8611962010-01-28 16:40:29 -08001265 c->mul = 2;
Colin Crossd8611962010-01-28 16:40:29 -08001266 return 0;
1267 }
Colin Cross71fc84c2010-06-07 20:49:46 -07001268 } else if (c->flags & DIV_U16) {
Colin Cross4729fd72011-02-12 16:43:05 -08001269 divider = clk_div16_get_divider(parent_rate, rate);
Colin Cross71fc84c2010-06-07 20:49:46 -07001270 if (divider >= 0) {
1271 val = clk_readl(c->reg);
1272 val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK;
1273 val |= divider;
1274 clk_writel(val, c->reg);
1275 c->div = divider + 1;
1276 c->mul = 1;
1277 return 0;
1278 }
Colin Cross4729fd72011-02-12 16:43:05 -08001279 } else if (parent_rate <= rate) {
Colin Cross71fc84c2010-06-07 20:49:46 -07001280 c->div = 1;
1281 c->mul = 1;
1282 return 0;
1283 }
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301284
Colin Cross71fc84c2010-06-07 20:49:46 -07001285 return -EINVAL;
1286}
1287
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301288static long tegra20_periph_clk_round_rate(struct clk_hw *hw,
1289 unsigned long rate, unsigned long *prate)
Colin Cross71fc84c2010-06-07 20:49:46 -07001290{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301291 struct clk_tegra *c = to_clk_tegra(hw);
1292 unsigned long parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
Colin Cross71fc84c2010-06-07 20:49:46 -07001293 int divider;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301294
1295 pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate);
1296
1297 if (prate)
1298 parent_rate = *prate;
Colin Cross71fc84c2010-06-07 20:49:46 -07001299
1300 if (c->flags & DIV_U71) {
Colin Cross4729fd72011-02-12 16:43:05 -08001301 divider = clk_div71_get_divider(parent_rate, rate);
Colin Cross71fc84c2010-06-07 20:49:46 -07001302 if (divider < 0)
1303 return divider;
1304
Colin Cross421186e2011-02-12 18:21:47 -08001305 return DIV_ROUND_UP(parent_rate * 2, divider + 2);
Colin Cross71fc84c2010-06-07 20:49:46 -07001306 } else if (c->flags & DIV_U16) {
Colin Cross4729fd72011-02-12 16:43:05 -08001307 divider = clk_div16_get_divider(parent_rate, rate);
Colin Cross71fc84c2010-06-07 20:49:46 -07001308 if (divider < 0)
1309 return divider;
Colin Cross421186e2011-02-12 18:21:47 -08001310 return DIV_ROUND_UP(parent_rate, divider + 1);
Colin Crossd8611962010-01-28 16:40:29 -08001311 }
1312 return -EINVAL;
1313}
1314
Prashant Gaikwad86edb872012-08-06 11:57:40 +05301315struct clk_ops tegra_periph_clk_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301316 .is_enabled = tegra20_periph_clk_is_enabled,
1317 .enable = tegra20_periph_clk_enable,
1318 .disable = tegra20_periph_clk_disable,
1319 .set_parent = tegra20_periph_clk_set_parent,
1320 .get_parent = tegra20_periph_clk_get_parent,
1321 .set_rate = tegra20_periph_clk_set_rate,
1322 .round_rate = tegra20_periph_clk_round_rate,
1323 .recalc_rate = tegra20_periph_clk_recalc_rate,
Colin Crossd8611962010-01-28 16:40:29 -08001324};
1325
Colin Cross6d296822010-11-22 18:37:54 -08001326/* External memory controller clock ops */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301327static void tegra20_emc_clk_init(struct clk_hw *hw)
Colin Cross6d296822010-11-22 18:37:54 -08001328{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301329 struct clk_tegra *c = to_clk_tegra(hw);
1330 c->max_rate = __clk_get_rate(hw->clk);
Colin Cross6d296822010-11-22 18:37:54 -08001331}
1332
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301333static long tegra20_emc_clk_round_rate(struct clk_hw *hw, unsigned long rate,
1334 unsigned long *prate)
Colin Cross6d296822010-11-22 18:37:54 -08001335{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301336 struct clk_tegra *c = to_clk_tegra(hw);
Stephen Warrene186ad72012-02-06 17:09:15 -08001337 long emc_rate;
1338 long clk_rate;
Colin Cross6d296822010-11-22 18:37:54 -08001339
Stephen Warrene186ad72012-02-06 17:09:15 -08001340 /*
1341 * The slowest entry in the EMC clock table that is at least as
1342 * fast as rate.
1343 */
1344 emc_rate = tegra_emc_round_rate(rate);
1345 if (emc_rate < 0)
Colin Cross6d296822010-11-22 18:37:54 -08001346 return c->max_rate;
1347
Stephen Warrene186ad72012-02-06 17:09:15 -08001348 /*
1349 * The fastest rate the PLL will generate that is at most the
1350 * requested rate.
1351 */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301352 clk_rate = tegra20_periph_clk_round_rate(hw, emc_rate, NULL);
Colin Cross6d296822010-11-22 18:37:54 -08001353
Stephen Warrene186ad72012-02-06 17:09:15 -08001354 /*
1355 * If this fails, and emc_rate > clk_rate, it's because the maximum
1356 * rate in the EMC tables is larger than the maximum rate of the EMC
1357 * clock. The EMC clock's max rate is the rate it was running when the
1358 * kernel booted. Such a mismatch is probably due to using the wrong
1359 * BCT, i.e. using a Tegra20 BCT with an EMC table written for Tegra25.
1360 */
1361 WARN_ONCE(emc_rate != clk_rate,
1362 "emc_rate %ld != clk_rate %ld",
1363 emc_rate, clk_rate);
1364
1365 return emc_rate;
Colin Cross6d296822010-11-22 18:37:54 -08001366}
1367
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301368static int tegra20_emc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
1369 unsigned long parent_rate)
Colin Cross6d296822010-11-22 18:37:54 -08001370{
1371 int ret;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301372
Colin Cross6d296822010-11-22 18:37:54 -08001373 /*
1374 * The Tegra2 memory controller has an interlock with the clock
1375 * block that allows memory shadowed registers to be updated,
1376 * and then transfer them to the main registers at the same
1377 * time as the clock update without glitches.
1378 */
1379 ret = tegra_emc_set_rate(rate);
1380 if (ret < 0)
1381 return ret;
1382
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301383 ret = tegra20_periph_clk_set_rate(hw, rate, parent_rate);
Colin Cross6d296822010-11-22 18:37:54 -08001384 udelay(1);
1385
1386 return ret;
1387}
1388
Prashant Gaikwad86edb872012-08-06 11:57:40 +05301389struct clk_ops tegra_emc_clk_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301390 .init = tegra20_emc_clk_init,
1391 .is_enabled = tegra20_periph_clk_is_enabled,
1392 .enable = tegra20_periph_clk_enable,
1393 .disable = tegra20_periph_clk_disable,
1394 .set_parent = tegra20_periph_clk_set_parent,
1395 .get_parent = tegra20_periph_clk_get_parent,
1396 .set_rate = tegra20_emc_clk_set_rate,
1397 .round_rate = tegra20_emc_clk_round_rate,
1398 .recalc_rate = tegra20_periph_clk_recalc_rate,
Colin Cross6d296822010-11-22 18:37:54 -08001399};
1400
Colin Crossd8611962010-01-28 16:40:29 -08001401/* Clock doubler ops */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301402static int tegra20_clk_double_is_enabled(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -08001403{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301404 struct clk_tegra *c = to_clk_tegra(hw);
1405
Colin Crossd8611962010-01-28 16:40:29 -08001406 c->state = ON;
Colin Cross1be3d052011-02-21 16:44:07 -08001407
1408 if (!c->u.periph.clk_num)
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301409 goto out;
Colin Cross1be3d052011-02-21 16:44:07 -08001410
Colin Crossd8611962010-01-28 16:40:29 -08001411 if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
1412 PERIPH_CLK_TO_ENB_BIT(c)))
1413 c->state = OFF;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301414
1415out:
1416 return c->state;
Colin Crossd8611962010-01-28 16:40:29 -08001417};
1418
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301419static unsigned long tegra20_clk_double_recalc_rate(struct clk_hw *hw,
1420 unsigned long prate)
Colin Cross71fc84c2010-06-07 20:49:46 -07001421{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301422 struct clk_tegra *c = to_clk_tegra(hw);
1423 u64 rate = prate;
1424
Colin Cross71fc84c2010-06-07 20:49:46 -07001425 c->mul = 2;
1426 c->div = 1;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301427
1428 rate *= c->mul;
1429 rate += c->div - 1; /* round up */
1430 do_div(rate, c->div);
1431
1432 return rate;
1433}
1434
1435static long tegra20_clk_double_round_rate(struct clk_hw *hw, unsigned long rate,
1436 unsigned long *prate)
1437{
1438 unsigned long output_rate = *prate;
1439
1440 do_div(output_rate, 2);
1441 return output_rate;
1442}
1443
1444static int tegra20_clk_double_set_rate(struct clk_hw *hw, unsigned long rate,
1445 unsigned long parent_rate)
1446{
1447 if (rate != 2 * parent_rate)
1448 return -EINVAL;
Colin Cross71fc84c2010-06-07 20:49:46 -07001449 return 0;
1450}
1451
Prashant Gaikwad86edb872012-08-06 11:57:40 +05301452struct clk_ops tegra_clk_double_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301453 .is_enabled = tegra20_clk_double_is_enabled,
1454 .enable = tegra20_periph_clk_enable,
1455 .disable = tegra20_periph_clk_disable,
1456 .set_rate = tegra20_clk_double_set_rate,
1457 .recalc_rate = tegra20_clk_double_recalc_rate,
1458 .round_rate = tegra20_clk_double_round_rate,
Colin Cross71fc84c2010-06-07 20:49:46 -07001459};
1460
Colin Crosscea62c82010-10-04 11:49:26 -07001461/* Audio sync clock ops */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301462static int tegra20_audio_sync_clk_is_enabled(struct clk_hw *hw)
Colin Cross71fc84c2010-06-07 20:49:46 -07001463{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301464 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross71fc84c2010-06-07 20:49:46 -07001465 u32 val = clk_readl(c->reg);
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301466
Colin Cross71fc84c2010-06-07 20:49:46 -07001467 c->state = (val & (1<<4)) ? OFF : ON;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301468 return c->state;
Colin Cross71fc84c2010-06-07 20:49:46 -07001469}
1470
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301471static int tegra20_audio_sync_clk_enable(struct clk_hw *hw)
Colin Cross71fc84c2010-06-07 20:49:46 -07001472{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301473 struct clk_tegra *c = to_clk_tegra(hw);
1474
Colin Cross71fc84c2010-06-07 20:49:46 -07001475 clk_writel(0, c->reg);
1476 return 0;
1477}
1478
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301479static void tegra20_audio_sync_clk_disable(struct clk_hw *hw)
Colin Cross71fc84c2010-06-07 20:49:46 -07001480{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301481 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross71fc84c2010-06-07 20:49:46 -07001482 clk_writel(1, c->reg);
1483}
1484
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301485static u8 tegra20_audio_sync_clk_get_parent(struct clk_hw *hw)
Colin Cross71fc84c2010-06-07 20:49:46 -07001486{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301487 struct clk_tegra *c = to_clk_tegra(hw);
1488 u32 val = clk_readl(c->reg);
1489 int source;
1490
1491 source = val & 0xf;
1492 return source;
1493}
1494
1495static int tegra20_audio_sync_clk_set_parent(struct clk_hw *hw, u8 index)
1496{
1497 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross71fc84c2010-06-07 20:49:46 -07001498 u32 val;
Colin Cross71fc84c2010-06-07 20:49:46 -07001499
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301500 val = clk_readl(c->reg);
1501 val &= ~0xf;
1502 val |= index;
Colin Cross71fc84c2010-06-07 20:49:46 -07001503
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301504 clk_writel(val, c->reg);
Colin Cross71fc84c2010-06-07 20:49:46 -07001505
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301506 return 0;
Colin Cross71fc84c2010-06-07 20:49:46 -07001507}
1508
Prashant Gaikwad86edb872012-08-06 11:57:40 +05301509struct clk_ops tegra_audio_sync_clk_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301510 .is_enabled = tegra20_audio_sync_clk_is_enabled,
1511 .enable = tegra20_audio_sync_clk_enable,
1512 .disable = tegra20_audio_sync_clk_disable,
1513 .set_parent = tegra20_audio_sync_clk_set_parent,
1514 .get_parent = tegra20_audio_sync_clk_get_parent,
Colin Crossd8611962010-01-28 16:40:29 -08001515};
1516
Colin Crosscea62c82010-10-04 11:49:26 -07001517/* cdev1 and cdev2 (dap_mclk1 and dap_mclk2) ops */
1518
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301519static int tegra20_cdev_clk_is_enabled(struct clk_hw *hw)
Colin Crosscea62c82010-10-04 11:49:26 -07001520{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301521 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crosscea62c82010-10-04 11:49:26 -07001522 /* We could un-tristate the cdev1 or cdev2 pingroup here; this is
1523 * currently done in the pinmux code. */
1524 c->state = ON;
Colin Cross1be3d052011-02-21 16:44:07 -08001525
1526 BUG_ON(!c->u.periph.clk_num);
1527
Colin Crosscea62c82010-10-04 11:49:26 -07001528 if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
1529 PERIPH_CLK_TO_ENB_BIT(c)))
1530 c->state = OFF;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301531 return c->state;
Colin Crosscea62c82010-10-04 11:49:26 -07001532}
1533
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301534static int tegra20_cdev_clk_enable(struct clk_hw *hw)
Colin Crosscea62c82010-10-04 11:49:26 -07001535{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301536 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross1be3d052011-02-21 16:44:07 -08001537 BUG_ON(!c->u.periph.clk_num);
1538
Colin Crosscea62c82010-10-04 11:49:26 -07001539 clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
1540 CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
1541 return 0;
1542}
1543
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301544static void tegra20_cdev_clk_disable(struct clk_hw *hw)
Colin Crosscea62c82010-10-04 11:49:26 -07001545{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301546 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross1be3d052011-02-21 16:44:07 -08001547 BUG_ON(!c->u.periph.clk_num);
1548
Colin Crosscea62c82010-10-04 11:49:26 -07001549 clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
1550 CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
1551}
1552
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301553static unsigned long tegra20_cdev_recalc_rate(struct clk_hw *hw,
1554 unsigned long prate)
1555{
1556 return to_clk_tegra(hw)->fixed_rate;
1557}
1558
Prashant Gaikwad86edb872012-08-06 11:57:40 +05301559struct clk_ops tegra_cdev_clk_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301560 .is_enabled = tegra20_cdev_clk_is_enabled,
1561 .enable = tegra20_cdev_clk_enable,
1562 .disable = tegra20_cdev_clk_disable,
1563 .recalc_rate = tegra20_cdev_recalc_rate,
Colin Cross310992c2011-02-12 16:14:03 -08001564};
Joseph Lodab403e2012-08-16 17:31:48 +08001565
1566/* Tegra20 CPU clock and reset control functions */
1567static void tegra20_wait_cpu_in_reset(u32 cpu)
1568{
1569 unsigned int reg;
1570
1571 do {
1572 reg = readl(reg_clk_base +
1573 TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
1574 cpu_relax();
1575 } while (!(reg & (1 << cpu))); /* check CPU been reset or not */
1576
1577 return;
1578}
1579
1580static void tegra20_put_cpu_in_reset(u32 cpu)
1581{
1582 writel(CPU_RESET(cpu),
1583 reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
1584 dmb();
1585}
1586
1587static void tegra20_cpu_out_of_reset(u32 cpu)
1588{
1589 writel(CPU_RESET(cpu),
1590 reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
1591 wmb();
1592}
1593
1594static void tegra20_enable_cpu_clock(u32 cpu)
1595{
1596 unsigned int reg;
1597
1598 reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
1599 writel(reg & ~CPU_CLOCK(cpu),
1600 reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
1601 barrier();
1602 reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
1603}
1604
1605static void tegra20_disable_cpu_clock(u32 cpu)
1606{
1607 unsigned int reg;
1608
1609 reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
1610 writel(reg | CPU_CLOCK(cpu),
1611 reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
1612}
1613
1614static struct tegra_cpu_car_ops tegra20_cpu_car_ops = {
1615 .wait_for_reset = tegra20_wait_cpu_in_reset,
1616 .put_in_reset = tegra20_put_cpu_in_reset,
1617 .out_of_reset = tegra20_cpu_out_of_reset,
1618 .enable_clock = tegra20_enable_cpu_clock,
1619 .disable_clock = tegra20_disable_cpu_clock,
1620};
1621
1622void __init tegra20_cpu_car_ops_init(void)
1623{
1624 tegra_cpu_car_ops = &tegra20_cpu_car_ops;
1625}