88b8ba9057
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>
74 lines
2.5 KiB
C
74 lines
2.5 KiB
C
/*
|
|
* linux/arch/arm/mach-omap2/clock.h
|
|
*
|
|
* Copyright (C) 2005-2008 Texas Instruments, Inc.
|
|
* Copyright (C) 2004-2008 Nokia Corporation
|
|
*
|
|
* Contacts:
|
|
* Richard Woodruff <r-woodruff2@ti.com>
|
|
* 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
|
|
|
|
#include <asm/arch/clock.h>
|
|
|
|
/* The maximum error between a target DPLL rate and the rounded rate in Hz */
|
|
#define DEFAULT_DPLL_RATE_TOLERANCE 50000
|
|
|
|
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);
|
|
int omap2_dpll_rate_tolerance_set(struct clk *clk, unsigned int tolerance);
|
|
long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate);
|
|
|
|
#ifdef CONFIG_OMAP_RESET_CLOCKS
|
|
void omap2_clk_disable_unused(struct clk *clk);
|
|
#else
|
|
#define omap2_clk_disable_unused NULL
|
|
#endif
|
|
|
|
void omap2_clksel_recalc(struct clk *clk);
|
|
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);
|
|
void omap2_fixed_divisor_recalc(struct clk *clk);
|
|
long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
|
|
int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
|
|
u32 omap2_get_dpll_rate(struct clk *clk);
|
|
int omap2_wait_clock_ready(void __iomem *reg, u32 cval, const char *name);
|
|
void omap2_clk_prepare_for_reboot(void);
|
|
|
|
extern u8 cpu_mask;
|
|
|
|
/* clksel_rate data common to 24xx/343x */
|
|
static const struct clksel_rate gpt_32k_rates[] = {
|
|
{ .div = 1, .val = 0, .flags = RATE_IN_24XX | RATE_IN_343X | DEFAULT_RATE },
|
|
{ .div = 0 }
|
|
};
|
|
|
|
static const struct clksel_rate gpt_sys_rates[] = {
|
|
{ .div = 1, .val = 1, .flags = RATE_IN_24XX | RATE_IN_343X | DEFAULT_RATE },
|
|
{ .div = 0 }
|
|
};
|
|
|
|
static const struct clksel_rate gfx_l3_rates[] = {
|
|
{ .div = 1, .val = 1, .flags = RATE_IN_24XX | RATE_IN_343X },
|
|
{ .div = 2, .val = 2, .flags = RATE_IN_24XX | RATE_IN_343X | DEFAULT_RATE },
|
|
{ .div = 3, .val = 3, .flags = RATE_IN_243X | RATE_IN_343X },
|
|
{ .div = 4, .val = 4, .flags = RATE_IN_243X | RATE_IN_343X },
|
|
{ .div = 0 }
|
|
};
|
|
|
|
|
|
#endif
|