diff options
author | Prashant Gaikwad <pgaikwad@nvidia.com> | 2012-08-06 02:27:43 -0400 |
---|---|---|
committer | Stephen Warren <swarren@nvidia.com> | 2012-09-06 13:47:20 -0400 |
commit | 92fe58f07f6e51185497785aed632d0e676afe6e (patch) | |
tree | 3791468579de25fa4ada69abacdaf9666a8b7657 /arch/arm/mach-tegra/tegra20_clocks.c | |
parent | 96a1bd1e11ade7be969d275edd4c06749684cdba (diff) |
ARM: tegra: Port tegra to generic clock framework
This patch converts tegra clock code to generic clock framework in following way:
- Implement clk_ops as required by generic clk framework. (tegraXX_clocks.c)
- Use platform specific struct clk_tegra in clk_ops implementation instead of struct clk.
- Initialize all clock data statically. (tegraXX_clocks_data.c)
Legacy framework did not have recalc_rate and is_enabled functions. Implemented these functions.
Removed init function. It's functionality is splitted into recalc_rate and is_enabled.
Static initialization is used since slab is not up in .init_early and clock
is needed to be initialized before clockevent/clocksource initialization.
Macros redefined for clk_tegra.
Also, single struct clk_tegra is used for all type of clocks (PLL, peripheral etc.). This
is to move quickly to generic common clock framework so that other dependent features will
not be blocked (such as DT binding).
Enabling COMMON_CLOCK config moved to ARCH_TEGRA since it is enabled for both Tegra20
and Tegra30.
Signed-off-by: Prashant Gaikwad <pgaikwad@nvidia.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/tegra20_clocks.c')
-rw-r--r-- | arch/arm/mach-tegra/tegra20_clocks.c | 1062 |
1 files changed, 565 insertions, 497 deletions
diff --git a/arch/arm/mach-tegra/tegra20_clocks.c b/arch/arm/mach-tegra/tegra20_clocks.c index 4a32030a4d9..a1e0f8a26b3 100644 --- a/arch/arm/mach-tegra/tegra20_clocks.c +++ b/arch/arm/mach-tegra/tegra20_clocks.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/mach-tegra/tegra2_clocks.c | 2 | * arch/arm/mach-tegra/tegra20_clocks.c |
3 | * | 3 | * |
4 | * Copyright (C) 2010 Google, Inc. | 4 | * Copyright (C) 2010 Google, Inc. |
5 | * Copyright (c) 2010-2012 NVIDIA CORPORATION. All rights reserved. | ||
5 | * | 6 | * |
6 | * Author: | 7 | * Author: |
7 | * Colin Cross <ccross@google.com> | 8 | * Colin Cross <ccross@google.com> |
@@ -98,7 +99,7 @@ | |||
98 | #define PLL_OUT_CLKEN (1<<1) | 99 | #define PLL_OUT_CLKEN (1<<1) |
99 | #define PLL_OUT_RESET_DISABLE (1<<0) | 100 | #define PLL_OUT_RESET_DISABLE (1<<0) |
100 | 101 | ||
101 | #define PLL_MISC(c) (((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc) | 102 | #define PLL_MISC(c) (((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc) |
102 | 103 | ||
103 | #define PLL_MISC_DCCON_SHIFT 20 | 104 | #define PLL_MISC_DCCON_SHIFT 20 |
104 | #define PLL_MISC_CPCON_SHIFT 8 | 105 | #define PLL_MISC_CPCON_SHIFT 8 |
@@ -191,7 +192,8 @@ static unsigned long clk_measure_input_freq(void) | |||
191 | } else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3) { | 192 | } else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3) { |
192 | return 26000000; | 193 | return 26000000; |
193 | } else { | 194 | } else { |
194 | pr_err("%s: Unexpected clock autodetect value %d", __func__, clock_autodetect); | 195 | pr_err("%s: Unexpected clock autodetect value %d", |
196 | __func__, clock_autodetect); | ||
195 | BUG(); | 197 | BUG(); |
196 | return 0; | 198 | return 0; |
197 | } | 199 | } |
@@ -230,12 +232,21 @@ static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate) | |||
230 | } | 232 | } |
231 | 233 | ||
232 | /* clk_m functions */ | 234 | /* clk_m functions */ |
233 | static unsigned long tegra2_clk_m_autodetect_rate(struct clk *c) | 235 | static unsigned long tegra20_clk_m_recalc_rate(struct clk_hw *hw, |
236 | unsigned long prate) | ||
234 | { | 237 | { |
235 | u32 auto_clock_control = clk_readl(OSC_CTRL) & ~OSC_CTRL_OSC_FREQ_MASK; | 238 | 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 | } | ||
242 | |||
243 | static 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; | ||
236 | 248 | ||
237 | c->rate = clk_measure_input_freq(); | 249 | switch (c->fixed_rate) { |
238 | switch (c->rate) { | ||
239 | case 12000000: | 250 | case 12000000: |
240 | auto_clock_control |= OSC_CTRL_OSC_FREQ_12MHZ; | 251 | auto_clock_control |= OSC_CTRL_OSC_FREQ_12MHZ; |
241 | break; | 252 | break; |
@@ -249,35 +260,14 @@ static unsigned long tegra2_clk_m_autodetect_rate(struct clk *c) | |||
249 | auto_clock_control |= OSC_CTRL_OSC_FREQ_26MHZ; | 260 | auto_clock_control |= OSC_CTRL_OSC_FREQ_26MHZ; |
250 | break; | 261 | break; |
251 | default: | 262 | default: |
252 | pr_err("%s: Unexpected clock rate %ld", __func__, c->rate); | ||
253 | BUG(); | 263 | BUG(); |
254 | } | 264 | } |
255 | clk_writel(auto_clock_control, OSC_CTRL); | 265 | clk_writel(auto_clock_control, OSC_CTRL); |
256 | return c->rate; | ||
257 | } | ||
258 | |||
259 | static void tegra2_clk_m_init(struct clk *c) | ||
260 | { | ||
261 | pr_debug("%s on clock %s\n", __func__, c->name); | ||
262 | tegra2_clk_m_autodetect_rate(c); | ||
263 | } | ||
264 | |||
265 | static int tegra2_clk_m_enable(struct clk *c) | ||
266 | { | ||
267 | pr_debug("%s on clock %s\n", __func__, c->name); | ||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static void tegra2_clk_m_disable(struct clk *c) | ||
272 | { | ||
273 | pr_debug("%s on clock %s\n", __func__, c->name); | ||
274 | BUG(); | ||
275 | } | 266 | } |
276 | 267 | ||
277 | struct clk_ops tegra_clk_m_ops = { | 268 | struct clk_ops tegra_clk_m_ops = { |
278 | .init = tegra2_clk_m_init, | 269 | .init = tegra20_clk_m_init, |
279 | .enable = tegra2_clk_m_enable, | 270 | .recalc_rate = tegra20_clk_m_recalc_rate, |
280 | .disable = tegra2_clk_m_disable, | ||
281 | }; | 271 | }; |
282 | 272 | ||
283 | /* super clock functions */ | 273 | /* super clock functions */ |
@@ -286,161 +276,108 @@ struct clk_ops tegra_clk_m_ops = { | |||
286 | * can't lower the voltage when using the clock skip, but we can if we | 276 | * can't lower the voltage when using the clock skip, but we can if we |
287 | * lower the PLL frequency. | 277 | * lower the PLL frequency. |
288 | */ | 278 | */ |
289 | static void tegra2_super_clk_init(struct clk *c) | 279 | static int tegra20_super_clk_is_enabled(struct clk_hw *hw) |
290 | { | 280 | { |
281 | struct clk_tegra *c = to_clk_tegra(hw); | ||
291 | u32 val; | 282 | u32 val; |
292 | int source; | 283 | |
293 | int shift; | ||
294 | const struct clk_mux_sel *sel; | ||
295 | val = clk_readl(c->reg + SUPER_CLK_MUX); | 284 | val = clk_readl(c->reg + SUPER_CLK_MUX); |
296 | c->state = ON; | ||
297 | BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) && | 285 | BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) && |
298 | ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE)); | 286 | ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE)); |
299 | shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ? | 287 | c->state = ON; |
300 | SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT; | 288 | return c->state; |
301 | source = (val >> shift) & SUPER_SOURCE_MASK; | ||
302 | for (sel = c->inputs; sel->input != NULL; sel++) { | ||
303 | if (sel->value == source) | ||
304 | break; | ||
305 | } | ||
306 | BUG_ON(sel->input == NULL); | ||
307 | c->parent = sel->input; | ||
308 | } | 289 | } |
309 | 290 | ||
310 | static int tegra2_super_clk_enable(struct clk *c) | 291 | static int tegra20_super_clk_enable(struct clk_hw *hw) |
311 | { | 292 | { |
293 | struct clk_tegra *c = to_clk_tegra(hw); | ||
312 | clk_writel(0, c->reg + SUPER_CLK_DIVIDER); | 294 | clk_writel(0, c->reg + SUPER_CLK_DIVIDER); |
313 | return 0; | 295 | return 0; |
314 | } | 296 | } |
315 | 297 | ||
316 | static void tegra2_super_clk_disable(struct clk *c) | 298 | static void tegra20_super_clk_disable(struct clk_hw *hw) |
317 | { | 299 | { |
318 | pr_debug("%s on clock %s\n", __func__, c->name); | 300 | pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk)); |
319 | 301 | ||
320 | /* oops - don't disable the CPU clock! */ | 302 | /* oops - don't disable the CPU clock! */ |
321 | BUG(); | 303 | BUG(); |
322 | } | 304 | } |
323 | 305 | ||
324 | static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p) | 306 | static u8 tegra20_super_clk_get_parent(struct clk_hw *hw) |
325 | { | 307 | { |
326 | u32 val; | 308 | struct clk_tegra *c = to_clk_tegra(hw); |
327 | const struct clk_mux_sel *sel; | 309 | int val = clk_readl(c->reg + SUPER_CLK_MUX); |
310 | int source; | ||
328 | int shift; | 311 | int shift; |
329 | 312 | ||
330 | val = clk_readl(c->reg + SUPER_CLK_MUX); | ||
331 | BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) && | 313 | BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) && |
332 | ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE)); | 314 | ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE)); |
333 | shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ? | 315 | shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ? |
334 | SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT; | 316 | SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT; |
335 | for (sel = c->inputs; sel->input != NULL; sel++) { | 317 | source = (val >> shift) & SUPER_SOURCE_MASK; |
336 | if (sel->input == p) { | 318 | return source; |
337 | val &= ~(SUPER_SOURCE_MASK << shift); | 319 | } |
338 | val |= sel->value << shift; | ||
339 | 320 | ||
340 | if (c->refcnt) | 321 | static int tegra20_super_clk_set_parent(struct clk_hw *hw, u8 index) |
341 | clk_enable(p); | 322 | { |
323 | struct clk_tegra *c = to_clk_tegra(hw); | ||
324 | u32 val = clk_readl(c->reg + SUPER_CLK_MUX); | ||
325 | int shift; | ||
342 | 326 | ||
343 | clk_writel(val, c->reg); | 327 | 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; | ||
331 | val &= ~(SUPER_SOURCE_MASK << shift); | ||
332 | val |= index << shift; | ||
344 | 333 | ||
345 | if (c->refcnt && c->parent) | 334 | clk_writel(val, c->reg); |
346 | clk_disable(c->parent); | ||
347 | 335 | ||
348 | clk_reparent(c, p); | 336 | return 0; |
349 | return 0; | ||
350 | } | ||
351 | } | ||
352 | return -EINVAL; | ||
353 | } | 337 | } |
354 | 338 | ||
355 | /* | 339 | /* FIX ME: Need to switch parents to change the source PLL rate */ |
356 | * Super clocks have "clock skippers" instead of dividers. Dividing using | 340 | static unsigned long tegra20_super_clk_recalc_rate(struct clk_hw *hw, |
357 | * a clock skipper does not allow the voltage to be scaled down, so instead | 341 | unsigned long prate) |
358 | * adjust the rate of the parent clock. This requires that the parent of a | ||
359 | * super clock have no other children, otherwise the rate will change | ||
360 | * underneath the other children. | ||
361 | */ | ||
362 | static int tegra2_super_clk_set_rate(struct clk *c, unsigned long rate) | ||
363 | { | 342 | { |
364 | return clk_set_rate(c->parent, rate); | 343 | return prate; |
365 | } | 344 | } |
366 | 345 | ||
367 | struct clk_ops tegra_super_ops = { | 346 | static long tegra20_super_clk_round_rate(struct clk_hw *hw, unsigned long rate, |
368 | .init = tegra2_super_clk_init, | 347 | unsigned long *prate) |
369 | .enable = tegra2_super_clk_enable, | ||
370 | .disable = tegra2_super_clk_disable, | ||
371 | .set_parent = tegra2_super_clk_set_parent, | ||
372 | .set_rate = tegra2_super_clk_set_rate, | ||
373 | }; | ||
374 | |||
375 | /* virtual cpu clock functions */ | ||
376 | /* some clocks can not be stopped (cpu, memory bus) while the SoC is running. | ||
377 | To change the frequency of these clocks, the parent pll may need to be | ||
378 | reprogrammed, so the clock must be moved off the pll, the pll reprogrammed, | ||
379 | and then the clock moved back to the pll. To hide this sequence, a virtual | ||
380 | clock handles it. | ||
381 | */ | ||
382 | static void tegra2_cpu_clk_init(struct clk *c) | ||
383 | { | 348 | { |
349 | return *prate; | ||
384 | } | 350 | } |
385 | 351 | ||
386 | static int tegra2_cpu_clk_enable(struct clk *c) | 352 | static int tegra20_super_clk_set_rate(struct clk_hw *hw, unsigned long rate, |
353 | unsigned long parent_rate) | ||
387 | { | 354 | { |
388 | return 0; | 355 | return 0; |
389 | } | 356 | } |
390 | 357 | ||
391 | static void tegra2_cpu_clk_disable(struct clk *c) | 358 | struct clk_ops tegra_super_ops = { |
392 | { | 359 | .is_enabled = tegra20_super_clk_is_enabled, |
393 | pr_debug("%s on clock %s\n", __func__, c->name); | 360 | .enable = tegra20_super_clk_enable, |
394 | 361 | .disable = tegra20_super_clk_disable, | |
395 | /* oops - don't disable the CPU clock! */ | 362 | .set_parent = tegra20_super_clk_set_parent, |
396 | BUG(); | 363 | .get_parent = tegra20_super_clk_get_parent, |
397 | } | 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 | }; | ||
398 | 368 | ||
399 | static int tegra2_cpu_clk_set_rate(struct clk *c, unsigned long rate) | 369 | static u8 tegra20_cop_clk_get_parent(struct clk_hw *hw) |
400 | { | 370 | { |
401 | int ret; | 371 | return 0; |
402 | /* | ||
403 | * Take an extra reference to the main pll so it doesn't turn | ||
404 | * off when we move the cpu off of it | ||
405 | */ | ||
406 | clk_enable(c->u.cpu.main); | ||
407 | |||
408 | ret = clk_set_parent(c->parent, c->u.cpu.backup); | ||
409 | if (ret) { | ||
410 | pr_err("Failed to switch cpu to clock %s\n", c->u.cpu.backup->name); | ||
411 | goto out; | ||
412 | } | ||
413 | |||
414 | if (rate == clk_get_rate(c->u.cpu.backup)) | ||
415 | goto out; | ||
416 | |||
417 | ret = clk_set_rate(c->u.cpu.main, rate); | ||
418 | if (ret) { | ||
419 | pr_err("Failed to change cpu pll to %lu\n", rate); | ||
420 | goto out; | ||
421 | } | ||
422 | |||
423 | ret = clk_set_parent(c->parent, c->u.cpu.main); | ||
424 | if (ret) { | ||
425 | pr_err("Failed to switch cpu to clock %s\n", c->u.cpu.main->name); | ||
426 | goto out; | ||
427 | } | ||
428 | |||
429 | out: | ||
430 | clk_disable(c->u.cpu.main); | ||
431 | return ret; | ||
432 | } | 372 | } |
433 | 373 | ||
434 | struct clk_ops tegra_cpu_ops = { | 374 | struct clk_ops tegra_cop_ops = { |
435 | .init = tegra2_cpu_clk_init, | 375 | .get_parent = tegra20_cop_clk_get_parent, |
436 | .enable = tegra2_cpu_clk_enable, | ||
437 | .disable = tegra2_cpu_clk_disable, | ||
438 | .set_rate = tegra2_cpu_clk_set_rate, | ||
439 | }; | 376 | }; |
440 | 377 | ||
441 | /* virtual cop clock functions. Used to acquire the fake 'cop' clock to | 378 | /* virtual cop clock functions. Used to acquire the fake 'cop' clock to |
442 | * reset the COP block (i.e. AVP) */ | 379 | * reset the COP block (i.e. AVP) */ |
443 | static void tegra2_cop_clk_reset(struct clk *c, bool assert) | 380 | void tegra2_cop_clk_reset(struct clk_hw *hw, bool assert) |
444 | { | 381 | { |
445 | unsigned long reg = assert ? RST_DEVICES_SET : RST_DEVICES_CLR; | 382 | unsigned long reg = assert ? RST_DEVICES_SET : RST_DEVICES_CLR; |
446 | 383 | ||
@@ -448,23 +385,21 @@ static void tegra2_cop_clk_reset(struct clk *c, bool assert) | |||
448 | clk_writel(1 << 1, reg); | 385 | clk_writel(1 << 1, reg); |
449 | } | 386 | } |
450 | 387 | ||
451 | struct clk_ops tegra_cop_ops = { | ||
452 | .reset = tegra2_cop_clk_reset, | ||
453 | }; | ||
454 | |||
455 | /* bus clock functions */ | 388 | /* bus clock functions */ |
456 | static void tegra2_bus_clk_init(struct clk *c) | 389 | static int tegra20_bus_clk_is_enabled(struct clk_hw *hw) |
457 | { | 390 | { |
391 | struct clk_tegra *c = to_clk_tegra(hw); | ||
458 | u32 val = clk_readl(c->reg); | 392 | u32 val = clk_readl(c->reg); |
393 | |||
459 | c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON; | 394 | c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON; |
460 | c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1; | 395 | return c->state; |
461 | c->mul = 1; | ||
462 | } | 396 | } |
463 | 397 | ||
464 | static int tegra2_bus_clk_enable(struct clk *c) | 398 | static int tegra20_bus_clk_enable(struct clk_hw *hw) |
465 | { | 399 | { |
466 | u32 val; | 400 | struct clk_tegra *c = to_clk_tegra(hw); |
467 | unsigned long flags; | 401 | unsigned long flags; |
402 | u32 val; | ||
468 | 403 | ||
469 | spin_lock_irqsave(&clock_register_lock, flags); | 404 | spin_lock_irqsave(&clock_register_lock, flags); |
470 | 405 | ||
@@ -477,10 +412,11 @@ static int tegra2_bus_clk_enable(struct clk *c) | |||
477 | return 0; | 412 | return 0; |
478 | } | 413 | } |
479 | 414 | ||
480 | static void tegra2_bus_clk_disable(struct clk *c) | 415 | static void tegra20_bus_clk_disable(struct clk_hw *hw) |
481 | { | 416 | { |
482 | u32 val; | 417 | struct clk_tegra *c = to_clk_tegra(hw); |
483 | unsigned long flags; | 418 | unsigned long flags; |
419 | u32 val; | ||
484 | 420 | ||
485 | spin_lock_irqsave(&clock_register_lock, flags); | 421 | spin_lock_irqsave(&clock_register_lock, flags); |
486 | 422 | ||
@@ -491,12 +427,31 @@ static void tegra2_bus_clk_disable(struct clk *c) | |||
491 | spin_unlock_irqrestore(&clock_register_lock, flags); | 427 | spin_unlock_irqrestore(&clock_register_lock, flags); |
492 | } | 428 | } |
493 | 429 | ||
494 | static int tegra2_bus_clk_set_rate(struct clk *c, unsigned long rate) | 430 | static unsigned long tegra20_bus_clk_recalc_rate(struct clk_hw *hw, |
431 | unsigned long prate) | ||
495 | { | 432 | { |
496 | u32 val; | 433 | struct clk_tegra *c = to_clk_tegra(hw); |
497 | unsigned long parent_rate = clk_get_rate(c->parent); | 434 | u32 val = clk_readl(c->reg); |
498 | unsigned long flags; | 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 | |||
448 | static 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); | ||
499 | int ret = -EINVAL; | 452 | int ret = -EINVAL; |
453 | unsigned long flags; | ||
454 | u32 val; | ||
500 | int i; | 455 | int i; |
501 | 456 | ||
502 | spin_lock_irqsave(&clock_register_lock, flags); | 457 | spin_lock_irqsave(&clock_register_lock, flags); |
@@ -519,21 +474,56 @@ static int tegra2_bus_clk_set_rate(struct clk *c, unsigned long rate) | |||
519 | return ret; | 474 | return ret; |
520 | } | 475 | } |
521 | 476 | ||
477 | static 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 | |||
522 | struct clk_ops tegra_bus_ops = { | 500 | struct clk_ops tegra_bus_ops = { |
523 | .init = tegra2_bus_clk_init, | 501 | .is_enabled = tegra20_bus_clk_is_enabled, |
524 | .enable = tegra2_bus_clk_enable, | 502 | .enable = tegra20_bus_clk_enable, |
525 | .disable = tegra2_bus_clk_disable, | 503 | .disable = tegra20_bus_clk_disable, |
526 | .set_rate = tegra2_bus_clk_set_rate, | 504 | .set_rate = tegra20_bus_clk_set_rate, |
505 | .round_rate = tegra20_bus_clk_round_rate, | ||
506 | .recalc_rate = tegra20_bus_clk_recalc_rate, | ||
527 | }; | 507 | }; |
528 | 508 | ||
529 | /* Blink output functions */ | 509 | /* Blink output functions */ |
530 | 510 | static int tegra20_blink_clk_is_enabled(struct clk_hw *hw) | |
531 | static void tegra2_blink_clk_init(struct clk *c) | ||
532 | { | 511 | { |
512 | struct clk_tegra *c = to_clk_tegra(hw); | ||
533 | u32 val; | 513 | u32 val; |
534 | 514 | ||
535 | val = pmc_readl(PMC_CTRL); | 515 | val = pmc_readl(PMC_CTRL); |
536 | c->state = (val & PMC_CTRL_BLINK_ENB) ? ON : OFF; | 516 | c->state = (val & PMC_CTRL_BLINK_ENB) ? ON : OFF; |
517 | return c->state; | ||
518 | } | ||
519 | |||
520 | static 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 | |||
537 | c->mul = 1; | 527 | c->mul = 1; |
538 | val = pmc_readl(c->reg); | 528 | val = pmc_readl(c->reg); |
539 | 529 | ||
@@ -550,9 +540,16 @@ static void tegra2_blink_clk_init(struct clk *c) | |||
550 | } else { | 540 | } else { |
551 | c->div = 1; | 541 | c->div = 1; |
552 | } | 542 | } |
543 | |||
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; | ||
553 | } | 550 | } |
554 | 551 | ||
555 | static int tegra2_blink_clk_enable(struct clk *c) | 552 | static int tegra20_blink_clk_enable(struct clk_hw *hw) |
556 | { | 553 | { |
557 | u32 val; | 554 | u32 val; |
558 | 555 | ||
@@ -565,7 +562,7 @@ static int tegra2_blink_clk_enable(struct clk *c) | |||
565 | return 0; | 562 | return 0; |
566 | } | 563 | } |
567 | 564 | ||
568 | static void tegra2_blink_clk_disable(struct clk *c) | 565 | static void tegra20_blink_clk_disable(struct clk_hw *hw) |
569 | { | 566 | { |
570 | u32 val; | 567 | u32 val; |
571 | 568 | ||
@@ -576,9 +573,11 @@ static void tegra2_blink_clk_disable(struct clk *c) | |||
576 | pmc_writel(val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE); | 573 | pmc_writel(val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE); |
577 | } | 574 | } |
578 | 575 | ||
579 | static int tegra2_blink_clk_set_rate(struct clk *c, unsigned long rate) | 576 | static int tegra20_blink_clk_set_rate(struct clk_hw *hw, unsigned long rate, |
577 | unsigned long parent_rate) | ||
580 | { | 578 | { |
581 | unsigned long parent_rate = clk_get_rate(c->parent); | 579 | struct clk_tegra *c = to_clk_tegra(hw); |
580 | |||
582 | if (rate >= parent_rate) { | 581 | if (rate >= parent_rate) { |
583 | c->div = 1; | 582 | c->div = 1; |
584 | pmc_writel(0, c->reg); | 583 | pmc_writel(0, c->reg); |
@@ -601,31 +600,74 @@ static int tegra2_blink_clk_set_rate(struct clk *c, unsigned long rate) | |||
601 | return 0; | 600 | return 0; |
602 | } | 601 | } |
603 | 602 | ||
603 | static 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 | |||
604 | struct clk_ops tegra_blink_clk_ops = { | 626 | struct clk_ops tegra_blink_clk_ops = { |
605 | .init = &tegra2_blink_clk_init, | 627 | .is_enabled = tegra20_blink_clk_is_enabled, |
606 | .enable = &tegra2_blink_clk_enable, | 628 | .enable = tegra20_blink_clk_enable, |
607 | .disable = &tegra2_blink_clk_disable, | 629 | .disable = tegra20_blink_clk_disable, |
608 | .set_rate = &tegra2_blink_clk_set_rate, | 630 | .set_rate = tegra20_blink_clk_set_rate, |
631 | .round_rate = tegra20_blink_clk_round_rate, | ||
632 | .recalc_rate = tegra20_blink_clk_recalc_rate, | ||
609 | }; | 633 | }; |
610 | 634 | ||
611 | /* PLL Functions */ | 635 | /* PLL Functions */ |
612 | static int tegra2_pll_clk_wait_for_lock(struct clk *c) | 636 | static int tegra20_pll_clk_wait_for_lock(struct clk_tegra *c) |
613 | { | 637 | { |
614 | udelay(c->u.pll.lock_delay); | 638 | udelay(c->u.pll.lock_delay); |
615 | |||
616 | return 0; | 639 | return 0; |
617 | } | 640 | } |
618 | 641 | ||
619 | static void tegra2_pll_clk_init(struct clk *c) | 642 | static int tegra20_pll_clk_is_enabled(struct clk_hw *hw) |
620 | { | 643 | { |
644 | struct clk_tegra *c = to_clk_tegra(hw); | ||
621 | u32 val = clk_readl(c->reg + PLL_BASE); | 645 | u32 val = clk_readl(c->reg + PLL_BASE); |
622 | 646 | ||
623 | c->state = (val & PLL_BASE_ENABLE) ? ON : OFF; | 647 | c->state = (val & PLL_BASE_ENABLE) ? ON : OFF; |
648 | return c->state; | ||
649 | } | ||
650 | |||
651 | static 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; | ||
624 | 657 | ||
625 | if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) { | 658 | if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) { |
626 | pr_warning("Clock %s has unknown fixed frequency\n", c->name); | 659 | const struct clk_pll_freq_table *sel; |
627 | c->mul = 1; | 660 | for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) { |
628 | c->div = 1; | 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(); | ||
629 | } else if (val & PLL_BASE_BYPASS) { | 671 | } else if (val & PLL_BASE_BYPASS) { |
630 | c->mul = 1; | 672 | c->mul = 1; |
631 | c->div = 1; | 673 | c->div = 1; |
@@ -637,42 +679,63 @@ static void tegra2_pll_clk_init(struct clk *c) | |||
637 | else | 679 | else |
638 | c->div *= (val & PLL_BASE_DIVP_MASK) ? 2 : 1; | 680 | c->div *= (val & PLL_BASE_DIVP_MASK) ? 2 : 1; |
639 | } | 681 | } |
682 | |||
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; | ||
640 | } | 689 | } |
641 | 690 | ||
642 | static int tegra2_pll_clk_enable(struct clk *c) | 691 | static int tegra20_pll_clk_enable(struct clk_hw *hw) |
643 | { | 692 | { |
693 | struct clk_tegra *c = to_clk_tegra(hw); | ||
644 | u32 val; | 694 | u32 val; |
645 | pr_debug("%s on clock %s\n", __func__, c->name); | 695 | pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk)); |
646 | 696 | ||
647 | val = clk_readl(c->reg + PLL_BASE); | 697 | val = clk_readl(c->reg + PLL_BASE); |
648 | val &= ~PLL_BASE_BYPASS; | 698 | val &= ~PLL_BASE_BYPASS; |
649 | val |= PLL_BASE_ENABLE; | 699 | val |= PLL_BASE_ENABLE; |
650 | clk_writel(val, c->reg + PLL_BASE); | 700 | clk_writel(val, c->reg + PLL_BASE); |
651 | 701 | ||
652 | tegra2_pll_clk_wait_for_lock(c); | 702 | tegra20_pll_clk_wait_for_lock(c); |
653 | 703 | ||
654 | return 0; | 704 | return 0; |
655 | } | 705 | } |
656 | 706 | ||
657 | static void tegra2_pll_clk_disable(struct clk *c) | 707 | static void tegra20_pll_clk_disable(struct clk_hw *hw) |
658 | { | 708 | { |
709 | struct clk_tegra *c = to_clk_tegra(hw); | ||
659 | u32 val; | 710 | u32 val; |
660 | pr_debug("%s on clock %s\n", __func__, c->name); | 711 | pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk)); |
661 | 712 | ||
662 | val = clk_readl(c->reg); | 713 | val = clk_readl(c->reg); |
663 | val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE); | 714 | val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE); |
664 | clk_writel(val, c->reg); | 715 | clk_writel(val, c->reg); |
665 | } | 716 | } |
666 | 717 | ||
667 | static int tegra2_pll_clk_set_rate(struct clk *c, unsigned long rate) | 718 | static int tegra20_pll_clk_set_rate(struct clk_hw *hw, unsigned long rate, |
719 | unsigned long parent_rate) | ||
668 | { | 720 | { |
669 | u32 val; | 721 | struct clk_tegra *c = to_clk_tegra(hw); |
670 | unsigned long input_rate; | 722 | unsigned long input_rate = parent_rate; |
671 | const struct clk_pll_freq_table *sel; | 723 | const struct clk_pll_freq_table *sel; |
724 | u32 val; | ||
672 | 725 | ||
673 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); | 726 | pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate); |
727 | |||
728 | 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 | } | ||
674 | 738 | ||
675 | input_rate = clk_get_rate(c->parent); | ||
676 | for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) { | 739 | for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) { |
677 | if (sel->input_rate == input_rate && sel->output_rate == rate) { | 740 | if (sel->input_rate == input_rate && sel->output_rate == rate) { |
678 | c->mul = sel->n; | 741 | c->mul = sel->n; |
@@ -703,41 +766,76 @@ static int tegra2_pll_clk_set_rate(struct clk *c, unsigned long rate) | |||
703 | } | 766 | } |
704 | 767 | ||
705 | if (c->state == ON) | 768 | if (c->state == ON) |
706 | tegra2_pll_clk_enable(c); | 769 | tegra20_pll_clk_enable(hw); |
707 | |||
708 | return 0; | 770 | return 0; |
709 | } | 771 | } |
710 | } | 772 | } |
711 | return -EINVAL; | 773 | return -EINVAL; |
712 | } | 774 | } |
713 | 775 | ||
776 | static 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 | |||
714 | struct clk_ops tegra_pll_ops = { | 806 | struct clk_ops tegra_pll_ops = { |
715 | .init = tegra2_pll_clk_init, | 807 | .is_enabled = tegra20_pll_clk_is_enabled, |
716 | .enable = tegra2_pll_clk_enable, | 808 | .enable = tegra20_pll_clk_enable, |
717 | .disable = tegra2_pll_clk_disable, | 809 | .disable = tegra20_pll_clk_disable, |
718 | .set_rate = tegra2_pll_clk_set_rate, | 810 | .set_rate = tegra20_pll_clk_set_rate, |
811 | .recalc_rate = tegra20_pll_clk_recalc_rate, | ||
812 | .round_rate = tegra20_pll_clk_round_rate, | ||
719 | }; | 813 | }; |
720 | 814 | ||
721 | static void tegra2_pllx_clk_init(struct clk *c) | 815 | static void tegra20_pllx_clk_init(struct clk_hw *hw) |
722 | { | 816 | { |
723 | tegra2_pll_clk_init(c); | 817 | struct clk_tegra *c = to_clk_tegra(hw); |
724 | 818 | ||
725 | if (tegra_sku_id == 7) | 819 | if (tegra_sku_id == 7) |
726 | c->max_rate = 750000000; | 820 | c->max_rate = 750000000; |
727 | } | 821 | } |
728 | 822 | ||
729 | struct clk_ops tegra_pllx_ops = { | 823 | struct clk_ops tegra_pllx_ops = { |
730 | .init = tegra2_pllx_clk_init, | 824 | .init = tegra20_pllx_clk_init, |
731 | .enable = tegra2_pll_clk_enable, | 825 | .is_enabled = tegra20_pll_clk_is_enabled, |
732 | .disable = tegra2_pll_clk_disable, | 826 | .enable = tegra20_pll_clk_enable, |
733 | .set_rate = tegra2_pll_clk_set_rate, | 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, | ||
734 | }; | 831 | }; |
735 | 832 | ||
736 | static int tegra2_plle_clk_enable(struct clk *c) | 833 | static int tegra20_plle_clk_enable(struct clk_hw *hw) |
737 | { | 834 | { |
835 | struct clk_tegra *c = to_clk_tegra(hw); | ||
738 | u32 val; | 836 | u32 val; |
739 | 837 | ||
740 | pr_debug("%s on clock %s\n", __func__, c->name); | 838 | pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk)); |
741 | 839 | ||
742 | mdelay(1); | 840 | mdelay(1); |
743 | 841 | ||
@@ -753,20 +851,35 @@ static int tegra2_plle_clk_enable(struct clk *c) | |||
753 | } | 851 | } |
754 | 852 | ||
755 | struct clk_ops tegra_plle_ops = { | 853 | struct clk_ops tegra_plle_ops = { |
756 | .init = tegra2_pll_clk_init, | 854 | .is_enabled = tegra20_pll_clk_is_enabled, |
757 | .enable = tegra2_plle_clk_enable, | 855 | .enable = tegra20_plle_clk_enable, |
758 | .set_rate = tegra2_pll_clk_set_rate, | 856 | .set_rate = tegra20_pll_clk_set_rate, |
857 | .recalc_rate = tegra20_pll_clk_recalc_rate, | ||
858 | .round_rate = tegra20_pll_clk_round_rate, | ||
759 | }; | 859 | }; |
760 | 860 | ||
761 | /* Clock divider ops */ | 861 | /* Clock divider ops */ |
762 | static void tegra2_pll_div_clk_init(struct clk *c) | 862 | static int tegra20_pll_div_clk_is_enabled(struct clk_hw *hw) |
763 | { | 863 | { |
864 | struct clk_tegra *c = to_clk_tegra(hw); | ||
764 | u32 val = clk_readl(c->reg); | 865 | u32 val = clk_readl(c->reg); |
765 | u32 divu71; | 866 | |
766 | val >>= c->reg_shift; | 867 | val >>= c->reg_shift; |
767 | c->state = (val & PLL_OUT_CLKEN) ? ON : OFF; | 868 | c->state = (val & PLL_OUT_CLKEN) ? ON : OFF; |
768 | if (!(val & PLL_OUT_RESET_DISABLE)) | 869 | if (!(val & PLL_OUT_RESET_DISABLE)) |
769 | c->state = OFF; | 870 | c->state = OFF; |
871 | return c->state; | ||
872 | } | ||
873 | |||
874 | static 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; | ||
770 | 883 | ||
771 | if (c->flags & DIV_U71) { | 884 | if (c->flags & DIV_U71) { |
772 | divu71 = (val & PLL_OUT_RATIO_MASK) >> PLL_OUT_RATIO_SHIFT; | 885 | divu71 = (val & PLL_OUT_RATIO_MASK) >> PLL_OUT_RATIO_SHIFT; |
@@ -779,15 +892,23 @@ static void tegra2_pll_div_clk_init(struct clk *c) | |||
779 | c->div = 1; | 892 | c->div = 1; |
780 | c->mul = 1; | 893 | c->mul = 1; |
781 | } | 894 | } |
895 | |||
896 | rate *= c->mul; | ||
897 | rate += c->div - 1; /* round up */ | ||
898 | do_div(rate, c->div); | ||
899 | |||
900 | return rate; | ||
782 | } | 901 | } |
783 | 902 | ||
784 | static int tegra2_pll_div_clk_enable(struct clk *c) | 903 | static int tegra20_pll_div_clk_enable(struct clk_hw *hw) |
785 | { | 904 | { |
786 | u32 val; | 905 | struct clk_tegra *c = to_clk_tegra(hw); |
787 | u32 new_val; | ||
788 | unsigned long flags; | 906 | unsigned long flags; |
907 | u32 new_val; | ||
908 | u32 val; | ||
909 | |||
910 | pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk)); | ||
789 | 911 | ||
790 | pr_debug("%s: %s\n", __func__, c->name); | ||
791 | if (c->flags & DIV_U71) { | 912 | if (c->flags & DIV_U71) { |
792 | spin_lock_irqsave(&clock_register_lock, flags); | 913 | spin_lock_irqsave(&clock_register_lock, flags); |
793 | val = clk_readl(c->reg); | 914 | val = clk_readl(c->reg); |
@@ -813,13 +934,15 @@ static int tegra2_pll_div_clk_enable(struct clk *c) | |||
813 | return -EINVAL; | 934 | return -EINVAL; |
814 | } | 935 | } |
815 | 936 | ||
816 | static void tegra2_pll_div_clk_disable(struct clk *c) | 937 | static void tegra20_pll_div_clk_disable(struct clk_hw *hw) |
817 | { | 938 | { |
818 | u32 val; | 939 | struct clk_tegra *c = to_clk_tegra(hw); |
819 | u32 new_val; | ||
820 | unsigned long flags; | 940 | unsigned long flags; |
941 | u32 new_val; | ||
942 | u32 val; | ||
943 | |||
944 | pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk)); | ||
821 | 945 | ||
822 | pr_debug("%s: %s\n", __func__, c->name); | ||
823 | if (c->flags & DIV_U71) { | 946 | if (c->flags & DIV_U71) { |
824 | spin_lock_irqsave(&clock_register_lock, flags); | 947 | spin_lock_irqsave(&clock_register_lock, flags); |
825 | val = clk_readl(c->reg); | 948 | val = clk_readl(c->reg); |
@@ -842,15 +965,17 @@ static void tegra2_pll_div_clk_disable(struct clk *c) | |||
842 | } | 965 | } |
843 | } | 966 | } |
844 | 967 | ||
845 | static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate) | 968 | static int tegra20_pll_div_clk_set_rate(struct clk_hw *hw, unsigned long rate, |
969 | unsigned long parent_rate) | ||
846 | { | 970 | { |
847 | u32 val; | 971 | struct clk_tegra *c = to_clk_tegra(hw); |
848 | u32 new_val; | ||
849 | int divider_u71; | ||
850 | unsigned long parent_rate = clk_get_rate(c->parent); | ||
851 | unsigned long flags; | 972 | unsigned long flags; |
973 | int divider_u71; | ||
974 | u32 new_val; | ||
975 | u32 val; | ||
976 | |||
977 | pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate); | ||
852 | 978 | ||
853 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); | ||
854 | if (c->flags & DIV_U71) { | 979 | if (c->flags & DIV_U71) { |
855 | divider_u71 = clk_div71_get_divider(parent_rate, rate); | 980 | divider_u71 = clk_div71_get_divider(parent_rate, rate); |
856 | if (divider_u71 >= 0) { | 981 | if (divider_u71 >= 0) { |
@@ -878,11 +1003,14 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate) | |||
878 | return -EINVAL; | 1003 | return -EINVAL; |
879 | } | 1004 | } |
880 | 1005 | ||
881 | static long tegra2_pll_div_clk_round_rate(struct clk *c, unsigned long rate) | 1006 | static long tegra20_pll_div_clk_round_rate(struct clk_hw *hw, unsigned long rate, |
1007 | unsigned long *prate) | ||
882 | { | 1008 | { |
1009 | struct clk_tegra *c = to_clk_tegra(hw); | ||
1010 | unsigned long parent_rate = *prate; | ||
883 | int divider; | 1011 | int divider; |
884 | unsigned long parent_rate = clk_get_rate(c->parent); | 1012 | |
885 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); | 1013 | pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate); |
886 | 1014 | ||
887 | if (c->flags & DIV_U71) { | 1015 | if (c->flags & DIV_U71) { |
888 | divider = clk_div71_get_divider(parent_rate, rate); | 1016 | divider = clk_div71_get_divider(parent_rate, rate); |
@@ -896,60 +1024,24 @@ static long tegra2_pll_div_clk_round_rate(struct clk *c, unsigned long rate) | |||
896 | } | 1024 | } |
897 | 1025 | ||
898 | struct clk_ops tegra_pll_div_ops = { | 1026 | struct clk_ops tegra_pll_div_ops = { |
899 | .init = tegra2_pll_div_clk_init, | 1027 | .is_enabled = tegra20_pll_div_clk_is_enabled, |
900 | .enable = tegra2_pll_div_clk_enable, | 1028 | .enable = tegra20_pll_div_clk_enable, |
901 | .disable = tegra2_pll_div_clk_disable, | 1029 | .disable = tegra20_pll_div_clk_disable, |
902 | .set_rate = tegra2_pll_div_clk_set_rate, | 1030 | .set_rate = tegra20_pll_div_clk_set_rate, |
903 | .round_rate = tegra2_pll_div_clk_round_rate, | 1031 | .round_rate = tegra20_pll_div_clk_round_rate, |
1032 | .recalc_rate = tegra20_pll_div_clk_recalc_rate, | ||
904 | }; | 1033 | }; |
905 | 1034 | ||
906 | /* Periph clk ops */ | 1035 | /* Periph clk ops */ |
907 | 1036 | ||
908 | static void tegra2_periph_clk_init(struct clk *c) | 1037 | static int tegra20_periph_clk_is_enabled(struct clk_hw *hw) |
909 | { | 1038 | { |
910 | u32 val = clk_readl(c->reg); | 1039 | struct clk_tegra *c = to_clk_tegra(hw); |
911 | const struct clk_mux_sel *mux = NULL; | ||
912 | const struct clk_mux_sel *sel; | ||
913 | u32 shift; | ||
914 | u32 mask; | ||
915 | |||
916 | if (c->flags & MUX_PWM) { | ||
917 | shift = PERIPH_CLK_SOURCE_PWM_SHIFT; | ||
918 | mask = PERIPH_CLK_SOURCE_PWM_MASK; | ||
919 | } else { | ||
920 | shift = PERIPH_CLK_SOURCE_SHIFT; | ||
921 | mask = PERIPH_CLK_SOURCE_MASK; | ||
922 | } | ||
923 | |||
924 | if (c->flags & MUX) { | ||
925 | for (sel = c->inputs; sel->input != NULL; sel++) { | ||
926 | if ((val & mask) >> shift == sel->value) | ||
927 | mux = sel; | ||
928 | } | ||
929 | BUG_ON(!mux); | ||
930 | |||
931 | c->parent = mux->input; | ||
932 | } else { | ||
933 | c->parent = c->inputs[0].input; | ||
934 | } | ||
935 | |||
936 | if (c->flags & DIV_U71) { | ||
937 | u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK; | ||
938 | c->div = divu71 + 2; | ||
939 | c->mul = 2; | ||
940 | } else if (c->flags & DIV_U16) { | ||
941 | u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK; | ||
942 | c->div = divu16 + 1; | ||
943 | c->mul = 1; | ||
944 | } else { | ||
945 | c->div = 1; | ||
946 | c->mul = 1; | ||
947 | } | ||
948 | 1040 | ||
949 | c->state = ON; | 1041 | c->state = ON; |
950 | 1042 | ||
951 | if (!c->u.periph.clk_num) | 1043 | if (!c->u.periph.clk_num) |
952 | return; | 1044 | goto out; |
953 | 1045 | ||
954 | if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & | 1046 | if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & |
955 | PERIPH_CLK_TO_ENB_BIT(c))) | 1047 | PERIPH_CLK_TO_ENB_BIT(c))) |
@@ -959,24 +1051,27 @@ static void tegra2_periph_clk_init(struct clk *c) | |||
959 | if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) & | 1051 | if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) & |
960 | PERIPH_CLK_TO_ENB_BIT(c)) | 1052 | PERIPH_CLK_TO_ENB_BIT(c)) |
961 | c->state = OFF; | 1053 | c->state = OFF; |
1054 | |||
1055 | out: | ||
1056 | return c->state; | ||
962 | } | 1057 | } |
963 | 1058 | ||
964 | static int tegra2_periph_clk_enable(struct clk *c) | 1059 | static int tegra20_periph_clk_enable(struct clk_hw *hw) |
965 | { | 1060 | { |
966 | u32 val; | 1061 | struct clk_tegra *c = to_clk_tegra(hw); |
967 | unsigned long flags; | 1062 | unsigned long flags; |
968 | int refcount; | 1063 | u32 val; |
969 | pr_debug("%s on clock %s\n", __func__, c->name); | 1064 | |
1065 | pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk)); | ||
970 | 1066 | ||
971 | if (!c->u.periph.clk_num) | 1067 | if (!c->u.periph.clk_num) |
972 | return 0; | 1068 | return 0; |
973 | 1069 | ||
974 | spin_lock_irqsave(&clock_register_lock, flags); | 1070 | tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++; |
975 | 1071 | if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 1) | |
976 | refcount = tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++; | 1072 | return 0; |
977 | 1073 | ||
978 | if (refcount > 1) | 1074 | spin_lock_irqsave(&clock_register_lock, flags); |
979 | goto out; | ||
980 | 1075 | ||
981 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), | 1076 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), |
982 | CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c)); | 1077 | CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c)); |
@@ -991,39 +1086,41 @@ static int tegra2_periph_clk_enable(struct clk *c) | |||
991 | clk_writel(val, c->reg); | 1086 | clk_writel(val, c->reg); |
992 | } | 1087 | } |
993 | 1088 | ||
994 | out: | ||
995 | spin_unlock_irqrestore(&clock_register_lock, flags); | 1089 | spin_unlock_irqrestore(&clock_register_lock, flags); |
996 | 1090 | ||
997 | return 0; | 1091 | return 0; |
998 | } | 1092 | } |
999 | 1093 | ||
1000 | static void tegra2_periph_clk_disable(struct clk *c) | 1094 | static void tegra20_periph_clk_disable(struct clk_hw *hw) |
1001 | { | 1095 | { |
1096 | struct clk_tegra *c = to_clk_tegra(hw); | ||
1002 | unsigned long flags; | 1097 | unsigned long flags; |
1003 | 1098 | ||
1004 | pr_debug("%s on clock %s\n", __func__, c->name); | 1099 | pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk)); |
1005 | 1100 | ||
1006 | if (!c->u.periph.clk_num) | 1101 | if (!c->u.periph.clk_num) |
1007 | return; | 1102 | return; |
1008 | 1103 | ||
1009 | spin_lock_irqsave(&clock_register_lock, flags); | 1104 | tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--; |
1010 | 1105 | ||
1011 | if (c->refcnt) | 1106 | if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 0) |
1012 | tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--; | 1107 | return; |
1013 | 1108 | ||
1014 | if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] == 0) | 1109 | spin_lock_irqsave(&clock_register_lock, flags); |
1015 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), | 1110 | |
1016 | CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c)); | 1111 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), |
1112 | CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c)); | ||
1017 | 1113 | ||
1018 | spin_unlock_irqrestore(&clock_register_lock, flags); | 1114 | spin_unlock_irqrestore(&clock_register_lock, flags); |
1019 | } | 1115 | } |
1020 | 1116 | ||
1021 | static void tegra2_periph_clk_reset(struct clk *c, bool assert) | 1117 | void tegra2_periph_clk_reset(struct clk_hw *hw, bool assert) |
1022 | { | 1118 | { |
1119 | struct clk_tegra *c = to_clk_tegra(hw); | ||
1023 | unsigned long base = assert ? RST_DEVICES_SET : RST_DEVICES_CLR; | 1120 | unsigned long base = assert ? RST_DEVICES_SET : RST_DEVICES_CLR; |
1024 | 1121 | ||
1025 | pr_debug("%s %s on clock %s\n", __func__, | 1122 | pr_debug("%s %s on clock %s\n", __func__, |
1026 | assert ? "assert" : "deassert", c->name); | 1123 | assert ? "assert" : "deassert", __clk_get_name(hw->clk)); |
1027 | 1124 | ||
1028 | BUG_ON(!c->u.periph.clk_num); | 1125 | BUG_ON(!c->u.periph.clk_num); |
1029 | 1126 | ||
@@ -1032,13 +1129,14 @@ static void tegra2_periph_clk_reset(struct clk *c, bool assert) | |||
1032 | base + PERIPH_CLK_TO_ENB_SET_REG(c)); | 1129 | base + PERIPH_CLK_TO_ENB_SET_REG(c)); |
1033 | } | 1130 | } |
1034 | 1131 | ||
1035 | static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p) | 1132 | static int tegra20_periph_clk_set_parent(struct clk_hw *hw, u8 index) |
1036 | { | 1133 | { |
1134 | struct clk_tegra *c = to_clk_tegra(hw); | ||
1037 | u32 val; | 1135 | u32 val; |
1038 | const struct clk_mux_sel *sel; | 1136 | u32 mask; |
1039 | u32 mask, shift; | 1137 | u32 shift; |
1040 | 1138 | ||
1041 | pr_debug("%s: %s %s\n", __func__, c->name, p->name); | 1139 | pr_debug("%s: %s %d\n", __func__, __clk_get_name(hw->clk), index); |
1042 | 1140 | ||
1043 | if (c->flags & MUX_PWM) { | 1141 | if (c->flags & MUX_PWM) { |
1044 | shift = PERIPH_CLK_SOURCE_PWM_SHIFT; | 1142 | shift = PERIPH_CLK_SOURCE_PWM_SHIFT; |
@@ -1048,36 +1146,78 @@ static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p) | |||
1048 | mask = PERIPH_CLK_SOURCE_MASK; | 1146 | mask = PERIPH_CLK_SOURCE_MASK; |
1049 | } | 1147 | } |
1050 | 1148 | ||
1051 | for (sel = c->inputs; sel->input != NULL; sel++) { | 1149 | val = clk_readl(c->reg); |
1052 | if (sel->input == p) { | 1150 | val &= ~mask; |
1053 | val = clk_readl(c->reg); | 1151 | val |= (index) << shift; |
1054 | val &= ~mask; | ||
1055 | val |= (sel->value) << shift; | ||
1056 | 1152 | ||
1057 | if (c->refcnt) | 1153 | clk_writel(val, c->reg); |
1058 | clk_enable(p); | ||
1059 | 1154 | ||
1060 | clk_writel(val, c->reg); | 1155 | return 0; |
1156 | } | ||
1061 | 1157 | ||
1062 | if (c->refcnt && c->parent) | 1158 | static u8 tegra20_periph_clk_get_parent(struct clk_hw *hw) |
1063 | clk_disable(c->parent); | 1159 | { |
1160 | struct clk_tegra *c = to_clk_tegra(hw); | ||
1161 | u32 val = clk_readl(c->reg); | ||
1162 | u32 mask; | ||
1163 | u32 shift; | ||
1064 | 1164 | ||
1065 | clk_reparent(c, p); | 1165 | if (c->flags & MUX_PWM) { |
1066 | return 0; | 1166 | shift = PERIPH_CLK_SOURCE_PWM_SHIFT; |
1067 | } | 1167 | mask = PERIPH_CLK_SOURCE_PWM_MASK; |
1168 | } else { | ||
1169 | shift = PERIPH_CLK_SOURCE_SHIFT; | ||
1170 | mask = PERIPH_CLK_SOURCE_MASK; | ||
1068 | } | 1171 | } |
1069 | 1172 | ||
1070 | return -EINVAL; | 1173 | if (c->flags & MUX) |
1174 | return (val & mask) >> shift; | ||
1175 | else | ||
1176 | return 0; | ||
1071 | } | 1177 | } |
1072 | 1178 | ||
1073 | static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate) | 1179 | static unsigned long tegra20_periph_clk_recalc_rate(struct clk_hw *hw, |
1180 | unsigned long prate) | ||
1074 | { | 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 | |||
1209 | static 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); | ||
1075 | u32 val; | 1213 | u32 val; |
1076 | int divider; | 1214 | int divider; |
1077 | unsigned long parent_rate = clk_get_rate(c->parent); | 1215 | |
1216 | val = clk_readl(c->reg); | ||
1078 | 1217 | ||
1079 | if (c->flags & DIV_U71) { | 1218 | if (c->flags & DIV_U71) { |
1080 | divider = clk_div71_get_divider(parent_rate, rate); | 1219 | divider = clk_div71_get_divider(parent_rate, rate); |
1220 | |||
1081 | if (divider >= 0) { | 1221 | if (divider >= 0) { |
1082 | val = clk_readl(c->reg); | 1222 | val = clk_readl(c->reg); |
1083 | val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK; | 1223 | val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK; |
@@ -1103,15 +1243,21 @@ static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate) | |||
1103 | c->mul = 1; | 1243 | c->mul = 1; |
1104 | return 0; | 1244 | return 0; |
1105 | } | 1245 | } |
1246 | |||
1106 | return -EINVAL; | 1247 | return -EINVAL; |
1107 | } | 1248 | } |
1108 | 1249 | ||
1109 | static long tegra2_periph_clk_round_rate(struct clk *c, | 1250 | static long tegra20_periph_clk_round_rate(struct clk_hw *hw, |
1110 | unsigned long rate) | 1251 | unsigned long rate, unsigned long *prate) |
1111 | { | 1252 | { |
1253 | struct clk_tegra *c = to_clk_tegra(hw); | ||
1254 | unsigned long parent_rate = __clk_get_rate(__clk_get_parent(hw->clk)); | ||
1112 | int divider; | 1255 | int divider; |
1113 | unsigned long parent_rate = clk_get_rate(c->parent); | 1256 | |
1114 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); | 1257 | pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate); |
1258 | |||
1259 | if (prate) | ||
1260 | parent_rate = *prate; | ||
1115 | 1261 | ||
1116 | if (c->flags & DIV_U71) { | 1262 | if (c->flags & DIV_U71) { |
1117 | divider = clk_div71_get_divider(parent_rate, rate); | 1263 | divider = clk_div71_get_divider(parent_rate, rate); |
@@ -1129,44 +1275,27 @@ static long tegra2_periph_clk_round_rate(struct clk *c, | |||
1129 | } | 1275 | } |
1130 | 1276 | ||
1131 | struct clk_ops tegra_periph_clk_ops = { | 1277 | struct clk_ops tegra_periph_clk_ops = { |
1132 | .init = &tegra2_periph_clk_init, | 1278 | .is_enabled = tegra20_periph_clk_is_enabled, |
1133 | .enable = &tegra2_periph_clk_enable, | 1279 | .enable = tegra20_periph_clk_enable, |
1134 | .disable = &tegra2_periph_clk_disable, | 1280 | .disable = tegra20_periph_clk_disable, |
1135 | .set_parent = &tegra2_periph_clk_set_parent, | 1281 | .set_parent = tegra20_periph_clk_set_parent, |
1136 | .set_rate = &tegra2_periph_clk_set_rate, | 1282 | .get_parent = tegra20_periph_clk_get_parent, |
1137 | .round_rate = &tegra2_periph_clk_round_rate, | 1283 | .set_rate = tegra20_periph_clk_set_rate, |
1138 | .reset = &tegra2_periph_clk_reset, | 1284 | .round_rate = tegra20_periph_clk_round_rate, |
1285 | .recalc_rate = tegra20_periph_clk_recalc_rate, | ||
1139 | }; | 1286 | }; |
1140 | 1287 | ||
1141 | /* The SDMMC controllers have extra bits in the clock source register that | ||
1142 | * adjust the delay between the clock and data to compenstate for delays | ||
1143 | * on the PCB. */ | ||
1144 | void tegra2_sdmmc_tap_delay(struct clk *c, int delay) | ||
1145 | { | ||
1146 | u32 reg; | ||
1147 | unsigned long flags; | ||
1148 | |||
1149 | spin_lock_irqsave(&c->spinlock, flags); | ||
1150 | |||
1151 | delay = clamp(delay, 0, 15); | ||
1152 | reg = clk_readl(c->reg); | ||
1153 | reg &= ~SDMMC_CLK_INT_FB_DLY_MASK; | ||
1154 | reg |= SDMMC_CLK_INT_FB_SEL; | ||
1155 | reg |= delay << SDMMC_CLK_INT_FB_DLY_SHIFT; | ||
1156 | clk_writel(reg, c->reg); | ||
1157 | |||
1158 | spin_unlock_irqrestore(&c->spinlock, flags); | ||
1159 | } | ||
1160 | |||
1161 | /* External memory controller clock ops */ | 1288 | /* External memory controller clock ops */ |
1162 | static void tegra2_emc_clk_init(struct clk *c) | 1289 | static void tegra20_emc_clk_init(struct clk_hw *hw) |
1163 | { | 1290 | { |
1164 | tegra2_periph_clk_init(c); | 1291 | struct clk_tegra *c = to_clk_tegra(hw); |
1165 | c->max_rate = clk_get_rate_locked(c); | 1292 | c->max_rate = __clk_get_rate(hw->clk); |
1166 | } | 1293 | } |
1167 | 1294 | ||
1168 | static long tegra2_emc_clk_round_rate(struct clk *c, unsigned long rate) | 1295 | static long tegra20_emc_clk_round_rate(struct clk_hw *hw, unsigned long rate, |
1296 | unsigned long *prate) | ||
1169 | { | 1297 | { |
1298 | struct clk_tegra *c = to_clk_tegra(hw); | ||
1170 | long emc_rate; | 1299 | long emc_rate; |
1171 | long clk_rate; | 1300 | long clk_rate; |
1172 | 1301 | ||
@@ -1182,7 +1311,7 @@ static long tegra2_emc_clk_round_rate(struct clk *c, unsigned long rate) | |||
1182 | * The fastest rate the PLL will generate that is at most the | 1311 | * The fastest rate the PLL will generate that is at most the |
1183 | * requested rate. | 1312 | * requested rate. |
1184 | */ | 1313 | */ |
1185 | clk_rate = tegra2_periph_clk_round_rate(c, emc_rate); | 1314 | clk_rate = tegra20_periph_clk_round_rate(hw, emc_rate, NULL); |
1186 | 1315 | ||
1187 | /* | 1316 | /* |
1188 | * If this fails, and emc_rate > clk_rate, it's because the maximum | 1317 | * If this fails, and emc_rate > clk_rate, it's because the maximum |
@@ -1198,9 +1327,11 @@ static long tegra2_emc_clk_round_rate(struct clk *c, unsigned long rate) | |||
1198 | return emc_rate; | 1327 | return emc_rate; |
1199 | } | 1328 | } |
1200 | 1329 | ||
1201 | static int tegra2_emc_clk_set_rate(struct clk *c, unsigned long rate) | 1330 | static int tegra20_emc_clk_set_rate(struct clk_hw *hw, unsigned long rate, |
1331 | unsigned long parent_rate) | ||
1202 | { | 1332 | { |
1203 | int ret; | 1333 | int ret; |
1334 | |||
1204 | /* | 1335 | /* |
1205 | * The Tegra2 memory controller has an interlock with the clock | 1336 | * The Tegra2 memory controller has an interlock with the clock |
1206 | * block that allows memory shadowed registers to be updated, | 1337 | * block that allows memory shadowed registers to be updated, |
@@ -1211,116 +1342,145 @@ static int tegra2_emc_clk_set_rate(struct clk *c, unsigned long rate) | |||
1211 | if (ret < 0) | 1342 | if (ret < 0) |
1212 | return ret; | 1343 | return ret; |
1213 | 1344 | ||
1214 | ret = tegra2_periph_clk_set_rate(c, rate); | 1345 | ret = tegra20_periph_clk_set_rate(hw, rate, parent_rate); |
1215 | udelay(1); | 1346 | udelay(1); |
1216 | 1347 | ||
1217 | return ret; | 1348 | return ret; |
1218 | } | 1349 | } |
1219 | 1350 | ||
1220 | struct clk_ops tegra_emc_clk_ops = { | 1351 | struct clk_ops tegra_emc_clk_ops = { |
1221 | .init = &tegra2_emc_clk_init, | 1352 | .init = tegra20_emc_clk_init, |
1222 | .enable = &tegra2_periph_clk_enable, | 1353 | .is_enabled = tegra20_periph_clk_is_enabled, |
1223 | .disable = &tegra2_periph_clk_disable, | 1354 | .enable = tegra20_periph_clk_enable, |
1224 | .set_parent = &tegra2_periph_clk_set_parent, | 1355 | .disable = tegra20_periph_clk_disable, |
1225 | .set_rate = &tegra2_emc_clk_set_rate, | 1356 | .set_parent = tegra20_periph_clk_set_parent, |
1226 | .round_rate = &tegra2_emc_clk_round_rate, | 1357 | .get_parent = tegra20_periph_clk_get_parent, |
1227 | .reset = &tegra2_periph_clk_reset, | 1358 | .set_rate = tegra20_emc_clk_set_rate, |
1359 | .round_rate = tegra20_emc_clk_round_rate, | ||
1360 | .recalc_rate = tegra20_periph_clk_recalc_rate, | ||
1228 | }; | 1361 | }; |
1229 | 1362 | ||
1230 | /* Clock doubler ops */ | 1363 | /* Clock doubler ops */ |
1231 | static void tegra2_clk_double_init(struct clk *c) | 1364 | static int tegra20_clk_double_is_enabled(struct clk_hw *hw) |
1232 | { | 1365 | { |
1233 | c->mul = 2; | 1366 | struct clk_tegra *c = to_clk_tegra(hw); |
1234 | c->div = 1; | 1367 | |
1235 | c->state = ON; | 1368 | c->state = ON; |
1236 | 1369 | ||
1237 | if (!c->u.periph.clk_num) | 1370 | if (!c->u.periph.clk_num) |
1238 | return; | 1371 | goto out; |
1239 | 1372 | ||
1240 | if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & | 1373 | if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & |
1241 | PERIPH_CLK_TO_ENB_BIT(c))) | 1374 | PERIPH_CLK_TO_ENB_BIT(c))) |
1242 | c->state = OFF; | 1375 | c->state = OFF; |
1376 | |||
1377 | out: | ||
1378 | return c->state; | ||
1243 | }; | 1379 | }; |
1244 | 1380 | ||
1245 | static int tegra2_clk_double_set_rate(struct clk *c, unsigned long rate) | 1381 | static unsigned long tegra20_clk_double_recalc_rate(struct clk_hw *hw, |
1382 | unsigned long prate) | ||
1246 | { | 1383 | { |
1247 | if (rate != 2 * clk_get_rate(c->parent)) | 1384 | struct clk_tegra *c = to_clk_tegra(hw); |
1248 | return -EINVAL; | 1385 | u64 rate = prate; |
1386 | |||
1249 | c->mul = 2; | 1387 | c->mul = 2; |
1250 | c->div = 1; | 1388 | c->div = 1; |
1389 | |||
1390 | rate *= c->mul; | ||
1391 | rate += c->div - 1; /* round up */ | ||
1392 | do_div(rate, c->div); | ||
1393 | |||
1394 | return rate; | ||
1395 | } | ||
1396 | |||
1397 | static 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 | |||
1406 | static 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; | ||
1251 | return 0; | 1411 | return 0; |
1252 | } | 1412 | } |
1253 | 1413 | ||
1254 | struct clk_ops tegra_clk_double_ops = { | 1414 | struct clk_ops tegra_clk_double_ops = { |
1255 | .init = &tegra2_clk_double_init, | 1415 | .is_enabled = tegra20_clk_double_is_enabled, |
1256 | .enable = &tegra2_periph_clk_enable, | 1416 | .enable = tegra20_periph_clk_enable, |
1257 | .disable = &tegra2_periph_clk_disable, | 1417 | .disable = tegra20_periph_clk_disable, |
1258 | .set_rate = &tegra2_clk_double_set_rate, | 1418 | .set_rate = tegra20_clk_double_set_rate, |
1419 | .recalc_rate = tegra20_clk_double_recalc_rate, | ||
1420 | .round_rate = tegra20_clk_double_round_rate, | ||
1259 | }; | 1421 | }; |
1260 | 1422 | ||
1261 | /* Audio sync clock ops */ | 1423 | /* Audio sync clock ops */ |
1262 | static void tegra2_audio_sync_clk_init(struct clk *c) | 1424 | static int tegra20_audio_sync_clk_is_enabled(struct clk_hw *hw) |
1263 | { | 1425 | { |
1264 | int source; | 1426 | struct clk_tegra *c = to_clk_tegra(hw); |
1265 | const struct clk_mux_sel *sel; | ||
1266 | u32 val = clk_readl(c->reg); | 1427 | u32 val = clk_readl(c->reg); |
1428 | |||
1267 | c->state = (val & (1<<4)) ? OFF : ON; | 1429 | c->state = (val & (1<<4)) ? OFF : ON; |
1268 | source = val & 0xf; | 1430 | return c->state; |
1269 | for (sel = c->inputs; sel->input != NULL; sel++) | ||
1270 | if (sel->value == source) | ||
1271 | break; | ||
1272 | BUG_ON(sel->input == NULL); | ||
1273 | c->parent = sel->input; | ||
1274 | } | 1431 | } |
1275 | 1432 | ||
1276 | static int tegra2_audio_sync_clk_enable(struct clk *c) | 1433 | static int tegra20_audio_sync_clk_enable(struct clk_hw *hw) |
1277 | { | 1434 | { |
1435 | struct clk_tegra *c = to_clk_tegra(hw); | ||
1436 | |||
1278 | clk_writel(0, c->reg); | 1437 | clk_writel(0, c->reg); |
1279 | return 0; | 1438 | return 0; |
1280 | } | 1439 | } |
1281 | 1440 | ||
1282 | static void tegra2_audio_sync_clk_disable(struct clk *c) | 1441 | static void tegra20_audio_sync_clk_disable(struct clk_hw *hw) |
1283 | { | 1442 | { |
1443 | struct clk_tegra *c = to_clk_tegra(hw); | ||
1284 | clk_writel(1, c->reg); | 1444 | clk_writel(1, c->reg); |
1285 | } | 1445 | } |
1286 | 1446 | ||
1287 | static int tegra2_audio_sync_clk_set_parent(struct clk *c, struct clk *p) | 1447 | static u8 tegra20_audio_sync_clk_get_parent(struct clk_hw *hw) |
1288 | { | 1448 | { |
1289 | u32 val; | 1449 | struct clk_tegra *c = to_clk_tegra(hw); |
1290 | const struct clk_mux_sel *sel; | 1450 | u32 val = clk_readl(c->reg); |
1291 | for (sel = c->inputs; sel->input != NULL; sel++) { | 1451 | int source; |
1292 | if (sel->input == p) { | ||
1293 | val = clk_readl(c->reg); | ||
1294 | val &= ~0xf; | ||
1295 | val |= sel->value; | ||
1296 | 1452 | ||
1297 | if (c->refcnt) | 1453 | source = val & 0xf; |
1298 | clk_enable(p); | 1454 | return source; |
1455 | } | ||
1299 | 1456 | ||
1300 | clk_writel(val, c->reg); | 1457 | static int tegra20_audio_sync_clk_set_parent(struct clk_hw *hw, u8 index) |
1458 | { | ||
1459 | struct clk_tegra *c = to_clk_tegra(hw); | ||
1460 | u32 val; | ||
1301 | 1461 | ||
1302 | if (c->refcnt && c->parent) | 1462 | val = clk_readl(c->reg); |
1303 | clk_disable(c->parent); | 1463 | val &= ~0xf; |
1464 | val |= index; | ||
1304 | 1465 | ||
1305 | clk_reparent(c, p); | 1466 | clk_writel(val, c->reg); |
1306 | return 0; | ||
1307 | } | ||
1308 | } | ||
1309 | 1467 | ||
1310 | return -EINVAL; | 1468 | return 0; |
1311 | } | 1469 | } |
1312 | 1470 | ||
1313 | struct clk_ops tegra_audio_sync_clk_ops = { | 1471 | struct clk_ops tegra_audio_sync_clk_ops = { |
1314 | .init = tegra2_audio_sync_clk_init, | 1472 | .is_enabled = tegra20_audio_sync_clk_is_enabled, |
1315 | .enable = tegra2_audio_sync_clk_enable, | 1473 | .enable = tegra20_audio_sync_clk_enable, |
1316 | .disable = tegra2_audio_sync_clk_disable, | 1474 | .disable = tegra20_audio_sync_clk_disable, |
1317 | .set_parent = tegra2_audio_sync_clk_set_parent, | 1475 | .set_parent = tegra20_audio_sync_clk_set_parent, |
1476 | .get_parent = tegra20_audio_sync_clk_get_parent, | ||
1318 | }; | 1477 | }; |
1319 | 1478 | ||
1320 | /* cdev1 and cdev2 (dap_mclk1 and dap_mclk2) ops */ | 1479 | /* cdev1 and cdev2 (dap_mclk1 and dap_mclk2) ops */ |
1321 | 1480 | ||
1322 | static void tegra2_cdev_clk_init(struct clk *c) | 1481 | static int tegra20_cdev_clk_is_enabled(struct clk_hw *hw) |
1323 | { | 1482 | { |
1483 | struct clk_tegra *c = to_clk_tegra(hw); | ||
1324 | /* We could un-tristate the cdev1 or cdev2 pingroup here; this is | 1484 | /* We could un-tristate the cdev1 or cdev2 pingroup here; this is |
1325 | * currently done in the pinmux code. */ | 1485 | * currently done in the pinmux code. */ |
1326 | c->state = ON; | 1486 | c->state = ON; |
@@ -1330,10 +1490,12 @@ static void tegra2_cdev_clk_init(struct clk *c) | |||
1330 | if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & | 1490 | if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & |
1331 | PERIPH_CLK_TO_ENB_BIT(c))) | 1491 | PERIPH_CLK_TO_ENB_BIT(c))) |
1332 | c->state = OFF; | 1492 | c->state = OFF; |
1493 | return c->state; | ||
1333 | } | 1494 | } |
1334 | 1495 | ||
1335 | static int tegra2_cdev_clk_enable(struct clk *c) | 1496 | static int tegra20_cdev_clk_enable(struct clk_hw *hw) |
1336 | { | 1497 | { |
1498 | struct clk_tegra *c = to_clk_tegra(hw); | ||
1337 | BUG_ON(!c->u.periph.clk_num); | 1499 | BUG_ON(!c->u.periph.clk_num); |
1338 | 1500 | ||
1339 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), | 1501 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), |
@@ -1341,118 +1503,24 @@ static int tegra2_cdev_clk_enable(struct clk *c) | |||
1341 | return 0; | 1503 | return 0; |
1342 | } | 1504 | } |
1343 | 1505 | ||
1344 | static void tegra2_cdev_clk_disable(struct clk *c) | 1506 | static void tegra20_cdev_clk_disable(struct clk_hw *hw) |
1345 | { | 1507 | { |
1508 | struct clk_tegra *c = to_clk_tegra(hw); | ||
1346 | BUG_ON(!c->u.periph.clk_num); | 1509 | BUG_ON(!c->u.periph.clk_num); |
1347 | 1510 | ||
1348 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), | 1511 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), |
1349 | CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c)); | 1512 | CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c)); |
1350 | } | 1513 | } |
1351 | 1514 | ||
1352 | struct clk_ops tegra_cdev_clk_ops = { | 1515 | static unsigned long tegra20_cdev_recalc_rate(struct clk_hw *hw, |
1353 | .init = &tegra2_cdev_clk_init, | 1516 | unsigned long prate) |
1354 | .enable = &tegra2_cdev_clk_enable, | ||
1355 | .disable = &tegra2_cdev_clk_disable, | ||
1356 | }; | ||
1357 | |||
1358 | /* shared bus ops */ | ||
1359 | /* | ||
1360 | * Some clocks may have multiple downstream users that need to request a | ||
1361 | * higher clock rate. Shared bus clocks provide a unique shared_bus_user | ||
1362 | * clock to each user. The frequency of the bus is set to the highest | ||
1363 | * enabled shared_bus_user clock, with a minimum value set by the | ||
1364 | * shared bus. | ||
1365 | */ | ||
1366 | static int tegra_clk_shared_bus_update(struct clk *bus) | ||
1367 | { | ||
1368 | struct clk *c; | ||
1369 | unsigned long rate = bus->min_rate; | ||
1370 | |||
1371 | list_for_each_entry(c, &bus->shared_bus_list, u.shared_bus_user.node) | ||
1372 | if (c->u.shared_bus_user.enabled) | ||
1373 | rate = max(c->u.shared_bus_user.rate, rate); | ||
1374 | |||
1375 | if (rate == clk_get_rate_locked(bus)) | ||
1376 | return 0; | ||
1377 | |||
1378 | return clk_set_rate_locked(bus, rate); | ||
1379 | }; | ||
1380 | |||
1381 | static void tegra_clk_shared_bus_init(struct clk *c) | ||
1382 | { | ||
1383 | unsigned long flags; | ||
1384 | |||
1385 | c->max_rate = c->parent->max_rate; | ||
1386 | c->u.shared_bus_user.rate = c->parent->max_rate; | ||
1387 | c->state = OFF; | ||
1388 | c->set = true; | ||
1389 | |||
1390 | spin_lock_irqsave(&c->parent->spinlock, flags); | ||
1391 | |||
1392 | list_add_tail(&c->u.shared_bus_user.node, | ||
1393 | &c->parent->shared_bus_list); | ||
1394 | |||
1395 | spin_unlock_irqrestore(&c->parent->spinlock, flags); | ||
1396 | } | ||
1397 | |||
1398 | static int tegra_clk_shared_bus_set_rate(struct clk *c, unsigned long rate) | ||
1399 | { | 1517 | { |
1400 | unsigned long flags; | 1518 | return to_clk_tegra(hw)->fixed_rate; |
1401 | int ret; | ||
1402 | long new_rate = rate; | ||
1403 | |||
1404 | new_rate = clk_round_rate(c->parent, new_rate); | ||
1405 | if (new_rate < 0) | ||
1406 | return new_rate; | ||
1407 | |||
1408 | spin_lock_irqsave(&c->parent->spinlock, flags); | ||
1409 | |||
1410 | c->u.shared_bus_user.rate = new_rate; | ||
1411 | ret = tegra_clk_shared_bus_update(c->parent); | ||
1412 | |||
1413 | spin_unlock_irqrestore(&c->parent->spinlock, flags); | ||
1414 | |||
1415 | return ret; | ||
1416 | } | ||
1417 | |||
1418 | static long tegra_clk_shared_bus_round_rate(struct clk *c, unsigned long rate) | ||
1419 | { | ||
1420 | return clk_round_rate(c->parent, rate); | ||
1421 | } | 1519 | } |
1422 | 1520 | ||
1423 | static int tegra_clk_shared_bus_enable(struct clk *c) | 1521 | struct clk_ops tegra_cdev_clk_ops = { |
1424 | { | 1522 | .is_enabled = tegra20_cdev_clk_is_enabled, |
1425 | unsigned long flags; | 1523 | .enable = tegra20_cdev_clk_enable, |
1426 | int ret; | 1524 | .disable = tegra20_cdev_clk_disable, |
1427 | 1525 | .recalc_rate = tegra20_cdev_recalc_rate, | |
1428 | spin_lock_irqsave(&c->parent->spinlock, flags); | ||
1429 | |||
1430 | c->u.shared_bus_user.enabled = true; | ||
1431 | ret = tegra_clk_shared_bus_update(c->parent); | ||
1432 | |||
1433 | spin_unlock_irqrestore(&c->parent->spinlock, flags); | ||
1434 | |||
1435 | return ret; | ||
1436 | } | ||
1437 | |||
1438 | static void tegra_clk_shared_bus_disable(struct clk *c) | ||
1439 | { | ||
1440 | unsigned long flags; | ||
1441 | int ret; | ||
1442 | |||
1443 | spin_lock_irqsave(&c->parent->spinlock, flags); | ||
1444 | |||
1445 | c->u.shared_bus_user.enabled = false; | ||
1446 | ret = tegra_clk_shared_bus_update(c->parent); | ||
1447 | WARN_ON_ONCE(ret); | ||
1448 | |||
1449 | spin_unlock_irqrestore(&c->parent->spinlock, flags); | ||
1450 | } | ||
1451 | |||
1452 | struct clk_ops tegra_clk_shared_bus_ops = { | ||
1453 | .init = tegra_clk_shared_bus_init, | ||
1454 | .enable = tegra_clk_shared_bus_enable, | ||
1455 | .disable = tegra_clk_shared_bus_disable, | ||
1456 | .set_rate = tegra_clk_shared_bus_set_rate, | ||
1457 | .round_rate = tegra_clk_shared_bus_round_rate, | ||
1458 | }; | 1526 | }; |