blob: a1e0f8a26b3dad42ad3f7eeb9015573664b8fe14 [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"
Colin Crossd8611962010-01-28 16:40:29 -080036
37#define RST_DEVICES 0x004
38#define RST_DEVICES_SET 0x300
39#define RST_DEVICES_CLR 0x304
Colin Cross71fc84c2010-06-07 20:49:46 -070040#define RST_DEVICES_NUM 3
Colin Crossd8611962010-01-28 16:40:29 -080041
42#define CLK_OUT_ENB 0x010
43#define CLK_OUT_ENB_SET 0x320
44#define CLK_OUT_ENB_CLR 0x324
Colin Cross71fc84c2010-06-07 20:49:46 -070045#define CLK_OUT_ENB_NUM 3
46
47#define CLK_MASK_ARM 0x44
48#define MISC_CLK_ENB 0x48
Colin Crossd8611962010-01-28 16:40:29 -080049
50#define OSC_CTRL 0x50
51#define OSC_CTRL_OSC_FREQ_MASK (3<<30)
52#define OSC_CTRL_OSC_FREQ_13MHZ (0<<30)
53#define OSC_CTRL_OSC_FREQ_19_2MHZ (1<<30)
54#define OSC_CTRL_OSC_FREQ_12MHZ (2<<30)
55#define OSC_CTRL_OSC_FREQ_26MHZ (3<<30)
Colin Crosscea62c82010-10-04 11:49:26 -070056#define OSC_CTRL_MASK (0x3f2 | OSC_CTRL_OSC_FREQ_MASK)
Colin Crossd8611962010-01-28 16:40:29 -080057
58#define OSC_FREQ_DET 0x58
59#define OSC_FREQ_DET_TRIG (1<<31)
60
61#define OSC_FREQ_DET_STATUS 0x5C
62#define OSC_FREQ_DET_BUSY (1<<31)
63#define OSC_FREQ_DET_CNT_MASK 0xFFFF
64
Colin Cross71fc84c2010-06-07 20:49:46 -070065#define PERIPH_CLK_SOURCE_I2S1 0x100
66#define PERIPH_CLK_SOURCE_EMC 0x19c
67#define PERIPH_CLK_SOURCE_OSC 0x1fc
68#define PERIPH_CLK_SOURCE_NUM \
69 ((PERIPH_CLK_SOURCE_OSC - PERIPH_CLK_SOURCE_I2S1) / 4)
70
Colin Crossd8611962010-01-28 16:40:29 -080071#define PERIPH_CLK_SOURCE_MASK (3<<30)
72#define PERIPH_CLK_SOURCE_SHIFT 30
Simon Quebb1dccf2011-12-16 20:11:22 +010073#define PERIPH_CLK_SOURCE_PWM_MASK (7<<28)
74#define PERIPH_CLK_SOURCE_PWM_SHIFT 28
Colin Crossd8611962010-01-28 16:40:29 -080075#define PERIPH_CLK_SOURCE_ENABLE (1<<28)
Colin Cross71fc84c2010-06-07 20:49:46 -070076#define PERIPH_CLK_SOURCE_DIVU71_MASK 0xFF
77#define PERIPH_CLK_SOURCE_DIVU16_MASK 0xFFFF
Colin Crossd8611962010-01-28 16:40:29 -080078#define PERIPH_CLK_SOURCE_DIV_SHIFT 0
79
Colin Cross9743b382011-02-12 18:24:32 -080080#define SDMMC_CLK_INT_FB_SEL (1 << 23)
81#define SDMMC_CLK_INT_FB_DLY_SHIFT 16
82#define SDMMC_CLK_INT_FB_DLY_MASK (0xF << SDMMC_CLK_INT_FB_DLY_SHIFT)
83
Colin Crossd8611962010-01-28 16:40:29 -080084#define PLL_BASE 0x0
85#define PLL_BASE_BYPASS (1<<31)
86#define PLL_BASE_ENABLE (1<<30)
87#define PLL_BASE_REF_ENABLE (1<<29)
88#define PLL_BASE_OVERRIDE (1<<28)
Colin Crossd8611962010-01-28 16:40:29 -080089#define PLL_BASE_DIVP_MASK (0x7<<20)
90#define PLL_BASE_DIVP_SHIFT 20
91#define PLL_BASE_DIVN_MASK (0x3FF<<8)
92#define PLL_BASE_DIVN_SHIFT 8
93#define PLL_BASE_DIVM_MASK (0x1F)
94#define PLL_BASE_DIVM_SHIFT 0
95
96#define PLL_OUT_RATIO_MASK (0xFF<<8)
97#define PLL_OUT_RATIO_SHIFT 8
98#define PLL_OUT_OVERRIDE (1<<2)
99#define PLL_OUT_CLKEN (1<<1)
100#define PLL_OUT_RESET_DISABLE (1<<0)
101
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530102#define PLL_MISC(c) (((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc)
Colin Cross71fc84c2010-06-07 20:49:46 -0700103
Colin Crossd8611962010-01-28 16:40:29 -0800104#define PLL_MISC_DCCON_SHIFT 20
Colin Crossd8611962010-01-28 16:40:29 -0800105#define PLL_MISC_CPCON_SHIFT 8
106#define PLL_MISC_CPCON_MASK (0xF<<PLL_MISC_CPCON_SHIFT)
107#define PLL_MISC_LFCON_SHIFT 4
108#define PLL_MISC_LFCON_MASK (0xF<<PLL_MISC_LFCON_SHIFT)
109#define PLL_MISC_VCOCON_SHIFT 0
110#define PLL_MISC_VCOCON_MASK (0xF<<PLL_MISC_VCOCON_SHIFT)
111
Colin Cross71fc84c2010-06-07 20:49:46 -0700112#define PLLU_BASE_POST_DIV (1<<20)
113
Colin Crossd8611962010-01-28 16:40:29 -0800114#define PLLD_MISC_CLKENABLE (1<<30)
115#define PLLD_MISC_DIV_RST (1<<23)
116#define PLLD_MISC_DCCON_SHIFT 12
117
Mike Rapoport8d685bc2010-09-27 11:26:32 +0200118#define PLLE_MISC_READY (1 << 15)
119
Colin Crossf1519612011-02-12 16:05:31 -0800120#define PERIPH_CLK_TO_ENB_REG(c) ((c->u.periph.clk_num / 32) * 4)
121#define PERIPH_CLK_TO_ENB_SET_REG(c) ((c->u.periph.clk_num / 32) * 8)
122#define PERIPH_CLK_TO_ENB_BIT(c) (1 << (c->u.periph.clk_num % 32))
Colin Crossd8611962010-01-28 16:40:29 -0800123
124#define SUPER_CLK_MUX 0x00
125#define SUPER_STATE_SHIFT 28
126#define SUPER_STATE_MASK (0xF << SUPER_STATE_SHIFT)
127#define SUPER_STATE_STANDBY (0x0 << SUPER_STATE_SHIFT)
128#define SUPER_STATE_IDLE (0x1 << SUPER_STATE_SHIFT)
129#define SUPER_STATE_RUN (0x2 << SUPER_STATE_SHIFT)
130#define SUPER_STATE_IRQ (0x3 << SUPER_STATE_SHIFT)
131#define SUPER_STATE_FIQ (0x4 << SUPER_STATE_SHIFT)
132#define SUPER_SOURCE_MASK 0xF
133#define SUPER_FIQ_SOURCE_SHIFT 12
134#define SUPER_IRQ_SOURCE_SHIFT 8
135#define SUPER_RUN_SOURCE_SHIFT 4
136#define SUPER_IDLE_SOURCE_SHIFT 0
137
138#define SUPER_CLK_DIVIDER 0x04
139
140#define BUS_CLK_DISABLE (1<<3)
141#define BUS_CLK_DIV_MASK 0x3
142
Colin Crosscea62c82010-10-04 11:49:26 -0700143#define PMC_CTRL 0x0
144 #define PMC_CTRL_BLINK_ENB (1 << 7)
145
146#define PMC_DPD_PADS_ORIDE 0x1c
147 #define PMC_DPD_PADS_ORIDE_BLINK_ENB (1 << 20)
148
149#define PMC_BLINK_TIMER_DATA_ON_SHIFT 0
150#define PMC_BLINK_TIMER_DATA_ON_MASK 0x7fff
151#define PMC_BLINK_TIMER_ENB (1 << 15)
152#define PMC_BLINK_TIMER_DATA_OFF_SHIFT 16
153#define PMC_BLINK_TIMER_DATA_OFF_MASK 0xffff
154
Colin Crossd8611962010-01-28 16:40:29 -0800155static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
Colin Crosscea62c82010-10-04 11:49:26 -0700156static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
Colin Crossd8611962010-01-28 16:40:29 -0800157
Colin Cross4729fd72011-02-12 16:43:05 -0800158/*
159 * Some clocks share a register with other clocks. Any clock op that
160 * non-atomically modifies a register used by another clock must lock
161 * clock_register_lock first.
162 */
163static DEFINE_SPINLOCK(clock_register_lock);
164
Colin Cross78f379b2010-10-20 19:19:58 -0700165/*
166 * Some peripheral clocks share an enable bit, so refcount the enable bits
167 * in registers CLK_ENABLE_L, CLK_ENABLE_H, and CLK_ENABLE_U
168 */
169static int tegra_periph_clk_enable_refcount[3 * 32];
170
Colin Crossd8611962010-01-28 16:40:29 -0800171#define clk_writel(value, reg) \
Olof Johanssond3959352011-09-08 17:56:59 -0700172 __raw_writel(value, reg_clk_base + (reg))
Colin Crossd8611962010-01-28 16:40:29 -0800173#define clk_readl(reg) \
Olof Johanssond3959352011-09-08 17:56:59 -0700174 __raw_readl(reg_clk_base + (reg))
Colin Crosscea62c82010-10-04 11:49:26 -0700175#define pmc_writel(value, reg) \
Olof Johanssond3959352011-09-08 17:56:59 -0700176 __raw_writel(value, reg_pmc_base + (reg))
Colin Crosscea62c82010-10-04 11:49:26 -0700177#define pmc_readl(reg) \
Olof Johanssond3959352011-09-08 17:56:59 -0700178 __raw_readl(reg_pmc_base + (reg))
Colin Crossd8611962010-01-28 16:40:29 -0800179
Peter De Schrijver8e4fab22011-12-14 17:03:16 +0200180static unsigned long clk_measure_input_freq(void)
Colin Crossd8611962010-01-28 16:40:29 -0800181{
182 u32 clock_autodetect;
183 clk_writel(OSC_FREQ_DET_TRIG | 1, OSC_FREQ_DET);
184 do {} while (clk_readl(OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY);
185 clock_autodetect = clk_readl(OSC_FREQ_DET_STATUS);
186 if (clock_autodetect >= 732 - 3 && clock_autodetect <= 732 + 3) {
187 return 12000000;
188 } else if (clock_autodetect >= 794 - 3 && clock_autodetect <= 794 + 3) {
189 return 13000000;
190 } else if (clock_autodetect >= 1172 - 3 && clock_autodetect <= 1172 + 3) {
191 return 19200000;
192 } else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3) {
193 return 26000000;
194 } else {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530195 pr_err("%s: Unexpected clock autodetect value %d",
196 __func__, clock_autodetect);
Colin Crossd8611962010-01-28 16:40:29 -0800197 BUG();
198 return 0;
199 }
200}
201
Colin Cross71fc84c2010-06-07 20:49:46 -0700202static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate)
Colin Crossd8611962010-01-28 16:40:29 -0800203{
Colin Cross71fc84c2010-06-07 20:49:46 -0700204 s64 divider_u71 = parent_rate * 2;
205 divider_u71 += rate - 1;
206 do_div(divider_u71, rate);
Colin Crossd8611962010-01-28 16:40:29 -0800207
Colin Cross71fc84c2010-06-07 20:49:46 -0700208 if (divider_u71 - 2 < 0)
209 return 0;
Colin Crossd8611962010-01-28 16:40:29 -0800210
Colin Cross71fc84c2010-06-07 20:49:46 -0700211 if (divider_u71 - 2 > 255)
Colin Crossd8611962010-01-28 16:40:29 -0800212 return -EINVAL;
213
214 return divider_u71 - 2;
215}
216
Colin Cross71fc84c2010-06-07 20:49:46 -0700217static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate)
Colin Crossd8611962010-01-28 16:40:29 -0800218{
Colin Cross71fc84c2010-06-07 20:49:46 -0700219 s64 divider_u16;
Colin Crossd8611962010-01-28 16:40:29 -0800220
Colin Cross71fc84c2010-06-07 20:49:46 -0700221 divider_u16 = parent_rate;
222 divider_u16 += rate - 1;
223 do_div(divider_u16, rate);
224
225 if (divider_u16 - 1 < 0)
226 return 0;
227
Stephen Warreneb70e1b2012-07-24 15:48:12 -0600228 if (divider_u16 - 1 > 0xFFFF)
Colin Cross71fc84c2010-06-07 20:49:46 -0700229 return -EINVAL;
230
231 return divider_u16 - 1;
Colin Crossd8611962010-01-28 16:40:29 -0800232}
233
Colin Crossd8611962010-01-28 16:40:29 -0800234/* clk_m functions */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530235static unsigned long tegra20_clk_m_recalc_rate(struct clk_hw *hw,
236 unsigned long prate)
Colin Crossd8611962010-01-28 16:40:29 -0800237{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530238 if (!to_clk_tegra(hw)->fixed_rate)
239 to_clk_tegra(hw)->fixed_rate = clk_measure_input_freq();
240 return to_clk_tegra(hw)->fixed_rate;
241}
Colin Crossd8611962010-01-28 16:40:29 -0800242
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530243static void tegra20_clk_m_init(struct clk_hw *hw)
244{
245 struct clk_tegra *c = to_clk_tegra(hw);
246 u32 osc_ctrl = clk_readl(OSC_CTRL);
247 u32 auto_clock_control = osc_ctrl & ~OSC_CTRL_OSC_FREQ_MASK;
248
249 switch (c->fixed_rate) {
Colin Crossd8611962010-01-28 16:40:29 -0800250 case 12000000:
251 auto_clock_control |= OSC_CTRL_OSC_FREQ_12MHZ;
252 break;
253 case 13000000:
254 auto_clock_control |= OSC_CTRL_OSC_FREQ_13MHZ;
255 break;
256 case 19200000:
257 auto_clock_control |= OSC_CTRL_OSC_FREQ_19_2MHZ;
258 break;
259 case 26000000:
260 auto_clock_control |= OSC_CTRL_OSC_FREQ_26MHZ;
261 break;
262 default:
Colin Crossd8611962010-01-28 16:40:29 -0800263 BUG();
264 }
265 clk_writel(auto_clock_control, OSC_CTRL);
Colin Crossd8611962010-01-28 16:40:29 -0800266}
267
Prashant Gaikwad86edb872012-08-06 11:57:40 +0530268struct clk_ops tegra_clk_m_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530269 .init = tegra20_clk_m_init,
270 .recalc_rate = tegra20_clk_m_recalc_rate,
Colin Crossd8611962010-01-28 16:40:29 -0800271};
272
273/* super clock functions */
274/* "super clocks" on tegra have two-stage muxes and a clock skipping
275 * super divider. We will ignore the clock skipping divider, since we
276 * can't lower the voltage when using the clock skip, but we can if we
277 * lower the PLL frequency.
278 */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530279static int tegra20_super_clk_is_enabled(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800280{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530281 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crossd8611962010-01-28 16:40:29 -0800282 u32 val;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530283
284 val = clk_readl(c->reg + SUPER_CLK_MUX);
285 BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
286 ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
287 c->state = ON;
288 return c->state;
289}
290
291static int tegra20_super_clk_enable(struct clk_hw *hw)
292{
293 struct clk_tegra *c = to_clk_tegra(hw);
294 clk_writel(0, c->reg + SUPER_CLK_DIVIDER);
295 return 0;
296}
297
298static void tegra20_super_clk_disable(struct clk_hw *hw)
299{
300 pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
301
302 /* oops - don't disable the CPU clock! */
303 BUG();
304}
305
306static u8 tegra20_super_clk_get_parent(struct clk_hw *hw)
307{
308 struct clk_tegra *c = to_clk_tegra(hw);
309 int val = clk_readl(c->reg + SUPER_CLK_MUX);
Colin Crossd8611962010-01-28 16:40:29 -0800310 int source;
311 int shift;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530312
Colin Crossd8611962010-01-28 16:40:29 -0800313 BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
314 ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
315 shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
316 SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
317 source = (val >> shift) & SUPER_SOURCE_MASK;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530318 return source;
Colin Crossd8611962010-01-28 16:40:29 -0800319}
320
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530321static int tegra20_super_clk_set_parent(struct clk_hw *hw, u8 index)
Colin Crossd8611962010-01-28 16:40:29 -0800322{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530323 struct clk_tegra *c = to_clk_tegra(hw);
324 u32 val = clk_readl(c->reg + SUPER_CLK_MUX);
Colin Crossd8611962010-01-28 16:40:29 -0800325 int shift;
Colin Cross71fc84c2010-06-07 20:49:46 -0700326
Colin Crossd8611962010-01-28 16:40:29 -0800327 BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
328 ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
329 shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
330 SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530331 val &= ~(SUPER_SOURCE_MASK << shift);
332 val |= index << shift;
Colin Cross71fc84c2010-06-07 20:49:46 -0700333
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530334 clk_writel(val, c->reg);
Colin Cross71fc84c2010-06-07 20:49:46 -0700335
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530336 return 0;
Colin Crossd8611962010-01-28 16:40:29 -0800337}
338
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530339/* FIX ME: Need to switch parents to change the source PLL rate */
340static unsigned long tegra20_super_clk_recalc_rate(struct clk_hw *hw,
341 unsigned long prate)
Colin Cross9c7dc562011-02-12 21:25:23 -0800342{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530343 return prate;
Colin Cross9c7dc562011-02-12 21:25:23 -0800344}
345
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530346static long tegra20_super_clk_round_rate(struct clk_hw *hw, unsigned long rate,
347 unsigned long *prate)
Colin Cross71fc84c2010-06-07 20:49:46 -0700348{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530349 return *prate;
Colin Cross71fc84c2010-06-07 20:49:46 -0700350}
351
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530352static int tegra20_super_clk_set_rate(struct clk_hw *hw, unsigned long rate,
353 unsigned long parent_rate)
Colin Cross71fc84c2010-06-07 20:49:46 -0700354{
355 return 0;
356}
357
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530358struct clk_ops tegra_super_ops = {
359 .is_enabled = tegra20_super_clk_is_enabled,
360 .enable = tegra20_super_clk_enable,
361 .disable = tegra20_super_clk_disable,
362 .set_parent = tegra20_super_clk_set_parent,
363 .get_parent = tegra20_super_clk_get_parent,
364 .set_rate = tegra20_super_clk_set_rate,
365 .round_rate = tegra20_super_clk_round_rate,
366 .recalc_rate = tegra20_super_clk_recalc_rate,
367};
Colin Cross71fc84c2010-06-07 20:49:46 -0700368
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530369static u8 tegra20_cop_clk_get_parent(struct clk_hw *hw)
370{
371 return 0;
Colin Cross71fc84c2010-06-07 20:49:46 -0700372}
373
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530374struct clk_ops tegra_cop_ops = {
375 .get_parent = tegra20_cop_clk_get_parent,
Colin Crossd8611962010-01-28 16:40:29 -0800376};
377
Colin Cross9c7dc562011-02-12 21:25:23 -0800378/* virtual cop clock functions. Used to acquire the fake 'cop' clock to
379 * reset the COP block (i.e. AVP) */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530380void tegra2_cop_clk_reset(struct clk_hw *hw, bool assert)
Colin Cross9c7dc562011-02-12 21:25:23 -0800381{
382 unsigned long reg = assert ? RST_DEVICES_SET : RST_DEVICES_CLR;
383
384 pr_debug("%s %s\n", __func__, assert ? "assert" : "deassert");
385 clk_writel(1 << 1, reg);
386}
387
Colin Crossd8611962010-01-28 16:40:29 -0800388/* bus clock functions */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530389static int tegra20_bus_clk_is_enabled(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800390{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530391 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crossd8611962010-01-28 16:40:29 -0800392 u32 val = clk_readl(c->reg);
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530393
Colin Crossd8611962010-01-28 16:40:29 -0800394 c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530395 return c->state;
Colin Crossd8611962010-01-28 16:40:29 -0800396}
397
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530398static int tegra20_bus_clk_enable(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800399{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530400 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross4729fd72011-02-12 16:43:05 -0800401 unsigned long flags;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530402 u32 val;
Colin Cross4729fd72011-02-12 16:43:05 -0800403
404 spin_lock_irqsave(&clock_register_lock, flags);
405
406 val = clk_readl(c->reg);
Colin Crossd8611962010-01-28 16:40:29 -0800407 val &= ~(BUS_CLK_DISABLE << c->reg_shift);
408 clk_writel(val, c->reg);
Colin Cross4729fd72011-02-12 16:43:05 -0800409
410 spin_unlock_irqrestore(&clock_register_lock, flags);
411
Colin Crossd8611962010-01-28 16:40:29 -0800412 return 0;
413}
414
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530415static void tegra20_bus_clk_disable(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800416{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530417 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross4729fd72011-02-12 16:43:05 -0800418 unsigned long flags;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530419 u32 val;
Colin Cross4729fd72011-02-12 16:43:05 -0800420
421 spin_lock_irqsave(&clock_register_lock, flags);
422
423 val = clk_readl(c->reg);
Colin Crossd8611962010-01-28 16:40:29 -0800424 val |= BUS_CLK_DISABLE << c->reg_shift;
425 clk_writel(val, c->reg);
Colin Cross4729fd72011-02-12 16:43:05 -0800426
427 spin_unlock_irqrestore(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -0800428}
429
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530430static unsigned long tegra20_bus_clk_recalc_rate(struct clk_hw *hw,
431 unsigned long prate)
Colin Crossd8611962010-01-28 16:40:29 -0800432{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530433 struct clk_tegra *c = to_clk_tegra(hw);
434 u32 val = clk_readl(c->reg);
435 u64 rate = prate;
436
437 c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1;
438 c->mul = 1;
439
440 if (c->mul != 0 && c->div != 0) {
441 rate *= c->mul;
442 rate += c->div - 1; /* round up */
443 do_div(rate, c->div);
444 }
445 return rate;
446}
447
448static int tegra20_bus_clk_set_rate(struct clk_hw *hw, unsigned long rate,
449 unsigned long parent_rate)
450{
451 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross4729fd72011-02-12 16:43:05 -0800452 int ret = -EINVAL;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530453 unsigned long flags;
454 u32 val;
Colin Crossd8611962010-01-28 16:40:29 -0800455 int i;
Colin Cross4729fd72011-02-12 16:43:05 -0800456
457 spin_lock_irqsave(&clock_register_lock, flags);
458
459 val = clk_readl(c->reg);
Colin Crossd8611962010-01-28 16:40:29 -0800460 for (i = 1; i <= 4; i++) {
461 if (rate == parent_rate / i) {
462 val &= ~(BUS_CLK_DIV_MASK << c->reg_shift);
463 val |= (i - 1) << c->reg_shift;
464 clk_writel(val, c->reg);
465 c->div = i;
466 c->mul = 1;
Colin Cross4729fd72011-02-12 16:43:05 -0800467 ret = 0;
468 break;
Colin Crossd8611962010-01-28 16:40:29 -0800469 }
470 }
Colin Cross4729fd72011-02-12 16:43:05 -0800471
472 spin_unlock_irqrestore(&clock_register_lock, flags);
473
474 return ret;
Colin Crossd8611962010-01-28 16:40:29 -0800475}
476
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530477static long tegra20_bus_clk_round_rate(struct clk_hw *hw, unsigned long rate,
478 unsigned long *prate)
479{
480 unsigned long parent_rate = *prate;
481 s64 divider;
482
483 if (rate >= parent_rate)
484 return rate;
485
486 divider = parent_rate;
487 divider += rate - 1;
488 do_div(divider, rate);
489
490 if (divider < 0)
491 return divider;
492
493 if (divider > 4)
494 divider = 4;
495 do_div(parent_rate, divider);
496
497 return parent_rate;
498}
499
Prashant Gaikwad86edb872012-08-06 11:57:40 +0530500struct clk_ops tegra_bus_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530501 .is_enabled = tegra20_bus_clk_is_enabled,
502 .enable = tegra20_bus_clk_enable,
503 .disable = tegra20_bus_clk_disable,
504 .set_rate = tegra20_bus_clk_set_rate,
505 .round_rate = tegra20_bus_clk_round_rate,
506 .recalc_rate = tegra20_bus_clk_recalc_rate,
Colin Crossd8611962010-01-28 16:40:29 -0800507};
508
Colin Crosscea62c82010-10-04 11:49:26 -0700509/* Blink output functions */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530510static int tegra20_blink_clk_is_enabled(struct clk_hw *hw)
Colin Crosscea62c82010-10-04 11:49:26 -0700511{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530512 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crosscea62c82010-10-04 11:49:26 -0700513 u32 val;
514
515 val = pmc_readl(PMC_CTRL);
516 c->state = (val & PMC_CTRL_BLINK_ENB) ? ON : OFF;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530517 return c->state;
518}
519
520static unsigned long tegra20_blink_clk_recalc_rate(struct clk_hw *hw,
521 unsigned long prate)
522{
523 struct clk_tegra *c = to_clk_tegra(hw);
524 u64 rate = prate;
525 u32 val;
526
Colin Crosscea62c82010-10-04 11:49:26 -0700527 c->mul = 1;
528 val = pmc_readl(c->reg);
529
530 if (val & PMC_BLINK_TIMER_ENB) {
531 unsigned int on_off;
532
533 on_off = (val >> PMC_BLINK_TIMER_DATA_ON_SHIFT) &
534 PMC_BLINK_TIMER_DATA_ON_MASK;
535 val >>= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
536 val &= PMC_BLINK_TIMER_DATA_OFF_MASK;
537 on_off += val;
538 /* each tick in the blink timer is 4 32KHz clocks */
539 c->div = on_off * 4;
540 } else {
541 c->div = 1;
542 }
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530543
544 if (c->mul != 0 && c->div != 0) {
545 rate *= c->mul;
546 rate += c->div - 1; /* round up */
547 do_div(rate, c->div);
548 }
549 return rate;
Colin Crosscea62c82010-10-04 11:49:26 -0700550}
551
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530552static int tegra20_blink_clk_enable(struct clk_hw *hw)
Colin Crosscea62c82010-10-04 11:49:26 -0700553{
554 u32 val;
555
556 val = pmc_readl(PMC_DPD_PADS_ORIDE);
557 pmc_writel(val | PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
558
559 val = pmc_readl(PMC_CTRL);
560 pmc_writel(val | PMC_CTRL_BLINK_ENB, PMC_CTRL);
561
562 return 0;
563}
564
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530565static void tegra20_blink_clk_disable(struct clk_hw *hw)
Colin Crosscea62c82010-10-04 11:49:26 -0700566{
567 u32 val;
568
569 val = pmc_readl(PMC_CTRL);
570 pmc_writel(val & ~PMC_CTRL_BLINK_ENB, PMC_CTRL);
571
572 val = pmc_readl(PMC_DPD_PADS_ORIDE);
573 pmc_writel(val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
574}
575
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530576static int tegra20_blink_clk_set_rate(struct clk_hw *hw, unsigned long rate,
577 unsigned long parent_rate)
Colin Crosscea62c82010-10-04 11:49:26 -0700578{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530579 struct clk_tegra *c = to_clk_tegra(hw);
580
Colin Cross4729fd72011-02-12 16:43:05 -0800581 if (rate >= parent_rate) {
Colin Crosscea62c82010-10-04 11:49:26 -0700582 c->div = 1;
583 pmc_writel(0, c->reg);
584 } else {
585 unsigned int on_off;
586 u32 val;
587
Colin Cross4729fd72011-02-12 16:43:05 -0800588 on_off = DIV_ROUND_UP(parent_rate / 8, rate);
Colin Crosscea62c82010-10-04 11:49:26 -0700589 c->div = on_off * 8;
590
591 val = (on_off & PMC_BLINK_TIMER_DATA_ON_MASK) <<
592 PMC_BLINK_TIMER_DATA_ON_SHIFT;
593 on_off &= PMC_BLINK_TIMER_DATA_OFF_MASK;
594 on_off <<= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
595 val |= on_off;
596 val |= PMC_BLINK_TIMER_ENB;
597 pmc_writel(val, c->reg);
598 }
599
600 return 0;
601}
602
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530603static long tegra20_blink_clk_round_rate(struct clk_hw *hw, unsigned long rate,
604 unsigned long *prate)
605{
606 int div;
607 int mul;
608 long round_rate = *prate;
609
610 mul = 1;
611
612 if (rate >= *prate) {
613 div = 1;
614 } else {
615 div = DIV_ROUND_UP(*prate / 8, rate);
616 div *= 8;
617 }
618
619 round_rate *= mul;
620 round_rate += div - 1;
621 do_div(round_rate, div);
622
623 return round_rate;
624}
625
Prashant Gaikwad86edb872012-08-06 11:57:40 +0530626struct clk_ops tegra_blink_clk_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530627 .is_enabled = tegra20_blink_clk_is_enabled,
628 .enable = tegra20_blink_clk_enable,
629 .disable = tegra20_blink_clk_disable,
630 .set_rate = tegra20_blink_clk_set_rate,
631 .round_rate = tegra20_blink_clk_round_rate,
632 .recalc_rate = tegra20_blink_clk_recalc_rate,
Colin Crosscea62c82010-10-04 11:49:26 -0700633};
634
Colin Crossd8611962010-01-28 16:40:29 -0800635/* PLL Functions */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530636static int tegra20_pll_clk_wait_for_lock(struct clk_tegra *c)
Colin Crossd8611962010-01-28 16:40:29 -0800637{
Colin Crossf1519612011-02-12 16:05:31 -0800638 udelay(c->u.pll.lock_delay);
Colin Crossd8611962010-01-28 16:40:29 -0800639 return 0;
640}
641
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530642static int tegra20_pll_clk_is_enabled(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800643{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530644 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crossd8611962010-01-28 16:40:29 -0800645 u32 val = clk_readl(c->reg + PLL_BASE);
646
647 c->state = (val & PLL_BASE_ENABLE) ? ON : OFF;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530648 return c->state;
649}
650
651static unsigned long tegra20_pll_clk_recalc_rate(struct clk_hw *hw,
652 unsigned long prate)
653{
654 struct clk_tegra *c = to_clk_tegra(hw);
655 u32 val = clk_readl(c->reg + PLL_BASE);
656 u64 rate = prate;
Colin Crossd8611962010-01-28 16:40:29 -0800657
658 if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530659 const struct clk_pll_freq_table *sel;
660 for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
661 if (sel->input_rate == prate &&
662 sel->output_rate == c->u.pll.fixed_rate) {
663 c->mul = sel->n;
664 c->div = sel->m * sel->p;
665 break;
666 }
667 }
668 pr_err("Clock %s has unknown fixed frequency\n",
669 __clk_get_name(hw->clk));
670 BUG();
Colin Crossd8611962010-01-28 16:40:29 -0800671 } else if (val & PLL_BASE_BYPASS) {
Colin Cross71fc84c2010-06-07 20:49:46 -0700672 c->mul = 1;
673 c->div = 1;
Colin Crossd8611962010-01-28 16:40:29 -0800674 } else {
Colin Cross71fc84c2010-06-07 20:49:46 -0700675 c->mul = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT;
676 c->div = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT;
677 if (c->flags & PLLU)
678 c->div *= (val & PLLU_BASE_POST_DIV) ? 1 : 2;
679 else
680 c->div *= (val & PLL_BASE_DIVP_MASK) ? 2 : 1;
Colin Crossd8611962010-01-28 16:40:29 -0800681 }
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530682
683 if (c->mul != 0 && c->div != 0) {
684 rate *= c->mul;
685 rate += c->div - 1; /* round up */
686 do_div(rate, c->div);
687 }
688 return rate;
Colin Crossd8611962010-01-28 16:40:29 -0800689}
690
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530691static int tegra20_pll_clk_enable(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800692{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530693 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crossd8611962010-01-28 16:40:29 -0800694 u32 val;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530695 pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
Colin Crossd8611962010-01-28 16:40:29 -0800696
697 val = clk_readl(c->reg + PLL_BASE);
698 val &= ~PLL_BASE_BYPASS;
699 val |= PLL_BASE_ENABLE;
700 clk_writel(val, c->reg + PLL_BASE);
701
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530702 tegra20_pll_clk_wait_for_lock(c);
Colin Crossd8611962010-01-28 16:40:29 -0800703
704 return 0;
705}
706
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530707static void tegra20_pll_clk_disable(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800708{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530709 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crossd8611962010-01-28 16:40:29 -0800710 u32 val;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530711 pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
Colin Crossd8611962010-01-28 16:40:29 -0800712
713 val = clk_readl(c->reg);
714 val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
715 clk_writel(val, c->reg);
716}
717
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530718static int tegra20_pll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
719 unsigned long parent_rate)
Colin Crossd8611962010-01-28 16:40:29 -0800720{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530721 struct clk_tegra *c = to_clk_tegra(hw);
722 unsigned long input_rate = parent_rate;
Colin Crossf1519612011-02-12 16:05:31 -0800723 const struct clk_pll_freq_table *sel;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530724 u32 val;
Colin Crossd8611962010-01-28 16:40:29 -0800725
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530726 pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate);
Colin Crossd8611962010-01-28 16:40:29 -0800727
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530728 if (c->flags & PLL_FIXED) {
729 int ret = 0;
730 if (rate != c->u.pll.fixed_rate) {
731 pr_err("%s: Can not change %s fixed rate %lu to %lu\n",
732 __func__, __clk_get_name(hw->clk),
733 c->u.pll.fixed_rate, rate);
734 ret = -EINVAL;
735 }
736 return ret;
737 }
738
Colin Crossf1519612011-02-12 16:05:31 -0800739 for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
Colin Crossd8611962010-01-28 16:40:29 -0800740 if (sel->input_rate == input_rate && sel->output_rate == rate) {
Colin Cross71fc84c2010-06-07 20:49:46 -0700741 c->mul = sel->n;
742 c->div = sel->m * sel->p;
Colin Crossd8611962010-01-28 16:40:29 -0800743
744 val = clk_readl(c->reg + PLL_BASE);
745 if (c->flags & PLL_FIXED)
746 val |= PLL_BASE_OVERRIDE;
747 val &= ~(PLL_BASE_DIVP_MASK | PLL_BASE_DIVN_MASK |
748 PLL_BASE_DIVM_MASK);
Colin Cross71fc84c2010-06-07 20:49:46 -0700749 val |= (sel->m << PLL_BASE_DIVM_SHIFT) |
750 (sel->n << PLL_BASE_DIVN_SHIFT);
751 BUG_ON(sel->p < 1 || sel->p > 2);
752 if (c->flags & PLLU) {
753 if (sel->p == 1)
754 val |= PLLU_BASE_POST_DIV;
755 } else {
756 if (sel->p == 2)
757 val |= 1 << PLL_BASE_DIVP_SHIFT;
758 }
Colin Crossd8611962010-01-28 16:40:29 -0800759 clk_writel(val, c->reg + PLL_BASE);
760
761 if (c->flags & PLL_HAS_CPCON) {
Colin Cross71fc84c2010-06-07 20:49:46 -0700762 val = clk_readl(c->reg + PLL_MISC(c));
763 val &= ~PLL_MISC_CPCON_MASK;
764 val |= sel->cpcon << PLL_MISC_CPCON_SHIFT;
Colin Crossd8611962010-01-28 16:40:29 -0800765 clk_writel(val, c->reg + PLL_MISC(c));
766 }
767
768 if (c->state == ON)
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530769 tegra20_pll_clk_enable(hw);
Colin Crossd8611962010-01-28 16:40:29 -0800770 return 0;
771 }
772 }
773 return -EINVAL;
774}
775
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530776static long tegra20_pll_clk_round_rate(struct clk_hw *hw, unsigned long rate,
777 unsigned long *prate)
778{
779 struct clk_tegra *c = to_clk_tegra(hw);
780 const struct clk_pll_freq_table *sel;
781 unsigned long input_rate = *prate;
782 unsigned long output_rate = *prate;
783 int mul;
784 int div;
785
786 if (c->flags & PLL_FIXED)
787 return c->u.pll.fixed_rate;
788
789 for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++)
790 if (sel->input_rate == input_rate && sel->output_rate == rate) {
791 mul = sel->n;
792 div = sel->m * sel->p;
793 break;
794 }
795
796 if (sel->input_rate == 0)
797 return -EINVAL;
798
799 output_rate *= mul;
800 output_rate += div - 1; /* round up */
801 do_div(output_rate, div);
802
803 return output_rate;
804}
805
Prashant Gaikwad86edb872012-08-06 11:57:40 +0530806struct clk_ops tegra_pll_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530807 .is_enabled = tegra20_pll_clk_is_enabled,
808 .enable = tegra20_pll_clk_enable,
809 .disable = tegra20_pll_clk_disable,
810 .set_rate = tegra20_pll_clk_set_rate,
811 .recalc_rate = tegra20_pll_clk_recalc_rate,
812 .round_rate = tegra20_pll_clk_round_rate,
Colin Cross71fc84c2010-06-07 20:49:46 -0700813};
814
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530815static void tegra20_pllx_clk_init(struct clk_hw *hw)
Colin Cross71fc84c2010-06-07 20:49:46 -0700816{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530817 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross71fc84c2010-06-07 20:49:46 -0700818
Olof Johansson9a1086d2011-10-13 00:31:20 -0700819 if (tegra_sku_id == 7)
Colin Cross71fc84c2010-06-07 20:49:46 -0700820 c->max_rate = 750000000;
821}
822
Prashant Gaikwad86edb872012-08-06 11:57:40 +0530823struct clk_ops tegra_pllx_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530824 .init = tegra20_pllx_clk_init,
825 .is_enabled = tegra20_pll_clk_is_enabled,
826 .enable = tegra20_pll_clk_enable,
827 .disable = tegra20_pll_clk_disable,
828 .set_rate = tegra20_pll_clk_set_rate,
829 .recalc_rate = tegra20_pll_clk_recalc_rate,
830 .round_rate = tegra20_pll_clk_round_rate,
Colin Crossd8611962010-01-28 16:40:29 -0800831};
832
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530833static int tegra20_plle_clk_enable(struct clk_hw *hw)
Mike Rapoport8d685bc2010-09-27 11:26:32 +0200834{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530835 struct clk_tegra *c = to_clk_tegra(hw);
Mike Rapoport8d685bc2010-09-27 11:26:32 +0200836 u32 val;
837
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530838 pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
Mike Rapoport8d685bc2010-09-27 11:26:32 +0200839
840 mdelay(1);
841
842 val = clk_readl(c->reg + PLL_BASE);
843 if (!(val & PLLE_MISC_READY))
844 return -EBUSY;
845
846 val = clk_readl(c->reg + PLL_BASE);
847 val |= PLL_BASE_ENABLE | PLL_BASE_BYPASS;
848 clk_writel(val, c->reg + PLL_BASE);
849
850 return 0;
851}
852
Prashant Gaikwad86edb872012-08-06 11:57:40 +0530853struct clk_ops tegra_plle_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530854 .is_enabled = tegra20_pll_clk_is_enabled,
855 .enable = tegra20_plle_clk_enable,
856 .set_rate = tegra20_pll_clk_set_rate,
857 .recalc_rate = tegra20_pll_clk_recalc_rate,
858 .round_rate = tegra20_pll_clk_round_rate,
Mike Rapoport8d685bc2010-09-27 11:26:32 +0200859};
860
Colin Crossd8611962010-01-28 16:40:29 -0800861/* Clock divider ops */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530862static int tegra20_pll_div_clk_is_enabled(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800863{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530864 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crossd8611962010-01-28 16:40:29 -0800865 u32 val = clk_readl(c->reg);
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530866
Colin Crossd8611962010-01-28 16:40:29 -0800867 val >>= c->reg_shift;
868 c->state = (val & PLL_OUT_CLKEN) ? ON : OFF;
869 if (!(val & PLL_OUT_RESET_DISABLE))
870 c->state = OFF;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530871 return c->state;
872}
873
874static unsigned long tegra20_pll_div_clk_recalc_rate(struct clk_hw *hw,
875 unsigned long prate)
876{
877 struct clk_tegra *c = to_clk_tegra(hw);
878 u64 rate = prate;
879 u32 val = clk_readl(c->reg);
880 u32 divu71;
881
882 val >>= c->reg_shift;
Colin Crossd8611962010-01-28 16:40:29 -0800883
884 if (c->flags & DIV_U71) {
885 divu71 = (val & PLL_OUT_RATIO_MASK) >> PLL_OUT_RATIO_SHIFT;
886 c->div = (divu71 + 2);
887 c->mul = 2;
888 } else if (c->flags & DIV_2) {
889 c->div = 2;
890 c->mul = 1;
891 } else {
892 c->div = 1;
893 c->mul = 1;
894 }
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530895
896 rate *= c->mul;
897 rate += c->div - 1; /* round up */
898 do_div(rate, c->div);
899
900 return rate;
Colin Crossd8611962010-01-28 16:40:29 -0800901}
902
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530903static int tegra20_pll_div_clk_enable(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800904{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530905 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross4729fd72011-02-12 16:43:05 -0800906 unsigned long flags;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530907 u32 new_val;
908 u32 val;
Colin Crossd8611962010-01-28 16:40:29 -0800909
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530910 pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
911
Colin Crossd8611962010-01-28 16:40:29 -0800912 if (c->flags & DIV_U71) {
Colin Cross4729fd72011-02-12 16:43:05 -0800913 spin_lock_irqsave(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -0800914 val = clk_readl(c->reg);
915 new_val = val >> c->reg_shift;
916 new_val &= 0xFFFF;
917
918 new_val |= PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE;
919
920 val &= ~(0xFFFF << c->reg_shift);
921 val |= new_val << c->reg_shift;
922 clk_writel(val, c->reg);
Colin Cross4729fd72011-02-12 16:43:05 -0800923 spin_unlock_irqrestore(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -0800924 return 0;
925 } else if (c->flags & DIV_2) {
926 BUG_ON(!(c->flags & PLLD));
Colin Cross4729fd72011-02-12 16:43:05 -0800927 spin_lock_irqsave(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -0800928 val = clk_readl(c->reg);
929 val &= ~PLLD_MISC_DIV_RST;
930 clk_writel(val, c->reg);
Colin Cross4729fd72011-02-12 16:43:05 -0800931 spin_unlock_irqrestore(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -0800932 return 0;
933 }
934 return -EINVAL;
935}
936
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530937static void tegra20_pll_div_clk_disable(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -0800938{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530939 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross4729fd72011-02-12 16:43:05 -0800940 unsigned long flags;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530941 u32 new_val;
942 u32 val;
Colin Crossd8611962010-01-28 16:40:29 -0800943
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530944 pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
945
Colin Crossd8611962010-01-28 16:40:29 -0800946 if (c->flags & DIV_U71) {
Colin Cross4729fd72011-02-12 16:43:05 -0800947 spin_lock_irqsave(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -0800948 val = clk_readl(c->reg);
949 new_val = val >> c->reg_shift;
950 new_val &= 0xFFFF;
951
952 new_val &= ~(PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE);
953
954 val &= ~(0xFFFF << c->reg_shift);
955 val |= new_val << c->reg_shift;
956 clk_writel(val, c->reg);
Colin Cross4729fd72011-02-12 16:43:05 -0800957 spin_unlock_irqrestore(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -0800958 } else if (c->flags & DIV_2) {
959 BUG_ON(!(c->flags & PLLD));
Colin Cross4729fd72011-02-12 16:43:05 -0800960 spin_lock_irqsave(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -0800961 val = clk_readl(c->reg);
962 val |= PLLD_MISC_DIV_RST;
963 clk_writel(val, c->reg);
Colin Cross4729fd72011-02-12 16:43:05 -0800964 spin_unlock_irqrestore(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -0800965 }
966}
967
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530968static int tegra20_pll_div_clk_set_rate(struct clk_hw *hw, unsigned long rate,
969 unsigned long parent_rate)
Colin Crossd8611962010-01-28 16:40:29 -0800970{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530971 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross4729fd72011-02-12 16:43:05 -0800972 unsigned long flags;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530973 int divider_u71;
974 u32 new_val;
975 u32 val;
Colin Cross4729fd72011-02-12 16:43:05 -0800976
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +0530977 pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate);
978
Colin Crossd8611962010-01-28 16:40:29 -0800979 if (c->flags & DIV_U71) {
Colin Cross4729fd72011-02-12 16:43:05 -0800980 divider_u71 = clk_div71_get_divider(parent_rate, rate);
Colin Crossd8611962010-01-28 16:40:29 -0800981 if (divider_u71 >= 0) {
Colin Cross4729fd72011-02-12 16:43:05 -0800982 spin_lock_irqsave(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -0800983 val = clk_readl(c->reg);
984 new_val = val >> c->reg_shift;
985 new_val &= 0xFFFF;
986 if (c->flags & DIV_U71_FIXED)
987 new_val |= PLL_OUT_OVERRIDE;
988 new_val &= ~PLL_OUT_RATIO_MASK;
989 new_val |= divider_u71 << PLL_OUT_RATIO_SHIFT;
990
991 val &= ~(0xFFFF << c->reg_shift);
992 val |= new_val << c->reg_shift;
993 clk_writel(val, c->reg);
994 c->div = divider_u71 + 2;
995 c->mul = 2;
Colin Cross4729fd72011-02-12 16:43:05 -0800996 spin_unlock_irqrestore(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -0800997 return 0;
998 }
999 } else if (c->flags & DIV_2) {
Colin Cross4729fd72011-02-12 16:43:05 -08001000 if (parent_rate == rate * 2)
Colin Crossd8611962010-01-28 16:40:29 -08001001 return 0;
Colin Crossd8611962010-01-28 16:40:29 -08001002 }
1003 return -EINVAL;
1004}
1005
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301006static long tegra20_pll_div_clk_round_rate(struct clk_hw *hw, unsigned long rate,
1007 unsigned long *prate)
Colin Cross71fc84c2010-06-07 20:49:46 -07001008{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301009 struct clk_tegra *c = to_clk_tegra(hw);
1010 unsigned long parent_rate = *prate;
Colin Cross71fc84c2010-06-07 20:49:46 -07001011 int divider;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301012
1013 pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate);
Colin Cross71fc84c2010-06-07 20:49:46 -07001014
1015 if (c->flags & DIV_U71) {
Colin Cross4729fd72011-02-12 16:43:05 -08001016 divider = clk_div71_get_divider(parent_rate, rate);
Colin Cross71fc84c2010-06-07 20:49:46 -07001017 if (divider < 0)
1018 return divider;
Colin Cross421186e2011-02-12 18:21:47 -08001019 return DIV_ROUND_UP(parent_rate * 2, divider + 2);
Colin Cross71fc84c2010-06-07 20:49:46 -07001020 } else if (c->flags & DIV_2) {
Colin Cross421186e2011-02-12 18:21:47 -08001021 return DIV_ROUND_UP(parent_rate, 2);
Colin Cross71fc84c2010-06-07 20:49:46 -07001022 }
1023 return -EINVAL;
1024}
Colin Crossd8611962010-01-28 16:40:29 -08001025
Prashant Gaikwad86edb872012-08-06 11:57:40 +05301026struct clk_ops tegra_pll_div_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301027 .is_enabled = tegra20_pll_div_clk_is_enabled,
1028 .enable = tegra20_pll_div_clk_enable,
1029 .disable = tegra20_pll_div_clk_disable,
1030 .set_rate = tegra20_pll_div_clk_set_rate,
1031 .round_rate = tegra20_pll_div_clk_round_rate,
1032 .recalc_rate = tegra20_pll_div_clk_recalc_rate,
Colin Crossd8611962010-01-28 16:40:29 -08001033};
1034
1035/* Periph clk ops */
1036
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301037static int tegra20_periph_clk_is_enabled(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -08001038{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301039 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crossd8611962010-01-28 16:40:29 -08001040
1041 c->state = ON;
Colin Cross1be3d052011-02-21 16:44:07 -08001042
1043 if (!c->u.periph.clk_num)
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301044 goto out;
Colin Cross1be3d052011-02-21 16:44:07 -08001045
Colin Crossd8611962010-01-28 16:40:29 -08001046 if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
1047 PERIPH_CLK_TO_ENB_BIT(c)))
1048 c->state = OFF;
Colin Cross1be3d052011-02-21 16:44:07 -08001049
Colin Crossd8611962010-01-28 16:40:29 -08001050 if (!(c->flags & PERIPH_NO_RESET))
1051 if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) &
1052 PERIPH_CLK_TO_ENB_BIT(c))
1053 c->state = OFF;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301054
1055out:
1056 return c->state;
Colin Crossd8611962010-01-28 16:40:29 -08001057}
1058
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301059static int tegra20_periph_clk_enable(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -08001060{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301061 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross78f379b2010-10-20 19:19:58 -07001062 unsigned long flags;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301063 u32 val;
1064
1065 pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
Colin Crossd8611962010-01-28 16:40:29 -08001066
Colin Cross1be3d052011-02-21 16:44:07 -08001067 if (!c->u.periph.clk_num)
1068 return 0;
1069
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301070 tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++;
1071 if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 1)
1072 return 0;
1073
Colin Cross78f379b2010-10-20 19:19:58 -07001074 spin_lock_irqsave(&clock_register_lock, flags);
1075
Colin Crossd8611962010-01-28 16:40:29 -08001076 clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
1077 CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
1078 if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET))
1079 clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
1080 RST_DEVICES_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
1081 if (c->flags & PERIPH_EMC_ENB) {
1082 /* The EMC peripheral clock has 2 extra enable bits */
1083 /* FIXME: Do they need to be disabled? */
1084 val = clk_readl(c->reg);
1085 val |= 0x3 << 24;
1086 clk_writel(val, c->reg);
1087 }
Colin Cross78f379b2010-10-20 19:19:58 -07001088
Colin Cross78f379b2010-10-20 19:19:58 -07001089 spin_unlock_irqrestore(&clock_register_lock, flags);
1090
Colin Crossd8611962010-01-28 16:40:29 -08001091 return 0;
1092}
1093
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301094static void tegra20_periph_clk_disable(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -08001095{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301096 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross78f379b2010-10-20 19:19:58 -07001097 unsigned long flags;
1098
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301099 pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
Colin Crossd8611962010-01-28 16:40:29 -08001100
Colin Cross1be3d052011-02-21 16:44:07 -08001101 if (!c->u.periph.clk_num)
1102 return;
1103
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301104 tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--;
1105
1106 if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 0)
1107 return;
1108
Colin Cross78f379b2010-10-20 19:19:58 -07001109 spin_lock_irqsave(&clock_register_lock, flags);
1110
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301111 clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
1112 CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
Colin Cross78f379b2010-10-20 19:19:58 -07001113
1114 spin_unlock_irqrestore(&clock_register_lock, flags);
Colin Crossd8611962010-01-28 16:40:29 -08001115}
1116
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301117void tegra2_periph_clk_reset(struct clk_hw *hw, bool assert)
Colin Crossd8611962010-01-28 16:40:29 -08001118{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301119 struct clk_tegra *c = to_clk_tegra(hw);
Dima Zavin2b84cb4f2010-09-02 19:11:11 -07001120 unsigned long base = assert ? RST_DEVICES_SET : RST_DEVICES_CLR;
1121
1122 pr_debug("%s %s on clock %s\n", __func__,
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301123 assert ? "assert" : "deassert", __clk_get_name(hw->clk));
Colin Cross1be3d052011-02-21 16:44:07 -08001124
1125 BUG_ON(!c->u.periph.clk_num);
1126
Colin Crossd8611962010-01-28 16:40:29 -08001127 if (!(c->flags & PERIPH_NO_RESET))
1128 clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
Dima Zavin2b84cb4f2010-09-02 19:11:11 -07001129 base + PERIPH_CLK_TO_ENB_SET_REG(c));
Colin Crossd8611962010-01-28 16:40:29 -08001130}
1131
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301132static int tegra20_periph_clk_set_parent(struct clk_hw *hw, u8 index)
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 Crossd8611962010-01-28 16:40:29 -08001135 u32 val;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301136 u32 mask;
1137 u32 shift;
Simon Quebb1dccf2011-12-16 20:11:22 +01001138
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301139 pr_debug("%s: %s %d\n", __func__, __clk_get_name(hw->clk), index);
Simon Quebb1dccf2011-12-16 20:11:22 +01001140
1141 if (c->flags & MUX_PWM) {
1142 shift = PERIPH_CLK_SOURCE_PWM_SHIFT;
1143 mask = PERIPH_CLK_SOURCE_PWM_MASK;
1144 } else {
1145 shift = PERIPH_CLK_SOURCE_SHIFT;
1146 mask = PERIPH_CLK_SOURCE_MASK;
1147 }
1148
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301149 val = clk_readl(c->reg);
1150 val &= ~mask;
1151 val |= (index) << shift;
Colin Cross71fc84c2010-06-07 20:49:46 -07001152
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301153 clk_writel(val, c->reg);
Colin Cross71fc84c2010-06-07 20:49:46 -07001154
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301155 return 0;
Colin Crossd8611962010-01-28 16:40:29 -08001156}
1157
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301158static u8 tegra20_periph_clk_get_parent(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -08001159{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301160 struct clk_tegra *c = to_clk_tegra(hw);
1161 u32 val = clk_readl(c->reg);
1162 u32 mask;
1163 u32 shift;
1164
1165 if (c->flags & MUX_PWM) {
1166 shift = PERIPH_CLK_SOURCE_PWM_SHIFT;
1167 mask = PERIPH_CLK_SOURCE_PWM_MASK;
1168 } else {
1169 shift = PERIPH_CLK_SOURCE_SHIFT;
1170 mask = PERIPH_CLK_SOURCE_MASK;
1171 }
1172
1173 if (c->flags & MUX)
1174 return (val & mask) >> shift;
1175 else
1176 return 0;
1177}
1178
1179static unsigned long tegra20_periph_clk_recalc_rate(struct clk_hw *hw,
1180 unsigned long prate)
1181{
1182 struct clk_tegra *c = to_clk_tegra(hw);
1183 unsigned long rate = prate;
1184 u32 val = clk_readl(c->reg);
1185
1186 if (c->flags & DIV_U71) {
1187 u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK;
1188 c->div = divu71 + 2;
1189 c->mul = 2;
1190 } else if (c->flags & DIV_U16) {
1191 u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK;
1192 c->div = divu16 + 1;
1193 c->mul = 1;
1194 } else {
1195 c->div = 1;
1196 c->mul = 1;
1197 return rate;
1198 }
1199
1200 if (c->mul != 0 && c->div != 0) {
1201 rate *= c->mul;
1202 rate += c->div - 1; /* round up */
1203 do_div(rate, c->div);
1204 }
1205
1206 return rate;
1207}
1208
1209static int tegra20_periph_clk_set_rate(struct clk_hw *hw, unsigned long rate,
1210 unsigned long parent_rate)
1211{
1212 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crossd8611962010-01-28 16:40:29 -08001213 u32 val;
Colin Cross71fc84c2010-06-07 20:49:46 -07001214 int divider;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301215
1216 val = clk_readl(c->reg);
Colin Cross4729fd72011-02-12 16:43:05 -08001217
Colin Crossd8611962010-01-28 16:40:29 -08001218 if (c->flags & DIV_U71) {
Colin Cross4729fd72011-02-12 16:43:05 -08001219 divider = clk_div71_get_divider(parent_rate, rate);
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301220
Colin Cross71fc84c2010-06-07 20:49:46 -07001221 if (divider >= 0) {
Colin Crossd8611962010-01-28 16:40:29 -08001222 val = clk_readl(c->reg);
Colin Cross71fc84c2010-06-07 20:49:46 -07001223 val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK;
1224 val |= divider;
Colin Crossd8611962010-01-28 16:40:29 -08001225 clk_writel(val, c->reg);
Colin Cross71fc84c2010-06-07 20:49:46 -07001226 c->div = divider + 2;
Colin Crossd8611962010-01-28 16:40:29 -08001227 c->mul = 2;
Colin Crossd8611962010-01-28 16:40:29 -08001228 return 0;
1229 }
Colin Cross71fc84c2010-06-07 20:49:46 -07001230 } else if (c->flags & DIV_U16) {
Colin Cross4729fd72011-02-12 16:43:05 -08001231 divider = clk_div16_get_divider(parent_rate, rate);
Colin Cross71fc84c2010-06-07 20:49:46 -07001232 if (divider >= 0) {
1233 val = clk_readl(c->reg);
1234 val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK;
1235 val |= divider;
1236 clk_writel(val, c->reg);
1237 c->div = divider + 1;
1238 c->mul = 1;
1239 return 0;
1240 }
Colin Cross4729fd72011-02-12 16:43:05 -08001241 } else if (parent_rate <= rate) {
Colin Cross71fc84c2010-06-07 20:49:46 -07001242 c->div = 1;
1243 c->mul = 1;
1244 return 0;
1245 }
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301246
Colin Cross71fc84c2010-06-07 20:49:46 -07001247 return -EINVAL;
1248}
1249
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301250static long tegra20_periph_clk_round_rate(struct clk_hw *hw,
1251 unsigned long rate, unsigned long *prate)
Colin Cross71fc84c2010-06-07 20:49:46 -07001252{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301253 struct clk_tegra *c = to_clk_tegra(hw);
1254 unsigned long parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
Colin Cross71fc84c2010-06-07 20:49:46 -07001255 int divider;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301256
1257 pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate);
1258
1259 if (prate)
1260 parent_rate = *prate;
Colin Cross71fc84c2010-06-07 20:49:46 -07001261
1262 if (c->flags & DIV_U71) {
Colin Cross4729fd72011-02-12 16:43:05 -08001263 divider = clk_div71_get_divider(parent_rate, rate);
Colin Cross71fc84c2010-06-07 20:49:46 -07001264 if (divider < 0)
1265 return divider;
1266
Colin Cross421186e2011-02-12 18:21:47 -08001267 return DIV_ROUND_UP(parent_rate * 2, divider + 2);
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 return divider;
Colin Cross421186e2011-02-12 18:21:47 -08001272 return DIV_ROUND_UP(parent_rate, divider + 1);
Colin Crossd8611962010-01-28 16:40:29 -08001273 }
1274 return -EINVAL;
1275}
1276
Prashant Gaikwad86edb872012-08-06 11:57:40 +05301277struct clk_ops tegra_periph_clk_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301278 .is_enabled = tegra20_periph_clk_is_enabled,
1279 .enable = tegra20_periph_clk_enable,
1280 .disable = tegra20_periph_clk_disable,
1281 .set_parent = tegra20_periph_clk_set_parent,
1282 .get_parent = tegra20_periph_clk_get_parent,
1283 .set_rate = tegra20_periph_clk_set_rate,
1284 .round_rate = tegra20_periph_clk_round_rate,
1285 .recalc_rate = tegra20_periph_clk_recalc_rate,
Colin Crossd8611962010-01-28 16:40:29 -08001286};
1287
Colin Cross6d296822010-11-22 18:37:54 -08001288/* External memory controller clock ops */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301289static void tegra20_emc_clk_init(struct clk_hw *hw)
Colin Cross6d296822010-11-22 18:37:54 -08001290{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301291 struct clk_tegra *c = to_clk_tegra(hw);
1292 c->max_rate = __clk_get_rate(hw->clk);
Colin Cross6d296822010-11-22 18:37:54 -08001293}
1294
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301295static long tegra20_emc_clk_round_rate(struct clk_hw *hw, unsigned long rate,
1296 unsigned long *prate)
Colin Cross6d296822010-11-22 18:37:54 -08001297{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301298 struct clk_tegra *c = to_clk_tegra(hw);
Stephen Warrene186ad72012-02-06 17:09:15 -08001299 long emc_rate;
1300 long clk_rate;
Colin Cross6d296822010-11-22 18:37:54 -08001301
Stephen Warrene186ad72012-02-06 17:09:15 -08001302 /*
1303 * The slowest entry in the EMC clock table that is at least as
1304 * fast as rate.
1305 */
1306 emc_rate = tegra_emc_round_rate(rate);
1307 if (emc_rate < 0)
Colin Cross6d296822010-11-22 18:37:54 -08001308 return c->max_rate;
1309
Stephen Warrene186ad72012-02-06 17:09:15 -08001310 /*
1311 * The fastest rate the PLL will generate that is at most the
1312 * requested rate.
1313 */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301314 clk_rate = tegra20_periph_clk_round_rate(hw, emc_rate, NULL);
Colin Cross6d296822010-11-22 18:37:54 -08001315
Stephen Warrene186ad72012-02-06 17:09:15 -08001316 /*
1317 * If this fails, and emc_rate > clk_rate, it's because the maximum
1318 * rate in the EMC tables is larger than the maximum rate of the EMC
1319 * clock. The EMC clock's max rate is the rate it was running when the
1320 * kernel booted. Such a mismatch is probably due to using the wrong
1321 * BCT, i.e. using a Tegra20 BCT with an EMC table written for Tegra25.
1322 */
1323 WARN_ONCE(emc_rate != clk_rate,
1324 "emc_rate %ld != clk_rate %ld",
1325 emc_rate, clk_rate);
1326
1327 return emc_rate;
Colin Cross6d296822010-11-22 18:37:54 -08001328}
1329
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301330static int tegra20_emc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
1331 unsigned long parent_rate)
Colin Cross6d296822010-11-22 18:37:54 -08001332{
1333 int ret;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301334
Colin Cross6d296822010-11-22 18:37:54 -08001335 /*
1336 * The Tegra2 memory controller has an interlock with the clock
1337 * block that allows memory shadowed registers to be updated,
1338 * and then transfer them to the main registers at the same
1339 * time as the clock update without glitches.
1340 */
1341 ret = tegra_emc_set_rate(rate);
1342 if (ret < 0)
1343 return ret;
1344
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301345 ret = tegra20_periph_clk_set_rate(hw, rate, parent_rate);
Colin Cross6d296822010-11-22 18:37:54 -08001346 udelay(1);
1347
1348 return ret;
1349}
1350
Prashant Gaikwad86edb872012-08-06 11:57:40 +05301351struct clk_ops tegra_emc_clk_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301352 .init = tegra20_emc_clk_init,
1353 .is_enabled = tegra20_periph_clk_is_enabled,
1354 .enable = tegra20_periph_clk_enable,
1355 .disable = tegra20_periph_clk_disable,
1356 .set_parent = tegra20_periph_clk_set_parent,
1357 .get_parent = tegra20_periph_clk_get_parent,
1358 .set_rate = tegra20_emc_clk_set_rate,
1359 .round_rate = tegra20_emc_clk_round_rate,
1360 .recalc_rate = tegra20_periph_clk_recalc_rate,
Colin Cross6d296822010-11-22 18:37:54 -08001361};
1362
Colin Crossd8611962010-01-28 16:40:29 -08001363/* Clock doubler ops */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301364static int tegra20_clk_double_is_enabled(struct clk_hw *hw)
Colin Crossd8611962010-01-28 16:40:29 -08001365{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301366 struct clk_tegra *c = to_clk_tegra(hw);
1367
Colin Crossd8611962010-01-28 16:40:29 -08001368 c->state = ON;
Colin Cross1be3d052011-02-21 16:44:07 -08001369
1370 if (!c->u.periph.clk_num)
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301371 goto out;
Colin Cross1be3d052011-02-21 16:44:07 -08001372
Colin Crossd8611962010-01-28 16:40:29 -08001373 if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
1374 PERIPH_CLK_TO_ENB_BIT(c)))
1375 c->state = OFF;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301376
1377out:
1378 return c->state;
Colin Crossd8611962010-01-28 16:40:29 -08001379};
1380
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301381static unsigned long tegra20_clk_double_recalc_rate(struct clk_hw *hw,
1382 unsigned long prate)
Colin Cross71fc84c2010-06-07 20:49:46 -07001383{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301384 struct clk_tegra *c = to_clk_tegra(hw);
1385 u64 rate = prate;
1386
Colin Cross71fc84c2010-06-07 20:49:46 -07001387 c->mul = 2;
1388 c->div = 1;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301389
1390 rate *= c->mul;
1391 rate += c->div - 1; /* round up */
1392 do_div(rate, c->div);
1393
1394 return rate;
1395}
1396
1397static long tegra20_clk_double_round_rate(struct clk_hw *hw, unsigned long rate,
1398 unsigned long *prate)
1399{
1400 unsigned long output_rate = *prate;
1401
1402 do_div(output_rate, 2);
1403 return output_rate;
1404}
1405
1406static int tegra20_clk_double_set_rate(struct clk_hw *hw, unsigned long rate,
1407 unsigned long parent_rate)
1408{
1409 if (rate != 2 * parent_rate)
1410 return -EINVAL;
Colin Cross71fc84c2010-06-07 20:49:46 -07001411 return 0;
1412}
1413
Prashant Gaikwad86edb872012-08-06 11:57:40 +05301414struct clk_ops tegra_clk_double_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301415 .is_enabled = tegra20_clk_double_is_enabled,
1416 .enable = tegra20_periph_clk_enable,
1417 .disable = tegra20_periph_clk_disable,
1418 .set_rate = tegra20_clk_double_set_rate,
1419 .recalc_rate = tegra20_clk_double_recalc_rate,
1420 .round_rate = tegra20_clk_double_round_rate,
Colin Cross71fc84c2010-06-07 20:49:46 -07001421};
1422
Colin Crosscea62c82010-10-04 11:49:26 -07001423/* Audio sync clock ops */
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301424static int tegra20_audio_sync_clk_is_enabled(struct clk_hw *hw)
Colin Cross71fc84c2010-06-07 20:49:46 -07001425{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301426 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross71fc84c2010-06-07 20:49:46 -07001427 u32 val = clk_readl(c->reg);
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301428
Colin Cross71fc84c2010-06-07 20:49:46 -07001429 c->state = (val & (1<<4)) ? OFF : ON;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301430 return c->state;
Colin Cross71fc84c2010-06-07 20:49:46 -07001431}
1432
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301433static int tegra20_audio_sync_clk_enable(struct clk_hw *hw)
Colin Cross71fc84c2010-06-07 20:49:46 -07001434{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301435 struct clk_tegra *c = to_clk_tegra(hw);
1436
Colin Cross71fc84c2010-06-07 20:49:46 -07001437 clk_writel(0, c->reg);
1438 return 0;
1439}
1440
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301441static void tegra20_audio_sync_clk_disable(struct clk_hw *hw)
Colin Cross71fc84c2010-06-07 20:49:46 -07001442{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301443 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross71fc84c2010-06-07 20:49:46 -07001444 clk_writel(1, c->reg);
1445}
1446
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301447static u8 tegra20_audio_sync_clk_get_parent(struct clk_hw *hw)
Colin Cross71fc84c2010-06-07 20:49:46 -07001448{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301449 struct clk_tegra *c = to_clk_tegra(hw);
1450 u32 val = clk_readl(c->reg);
1451 int source;
1452
1453 source = val & 0xf;
1454 return source;
1455}
1456
1457static int tegra20_audio_sync_clk_set_parent(struct clk_hw *hw, u8 index)
1458{
1459 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross71fc84c2010-06-07 20:49:46 -07001460 u32 val;
Colin Cross71fc84c2010-06-07 20:49:46 -07001461
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301462 val = clk_readl(c->reg);
1463 val &= ~0xf;
1464 val |= index;
Colin Cross71fc84c2010-06-07 20:49:46 -07001465
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301466 clk_writel(val, c->reg);
Colin Cross71fc84c2010-06-07 20:49:46 -07001467
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301468 return 0;
Colin Cross71fc84c2010-06-07 20:49:46 -07001469}
1470
Prashant Gaikwad86edb872012-08-06 11:57:40 +05301471struct clk_ops tegra_audio_sync_clk_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301472 .is_enabled = tegra20_audio_sync_clk_is_enabled,
1473 .enable = tegra20_audio_sync_clk_enable,
1474 .disable = tegra20_audio_sync_clk_disable,
1475 .set_parent = tegra20_audio_sync_clk_set_parent,
1476 .get_parent = tegra20_audio_sync_clk_get_parent,
Colin Crossd8611962010-01-28 16:40:29 -08001477};
1478
Colin Crosscea62c82010-10-04 11:49:26 -07001479/* cdev1 and cdev2 (dap_mclk1 and dap_mclk2) ops */
1480
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301481static int tegra20_cdev_clk_is_enabled(struct clk_hw *hw)
Colin Crosscea62c82010-10-04 11:49:26 -07001482{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301483 struct clk_tegra *c = to_clk_tegra(hw);
Colin Crosscea62c82010-10-04 11:49:26 -07001484 /* We could un-tristate the cdev1 or cdev2 pingroup here; this is
1485 * currently done in the pinmux code. */
1486 c->state = ON;
Colin Cross1be3d052011-02-21 16:44:07 -08001487
1488 BUG_ON(!c->u.periph.clk_num);
1489
Colin Crosscea62c82010-10-04 11:49:26 -07001490 if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
1491 PERIPH_CLK_TO_ENB_BIT(c)))
1492 c->state = OFF;
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301493 return c->state;
Colin Crosscea62c82010-10-04 11:49:26 -07001494}
1495
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301496static int tegra20_cdev_clk_enable(struct clk_hw *hw)
Colin Crosscea62c82010-10-04 11:49:26 -07001497{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301498 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross1be3d052011-02-21 16:44:07 -08001499 BUG_ON(!c->u.periph.clk_num);
1500
Colin Crosscea62c82010-10-04 11:49:26 -07001501 clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
1502 CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
1503 return 0;
1504}
1505
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301506static void tegra20_cdev_clk_disable(struct clk_hw *hw)
Colin Crosscea62c82010-10-04 11:49:26 -07001507{
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301508 struct clk_tegra *c = to_clk_tegra(hw);
Colin Cross1be3d052011-02-21 16:44:07 -08001509 BUG_ON(!c->u.periph.clk_num);
1510
Colin Crosscea62c82010-10-04 11:49:26 -07001511 clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
1512 CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
1513}
1514
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301515static unsigned long tegra20_cdev_recalc_rate(struct clk_hw *hw,
1516 unsigned long prate)
1517{
1518 return to_clk_tegra(hw)->fixed_rate;
1519}
1520
Prashant Gaikwad86edb872012-08-06 11:57:40 +05301521struct clk_ops tegra_cdev_clk_ops = {
Prashant Gaikwad92fe58f2012-08-06 11:57:43 +05301522 .is_enabled = tegra20_cdev_clk_is_enabled,
1523 .enable = tegra20_cdev_clk_enable,
1524 .disable = tegra20_cdev_clk_disable,
1525 .recalc_rate = tegra20_cdev_recalc_rate,
Colin Cross310992c2011-02-12 16:14:03 -08001526};