2005-11-10 22:26:53 +08:00
|
|
|
/*
|
2008-08-05 23:14:15 +08:00
|
|
|
* arch/arm/plat-omap/include/mach/clock.h
|
2005-11-10 22:26:53 +08:00
|
|
|
*
|
|
|
|
* Copyright (C) 2004 - 2005 Nokia corporation
|
|
|
|
* Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
|
|
|
|
* Based on clocks.h by Tony Lindgren, Gordon McNutt and RidgeRun, Inc
|
|
|
|
*
|
|
|
|
* 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_OMAP_CLOCK_H
|
|
|
|
#define __ARCH_ARM_OMAP_CLOCK_H
|
|
|
|
|
2009-12-09 07:21:29 +08:00
|
|
|
#include <linux/list.h>
|
|
|
|
|
2005-11-10 22:26:53 +08:00
|
|
|
struct module;
|
2008-03-18 16:35:15 +08:00
|
|
|
struct clk;
|
2008-08-19 16:08:44 +08:00
|
|
|
struct clockdomain;
|
2008-03-18 16:35:15 +08:00
|
|
|
|
2008-11-04 22:02:46 +08:00
|
|
|
struct clkops {
|
|
|
|
int (*enable)(struct clk *);
|
|
|
|
void (*disable)(struct clk *);
|
2009-07-25 09:44:03 +08:00
|
|
|
void (*find_idlest)(struct clk *, void __iomem **, u8 *);
|
|
|
|
void (*find_companion)(struct clk *, void __iomem **, u8 *);
|
2008-11-04 22:02:46 +08:00
|
|
|
};
|
|
|
|
|
2009-05-29 05:16:04 +08:00
|
|
|
#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \
|
|
|
|
defined(CONFIG_ARCH_OMAP4)
|
2008-03-18 16:35:15 +08:00
|
|
|
|
|
|
|
struct clksel_rate {
|
|
|
|
u32 val;
|
2008-11-05 05:50:46 +08:00
|
|
|
u8 div;
|
2008-03-18 16:35:15 +08:00
|
|
|
u8 flags;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct clksel {
|
|
|
|
struct clk *parent;
|
|
|
|
const struct clksel_rate *rates;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct dpll_data {
|
|
|
|
void __iomem *mult_div1_reg;
|
|
|
|
u32 mult_mask;
|
|
|
|
u32 div1_mask;
|
[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
|
|
|
struct clk *clk_bypass;
|
|
|
|
struct clk *clk_ref;
|
|
|
|
void __iomem *control_reg;
|
|
|
|
u32 enable_mask;
|
2008-11-05 05:50:46 +08:00
|
|
|
unsigned int rate_tolerance;
|
|
|
|
unsigned long last_rounded_rate;
|
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
|
|
|
u16 last_rounded_m;
|
|
|
|
u8 last_rounded_n;
|
2009-01-29 03:08:44 +08:00
|
|
|
u8 min_divider;
|
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
|
|
|
u8 max_divider;
|
|
|
|
u32 max_tolerance;
|
2008-11-05 05:50:46 +08:00
|
|
|
u16 max_multiplier;
|
2009-05-29 05:16:04 +08:00
|
|
|
#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
|
2008-07-03 17:24:45 +08:00
|
|
|
u8 modes;
|
2008-11-05 05:50:46 +08:00
|
|
|
void __iomem *autoidle_reg;
|
|
|
|
void __iomem *idlest_reg;
|
|
|
|
u32 autoidle_mask;
|
2009-01-28 10:12:47 +08:00
|
|
|
u32 freqsel_mask;
|
2009-01-29 03:08:17 +08:00
|
|
|
u32 idlest_mask;
|
2008-03-18 17:24:28 +08:00
|
|
|
u8 auto_recal_bit;
|
|
|
|
u8 recal_en_bit;
|
|
|
|
u8 recal_st_bit;
|
|
|
|
# endif
|
2008-03-18 16:35:15 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|
2005-11-10 22:26:53 +08:00
|
|
|
|
|
|
|
struct clk {
|
|
|
|
struct list_head node;
|
2008-11-04 22:02:46 +08:00
|
|
|
const struct clkops *ops;
|
2005-11-10 22:26:53 +08:00
|
|
|
const char *name;
|
2006-04-03 00:46:20 +08:00
|
|
|
int id;
|
2005-11-10 22:26:53 +08:00
|
|
|
struct clk *parent;
|
2009-01-31 18:05:51 +08:00
|
|
|
struct list_head children;
|
|
|
|
struct list_head sibling; /* node for children */
|
2005-11-10 22:26:53 +08:00
|
|
|
unsigned long rate;
|
|
|
|
__u32 flags;
|
|
|
|
void __iomem *enable_reg;
|
2009-02-12 18:12:59 +08:00
|
|
|
unsigned long (*recalc)(struct clk *);
|
2005-11-10 22:26:53 +08:00
|
|
|
int (*set_rate)(struct clk *, unsigned long);
|
|
|
|
long (*round_rate)(struct clk *, unsigned long);
|
|
|
|
void (*init)(struct clk *);
|
2008-11-05 05:50:46 +08:00
|
|
|
__u8 enable_bit;
|
|
|
|
__s8 usecount;
|
2009-05-29 05:16:04 +08:00
|
|
|
#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \
|
|
|
|
defined(CONFIG_ARCH_OMAP4)
|
2008-03-18 16:35:15 +08:00
|
|
|
u8 fixed_div;
|
|
|
|
void __iomem *clksel_reg;
|
|
|
|
u32 clksel_mask;
|
|
|
|
const struct clksel *clksel;
|
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
|
|
|
struct dpll_data *dpll_data;
|
2008-08-19 16:08:44 +08:00
|
|
|
const char *clkdm_name;
|
|
|
|
struct clockdomain *clkdm;
|
2008-03-18 16:35:15 +08:00
|
|
|
#else
|
|
|
|
__u8 rate_offset;
|
|
|
|
__u8 src_offset;
|
|
|
|
#endif
|
2008-07-03 17:24:41 +08:00
|
|
|
#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
|
|
|
|
struct dentry *dent; /* For visible tree hierarchy */
|
|
|
|
#endif
|
2005-11-10 22:26:53 +08:00
|
|
|
};
|
|
|
|
|
2008-05-22 23:38:50 +08:00
|
|
|
struct cpufreq_frequency_table;
|
|
|
|
|
2005-11-10 22:26:53 +08:00
|
|
|
struct clk_functions {
|
|
|
|
int (*clk_enable)(struct clk *clk);
|
|
|
|
void (*clk_disable)(struct clk *clk);
|
|
|
|
long (*clk_round_rate)(struct clk *clk, unsigned long rate);
|
|
|
|
int (*clk_set_rate)(struct clk *clk, unsigned long rate);
|
|
|
|
int (*clk_set_parent)(struct clk *clk, struct clk *parent);
|
|
|
|
void (*clk_allow_idle)(struct clk *clk);
|
|
|
|
void (*clk_deny_idle)(struct clk *clk);
|
2006-09-25 18:27:20 +08:00
|
|
|
void (*clk_disable_unused)(struct clk *clk);
|
2008-05-22 23:38:50 +08:00
|
|
|
#ifdef CONFIG_CPU_FREQ
|
|
|
|
void (*clk_init_cpufreq_table)(struct cpufreq_frequency_table **);
|
|
|
|
#endif
|
2005-11-10 22:26:53 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
extern unsigned int mpurate;
|
|
|
|
|
2009-01-28 10:12:50 +08:00
|
|
|
extern int clk_init(struct clk_functions *custom_clocks);
|
2009-05-13 07:50:30 +08:00
|
|
|
extern void clk_preinit(struct clk *clk);
|
2005-11-10 22:26:53 +08:00
|
|
|
extern int clk_register(struct clk *clk);
|
2009-01-31 18:05:51 +08:00
|
|
|
extern void clk_reparent(struct clk *child, struct clk *parent);
|
2005-11-10 22:26:53 +08:00
|
|
|
extern void clk_unregister(struct clk *clk);
|
|
|
|
extern void propagate_rate(struct clk *clk);
|
2008-03-18 16:35:15 +08:00
|
|
|
extern void recalculate_root_clocks(void);
|
2009-02-12 18:12:59 +08:00
|
|
|
extern unsigned long followparent_recalc(struct clk *clk);
|
2008-03-18 16:35:15 +08:00
|
|
|
extern void clk_enable_init_clocks(void);
|
2009-01-28 10:13:38 +08:00
|
|
|
#ifdef CONFIG_CPU_FREQ
|
|
|
|
extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
|
|
|
|
#endif
|
2005-11-10 22:26:53 +08:00
|
|
|
|
2008-11-05 00:35:03 +08:00
|
|
|
extern const struct clkops clkops_null;
|
|
|
|
|
2005-11-10 22:26:53 +08:00
|
|
|
/* Clock flags */
|
2009-02-09 00:07:46 +08:00
|
|
|
/* bit 0 is free */
|
2005-11-10 22:26:53 +08:00
|
|
|
#define RATE_FIXED (1 << 1) /* Fixed clock rate */
|
2009-01-31 18:05:51 +08:00
|
|
|
/* bits 2-4 are free */
|
2005-11-10 22:26:53 +08:00
|
|
|
#define ENABLE_REG_32BIT (1 << 5) /* Use 32-bit access */
|
|
|
|
#define CLOCK_IDLE_CONTROL (1 << 7)
|
|
|
|
#define CLOCK_NO_IDLE_PARENT (1 << 8)
|
|
|
|
#define DELAYED_APP (1 << 9) /* Delay application of clock */
|
|
|
|
#define CONFIG_PARTICIPANT (1 << 10) /* Fundamental clock */
|
2008-03-18 16:35:15 +08:00
|
|
|
#define ENABLE_ON_INIT (1 << 11) /* Enable upon framework init */
|
|
|
|
#define INVERT_ENABLE (1 << 12) /* 0 enables, 1 disables */
|
2009-12-09 09:46:28 +08:00
|
|
|
#define CLOCK_IN_OMAP4430 (1 << 13)
|
|
|
|
#define ALWAYS_ENABLED (1 << 14)
|
2009-01-19 23:51:11 +08:00
|
|
|
/* bits 13-31 are currently free */
|
2008-03-18 16:35:15 +08:00
|
|
|
|
|
|
|
/* Clksel_rate flags */
|
|
|
|
#define DEFAULT_RATE (1 << 0)
|
|
|
|
#define RATE_IN_242X (1 << 1)
|
|
|
|
#define RATE_IN_243X (1 << 2)
|
|
|
|
#define RATE_IN_343X (1 << 3) /* rates common to all 343X */
|
|
|
|
#define RATE_IN_3430ES2 (1 << 4) /* 3430ES2 rates only */
|
2009-12-09 09:46:28 +08:00
|
|
|
#define RATE_IN_4430 (1 << 5)
|
2008-03-18 16:35:15 +08:00
|
|
|
|
|
|
|
#define RATE_IN_24XX (RATE_IN_242X | RATE_IN_243X)
|
|
|
|
|
2005-11-10 22:26:53 +08:00
|
|
|
|
|
|
|
#endif
|