2008-03-18 16:22:06 +08:00
|
|
|
/*
|
|
|
|
* linux/arch/arm/mach-omap2/clock.h
|
|
|
|
*
|
2009-12-09 07:21:29 +08:00
|
|
|
* Copyright (C) 2005-2009 Texas Instruments, Inc.
|
|
|
|
* Copyright (C) 2004-2009 Nokia Corporation
|
2008-03-18 16:22:06 +08:00
|
|
|
*
|
2008-03-18 17:56:39 +08:00
|
|
|
* Contacts:
|
|
|
|
* Richard Woodruff <r-woodruff2@ti.com>
|
2008-03-18 16:22:06 +08:00
|
|
|
* Paul Walmsley
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
|
|
* published by the Free Software Foundation.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK_H
|
|
|
|
#define __ARCH_ARM_MACH_OMAP2_CLOCK_H
|
|
|
|
|
2009-10-21 00:40:47 +08:00
|
|
|
#include <plat/clock.h>
|
2008-03-18 16:22:06 +08:00
|
|
|
|
ARM: OMAP2: Clock: New OMAP2/3 DPLL rate rounding algorithm
This patch adds a new rate rounding algorithm for DPLL clocks on the
OMAP2/3 architecture.
For a desired DPLL target rate, there may be several
multiplier/divider (M, N) values which will generate a sufficiently
close rate. Lower N values result in greater power economy. However,
lower N values can cause the difference between the rounded rate and
the target rate ("rate error") to be larger than it would be with a
higher N. This can cause downstream devices to run more slowly than
they otherwise would.
This DPLL rate rounding algorithm:
- attempts to find the lowest possible N (DPLL divider) to reach the
target_rate (since, according to Richard Woodruff <r-woodruff@ti.com>,
lower N values save more power than higher N values).
- allows developers to set an upper bound on the error between the
rounded rate and the desired target rate ("rate tolerance"), so an
appropriate balance between rate fidelity and power savings can be
set. This maximum rate error tolerance is set via
omap2_set_dpll_rate_tolerance().
- never returns a rounded rate higher than the target rate.
The rate rounding algorithm caches the last rounded M, N, and rate
computation to avoid rounding the rate twice for each clk_set_rate()
call. (This patch does not yet implement set_rate for DPLLs; that
follows in a future patch.)
The algorithm trades execution speed for rate accuracy. It will find
the (M, N) set that results in the least rate error, within a
specified rate tolerance. It does this by evaluating each divider
setting - on OMAP3, this involves 128 steps. Another approach to DPLL
rate rounding would be to bail out as soon as a valid rate is found
within the rate tolerance, which would trade rate accuracy for
execution speed. Alternate implementations welcome.
This code is not yet used by the OMAP24XX DPLL clock, since it
is currently defined as a composite clock, fusing the DPLL M,N and the
M2 output divider. This patch also renames the existing OMAP24xx DPLL
programming functions to highlight that they program both the DPLL and
the DPLL's output multiplier.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
2008-07-03 17:24:46 +08:00
|
|
|
/* The maximum error between a target DPLL rate and the rounded rate in Hz */
|
|
|
|
#define DEFAULT_DPLL_RATE_TOLERANCE 50000
|
|
|
|
|
[ARM] omap: add support for bypassing DPLLs
This roughly corresponds with OMAP commits: 7d06c48, 3241b19,
88b5d9b, 18a5500, 9c909ac, 5c6497b, 8b1f0bd, 2ac1da8.
For both OMAP2 and OMAP3, we note the reference and bypass clocks in
the DPLL data structure. Whenever we modify the DPLL rate, we first
ensure that both the reference and bypass clocks are enabled. Then,
we decide whether to use the reference and DPLL, or the bypass clock
if the desired rate is identical to the bypass rate, and program the
DPLL appropriately. Finally, we update the clock's parent, and then
disable the unused clocks.
This keeps the parents correctly balanced, and more importantly ensures
that the bypass clock is running whenever we reprogram the DPLL. This
is especially important because the procedure for reprogramming the DPLL
involves switching to the bypass clock.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
2009-02-19 21:29:22 +08:00
|
|
|
/* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */
|
|
|
|
#define CORE_CLK_SRC_32K 0x0
|
|
|
|
#define CORE_CLK_SRC_DPLL 0x1
|
|
|
|
#define CORE_CLK_SRC_DPLL_X2 0x2
|
|
|
|
|
|
|
|
/* OMAP2xxx CM_CLKEN_PLL.EN_DPLL bits - for omap2_get_dpll_rate() */
|
|
|
|
#define OMAP2XXX_EN_DPLL_LPBYPASS 0x1
|
|
|
|
#define OMAP2XXX_EN_DPLL_FRBYPASS 0x2
|
|
|
|
#define OMAP2XXX_EN_DPLL_LOCKED 0x3
|
|
|
|
|
|
|
|
/* OMAP3xxx CM_CLKEN_PLL*.EN_*_DPLL bits - for omap2_get_dpll_rate() */
|
|
|
|
#define OMAP3XXX_EN_DPLL_LPBYPASS 0x5
|
|
|
|
#define OMAP3XXX_EN_DPLL_FRBYPASS 0x6
|
|
|
|
#define OMAP3XXX_EN_DPLL_LOCKED 0x7
|
|
|
|
|
2009-12-09 09:47:16 +08:00
|
|
|
/* OMAP4xxx CM_CLKMODE_DPLL*.EN_*_DPLL bits - for omap2_get_dpll_rate() */
|
|
|
|
#define OMAP4XXX_EN_DPLL_MNBYPASS 0x4
|
|
|
|
#define OMAP4XXX_EN_DPLL_LPBYPASS 0x5
|
|
|
|
#define OMAP4XXX_EN_DPLL_FRBYPASS 0x6
|
|
|
|
#define OMAP4XXX_EN_DPLL_LOCKED 0x7
|
|
|
|
|
2009-12-09 09:47:16 +08:00
|
|
|
/* CM_CLKEN_PLL*.EN* bit values - not all are available for every DPLL */
|
|
|
|
#define DPLL_LOW_POWER_STOP 0x1
|
|
|
|
#define DPLL_LOW_POWER_BYPASS 0x5
|
|
|
|
#define DPLL_LOCKED 0x7
|
|
|
|
|
2010-02-23 13:09:08 +08:00
|
|
|
/* DPLL Type and DCO Selection Flags */
|
|
|
|
#define DPLL_J_TYPE 0x1
|
|
|
|
#define DPLL_NO_DCO_SEL 0x2
|
|
|
|
|
2008-03-18 16:22:06 +08:00
|
|
|
int omap2_clk_enable(struct clk *clk);
|
|
|
|
void omap2_clk_disable(struct clk *clk);
|
|
|
|
long omap2_clk_round_rate(struct clk *clk, unsigned long rate);
|
|
|
|
int omap2_clk_set_rate(struct clk *clk, unsigned long rate);
|
|
|
|
int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent);
|
2009-01-28 10:12:50 +08:00
|
|
|
int omap2_dpll_set_rate_tolerance(struct clk *clk, unsigned int tolerance);
|
ARM: OMAP2: Clock: New OMAP2/3 DPLL rate rounding algorithm
This patch adds a new rate rounding algorithm for DPLL clocks on the
OMAP2/3 architecture.
For a desired DPLL target rate, there may be several
multiplier/divider (M, N) values which will generate a sufficiently
close rate. Lower N values result in greater power economy. However,
lower N values can cause the difference between the rounded rate and
the target rate ("rate error") to be larger than it would be with a
higher N. This can cause downstream devices to run more slowly than
they otherwise would.
This DPLL rate rounding algorithm:
- attempts to find the lowest possible N (DPLL divider) to reach the
target_rate (since, according to Richard Woodruff <r-woodruff@ti.com>,
lower N values save more power than higher N values).
- allows developers to set an upper bound on the error between the
rounded rate and the desired target rate ("rate tolerance"), so an
appropriate balance between rate fidelity and power savings can be
set. This maximum rate error tolerance is set via
omap2_set_dpll_rate_tolerance().
- never returns a rounded rate higher than the target rate.
The rate rounding algorithm caches the last rounded M, N, and rate
computation to avoid rounding the rate twice for each clk_set_rate()
call. (This patch does not yet implement set_rate for DPLLs; that
follows in a future patch.)
The algorithm trades execution speed for rate accuracy. It will find
the (M, N) set that results in the least rate error, within a
specified rate tolerance. It does this by evaluating each divider
setting - on OMAP3, this involves 128 steps. Another approach to DPLL
rate rounding would be to bail out as soon as a valid rate is found
within the rate tolerance, which would trade rate accuracy for
execution speed. Alternate implementations welcome.
This code is not yet used by the OMAP24XX DPLL clock, since it
is currently defined as a composite clock, fusing the DPLL M,N and the
M2 output divider. This patch also renames the existing OMAP24xx DPLL
programming functions to highlight that they program both the DPLL and
the DPLL's output multiplier.
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
2008-07-03 17:24:46 +08:00
|
|
|
long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate);
|
2009-12-09 09:47:16 +08:00
|
|
|
unsigned long omap3_dpll_recalc(struct clk *clk);
|
|
|
|
unsigned long omap3_clkoutx2_recalc(struct clk *clk);
|
|
|
|
void omap3_dpll_allow_idle(struct clk *clk);
|
|
|
|
void omap3_dpll_deny_idle(struct clk *clk);
|
|
|
|
u32 omap3_dpll_autoidle_read(struct clk *clk);
|
|
|
|
int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate);
|
|
|
|
int omap3_noncore_dpll_enable(struct clk *clk);
|
|
|
|
void omap3_noncore_dpll_disable(struct clk *clk);
|
2008-03-18 16:22:06 +08:00
|
|
|
|
|
|
|
#ifdef CONFIG_OMAP_RESET_CLOCKS
|
|
|
|
void omap2_clk_disable_unused(struct clk *clk);
|
|
|
|
#else
|
|
|
|
#define omap2_clk_disable_unused NULL
|
|
|
|
#endif
|
|
|
|
|
2009-02-12 18:12:59 +08:00
|
|
|
unsigned long omap2_clksel_recalc(struct clk *clk);
|
2008-08-19 16:08:45 +08:00
|
|
|
void omap2_init_clk_clkdm(struct clk *clk);
|
2008-03-18 16:22:06 +08:00
|
|
|
void omap2_init_clksel_parent(struct clk *clk);
|
|
|
|
u32 omap2_clksel_get_divisor(struct clk *clk);
|
|
|
|
u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
|
|
|
|
u32 *new_div);
|
|
|
|
u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val);
|
|
|
|
u32 omap2_divisor_to_clksel(struct clk *clk, u32 div);
|
|
|
|
long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
|
|
|
|
int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
|
2010-01-27 11:13:04 +08:00
|
|
|
int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent);
|
2008-03-18 16:22:06 +08:00
|
|
|
u32 omap2_get_dpll_rate(struct clk *clk);
|
2009-12-09 09:47:17 +08:00
|
|
|
void omap2_init_dpll_parent(struct clk *clk);
|
2008-03-18 16:22:06 +08:00
|
|
|
int omap2_wait_clock_ready(void __iomem *reg, u32 cval, const char *name);
|
2010-02-13 04:26:46 +08:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_ARCH_OMAP2
|
|
|
|
void omap2xxx_clk_prepare_for_reboot(void);
|
|
|
|
#else
|
|
|
|
static inline void omap2xxx_clk_prepare_for_reboot(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef CONFIG_ARCH_OMAP3
|
|
|
|
void omap3_clk_prepare_for_reboot(void);
|
|
|
|
#else
|
|
|
|
static inline void omap3_clk_prepare_for_reboot(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef CONFIG_ARCH_OMAP4
|
|
|
|
void omap4_clk_prepare_for_reboot(void);
|
|
|
|
#else
|
|
|
|
static inline void omap4_clk_prepare_for_reboot(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-07-25 09:44:03 +08:00
|
|
|
int omap2_dflt_clk_enable(struct clk *clk);
|
|
|
|
void omap2_dflt_clk_disable(struct clk *clk);
|
|
|
|
void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg,
|
|
|
|
u8 *other_bit);
|
|
|
|
void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
|
2010-02-25 03:05:54 +08:00
|
|
|
u8 *idlest_bit, u8 *idlest_val);
|
2010-02-23 13:09:36 +08:00
|
|
|
int omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name);
|
|
|
|
void omap2_clk_print_new_rates(const char *hfclkin_ck_name,
|
|
|
|
const char *core_ck_name,
|
|
|
|
const char *mpu_ck_name);
|
2008-03-18 16:22:06 +08:00
|
|
|
|
2009-12-09 07:21:29 +08:00
|
|
|
extern u8 cpu_mask;
|
|
|
|
|
2008-11-05 01:59:52 +08:00
|
|
|
extern const struct clkops clkops_omap2_dflt_wait;
|
2008-11-05 02:59:32 +08:00
|
|
|
extern const struct clkops clkops_omap2_dflt;
|
2008-11-05 01:59:52 +08:00
|
|
|
|
2009-12-09 07:18:47 +08:00
|
|
|
extern struct clk_functions omap2_clk_functions;
|
2009-12-09 07:21:29 +08:00
|
|
|
extern struct clk *vclk, *sclk;
|
2009-12-09 07:18:47 +08:00
|
|
|
|
2009-12-09 07:21:29 +08:00
|
|
|
extern const struct clksel_rate gpt_32k_rates[];
|
|
|
|
extern const struct clksel_rate gpt_sys_rates[];
|
|
|
|
extern const struct clksel_rate gfx_l3_rates[];
|
2008-03-18 16:22:06 +08:00
|
|
|
|
2010-02-13 04:26:47 +08:00
|
|
|
#if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_CPU_FREQ)
|
2010-01-27 11:13:04 +08:00
|
|
|
extern void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
|
|
|
|
extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
|
|
|
|
#else
|
|
|
|
#define omap2_clk_init_cpufreq_table 0
|
|
|
|
#define omap2_clk_exit_cpufreq_table 0
|
|
|
|
#endif
|
2008-03-18 16:22:06 +08:00
|
|
|
|
OMAP3/4 clock: split into per-chip family files
clock34xx_data.c now contains data for the OMAP34xx family, the
OMAP36xx family, and the OMAP3517 family, so rename it to
clock3xxx_data.c. Rename clock34xx.c to clock3xxx.c, and move the
chip family-specific clock functions to clock34xx.c, clock36xx.c, or
clock3517.c, as appropriate. So now "clock3xxx.*" refers to the OMAP3
superset.
The main goal here is to prepare to compile chip family-specific clock
functions only for kernel builds that target that chip family. To get to
that point, we also need to add CONFIG_SOC_* options for those other
chip families; that will be done in future patches, planned for 2.6.35.
OMAP4 is also affected by this. It duplicated the OMAP3 non-CORE DPLL
clkops structure. The OMAP4 variant of this clkops structure has been
removed, and since there was nothing else currently in clock44xx.c, it
too has been removed -- it can always be added back later when there
is some content for it. (The OMAP4 clock autogeneration scripts have been
updated accordingly.)
Signed-off-by: Paul Walmsley <paul@pwsan.com>
Cc: Benoît Cousson <b-cousson@ti.com>
Cc: Rajendra Nayak <rnayak@ti.com>
Cc: Ranjith Lohithakshan <ranjithl@ti.com>
Cc: Tony Lindgren <tony@atomide.com>
2010-02-23 13:09:20 +08:00
|
|
|
extern const struct clkops clkops_omap3_noncore_dpll_ops;
|
|
|
|
|
2008-03-18 16:22:06 +08:00
|
|
|
#endif
|