Merge branches 'at91', 'dyntick', 'ep93xx', 'iop', 'ixp', 'misc', 'orion', 'omap-reviewed', 'rpc', 'rtc' and 's3c' into devel
This commit is contained in:
committed by
Russell King
@@ -3,9 +3,15 @@
|
||||
#
|
||||
|
||||
# Common support
|
||||
obj-y := irq.o id.o io.o sram-fn.o memory.o control.o prcm.o clock.o mux.o \
|
||||
obj-y := irq.o id.o io.o memory.o control.o prcm.o clock.o mux.o \
|
||||
devices.o serial.o gpmc.o timer-gp.o
|
||||
|
||||
obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
|
||||
|
||||
# Functions loaded to SRAM
|
||||
obj-$(CONFIG_ARCH_OMAP2420) += sram242x.o
|
||||
obj-$(CONFIG_ARCH_OMAP2430) += sram243x.o
|
||||
|
||||
# Power Management
|
||||
obj-$(CONFIG_PM) += pm.o sleep.o
|
||||
|
||||
|
@@ -41,6 +41,24 @@
|
||||
|
||||
#define MAX_CLOCK_ENABLE_WAIT 100000
|
||||
|
||||
/* DPLL rate rounding: minimum DPLL multiplier, divider values */
|
||||
#define DPLL_MIN_MULTIPLIER 1
|
||||
#define DPLL_MIN_DIVIDER 1
|
||||
|
||||
/* Possible error results from _dpll_test_mult */
|
||||
#define DPLL_MULT_UNDERFLOW (1 << 0)
|
||||
|
||||
/*
|
||||
* Scale factor to mitigate roundoff errors in DPLL rate rounding.
|
||||
* The higher the scale factor, the greater the risk of arithmetic overflow,
|
||||
* but the closer the rounded rate to the target rate. DPLL_SCALE_FACTOR
|
||||
* must be a power of DPLL_SCALE_BASE.
|
||||
*/
|
||||
#define DPLL_SCALE_FACTOR 64
|
||||
#define DPLL_SCALE_BASE 2
|
||||
#define DPLL_ROUNDING_VAL ((DPLL_SCALE_BASE / 2) * \
|
||||
(DPLL_SCALE_FACTOR / DPLL_SCALE_BASE))
|
||||
|
||||
u8 cpu_mask;
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
@@ -95,7 +113,7 @@ u32 omap2_get_dpll_rate(struct clk *clk)
|
||||
{
|
||||
long long dpll_clk;
|
||||
u32 dpll_mult, dpll_div, dpll;
|
||||
const struct dpll_data *dd;
|
||||
struct dpll_data *dd;
|
||||
|
||||
dd = clk->dpll_data;
|
||||
/* REVISIT: What do we return on error? */
|
||||
@@ -603,7 +621,8 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
|
||||
clk->rate = clk->parent->rate / new_div;
|
||||
|
||||
if (clk->flags & DELAYED_APP && cpu_is_omap24xx()) {
|
||||
__raw_writel(OMAP24XX_VALID_CONFIG, OMAP24XX_PRCM_CLKCFG_CTRL);
|
||||
prm_write_mod_reg(OMAP24XX_VALID_CONFIG,
|
||||
OMAP24XX_GR_MOD, OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET);
|
||||
wmb();
|
||||
}
|
||||
|
||||
@@ -723,6 +742,184 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* DPLL rate rounding code */
|
||||
|
||||
/**
|
||||
* omap2_dpll_set_rate_tolerance: set the error tolerance during rate rounding
|
||||
* @clk: struct clk * of the DPLL
|
||||
* @tolerance: maximum rate error tolerance
|
||||
*
|
||||
* Set the maximum DPLL rate error tolerance for the rate rounding
|
||||
* algorithm. The rate tolerance is an attempt to balance DPLL power
|
||||
* saving (the least divider value "n") vs. rate fidelity (the least
|
||||
* difference between the desired DPLL target rate and the rounded
|
||||
* rate out of the algorithm). So, increasing the tolerance is likely
|
||||
* to decrease DPLL power consumption and increase DPLL rate error.
|
||||
* Returns -EINVAL if provided a null clock ptr or a clk that is not a
|
||||
* DPLL; or 0 upon success.
|
||||
*/
|
||||
int omap2_dpll_set_rate_tolerance(struct clk *clk, unsigned int tolerance)
|
||||
{
|
||||
if (!clk || !clk->dpll_data)
|
||||
return -EINVAL;
|
||||
|
||||
clk->dpll_data->rate_tolerance = tolerance;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long _dpll_compute_new_rate(unsigned long parent_rate, unsigned int m, unsigned int n)
|
||||
{
|
||||
unsigned long long num;
|
||||
|
||||
num = (unsigned long long)parent_rate * m;
|
||||
do_div(num, n);
|
||||
return num;
|
||||
}
|
||||
|
||||
/*
|
||||
* _dpll_test_mult - test a DPLL multiplier value
|
||||
* @m: pointer to the DPLL m (multiplier) value under test
|
||||
* @n: current DPLL n (divider) value under test
|
||||
* @new_rate: pointer to storage for the resulting rounded rate
|
||||
* @target_rate: the desired DPLL rate
|
||||
* @parent_rate: the DPLL's parent clock rate
|
||||
*
|
||||
* This code tests a DPLL multiplier value, ensuring that the
|
||||
* resulting rate will not be higher than the target_rate, and that
|
||||
* the multiplier value itself is valid for the DPLL. Initially, the
|
||||
* integer pointed to by the m argument should be prescaled by
|
||||
* multiplying by DPLL_SCALE_FACTOR. The code will replace this with
|
||||
* a non-scaled m upon return. This non-scaled m will result in a
|
||||
* new_rate as close as possible to target_rate (but not greater than
|
||||
* target_rate) given the current (parent_rate, n, prescaled m)
|
||||
* triple. Returns DPLL_MULT_UNDERFLOW in the event that the
|
||||
* non-scaled m attempted to underflow, which can allow the calling
|
||||
* function to bail out early; or 0 upon success.
|
||||
*/
|
||||
static int _dpll_test_mult(int *m, int n, unsigned long *new_rate,
|
||||
unsigned long target_rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
int flags = 0, carry = 0;
|
||||
|
||||
/* Unscale m and round if necessary */
|
||||
if (*m % DPLL_SCALE_FACTOR >= DPLL_ROUNDING_VAL)
|
||||
carry = 1;
|
||||
*m = (*m / DPLL_SCALE_FACTOR) + carry;
|
||||
|
||||
/*
|
||||
* The new rate must be <= the target rate to avoid programming
|
||||
* a rate that is impossible for the hardware to handle
|
||||
*/
|
||||
*new_rate = _dpll_compute_new_rate(parent_rate, *m, n);
|
||||
if (*new_rate > target_rate) {
|
||||
(*m)--;
|
||||
*new_rate = 0;
|
||||
}
|
||||
|
||||
/* Guard against m underflow */
|
||||
if (*m < DPLL_MIN_MULTIPLIER) {
|
||||
*m = DPLL_MIN_MULTIPLIER;
|
||||
*new_rate = 0;
|
||||
flags = DPLL_MULT_UNDERFLOW;
|
||||
}
|
||||
|
||||
if (*new_rate == 0)
|
||||
*new_rate = _dpll_compute_new_rate(parent_rate, *m, n);
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* omap2_dpll_round_rate - round a target rate for an OMAP DPLL
|
||||
* @clk: struct clk * for a DPLL
|
||||
* @target_rate: desired DPLL clock rate
|
||||
*
|
||||
* Given a DPLL, a desired target rate, and a rate tolerance, round
|
||||
* the target rate to a possible, programmable rate for this DPLL.
|
||||
* Rate tolerance is assumed to be set by the caller before this
|
||||
* function is called. Attempts to select the minimum possible n
|
||||
* within the tolerance to reduce power consumption. Stores the
|
||||
* computed (m, n) in the DPLL's dpll_data structure so set_rate()
|
||||
* will not need to call this (expensive) function again. Returns ~0
|
||||
* if the target rate cannot be rounded, either because the rate is
|
||||
* too low or because the rate tolerance is set too tightly; or the
|
||||
* rounded rate upon success.
|
||||
*/
|
||||
long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
|
||||
{
|
||||
int m, n, r, e, scaled_max_m;
|
||||
unsigned long scaled_rt_rp, new_rate;
|
||||
int min_e = -1, min_e_m = -1, min_e_n = -1;
|
||||
|
||||
if (!clk || !clk->dpll_data)
|
||||
return ~0;
|
||||
|
||||
pr_debug("clock: starting DPLL round_rate for clock %s, target rate "
|
||||
"%ld\n", clk->name, target_rate);
|
||||
|
||||
scaled_rt_rp = target_rate / (clk->parent->rate / DPLL_SCALE_FACTOR);
|
||||
scaled_max_m = clk->dpll_data->max_multiplier * DPLL_SCALE_FACTOR;
|
||||
|
||||
clk->dpll_data->last_rounded_rate = 0;
|
||||
|
||||
for (n = clk->dpll_data->max_divider; n >= DPLL_MIN_DIVIDER; n--) {
|
||||
|
||||
/* Compute the scaled DPLL multiplier, based on the divider */
|
||||
m = scaled_rt_rp * n;
|
||||
|
||||
/*
|
||||
* Since we're counting n down, a m overflow means we can
|
||||
* can immediately skip to the next n
|
||||
*/
|
||||
if (m > scaled_max_m)
|
||||
continue;
|
||||
|
||||
r = _dpll_test_mult(&m, n, &new_rate, target_rate,
|
||||
clk->parent->rate);
|
||||
|
||||
e = target_rate - new_rate;
|
||||
pr_debug("clock: n = %d: m = %d: rate error is %d "
|
||||
"(new_rate = %ld)\n", n, m, e, new_rate);
|
||||
|
||||
if (min_e == -1 ||
|
||||
min_e >= (int)(abs(e) - clk->dpll_data->rate_tolerance)) {
|
||||
min_e = e;
|
||||
min_e_m = m;
|
||||
min_e_n = n;
|
||||
|
||||
pr_debug("clock: found new least error %d\n", min_e);
|
||||
}
|
||||
|
||||
/*
|
||||
* Since we're counting n down, a m underflow means we
|
||||
* can bail out completely (since as n decreases in
|
||||
* the next iteration, there's no way that m can
|
||||
* increase beyond the current m)
|
||||
*/
|
||||
if (r & DPLL_MULT_UNDERFLOW)
|
||||
break;
|
||||
}
|
||||
|
||||
if (min_e < 0) {
|
||||
pr_debug("clock: error: target rate or tolerance too low\n");
|
||||
return ~0;
|
||||
}
|
||||
|
||||
clk->dpll_data->last_rounded_m = min_e_m;
|
||||
clk->dpll_data->last_rounded_n = min_e_n;
|
||||
clk->dpll_data->last_rounded_rate =
|
||||
_dpll_compute_new_rate(clk->parent->rate, min_e_m, min_e_n);
|
||||
|
||||
pr_debug("clock: final least error: e = %d, m = %d, n = %d\n",
|
||||
min_e, min_e_m, min_e_n);
|
||||
pr_debug("clock: final rate: %ld (target rate: %ld)\n",
|
||||
clk->dpll_data->last_rounded_rate, target_rate);
|
||||
|
||||
return clk->dpll_data->last_rounded_rate;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Omap2 clock reset and init functions
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
@@ -18,11 +18,16 @@
|
||||
|
||||
#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);
|
||||
@@ -42,6 +47,7 @@ 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;
|
||||
|
||||
|
@@ -154,7 +154,7 @@ static void omap2_clk_fixed_disable(struct clk *clk)
|
||||
* Uses the current prcm set to tell if a rate is valid.
|
||||
* You can go slower, but not faster within a given rate set.
|
||||
*/
|
||||
static u32 omap2_dpll_round_rate(unsigned long target_rate)
|
||||
long omap2_dpllcore_round_rate(unsigned long target_rate)
|
||||
{
|
||||
u32 high, low, core_clk_src;
|
||||
|
||||
@@ -183,14 +183,14 @@ static u32 omap2_dpll_round_rate(unsigned long target_rate)
|
||||
|
||||
}
|
||||
|
||||
static void omap2_dpll_recalc(struct clk *clk)
|
||||
static void omap2_dpllcore_recalc(struct clk *clk)
|
||||
{
|
||||
clk->rate = omap2_get_dpll_rate_24xx(clk);
|
||||
|
||||
propagate_rate(clk);
|
||||
}
|
||||
|
||||
static int omap2_reprogram_dpll(struct clk *clk, unsigned long rate)
|
||||
static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
u32 cur_rate, low, mult, div, valid_rate, done_rate;
|
||||
u32 bypass = 0;
|
||||
@@ -209,7 +209,7 @@ static int omap2_reprogram_dpll(struct clk *clk, unsigned long rate)
|
||||
} else if ((rate == (cur_rate * 2)) && (mult == 1)) {
|
||||
omap2_reprogram_sdrc(CORE_CLK_SRC_DPLL_X2, 1);
|
||||
} else if (rate != cur_rate) {
|
||||
valid_rate = omap2_dpll_round_rate(rate);
|
||||
valid_rate = omap2_dpllcore_round_rate(rate);
|
||||
if (valid_rate != rate)
|
||||
goto dpll_exit;
|
||||
|
||||
@@ -256,7 +256,7 @@ static int omap2_reprogram_dpll(struct clk *clk, unsigned long rate)
|
||||
omap2_init_memory_params(omap2_dll_force_needed());
|
||||
omap2_reprogram_sdrc(done_rate, 0);
|
||||
}
|
||||
omap2_dpll_recalc(&dpll_ck);
|
||||
omap2_dpllcore_recalc(&dpll_ck);
|
||||
ret = 0;
|
||||
|
||||
dpll_exit:
|
||||
@@ -383,7 +383,7 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
omap2_dpll_recalc(&dpll_ck);
|
||||
omap2_dpllcore_recalc(&dpll_ck);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -30,12 +30,12 @@ static long omap2_round_to_table_rate(struct clk *clk, unsigned long rate);
|
||||
static void omap2_sys_clk_recalc(struct clk *clk);
|
||||
static void omap2_osc_clk_recalc(struct clk *clk);
|
||||
static void omap2_sys_clk_recalc(struct clk *clk);
|
||||
static void omap2_dpll_recalc(struct clk *clk);
|
||||
static void omap2_dpllcore_recalc(struct clk *clk);
|
||||
static int omap2_clk_fixed_enable(struct clk *clk);
|
||||
static void omap2_clk_fixed_disable(struct clk *clk);
|
||||
static int omap2_enable_osc_ck(struct clk *clk);
|
||||
static void omap2_disable_osc_ck(struct clk *clk);
|
||||
static int omap2_reprogram_dpll(struct clk *clk, unsigned long rate);
|
||||
static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate);
|
||||
|
||||
/* Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
|
||||
* xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP
|
||||
@@ -665,20 +665,27 @@ static struct clk alt_ck = { /* Typical 54M or 48M, may not exist */
|
||||
* deal with this
|
||||
*/
|
||||
|
||||
static const struct dpll_data dpll_dd = {
|
||||
static struct dpll_data dpll_dd = {
|
||||
.mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
|
||||
.mult_mask = OMAP24XX_DPLL_MULT_MASK,
|
||||
.div1_mask = OMAP24XX_DPLL_DIV_MASK,
|
||||
.max_multiplier = 1024,
|
||||
.max_divider = 16,
|
||||
.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
|
||||
};
|
||||
|
||||
/*
|
||||
* XXX Cannot add round_rate here yet, as this is still a composite clock,
|
||||
* not just a DPLL
|
||||
*/
|
||||
static struct clk dpll_ck = {
|
||||
.name = "dpll_ck",
|
||||
.parent = &sys_ck, /* Can be func_32k also */
|
||||
.dpll_data = &dpll_dd,
|
||||
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X |
|
||||
RATE_PROPAGATES | ALWAYS_ENABLED,
|
||||
.recalc = &omap2_dpll_recalc,
|
||||
.set_rate = &omap2_reprogram_dpll,
|
||||
.recalc = &omap2_dpllcore_recalc,
|
||||
.set_rate = &omap2_reprogram_dpllcore,
|
||||
};
|
||||
|
||||
static struct clk apll96_ck = {
|
||||
@@ -1747,7 +1754,8 @@ static struct clk gpt12_fck = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp1_ick = {
|
||||
.name = "mcbsp1_ick",
|
||||
.name = "mcbsp_ick",
|
||||
.id = 1,
|
||||
.parent = &l4_ck,
|
||||
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
|
||||
@@ -1756,7 +1764,8 @@ static struct clk mcbsp1_ick = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp1_fck = {
|
||||
.name = "mcbsp1_fck",
|
||||
.name = "mcbsp_fck",
|
||||
.id = 1,
|
||||
.parent = &func_96m_ck,
|
||||
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
|
||||
@@ -1765,7 +1774,8 @@ static struct clk mcbsp1_fck = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp2_ick = {
|
||||
.name = "mcbsp2_ick",
|
||||
.name = "mcbsp_ick",
|
||||
.id = 2,
|
||||
.parent = &l4_ck,
|
||||
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
|
||||
@@ -1774,7 +1784,8 @@ static struct clk mcbsp2_ick = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp2_fck = {
|
||||
.name = "mcbsp2_fck",
|
||||
.name = "mcbsp_fck",
|
||||
.id = 2,
|
||||
.parent = &func_96m_ck,
|
||||
.flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
|
||||
@@ -1783,7 +1794,8 @@ static struct clk mcbsp2_fck = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp3_ick = {
|
||||
.name = "mcbsp3_ick",
|
||||
.name = "mcbsp_ick",
|
||||
.id = 3,
|
||||
.parent = &l4_ck,
|
||||
.flags = CLOCK_IN_OMAP243X,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
|
||||
@@ -1792,7 +1804,8 @@ static struct clk mcbsp3_ick = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp3_fck = {
|
||||
.name = "mcbsp3_fck",
|
||||
.name = "mcbsp_fck",
|
||||
.id = 3,
|
||||
.parent = &func_96m_ck,
|
||||
.flags = CLOCK_IN_OMAP243X,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
|
||||
@@ -1801,7 +1814,8 @@ static struct clk mcbsp3_fck = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp4_ick = {
|
||||
.name = "mcbsp4_ick",
|
||||
.name = "mcbsp_ick",
|
||||
.id = 4,
|
||||
.parent = &l4_ck,
|
||||
.flags = CLOCK_IN_OMAP243X,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
|
||||
@@ -1810,7 +1824,8 @@ static struct clk mcbsp4_ick = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp4_fck = {
|
||||
.name = "mcbsp4_fck",
|
||||
.name = "mcbsp_fck",
|
||||
.id = 4,
|
||||
.parent = &func_96m_ck,
|
||||
.flags = CLOCK_IN_OMAP243X,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
|
||||
@@ -1819,7 +1834,8 @@ static struct clk mcbsp4_fck = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp5_ick = {
|
||||
.name = "mcbsp5_ick",
|
||||
.name = "mcbsp_ick",
|
||||
.id = 5,
|
||||
.parent = &l4_ck,
|
||||
.flags = CLOCK_IN_OMAP243X,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
|
||||
@@ -1828,7 +1844,8 @@ static struct clk mcbsp5_ick = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp5_fck = {
|
||||
.name = "mcbsp5_fck",
|
||||
.name = "mcbsp_fck",
|
||||
.id = 5,
|
||||
.parent = &func_96m_ck,
|
||||
.flags = CLOCK_IN_OMAP243X,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
|
||||
|
@@ -1,10 +1,11 @@
|
||||
/*
|
||||
* OMAP3-specific clock framework functions
|
||||
*
|
||||
* Copyright (C) 2007 Texas Instruments, Inc.
|
||||
* Copyright (C) 2007 Nokia Corporation
|
||||
* Copyright (C) 2007-2008 Texas Instruments, Inc.
|
||||
* Copyright (C) 2007-2008 Nokia Corporation
|
||||
*
|
||||
* Written by Paul Walmsley
|
||||
* Testing and integration fixes by Jouni Högander
|
||||
*
|
||||
* Parts of this code are based on code written by
|
||||
* Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu
|
||||
@@ -23,6 +24,7 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/limits.h>
|
||||
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/sram.h>
|
||||
@@ -37,8 +39,11 @@
|
||||
#include "cm.h"
|
||||
#include "cm-regbits-34xx.h"
|
||||
|
||||
/* CM_CLKEN_PLL*.EN* bit values */
|
||||
#define DPLL_LOCKED 0x7
|
||||
/* CM_AUTOIDLE_PLL*.AUTO_* bit values */
|
||||
#define DPLL_AUTOIDLE_DISABLE 0x0
|
||||
#define DPLL_AUTOIDLE_LOW_POWER_STOP 0x1
|
||||
|
||||
#define MAX_DPLL_WAIT_TRIES 1000000
|
||||
|
||||
/**
|
||||
* omap3_dpll_recalc - recalculate DPLL rate
|
||||
@@ -53,6 +58,290 @@ static void omap3_dpll_recalc(struct clk *clk)
|
||||
propagate_rate(clk);
|
||||
}
|
||||
|
||||
/* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
|
||||
static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits)
|
||||
{
|
||||
const struct dpll_data *dd;
|
||||
|
||||
dd = clk->dpll_data;
|
||||
|
||||
cm_rmw_reg_bits(dd->enable_mask, clken_bits << __ffs(dd->enable_mask),
|
||||
dd->control_reg);
|
||||
}
|
||||
|
||||
/* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
|
||||
static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
|
||||
{
|
||||
const struct dpll_data *dd;
|
||||
int i = 0;
|
||||
int ret = -EINVAL;
|
||||
u32 idlest_mask;
|
||||
|
||||
dd = clk->dpll_data;
|
||||
|
||||
state <<= dd->idlest_bit;
|
||||
idlest_mask = 1 << dd->idlest_bit;
|
||||
|
||||
while (((cm_read_reg(dd->idlest_reg) & idlest_mask) != state) &&
|
||||
i < MAX_DPLL_WAIT_TRIES) {
|
||||
i++;
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
if (i == MAX_DPLL_WAIT_TRIES) {
|
||||
printk(KERN_ERR "clock: %s failed transition to '%s'\n",
|
||||
clk->name, (state) ? "locked" : "bypassed");
|
||||
} else {
|
||||
pr_debug("clock: %s transition to '%s' in %d loops\n",
|
||||
clk->name, (state) ? "locked" : "bypassed", i);
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Non-CORE DPLL (e.g., DPLLs that do not control SDRC) clock functions */
|
||||
|
||||
/*
|
||||
* _omap3_noncore_dpll_lock - instruct a DPLL to lock and wait for readiness
|
||||
* @clk: pointer to a DPLL struct clk
|
||||
*
|
||||
* Instructs a non-CORE DPLL to lock. Waits for the DPLL to report
|
||||
* readiness before returning. Will save and restore the DPLL's
|
||||
* autoidle state across the enable, per the CDP code. If the DPLL
|
||||
* locked successfully, return 0; if the DPLL did not lock in the time
|
||||
* allotted, or DPLL3 was passed in, return -EINVAL.
|
||||
*/
|
||||
static int _omap3_noncore_dpll_lock(struct clk *clk)
|
||||
{
|
||||
u8 ai;
|
||||
int r;
|
||||
|
||||
if (clk == &dpll3_ck)
|
||||
return -EINVAL;
|
||||
|
||||
pr_debug("clock: locking DPLL %s\n", clk->name);
|
||||
|
||||
ai = omap3_dpll_autoidle_read(clk);
|
||||
|
||||
_omap3_dpll_write_clken(clk, DPLL_LOCKED);
|
||||
|
||||
if (ai) {
|
||||
/*
|
||||
* If no downstream clocks are enabled, CM_IDLEST bit
|
||||
* may never become active, so don't wait for DPLL to lock.
|
||||
*/
|
||||
r = 0;
|
||||
omap3_dpll_allow_idle(clk);
|
||||
} else {
|
||||
r = _omap3_wait_dpll_status(clk, 1);
|
||||
omap3_dpll_deny_idle(clk);
|
||||
};
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* omap3_noncore_dpll_bypass - instruct a DPLL to bypass and wait for readiness
|
||||
* @clk: pointer to a DPLL struct clk
|
||||
*
|
||||
* Instructs a non-CORE DPLL to enter low-power bypass mode. In
|
||||
* bypass mode, the DPLL's rate is set equal to its parent clock's
|
||||
* rate. Waits for the DPLL to report readiness before returning.
|
||||
* Will save and restore the DPLL's autoidle state across the enable,
|
||||
* per the CDP code. If the DPLL entered bypass mode successfully,
|
||||
* return 0; if the DPLL did not enter bypass in the time allotted, or
|
||||
* DPLL3 was passed in, or the DPLL does not support low-power bypass,
|
||||
* return -EINVAL.
|
||||
*/
|
||||
static int _omap3_noncore_dpll_bypass(struct clk *clk)
|
||||
{
|
||||
int r;
|
||||
u8 ai;
|
||||
|
||||
if (clk == &dpll3_ck)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS)))
|
||||
return -EINVAL;
|
||||
|
||||
pr_debug("clock: configuring DPLL %s for low-power bypass\n",
|
||||
clk->name);
|
||||
|
||||
ai = omap3_dpll_autoidle_read(clk);
|
||||
|
||||
_omap3_dpll_write_clken(clk, DPLL_LOW_POWER_BYPASS);
|
||||
|
||||
r = _omap3_wait_dpll_status(clk, 0);
|
||||
|
||||
if (ai)
|
||||
omap3_dpll_allow_idle(clk);
|
||||
else
|
||||
omap3_dpll_deny_idle(clk);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* _omap3_noncore_dpll_stop - instruct a DPLL to stop
|
||||
* @clk: pointer to a DPLL struct clk
|
||||
*
|
||||
* Instructs a non-CORE DPLL to enter low-power stop. Will save and
|
||||
* restore the DPLL's autoidle state across the stop, per the CDP
|
||||
* code. If DPLL3 was passed in, or the DPLL does not support
|
||||
* low-power stop, return -EINVAL; otherwise, return 0.
|
||||
*/
|
||||
static int _omap3_noncore_dpll_stop(struct clk *clk)
|
||||
{
|
||||
u8 ai;
|
||||
|
||||
if (clk == &dpll3_ck)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(clk->dpll_data->modes & (1 << DPLL_LOW_POWER_STOP)))
|
||||
return -EINVAL;
|
||||
|
||||
pr_debug("clock: stopping DPLL %s\n", clk->name);
|
||||
|
||||
ai = omap3_dpll_autoidle_read(clk);
|
||||
|
||||
_omap3_dpll_write_clken(clk, DPLL_LOW_POWER_STOP);
|
||||
|
||||
if (ai)
|
||||
omap3_dpll_allow_idle(clk);
|
||||
else
|
||||
omap3_dpll_deny_idle(clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode
|
||||
* @clk: pointer to a DPLL struct clk
|
||||
*
|
||||
* Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock.
|
||||
* The choice of modes depends on the DPLL's programmed rate: if it is
|
||||
* the same as the DPLL's parent clock, it will enter bypass;
|
||||
* otherwise, it will enter lock. This code will wait for the DPLL to
|
||||
* indicate readiness before returning, unless the DPLL takes too long
|
||||
* to enter the target state. Intended to be used as the struct clk's
|
||||
* enable function. If DPLL3 was passed in, or the DPLL does not
|
||||
* support low-power stop, or if the DPLL took too long to enter
|
||||
* bypass or lock, return -EINVAL; otherwise, return 0.
|
||||
*/
|
||||
static int omap3_noncore_dpll_enable(struct clk *clk)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (clk == &dpll3_ck)
|
||||
return -EINVAL;
|
||||
|
||||
if (clk->parent->rate == clk_get_rate(clk))
|
||||
r = _omap3_noncore_dpll_bypass(clk);
|
||||
else
|
||||
r = _omap3_noncore_dpll_lock(clk);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode
|
||||
* @clk: pointer to a DPLL struct clk
|
||||
*
|
||||
* Instructs a non-CORE DPLL to enable, e.g., to enter bypass or lock.
|
||||
* The choice of modes depends on the DPLL's programmed rate: if it is
|
||||
* the same as the DPLL's parent clock, it will enter bypass;
|
||||
* otherwise, it will enter lock. This code will wait for the DPLL to
|
||||
* indicate readiness before returning, unless the DPLL takes too long
|
||||
* to enter the target state. Intended to be used as the struct clk's
|
||||
* enable function. If DPLL3 was passed in, or the DPLL does not
|
||||
* support low-power stop, or if the DPLL took too long to enter
|
||||
* bypass or lock, return -EINVAL; otherwise, return 0.
|
||||
*/
|
||||
static void omap3_noncore_dpll_disable(struct clk *clk)
|
||||
{
|
||||
if (clk == &dpll3_ck)
|
||||
return;
|
||||
|
||||
_omap3_noncore_dpll_stop(clk);
|
||||
}
|
||||
|
||||
/**
|
||||
* omap3_dpll_autoidle_read - read a DPLL's autoidle bits
|
||||
* @clk: struct clk * of the DPLL to read
|
||||
*
|
||||
* Return the DPLL's autoidle bits, shifted down to bit 0. Returns
|
||||
* -EINVAL if passed a null pointer or if the struct clk does not
|
||||
* appear to refer to a DPLL.
|
||||
*/
|
||||
static u32 omap3_dpll_autoidle_read(struct clk *clk)
|
||||
{
|
||||
const struct dpll_data *dd;
|
||||
u32 v;
|
||||
|
||||
if (!clk || !clk->dpll_data)
|
||||
return -EINVAL;
|
||||
|
||||
dd = clk->dpll_data;
|
||||
|
||||
v = cm_read_reg(dd->autoidle_reg);
|
||||
v &= dd->autoidle_mask;
|
||||
v >>= __ffs(dd->autoidle_mask);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* omap3_dpll_allow_idle - enable DPLL autoidle bits
|
||||
* @clk: struct clk * of the DPLL to operate on
|
||||
*
|
||||
* Enable DPLL automatic idle control. This automatic idle mode
|
||||
* switching takes effect only when the DPLL is locked, at least on
|
||||
* OMAP3430. The DPLL will enter low-power stop when its downstream
|
||||
* clocks are gated. No return value.
|
||||
*/
|
||||
static void omap3_dpll_allow_idle(struct clk *clk)
|
||||
{
|
||||
const struct dpll_data *dd;
|
||||
|
||||
if (!clk || !clk->dpll_data)
|
||||
return;
|
||||
|
||||
dd = clk->dpll_data;
|
||||
|
||||
/*
|
||||
* REVISIT: CORE DPLL can optionally enter low-power bypass
|
||||
* by writing 0x5 instead of 0x1. Add some mechanism to
|
||||
* optionally enter this mode.
|
||||
*/
|
||||
cm_rmw_reg_bits(dd->autoidle_mask,
|
||||
DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask),
|
||||
dd->autoidle_reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* omap3_dpll_deny_idle - prevent DPLL from automatically idling
|
||||
* @clk: struct clk * of the DPLL to operate on
|
||||
*
|
||||
* Disable DPLL automatic idle control. No return value.
|
||||
*/
|
||||
static void omap3_dpll_deny_idle(struct clk *clk)
|
||||
{
|
||||
const struct dpll_data *dd;
|
||||
|
||||
if (!clk || !clk->dpll_data)
|
||||
return;
|
||||
|
||||
dd = clk->dpll_data;
|
||||
|
||||
cm_rmw_reg_bits(dd->autoidle_mask,
|
||||
DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask),
|
||||
dd->autoidle_reg);
|
||||
}
|
||||
|
||||
/* Clock control for DPLL outputs */
|
||||
|
||||
/**
|
||||
* omap3_clkoutx2_recalc - recalculate DPLL X2 output virtual clock rate
|
||||
* @clk: DPLL output struct clk
|
||||
@@ -89,6 +378,8 @@ static void omap3_clkoutx2_recalc(struct clk *clk)
|
||||
propagate_rate(clk);
|
||||
}
|
||||
|
||||
/* Common clock code */
|
||||
|
||||
/*
|
||||
* As it is structured now, this will prevent an OMAP2/3 multiboot
|
||||
* kernel from compiling. This will need further attention.
|
||||
|
@@ -1,14 +1,19 @@
|
||||
/*
|
||||
* OMAP3 clock framework
|
||||
*
|
||||
* Virtual clocks are introduced as a convenient tools.
|
||||
* They are sources for other clocks and not supposed
|
||||
* to be requested from drivers directly.
|
||||
*
|
||||
* Copyright (C) 2007-2008 Texas Instruments, Inc.
|
||||
* Copyright (C) 2007-2008 Nokia Corporation
|
||||
*
|
||||
* Written by Paul Walmsley
|
||||
* With many device clock fixes by Kevin Hilman and Jouni Högander
|
||||
* DPLL bypass clock support added by Roman Tereshonkov
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Virtual clocks are introduced as convenient tools.
|
||||
* They are sources for other clocks and not supposed
|
||||
* to be requested from drivers directly.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
|
||||
@@ -24,6 +29,15 @@
|
||||
|
||||
static void omap3_dpll_recalc(struct clk *clk);
|
||||
static void omap3_clkoutx2_recalc(struct clk *clk);
|
||||
static void omap3_dpll_allow_idle(struct clk *clk);
|
||||
static void omap3_dpll_deny_idle(struct clk *clk);
|
||||
static u32 omap3_dpll_autoidle_read(struct clk *clk);
|
||||
static int omap3_noncore_dpll_enable(struct clk *clk);
|
||||
static void omap3_noncore_dpll_disable(struct clk *clk);
|
||||
|
||||
/* Maximum DPLL multiplier, divider values for OMAP3 */
|
||||
#define OMAP3_MAX_DPLL_MULT 2048
|
||||
#define OMAP3_MAX_DPLL_DIV 128
|
||||
|
||||
/*
|
||||
* DPLL1 supplies clock to the MPU.
|
||||
@@ -33,6 +47,11 @@ static void omap3_clkoutx2_recalc(struct clk *clk);
|
||||
* DPLL5 supplies other peripheral clocks (USBHOST, USIM).
|
||||
*/
|
||||
|
||||
/* 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
|
||||
|
||||
/* PRM CLOCKS */
|
||||
|
||||
/* According to timer32k.c, this is a 32768Hz clock, not a 32000Hz clock. */
|
||||
@@ -240,15 +259,23 @@ static const struct clksel_rate div16_dpll_rates[] = {
|
||||
/* DPLL1 */
|
||||
/* MPU clock source */
|
||||
/* Type: DPLL */
|
||||
static const struct dpll_data dpll1_dd = {
|
||||
static struct dpll_data dpll1_dd = {
|
||||
.mult_div1_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
|
||||
.mult_mask = OMAP3430_MPU_DPLL_MULT_MASK,
|
||||
.div1_mask = OMAP3430_MPU_DPLL_DIV_MASK,
|
||||
.control_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKEN_PLL),
|
||||
.enable_mask = OMAP3430_EN_MPU_DPLL_MASK,
|
||||
.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
|
||||
.auto_recal_bit = OMAP3430_EN_MPU_DPLL_DRIFTGUARD_SHIFT,
|
||||
.recal_en_bit = OMAP3430_MPU_DPLL_RECAL_EN_SHIFT,
|
||||
.recal_st_bit = OMAP3430_MPU_DPLL_ST_SHIFT,
|
||||
.autoidle_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_AUTOIDLE_PLL),
|
||||
.autoidle_mask = OMAP3430_AUTO_MPU_DPLL_MASK,
|
||||
.idlest_reg = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
|
||||
.idlest_bit = OMAP3430_ST_MPU_CLK_SHIFT,
|
||||
.max_multiplier = OMAP3_MAX_DPLL_MULT,
|
||||
.max_divider = OMAP3_MAX_DPLL_DIV,
|
||||
.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
|
||||
};
|
||||
|
||||
static struct clk dpll1_ck = {
|
||||
@@ -256,6 +283,7 @@ static struct clk dpll1_ck = {
|
||||
.parent = &sys_ck,
|
||||
.dpll_data = &dpll1_dd,
|
||||
.flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
|
||||
.round_rate = &omap2_dpll_round_rate,
|
||||
.recalc = &omap3_dpll_recalc,
|
||||
};
|
||||
|
||||
@@ -297,22 +325,34 @@ static struct clk dpll1_x2m2_ck = {
|
||||
/* IVA2 clock source */
|
||||
/* Type: DPLL */
|
||||
|
||||
static const struct dpll_data dpll2_dd = {
|
||||
static struct dpll_data dpll2_dd = {
|
||||
.mult_div1_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
|
||||
.mult_mask = OMAP3430_IVA2_DPLL_MULT_MASK,
|
||||
.div1_mask = OMAP3430_IVA2_DPLL_DIV_MASK,
|
||||
.control_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL),
|
||||
.enable_mask = OMAP3430_EN_IVA2_DPLL_MASK,
|
||||
.modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED) |
|
||||
(1 << DPLL_LOW_POWER_BYPASS),
|
||||
.auto_recal_bit = OMAP3430_EN_IVA2_DPLL_DRIFTGUARD_SHIFT,
|
||||
.recal_en_bit = OMAP3430_PRM_IRQENABLE_MPU_IVA2_DPLL_RECAL_EN_SHIFT,
|
||||
.recal_st_bit = OMAP3430_PRM_IRQSTATUS_MPU_IVA2_DPLL_ST_SHIFT,
|
||||
.autoidle_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_AUTOIDLE_PLL),
|
||||
.autoidle_mask = OMAP3430_AUTO_IVA2_DPLL_MASK,
|
||||
.idlest_reg = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_IDLEST_PLL),
|
||||
.idlest_bit = OMAP3430_ST_IVA2_CLK_SHIFT,
|
||||
.max_multiplier = OMAP3_MAX_DPLL_MULT,
|
||||
.max_divider = OMAP3_MAX_DPLL_DIV,
|
||||
.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
|
||||
};
|
||||
|
||||
static struct clk dpll2_ck = {
|
||||
.name = "dpll2_ck",
|
||||
.parent = &sys_ck,
|
||||
.dpll_data = &dpll2_dd,
|
||||
.flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
|
||||
.flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES,
|
||||
.enable = &omap3_noncore_dpll_enable,
|
||||
.disable = &omap3_noncore_dpll_disable,
|
||||
.round_rate = &omap2_dpll_round_rate,
|
||||
.recalc = &omap3_dpll_recalc,
|
||||
};
|
||||
|
||||
@@ -338,10 +378,12 @@ static struct clk dpll2_m2_ck = {
|
||||
.recalc = &omap2_clksel_recalc,
|
||||
};
|
||||
|
||||
/* DPLL3 */
|
||||
/* Source clock for all interfaces and for some device fclks */
|
||||
/* Type: DPLL */
|
||||
static const struct dpll_data dpll3_dd = {
|
||||
/*
|
||||
* DPLL3
|
||||
* Source clock for all interfaces and for some device fclks
|
||||
* REVISIT: Also supports fast relock bypass - not included below
|
||||
*/
|
||||
static struct dpll_data dpll3_dd = {
|
||||
.mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
|
||||
.mult_mask = OMAP3430_CORE_DPLL_MULT_MASK,
|
||||
.div1_mask = OMAP3430_CORE_DPLL_DIV_MASK,
|
||||
@@ -350,6 +392,11 @@ static const struct dpll_data dpll3_dd = {
|
||||
.auto_recal_bit = OMAP3430_EN_CORE_DPLL_DRIFTGUARD_SHIFT,
|
||||
.recal_en_bit = OMAP3430_CORE_DPLL_RECAL_EN_SHIFT,
|
||||
.recal_st_bit = OMAP3430_CORE_DPLL_ST_SHIFT,
|
||||
.autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
|
||||
.autoidle_mask = OMAP3430_AUTO_CORE_DPLL_MASK,
|
||||
.max_multiplier = OMAP3_MAX_DPLL_MULT,
|
||||
.max_divider = OMAP3_MAX_DPLL_DIV,
|
||||
.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
|
||||
};
|
||||
|
||||
static struct clk dpll3_ck = {
|
||||
@@ -357,6 +404,7 @@ static struct clk dpll3_ck = {
|
||||
.parent = &sys_ck,
|
||||
.dpll_data = &dpll3_dd,
|
||||
.flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
|
||||
.round_rate = &omap2_dpll_round_rate,
|
||||
.recalc = &omap3_dpll_recalc,
|
||||
};
|
||||
|
||||
@@ -439,7 +487,7 @@ static struct clk core_ck = {
|
||||
.name = "core_ck",
|
||||
.init = &omap2_init_clksel_parent,
|
||||
.clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
|
||||
.clksel_mask = OMAP3430_ST_CORE_CLK,
|
||||
.clksel_mask = OMAP3430_ST_CORE_CLK_MASK,
|
||||
.clksel = core_ck_clksel,
|
||||
.flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
|
||||
PARENT_CONTROLS_CLOCK,
|
||||
@@ -456,7 +504,7 @@ static struct clk dpll3_m2x2_ck = {
|
||||
.name = "dpll3_m2x2_ck",
|
||||
.init = &omap2_init_clksel_parent,
|
||||
.clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
|
||||
.clksel_mask = OMAP3430_ST_CORE_CLK,
|
||||
.clksel_mask = OMAP3430_ST_CORE_CLK_MASK,
|
||||
.clksel = dpll3_m2x2_ck_clksel,
|
||||
.flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
|
||||
PARENT_CONTROLS_CLOCK,
|
||||
@@ -503,7 +551,7 @@ static struct clk emu_core_alwon_ck = {
|
||||
.parent = &dpll3_m3x2_ck,
|
||||
.init = &omap2_init_clksel_parent,
|
||||
.clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
|
||||
.clksel_mask = OMAP3430_ST_CORE_CLK,
|
||||
.clksel_mask = OMAP3430_ST_CORE_CLK_MASK,
|
||||
.clksel = emu_core_alwon_ck_clksel,
|
||||
.flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
|
||||
PARENT_CONTROLS_CLOCK,
|
||||
@@ -513,22 +561,33 @@ static struct clk emu_core_alwon_ck = {
|
||||
/* DPLL4 */
|
||||
/* Supplies 96MHz, 54Mhz TV DAC, DSS fclk, CAM sensor clock, emul trace clk */
|
||||
/* Type: DPLL */
|
||||
static const struct dpll_data dpll4_dd = {
|
||||
static struct dpll_data dpll4_dd = {
|
||||
.mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2),
|
||||
.mult_mask = OMAP3430_PERIPH_DPLL_MULT_MASK,
|
||||
.div1_mask = OMAP3430_PERIPH_DPLL_DIV_MASK,
|
||||
.control_reg = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
|
||||
.enable_mask = OMAP3430_EN_PERIPH_DPLL_MASK,
|
||||
.modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
|
||||
.auto_recal_bit = OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT,
|
||||
.recal_en_bit = OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT,
|
||||
.recal_st_bit = OMAP3430_PERIPH_DPLL_ST_SHIFT,
|
||||
.autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
|
||||
.autoidle_mask = OMAP3430_AUTO_PERIPH_DPLL_MASK,
|
||||
.idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
|
||||
.idlest_bit = OMAP3430_ST_PERIPH_CLK_SHIFT,
|
||||
.max_multiplier = OMAP3_MAX_DPLL_MULT,
|
||||
.max_divider = OMAP3_MAX_DPLL_DIV,
|
||||
.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
|
||||
};
|
||||
|
||||
static struct clk dpll4_ck = {
|
||||
.name = "dpll4_ck",
|
||||
.parent = &sys_ck,
|
||||
.dpll_data = &dpll4_dd,
|
||||
.flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES | ALWAYS_ENABLED,
|
||||
.flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES,
|
||||
.enable = &omap3_noncore_dpll_enable,
|
||||
.disable = &omap3_noncore_dpll_disable,
|
||||
.round_rate = &omap2_dpll_round_rate,
|
||||
.recalc = &omap3_dpll_recalc,
|
||||
};
|
||||
|
||||
@@ -584,7 +643,7 @@ static struct clk omap_96m_alwon_fck = {
|
||||
.parent = &dpll4_m2x2_ck,
|
||||
.init = &omap2_init_clksel_parent,
|
||||
.clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
|
||||
.clksel_mask = OMAP3430_ST_PERIPH_CLK,
|
||||
.clksel_mask = OMAP3430_ST_PERIPH_CLK_MASK,
|
||||
.clksel = omap_96m_alwon_fck_clksel,
|
||||
.flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
|
||||
PARENT_CONTROLS_CLOCK,
|
||||
@@ -610,7 +669,7 @@ static struct clk cm_96m_fck = {
|
||||
.parent = &dpll4_m2x2_ck,
|
||||
.init = &omap2_init_clksel_parent,
|
||||
.clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
|
||||
.clksel_mask = OMAP3430_ST_PERIPH_CLK,
|
||||
.clksel_mask = OMAP3430_ST_PERIPH_CLK_MASK,
|
||||
.clksel = cm_96m_fck_clksel,
|
||||
.flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
|
||||
PARENT_CONTROLS_CLOCK,
|
||||
@@ -652,7 +711,7 @@ static struct clk virt_omap_54m_fck = {
|
||||
.parent = &dpll4_m3x2_ck,
|
||||
.init = &omap2_init_clksel_parent,
|
||||
.clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
|
||||
.clksel_mask = OMAP3430_ST_PERIPH_CLK,
|
||||
.clksel_mask = OMAP3430_ST_PERIPH_CLK_MASK,
|
||||
.clksel = virt_omap_54m_fck_clksel,
|
||||
.flags = CLOCK_IN_OMAP343X | RATE_PROPAGATES |
|
||||
PARENT_CONTROLS_CLOCK,
|
||||
@@ -804,23 +863,33 @@ static struct clk emu_per_alwon_ck = {
|
||||
/* Supplies 120MHz clock, USIM source clock */
|
||||
/* Type: DPLL */
|
||||
/* 3430ES2 only */
|
||||
static const struct dpll_data dpll5_dd = {
|
||||
static struct dpll_data dpll5_dd = {
|
||||
.mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL4),
|
||||
.mult_mask = OMAP3430ES2_PERIPH2_DPLL_MULT_MASK,
|
||||
.div1_mask = OMAP3430ES2_PERIPH2_DPLL_DIV_MASK,
|
||||
.control_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKEN2),
|
||||
.enable_mask = OMAP3430ES2_EN_PERIPH2_DPLL_MASK,
|
||||
.modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
|
||||
.auto_recal_bit = OMAP3430ES2_EN_PERIPH2_DPLL_DRIFTGUARD_SHIFT,
|
||||
.recal_en_bit = OMAP3430ES2_SND_PERIPH_DPLL_RECAL_EN_SHIFT,
|
||||
.recal_st_bit = OMAP3430ES2_SND_PERIPH_DPLL_ST_SHIFT,
|
||||
.autoidle_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_AUTOIDLE2_PLL),
|
||||
.autoidle_mask = OMAP3430ES2_AUTO_PERIPH2_DPLL_MASK,
|
||||
.idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2),
|
||||
.idlest_bit = OMAP3430ES2_ST_PERIPH2_CLK_SHIFT,
|
||||
.max_multiplier = OMAP3_MAX_DPLL_MULT,
|
||||
.max_divider = OMAP3_MAX_DPLL_DIV,
|
||||
.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
|
||||
};
|
||||
|
||||
static struct clk dpll5_ck = {
|
||||
.name = "dpll5_ck",
|
||||
.parent = &sys_ck,
|
||||
.dpll_data = &dpll5_dd,
|
||||
.flags = CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES |
|
||||
ALWAYS_ENABLED,
|
||||
.flags = CLOCK_IN_OMAP3430ES2 | RATE_PROPAGATES,
|
||||
.enable = &omap3_noncore_dpll_enable,
|
||||
.disable = &omap3_noncore_dpll_disable,
|
||||
.round_rate = &omap2_dpll_round_rate,
|
||||
.recalc = &omap3_dpll_recalc,
|
||||
};
|
||||
|
||||
@@ -1365,7 +1434,8 @@ static const struct clksel mcbsp_15_clksel[] = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp5_fck = {
|
||||
.name = "mcbsp5_fck",
|
||||
.name = "mcbsp_fck",
|
||||
.id = 5,
|
||||
.init = &omap2_init_clksel_parent,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
|
||||
.enable_bit = OMAP3430_EN_MCBSP5_SHIFT,
|
||||
@@ -1377,7 +1447,8 @@ static struct clk mcbsp5_fck = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp1_fck = {
|
||||
.name = "mcbsp1_fck",
|
||||
.name = "mcbsp_fck",
|
||||
.id = 1,
|
||||
.init = &omap2_init_clksel_parent,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
|
||||
.enable_bit = OMAP3430_EN_MCBSP1_SHIFT,
|
||||
@@ -1789,7 +1860,8 @@ static struct clk gpt10_ick = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp5_ick = {
|
||||
.name = "mcbsp5_ick",
|
||||
.name = "mcbsp_ick",
|
||||
.id = 5,
|
||||
.parent = &core_l4_ick,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
|
||||
.enable_bit = OMAP3430_EN_MCBSP5_SHIFT,
|
||||
@@ -1798,7 +1870,8 @@ static struct clk mcbsp5_ick = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp1_ick = {
|
||||
.name = "mcbsp1_ick",
|
||||
.name = "mcbsp_ick",
|
||||
.id = 1,
|
||||
.parent = &core_l4_ick,
|
||||
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
|
||||
.enable_bit = OMAP3430_EN_MCBSP1_SHIFT,
|
||||
@@ -1935,7 +2008,7 @@ static struct clk dss1_alwon_fck = {
|
||||
.enable_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
|
||||
.enable_bit = OMAP3430_EN_DSS1_SHIFT,
|
||||
.clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
|
||||
.clksel_mask = OMAP3430_ST_PERIPH_CLK,
|
||||
.clksel_mask = OMAP3430_ST_PERIPH_CLK_MASK,
|
||||
.clksel = dss1_alwon_fck_clksel,
|
||||
.flags = CLOCK_IN_OMAP343X,
|
||||
.recalc = &omap2_clksel_recalc,
|
||||
@@ -1991,7 +2064,7 @@ static struct clk cam_mclk = {
|
||||
.parent = &dpll4_m5x2_ck,
|
||||
.init = &omap2_init_clksel_parent,
|
||||
.clksel_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
|
||||
.clksel_mask = OMAP3430_ST_PERIPH_CLK,
|
||||
.clksel_mask = OMAP3430_ST_PERIPH_CLK_MASK,
|
||||
.clksel = cam_mclk_clksel,
|
||||
.enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
|
||||
.enable_bit = OMAP3430_EN_CAM_SHIFT,
|
||||
@@ -2541,7 +2614,8 @@ static struct clk gpt2_ick = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp2_ick = {
|
||||
.name = "mcbsp2_ick",
|
||||
.name = "mcbsp_ick",
|
||||
.id = 2,
|
||||
.parent = &per_l4_ick,
|
||||
.enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
|
||||
.enable_bit = OMAP3430_EN_MCBSP2_SHIFT,
|
||||
@@ -2550,7 +2624,8 @@ static struct clk mcbsp2_ick = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp3_ick = {
|
||||
.name = "mcbsp3_ick",
|
||||
.name = "mcbsp_ick",
|
||||
.id = 3,
|
||||
.parent = &per_l4_ick,
|
||||
.enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
|
||||
.enable_bit = OMAP3430_EN_MCBSP3_SHIFT,
|
||||
@@ -2559,7 +2634,8 @@ static struct clk mcbsp3_ick = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp4_ick = {
|
||||
.name = "mcbsp4_ick",
|
||||
.name = "mcbsp_ick",
|
||||
.id = 4,
|
||||
.parent = &per_l4_ick,
|
||||
.enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
|
||||
.enable_bit = OMAP3430_EN_MCBSP4_SHIFT,
|
||||
@@ -2574,7 +2650,8 @@ static const struct clksel mcbsp_234_clksel[] = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp2_fck = {
|
||||
.name = "mcbsp2_fck",
|
||||
.name = "mcbsp_fck",
|
||||
.id = 2,
|
||||
.init = &omap2_init_clksel_parent,
|
||||
.enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
|
||||
.enable_bit = OMAP3430_EN_MCBSP2_SHIFT,
|
||||
@@ -2586,7 +2663,8 @@ static struct clk mcbsp2_fck = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp3_fck = {
|
||||
.name = "mcbsp3_fck",
|
||||
.name = "mcbsp_fck",
|
||||
.id = 3,
|
||||
.init = &omap2_init_clksel_parent,
|
||||
.enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
|
||||
.enable_bit = OMAP3430_EN_MCBSP3_SHIFT,
|
||||
@@ -2598,7 +2676,8 @@ static struct clk mcbsp3_fck = {
|
||||
};
|
||||
|
||||
static struct clk mcbsp4_fck = {
|
||||
.name = "mcbsp4_fck",
|
||||
.name = "mcbsp_fck",
|
||||
.id = 4,
|
||||
.init = &omap2_init_clksel_parent,
|
||||
.enable_reg = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
|
||||
.enable_bit = OMAP3430_EN_MCBSP4_SHIFT,
|
||||
|
@@ -72,7 +72,8 @@
|
||||
#define OMAP3430_ST_IVA2 (1 << 0)
|
||||
|
||||
/* CM_IDLEST_PLL_IVA2 */
|
||||
#define OMAP3430_ST_IVA2_CLK (1 << 0)
|
||||
#define OMAP3430_ST_IVA2_CLK_SHIFT 0
|
||||
#define OMAP3430_ST_IVA2_CLK_MASK (1 << 0)
|
||||
|
||||
/* CM_AUTOIDLE_PLL_IVA2 */
|
||||
#define OMAP3430_AUTO_IVA2_DPLL_SHIFT 0
|
||||
@@ -115,10 +116,7 @@
|
||||
#define OMAP3430_ST_MPU (1 << 0)
|
||||
|
||||
/* CM_IDLEST_PLL_MPU */
|
||||
#define OMAP3430_ST_MPU_CLK (1 << 0)
|
||||
#define OMAP3430_ST_IVA2_CLK_MASK (1 << 0)
|
||||
|
||||
/* CM_IDLEST_PLL_MPU */
|
||||
#define OMAP3430_ST_MPU_CLK_SHIFT 0
|
||||
#define OMAP3430_ST_MPU_CLK_MASK (1 << 0)
|
||||
|
||||
/* CM_AUTOIDLE_PLL_MPU */
|
||||
@@ -408,8 +406,10 @@
|
||||
#define OMAP3430_ST_12M_CLK (1 << 4)
|
||||
#define OMAP3430_ST_48M_CLK (1 << 3)
|
||||
#define OMAP3430_ST_96M_CLK (1 << 2)
|
||||
#define OMAP3430_ST_PERIPH_CLK (1 << 1)
|
||||
#define OMAP3430_ST_CORE_CLK (1 << 0)
|
||||
#define OMAP3430_ST_PERIPH_CLK_SHIFT 1
|
||||
#define OMAP3430_ST_PERIPH_CLK_MASK (1 << 1)
|
||||
#define OMAP3430_ST_CORE_CLK_SHIFT 0
|
||||
#define OMAP3430_ST_CORE_CLK_MASK (1 << 0)
|
||||
|
||||
/* CM_IDLEST2_CKGEN */
|
||||
#define OMAP3430ES2_ST_120M_CLK_SHIFT 1
|
||||
@@ -423,6 +423,10 @@
|
||||
#define OMAP3430_AUTO_CORE_DPLL_SHIFT 0
|
||||
#define OMAP3430_AUTO_CORE_DPLL_MASK (0x7 << 0)
|
||||
|
||||
/* CM_AUTOIDLE2_PLL */
|
||||
#define OMAP3430ES2_AUTO_PERIPH2_DPLL_SHIFT 0
|
||||
#define OMAP3430ES2_AUTO_PERIPH2_DPLL_MASK (0x7 << 0)
|
||||
|
||||
/* CM_CLKSEL1_PLL */
|
||||
/* Note that OMAP3430_CORE_DPLL_CLKOUT_DIV_MASK was (0x3 << 27) on 3430ES1 */
|
||||
#define OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT 27
|
||||
|
@@ -81,6 +81,7 @@
|
||||
#define OMAP3430ES2_CM_FCLKEN3 0x0008
|
||||
#define OMAP3430_CM_IDLEST_PLL CM_IDLEST2
|
||||
#define OMAP3430_CM_AUTOIDLE_PLL CM_AUTOIDLE2
|
||||
#define OMAP3430ES2_CM_AUTOIDLE2_PLL CM_AUTOIDLE2
|
||||
#define OMAP3430_CM_CLKSEL1 CM_CLKSEL
|
||||
#define OMAP3430_CM_CLKSEL1_PLL CM_CLKSEL
|
||||
#define OMAP3430_CM_CLKSEL2_PLL CM_CLKSEL2
|
||||
@@ -96,15 +97,21 @@
|
||||
/* Clock management domain register get/set */
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
static inline void cm_write_mod_reg(u32 val, s16 module, s16 idx)
|
||||
|
||||
extern u32 cm_read_mod_reg(s16 module, u16 idx);
|
||||
extern void cm_write_mod_reg(u32 val, s16 module, u16 idx);
|
||||
extern u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
|
||||
|
||||
static inline u32 cm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
|
||||
{
|
||||
__raw_writel(val, OMAP_CM_REGADDR(module, idx));
|
||||
return cm_rmw_mod_reg_bits(bits, bits, module, idx);
|
||||
}
|
||||
|
||||
static inline u32 cm_read_mod_reg(s16 module, s16 idx)
|
||||
static inline u32 cm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
|
||||
{
|
||||
return __raw_readl(OMAP_CM_REGADDR(module, idx));
|
||||
return cm_rmw_mod_reg_bits(bits, 0x0, module, idx);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* CM register bits shared between 24XX and 3430 */
|
||||
|
@@ -13,22 +13,21 @@
|
||||
#undef DEBUG
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/arch/common.h>
|
||||
#include <asm/arch/control.h>
|
||||
|
||||
static u32 omap2_ctrl_base;
|
||||
static void __iomem *omap2_ctrl_base;
|
||||
|
||||
#define OMAP_CTRL_REGADDR(reg) (void __iomem *)IO_ADDRESS(omap2_ctrl_base \
|
||||
+ (reg))
|
||||
#define OMAP_CTRL_REGADDR(reg) (omap2_ctrl_base + (reg))
|
||||
|
||||
void omap_ctrl_base_set(u32 base)
|
||||
void __init omap2_set_globals_control(struct omap_globals *omap2_globals)
|
||||
{
|
||||
omap2_ctrl_base = base;
|
||||
omap2_ctrl_base = omap2_globals->ctrl;
|
||||
}
|
||||
|
||||
u32 omap_ctrl_base_get(void)
|
||||
void __iomem *omap_ctrl_base_get(void)
|
||||
{
|
||||
return omap2_ctrl_base;
|
||||
}
|
||||
@@ -50,25 +49,16 @@ u32 omap_ctrl_readl(u16 offset)
|
||||
|
||||
void omap_ctrl_writeb(u8 val, u16 offset)
|
||||
{
|
||||
pr_debug("omap_ctrl_writeb: writing 0x%0x to 0x%0x\n", val,
|
||||
(u32)OMAP_CTRL_REGADDR(offset));
|
||||
|
||||
__raw_writeb(val, OMAP_CTRL_REGADDR(offset));
|
||||
}
|
||||
|
||||
void omap_ctrl_writew(u16 val, u16 offset)
|
||||
{
|
||||
pr_debug("omap_ctrl_writew: writing 0x%0x to 0x%0x\n", val,
|
||||
(u32)OMAP_CTRL_REGADDR(offset));
|
||||
|
||||
__raw_writew(val, OMAP_CTRL_REGADDR(offset));
|
||||
}
|
||||
|
||||
void omap_ctrl_writel(u32 val, u16 offset)
|
||||
{
|
||||
pr_debug("omap_ctrl_writel: writing 0x%0x to 0x%0x\n", val,
|
||||
(u32)OMAP_CTRL_REGADDR(offset));
|
||||
|
||||
__raw_writel(val, OMAP_CTRL_REGADDR(offset));
|
||||
}
|
||||
|
||||
|
@@ -42,7 +42,7 @@
|
||||
#define GPMC_STATUS 0x54
|
||||
#define GPMC_PREFETCH_CONFIG1 0x1e0
|
||||
#define GPMC_PREFETCH_CONFIG2 0x1e4
|
||||
#define GPMC_PREFETCH_CONTROL 0x1e8
|
||||
#define GPMC_PREFETCH_CONTROL 0x1ec
|
||||
#define GPMC_PREFETCH_STATUS 0x1f0
|
||||
#define GPMC_ECC_CONFIG 0x1f4
|
||||
#define GPMC_ECC_CONTROL 0x1f8
|
||||
|
@@ -17,16 +17,23 @@
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#if defined(CONFIG_ARCH_OMAP2420)
|
||||
#define OMAP24XX_TAP_BASE io_p2v(0x48014000)
|
||||
#endif
|
||||
#include <asm/arch/control.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
|
||||
#if defined(CONFIG_ARCH_OMAP2430)
|
||||
#define OMAP24XX_TAP_BASE io_p2v(0x4900A000)
|
||||
#if defined(CONFIG_ARCH_OMAP2420)
|
||||
#define TAP_BASE io_p2v(0x48014000)
|
||||
#elif defined(CONFIG_ARCH_OMAP2430)
|
||||
#define TAP_BASE io_p2v(0x4900A000)
|
||||
#elif defined(CONFIG_ARCH_OMAP34XX)
|
||||
#define TAP_BASE io_p2v(0x4830A000)
|
||||
#endif
|
||||
|
||||
#define OMAP_TAP_IDCODE 0x0204
|
||||
#if defined(CONFIG_ARCH_OMAP34XX)
|
||||
#define OMAP_TAP_PROD_ID 0x0210
|
||||
#else
|
||||
#define OMAP_TAP_PROD_ID 0x0208
|
||||
#endif
|
||||
|
||||
#define OMAP_TAP_DIE_ID_0 0x0218
|
||||
#define OMAP_TAP_DIE_ID_1 0x021C
|
||||
@@ -56,9 +63,134 @@ static struct omap_id omap_ids[] __initdata = {
|
||||
{ .hawkeye = 0xb68a, .dev = 0x0, .type = 0x24300000 },
|
||||
};
|
||||
|
||||
static struct omap_chip_id omap_chip;
|
||||
|
||||
/**
|
||||
* omap_chip_is - test whether currently running OMAP matches a chip type
|
||||
* @oc: omap_chip_t to test against
|
||||
*
|
||||
* Test whether the currently-running OMAP chip matches the supplied
|
||||
* chip type 'oc'. Returns 1 upon a match; 0 upon failure.
|
||||
*/
|
||||
int omap_chip_is(struct omap_chip_id oci)
|
||||
{
|
||||
return (oci.oc & omap_chip.oc) ? 1 : 0;
|
||||
}
|
||||
EXPORT_SYMBOL(omap_chip_is);
|
||||
|
||||
static u32 __init read_tap_reg(int reg)
|
||||
{
|
||||
return __raw_readl(OMAP24XX_TAP_BASE + reg);
|
||||
unsigned int regval = 0;
|
||||
u32 cpuid;
|
||||
|
||||
/* Reading the IDCODE register on 3430 ES1 results in a
|
||||
* data abort as the register is not exposed on the OCP
|
||||
* Hence reading the Cortex Rev
|
||||
*/
|
||||
cpuid = read_cpuid(CPUID_ID);
|
||||
|
||||
/* If the processor type is Cortex-A8 and the revision is 0x0
|
||||
* it means its Cortex r0p0 which is 3430 ES1
|
||||
*/
|
||||
if ((((cpuid >> 4) & 0xFFF) == 0xC08) && ((cpuid & 0xF) == 0x0)) {
|
||||
switch (reg) {
|
||||
case OMAP_TAP_IDCODE : regval = 0x0B7AE02F; break;
|
||||
/* Making DevType as 0xF in ES1 to differ from ES2 */
|
||||
case OMAP_TAP_PROD_ID : regval = 0x000F00F0; break;
|
||||
case OMAP_TAP_DIE_ID_0: regval = 0x01000000; break;
|
||||
case OMAP_TAP_DIE_ID_1: regval = 0x1012d687; break;
|
||||
case OMAP_TAP_DIE_ID_2: regval = 0x00000000; break;
|
||||
case OMAP_TAP_DIE_ID_3: regval = 0x2d2c0000; break;
|
||||
}
|
||||
} else
|
||||
regval = __raw_readl(TAP_BASE + reg);
|
||||
|
||||
return regval;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* _set_system_rev - set the system_rev global based on current OMAP chip type
|
||||
*
|
||||
* Set the system_rev global. This is primarily used by the cpu_is_omapxxxx()
|
||||
* macros.
|
||||
*/
|
||||
static void __init _set_system_rev(u32 type, u8 rev)
|
||||
{
|
||||
u32 i, ctrl_status;
|
||||
|
||||
/*
|
||||
* system_rev encoding is as follows
|
||||
* system_rev & 0xff000000 -> Omap Class (24xx/34xx)
|
||||
* system_rev & 0xfff00000 -> Omap Sub Class (242x/343x)
|
||||
* system_rev & 0xffff0000 -> Omap type (2420/2422/2423/2430/3430)
|
||||
* system_rev & 0x0000f000 -> Silicon revision (ES1, ES2 )
|
||||
* system_rev & 0x00000700 -> Device Type ( EMU/HS/GP/BAD )
|
||||
* system_rev & 0x000000c0 -> IDCODE revision[6:7]
|
||||
* system_rev & 0x0000003f -> sys_boot[0:5]
|
||||
*/
|
||||
/* Embedding the ES revision info in type field */
|
||||
system_rev = type;
|
||||
/* Also add IDCODE revision info only two lower bits */
|
||||
system_rev |= ((rev & 0x3) << 6);
|
||||
|
||||
/* Add in the device type and sys_boot fields (see above) */
|
||||
if (cpu_is_omap24xx()) {
|
||||
i = OMAP24XX_CONTROL_STATUS;
|
||||
} else if (cpu_is_omap343x()) {
|
||||
i = OMAP343X_CONTROL_STATUS;
|
||||
} else {
|
||||
printk(KERN_ERR "id: unknown CPU type\n");
|
||||
BUG();
|
||||
}
|
||||
ctrl_status = omap_ctrl_readl(i);
|
||||
system_rev |= (ctrl_status & (OMAP2_SYSBOOT_5_MASK |
|
||||
OMAP2_SYSBOOT_4_MASK |
|
||||
OMAP2_SYSBOOT_3_MASK |
|
||||
OMAP2_SYSBOOT_2_MASK |
|
||||
OMAP2_SYSBOOT_1_MASK |
|
||||
OMAP2_SYSBOOT_0_MASK));
|
||||
system_rev |= (ctrl_status & OMAP2_DEVICETYPE_MASK);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* _set_omap_chip - set the omap_chip global based on OMAP chip type
|
||||
*
|
||||
* Build the omap_chip bits. This variable is used by powerdomain and
|
||||
* clockdomain code to indicate whether structures are applicable for
|
||||
* the current OMAP chip type by ANDing it against a 'platform' bitfield
|
||||
* in the structure.
|
||||
*/
|
||||
static void __init _set_omap_chip(void)
|
||||
{
|
||||
if (cpu_is_omap343x()) {
|
||||
|
||||
omap_chip.oc = CHIP_IS_OMAP3430;
|
||||
if (is_sil_rev_equal_to(OMAP3430_REV_ES1_0))
|
||||
omap_chip.oc |= CHIP_IS_OMAP3430ES1;
|
||||
else if (is_sil_rev_greater_than(OMAP3430_REV_ES1_0))
|
||||
omap_chip.oc |= CHIP_IS_OMAP3430ES2;
|
||||
|
||||
} else if (cpu_is_omap243x()) {
|
||||
|
||||
/* Currently only supports 2430ES2.1 and 2430-all */
|
||||
omap_chip.oc |= CHIP_IS_OMAP2430;
|
||||
|
||||
} else if (cpu_is_omap242x()) {
|
||||
|
||||
/* Currently only supports 2420ES2.1.1 and 2420-all */
|
||||
omap_chip.oc |= CHIP_IS_OMAP2420;
|
||||
|
||||
} else {
|
||||
|
||||
/* Current CPU not supported by this code. */
|
||||
printk(KERN_WARNING "OMAP chip type code does not yet support "
|
||||
"this CPU type.\n");
|
||||
WARN_ON(1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void __init omap2_check_revision(void)
|
||||
@@ -76,21 +208,31 @@ void __init omap2_check_revision(void)
|
||||
rev = (idcode >> 28) & 0x0f;
|
||||
dev_type = (prod_id >> 16) & 0x0f;
|
||||
|
||||
#ifdef DEBUG
|
||||
printk(KERN_DEBUG "OMAP_TAP_IDCODE 0x%08x REV %i HAWKEYE 0x%04x MANF %03x\n",
|
||||
idcode, rev, hawkeye, (idcode >> 1) & 0x7ff);
|
||||
printk(KERN_DEBUG "OMAP_TAP_DIE_ID_0: 0x%08x\n",
|
||||
read_tap_reg(OMAP_TAP_DIE_ID_0));
|
||||
printk(KERN_DEBUG "OMAP_TAP_DIE_ID_1: 0x%08x DEV_REV: %i\n",
|
||||
read_tap_reg(OMAP_TAP_DIE_ID_1),
|
||||
(read_tap_reg(OMAP_TAP_DIE_ID_1) >> 28) & 0xf);
|
||||
printk(KERN_DEBUG "OMAP_TAP_DIE_ID_2: 0x%08x\n",
|
||||
read_tap_reg(OMAP_TAP_DIE_ID_2));
|
||||
printk(KERN_DEBUG "OMAP_TAP_DIE_ID_3: 0x%08x\n",
|
||||
read_tap_reg(OMAP_TAP_DIE_ID_3));
|
||||
printk(KERN_DEBUG "OMAP_TAP_PROD_ID_0: 0x%08x DEV_TYPE: %i\n",
|
||||
prod_id, dev_type);
|
||||
#endif
|
||||
pr_debug("OMAP_TAP_IDCODE 0x%08x REV %i HAWKEYE 0x%04x MANF %03x\n",
|
||||
idcode, rev, hawkeye, (idcode >> 1) & 0x7ff);
|
||||
pr_debug("OMAP_TAP_DIE_ID_0: 0x%08x\n",
|
||||
read_tap_reg(OMAP_TAP_DIE_ID_0));
|
||||
pr_debug("OMAP_TAP_DIE_ID_1: 0x%08x DEV_REV: %i\n",
|
||||
read_tap_reg(OMAP_TAP_DIE_ID_1),
|
||||
(read_tap_reg(OMAP_TAP_DIE_ID_1) >> 28) & 0xf);
|
||||
pr_debug("OMAP_TAP_DIE_ID_2: 0x%08x\n",
|
||||
read_tap_reg(OMAP_TAP_DIE_ID_2));
|
||||
pr_debug("OMAP_TAP_DIE_ID_3: 0x%08x\n",
|
||||
read_tap_reg(OMAP_TAP_DIE_ID_3));
|
||||
pr_debug("OMAP_TAP_PROD_ID_0: 0x%08x DEV_TYPE: %i\n",
|
||||
prod_id, dev_type);
|
||||
|
||||
/*
|
||||
* Detection for 34xx ES2.0 and above can be done with just
|
||||
* hawkeye and rev. See TRM 1.5.2 Device Identification.
|
||||
* Note that rev cannot be used directly as ES1.0 uses value 0.
|
||||
*/
|
||||
if (hawkeye == 0xb7ae) {
|
||||
system_rev = 0x34300000 | ((1 + rev) << 12);
|
||||
pr_info("OMAP%04x ES2.%i\n", system_rev >> 16, rev);
|
||||
_set_omap_chip();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check hawkeye ids */
|
||||
for (i = 0; i < ARRAY_SIZE(omap_ids); i++) {
|
||||
@@ -114,16 +256,15 @@ void __init omap2_check_revision(void)
|
||||
omap_ids[i].type >> 16);
|
||||
j = i;
|
||||
}
|
||||
system_rev = omap_ids[j].type;
|
||||
|
||||
system_rev |= rev << 8;
|
||||
_set_system_rev(omap_ids[j].type, rev);
|
||||
|
||||
/* Add the cpu class info (24xx) */
|
||||
system_rev |= 0x24;
|
||||
_set_omap_chip();
|
||||
|
||||
pr_info("OMAP%04x", system_rev >> 16);
|
||||
if ((system_rev >> 8) & 0x0f)
|
||||
printk("%x", (system_rev >> 8) & 0x0f);
|
||||
printk("\n");
|
||||
pr_info("ES%x", (system_rev >> 12) & 0xf);
|
||||
pr_info("\n");
|
||||
|
||||
}
|
||||
|
||||
|
208
arch/arm/mach-omap2/mcbsp.c
Normal file
208
arch/arm/mach-omap2/mcbsp.c
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-omap2/mcbsp.c
|
||||
*
|
||||
* Copyright (C) 2008 Instituto Nokia de Tecnologia
|
||||
* Contact: Eduardo Valentin <eduardo.valentin@indt.org.br>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Multichannel mode not supported.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/arch/dma.h>
|
||||
#include <asm/arch/mux.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/mcbsp.h>
|
||||
|
||||
struct mcbsp_internal_clk {
|
||||
struct clk clk;
|
||||
struct clk **childs;
|
||||
int n_childs;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
|
||||
static void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk)
|
||||
{
|
||||
const char *clk_names[] = { "mcbsp_ick", "mcbsp_fck" };
|
||||
int i;
|
||||
|
||||
mclk->n_childs = ARRAY_SIZE(clk_names);
|
||||
mclk->childs = kzalloc(mclk->n_childs * sizeof(struct clk *),
|
||||
GFP_KERNEL);
|
||||
|
||||
for (i = 0; i < mclk->n_childs; i++) {
|
||||
/* We fake a platform device to get correct device id */
|
||||
struct platform_device pdev;
|
||||
|
||||
pdev.dev.bus = &platform_bus_type;
|
||||
pdev.id = mclk->clk.id;
|
||||
mclk->childs[i] = clk_get(&pdev.dev, clk_names[i]);
|
||||
if (IS_ERR(mclk->childs[i]))
|
||||
printk(KERN_ERR "Could not get clock %s (%d).\n",
|
||||
clk_names[i], mclk->clk.id);
|
||||
}
|
||||
}
|
||||
|
||||
static int omap_mcbsp_clk_enable(struct clk *clk)
|
||||
{
|
||||
struct mcbsp_internal_clk *mclk = container_of(clk,
|
||||
struct mcbsp_internal_clk, clk);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mclk->n_childs; i++)
|
||||
clk_enable(mclk->childs[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void omap_mcbsp_clk_disable(struct clk *clk)
|
||||
{
|
||||
struct mcbsp_internal_clk *mclk = container_of(clk,
|
||||
struct mcbsp_internal_clk, clk);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mclk->n_childs; i++)
|
||||
clk_disable(mclk->childs[i]);
|
||||
}
|
||||
|
||||
static struct mcbsp_internal_clk omap_mcbsp_clks[] = {
|
||||
{
|
||||
.clk = {
|
||||
.name = "mcbsp_clk",
|
||||
.id = 1,
|
||||
.enable = omap_mcbsp_clk_enable,
|
||||
.disable = omap_mcbsp_clk_disable,
|
||||
},
|
||||
},
|
||||
{
|
||||
.clk = {
|
||||
.name = "mcbsp_clk",
|
||||
.id = 2,
|
||||
.enable = omap_mcbsp_clk_enable,
|
||||
.disable = omap_mcbsp_clk_disable,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
#define omap_mcbsp_clks_size ARRAY_SIZE(omap_mcbsp_clks)
|
||||
#else
|
||||
#define omap_mcbsp_clks_size 0
|
||||
static struct mcbsp_internal_clk __initdata *omap_mcbsp_clks;
|
||||
static inline void omap_mcbsp_clk_init(struct clk *clk)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
static void omap2_mcbsp2_mux_setup(void)
|
||||
{
|
||||
omap_cfg_reg(Y15_24XX_MCBSP2_CLKX);
|
||||
omap_cfg_reg(R14_24XX_MCBSP2_FSX);
|
||||
omap_cfg_reg(W15_24XX_MCBSP2_DR);
|
||||
omap_cfg_reg(V15_24XX_MCBSP2_DX);
|
||||
omap_cfg_reg(V14_24XX_GPIO117);
|
||||
/*
|
||||
* TODO: Need to add MUX settings for OMAP 2430 SDP
|
||||
*/
|
||||
}
|
||||
|
||||
static void omap2_mcbsp_request(unsigned int id)
|
||||
{
|
||||
if (cpu_is_omap2420() && (id == OMAP_MCBSP2))
|
||||
omap2_mcbsp2_mux_setup();
|
||||
}
|
||||
|
||||
static int omap2_mcbsp_check(unsigned int id)
|
||||
{
|
||||
if (id > OMAP_MAX_MCBSP_COUNT - 1) {
|
||||
printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct omap_mcbsp_ops omap2_mcbsp_ops = {
|
||||
.request = omap2_mcbsp_request,
|
||||
.check = omap2_mcbsp_check,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP24XX
|
||||
static struct omap_mcbsp_platform_data omap24xx_mcbsp_pdata[] = {
|
||||
{
|
||||
.virt_base = IO_ADDRESS(OMAP24XX_MCBSP1_BASE),
|
||||
.dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX,
|
||||
.dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX,
|
||||
.rx_irq = INT_24XX_MCBSP1_IRQ_RX,
|
||||
.tx_irq = INT_24XX_MCBSP1_IRQ_TX,
|
||||
.ops = &omap2_mcbsp_ops,
|
||||
.clk_name = "mcbsp_clk",
|
||||
},
|
||||
{
|
||||
.virt_base = IO_ADDRESS(OMAP24XX_MCBSP2_BASE),
|
||||
.dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX,
|
||||
.dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX,
|
||||
.rx_irq = INT_24XX_MCBSP2_IRQ_RX,
|
||||
.tx_irq = INT_24XX_MCBSP2_IRQ_TX,
|
||||
.ops = &omap2_mcbsp_ops,
|
||||
.clk_name = "mcbsp_clk",
|
||||
},
|
||||
};
|
||||
#define OMAP24XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap24xx_mcbsp_pdata)
|
||||
#else
|
||||
#define omap24xx_mcbsp_pdata NULL
|
||||
#define OMAP24XX_MCBSP_PDATA_SZ 0
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP34XX
|
||||
static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
|
||||
{
|
||||
.virt_base = IO_ADDRESS(OMAP34XX_MCBSP1_BASE),
|
||||
.dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX,
|
||||
.dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX,
|
||||
.rx_irq = INT_24XX_MCBSP1_IRQ_RX,
|
||||
.tx_irq = INT_24XX_MCBSP1_IRQ_TX,
|
||||
.ops = &omap2_mcbsp_ops,
|
||||
.clk_name = "mcbsp_clk",
|
||||
},
|
||||
{
|
||||
.virt_base = IO_ADDRESS(OMAP34XX_MCBSP2_BASE),
|
||||
.dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX,
|
||||
.dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX,
|
||||
.rx_irq = INT_24XX_MCBSP2_IRQ_RX,
|
||||
.tx_irq = INT_24XX_MCBSP2_IRQ_TX,
|
||||
.ops = &omap2_mcbsp_ops,
|
||||
.clk_name = "mcbsp_clk",
|
||||
},
|
||||
};
|
||||
#define OMAP34XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap34xx_mcbsp_pdata)
|
||||
#else
|
||||
#define omap34xx_mcbsp_pdata NULL
|
||||
#define OMAP34XX_MCBSP_PDATA_SZ 0
|
||||
#endif
|
||||
|
||||
int __init omap2_mcbsp_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < omap_mcbsp_clks_size; i++) {
|
||||
/* Once we call clk_get inside init, we do not register it */
|
||||
omap_mcbsp_clk_init(&omap_mcbsp_clks[i]);
|
||||
clk_register(&omap_mcbsp_clks[i].clk);
|
||||
}
|
||||
|
||||
if (cpu_is_omap24xx())
|
||||
omap_mcbsp_register_board_cfg(omap24xx_mcbsp_pdata,
|
||||
OMAP24XX_MCBSP_PDATA_SZ);
|
||||
|
||||
if (cpu_is_omap34xx())
|
||||
omap_mcbsp_register_board_cfg(omap34xx_mcbsp_pdata,
|
||||
OMAP34XX_MCBSP_PDATA_SZ);
|
||||
|
||||
return omap_mcbsp_init();
|
||||
}
|
||||
arch_initcall(omap2_mcbsp_init);
|
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#include <asm/arch/common.h>
|
||||
#include <asm/arch/clock.h>
|
||||
#include <asm/arch/sram.h>
|
||||
|
||||
@@ -32,8 +33,8 @@
|
||||
#include "memory.h"
|
||||
#include "sdrc.h"
|
||||
|
||||
unsigned long omap2_sdrc_base;
|
||||
unsigned long omap2_sms_base;
|
||||
void __iomem *omap2_sdrc_base;
|
||||
void __iomem *omap2_sms_base;
|
||||
|
||||
static struct memory_timings mem_timings;
|
||||
static u32 curr_perf_level = CORE_CLK_SRC_DPLL_X2;
|
||||
@@ -154,6 +155,12 @@ void omap2_init_memory_params(u32 force_lock_to_unlock_mode)
|
||||
mem_timings.slow_dll_ctrl |= ((1 << 1) | (3 << 8));
|
||||
}
|
||||
|
||||
void __init omap2_set_globals_memory(struct omap_globals *omap2_globals)
|
||||
{
|
||||
omap2_sdrc_base = omap2_globals->sdrc;
|
||||
omap2_sms_base = omap2_globals->sms;
|
||||
}
|
||||
|
||||
/* turn on smart idle modes for SDRAM scheduler and controller */
|
||||
void __init omap2_init_memory(void)
|
||||
{
|
||||
|
@@ -236,7 +236,7 @@ void __init_or_module omap2_cfg_debug(const struct pin_config *cfg, u8 reg)
|
||||
warn = (orig != reg);
|
||||
if (debug || warn)
|
||||
printk(KERN_WARNING
|
||||
"MUX: setup %s (0x%08x): 0x%02x -> 0x%02x\n",
|
||||
"MUX: setup %s (0x%p): 0x%04x -> 0x%04x\n",
|
||||
cfg->name, omap_ctrl_base_get() + cfg->mux_reg,
|
||||
orig, reg);
|
||||
}
|
||||
|
@@ -57,13 +57,6 @@ void omap2_pm_idle(void)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since an interrupt may set up a timer, we don't want to
|
||||
* reprogram the hardware timer with interrupts enabled.
|
||||
* Re-enable interrupts only after returning from idle.
|
||||
*/
|
||||
timer_dyn_reprogram();
|
||||
|
||||
omap2_sram_idle();
|
||||
local_fiq_enable();
|
||||
local_irq_enable();
|
||||
|
@@ -32,6 +32,7 @@
|
||||
|
||||
|
||||
/* Chip-specific module offsets */
|
||||
#define OMAP24XX_GR_MOD OCP_MOD
|
||||
#define OMAP24XX_DSP_MOD 0x800
|
||||
|
||||
#define OMAP2430_MDM_MOD 0xc00
|
||||
|
@@ -16,16 +16,21 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/arch/common.h>
|
||||
#include <asm/arch/prcm.h>
|
||||
|
||||
#include "clock.h"
|
||||
#include "prm.h"
|
||||
#include "prm-regbits-24xx.h"
|
||||
|
||||
extern void omap2_clk_prepare_for_reboot(void);
|
||||
static void __iomem *prm_base;
|
||||
static void __iomem *cm_base;
|
||||
|
||||
u32 omap_prcm_get_reset_sources(void)
|
||||
{
|
||||
/* XXX This presumably needs modification for 34XX */
|
||||
return prm_read_mod_reg(WKUP_MOD, RM_RSTST) & 0x7f;
|
||||
}
|
||||
EXPORT_SYMBOL(omap_prcm_get_reset_sources);
|
||||
@@ -33,11 +38,90 @@ EXPORT_SYMBOL(omap_prcm_get_reset_sources);
|
||||
/* Resets clock rates and reboots the system. Only called from system.h */
|
||||
void omap_prcm_arch_reset(char mode)
|
||||
{
|
||||
u32 wkup;
|
||||
s16 prcm_offs;
|
||||
omap2_clk_prepare_for_reboot();
|
||||
|
||||
if (cpu_is_omap24xx()) {
|
||||
wkup = prm_read_mod_reg(WKUP_MOD, RM_RSTCTRL) | OMAP_RST_DPLL3;
|
||||
prm_write_mod_reg(wkup, WKUP_MOD, RM_RSTCTRL);
|
||||
}
|
||||
if (cpu_is_omap24xx())
|
||||
prcm_offs = WKUP_MOD;
|
||||
else if (cpu_is_omap34xx())
|
||||
prcm_offs = OMAP3430_GR_MOD;
|
||||
else
|
||||
WARN_ON(1);
|
||||
|
||||
prm_set_mod_reg_bits(OMAP_RST_DPLL3, prcm_offs, RM_RSTCTRL);
|
||||
}
|
||||
|
||||
static inline u32 __omap_prcm_read(void __iomem *base, s16 module, u16 reg)
|
||||
{
|
||||
BUG_ON(!base);
|
||||
return __raw_readl(base + module + reg);
|
||||
}
|
||||
|
||||
static inline void __omap_prcm_write(u32 value, void __iomem *base,
|
||||
s16 module, u16 reg)
|
||||
{
|
||||
BUG_ON(!base);
|
||||
__raw_writel(value, base + module + reg);
|
||||
}
|
||||
|
||||
/* Read a register in a PRM module */
|
||||
u32 prm_read_mod_reg(s16 module, u16 idx)
|
||||
{
|
||||
return __omap_prcm_read(prm_base, module, idx);
|
||||
}
|
||||
EXPORT_SYMBOL(prm_read_mod_reg);
|
||||
|
||||
/* Write into a register in a PRM module */
|
||||
void prm_write_mod_reg(u32 val, s16 module, u16 idx)
|
||||
{
|
||||
__omap_prcm_write(val, prm_base, module, idx);
|
||||
}
|
||||
EXPORT_SYMBOL(prm_write_mod_reg);
|
||||
|
||||
/* Read-modify-write a register in a PRM module. Caller must lock */
|
||||
u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
v = prm_read_mod_reg(module, idx);
|
||||
v &= ~mask;
|
||||
v |= bits;
|
||||
prm_write_mod_reg(v, module, idx);
|
||||
|
||||
return v;
|
||||
}
|
||||
EXPORT_SYMBOL(prm_rmw_mod_reg_bits);
|
||||
|
||||
/* Read a register in a CM module */
|
||||
u32 cm_read_mod_reg(s16 module, u16 idx)
|
||||
{
|
||||
return __omap_prcm_read(cm_base, module, idx);
|
||||
}
|
||||
EXPORT_SYMBOL(cm_read_mod_reg);
|
||||
|
||||
/* Write into a register in a CM module */
|
||||
void cm_write_mod_reg(u32 val, s16 module, u16 idx)
|
||||
{
|
||||
__omap_prcm_write(val, cm_base, module, idx);
|
||||
}
|
||||
EXPORT_SYMBOL(cm_write_mod_reg);
|
||||
|
||||
/* Read-modify-write a register in a CM module. Caller must lock */
|
||||
u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
v = cm_read_mod_reg(module, idx);
|
||||
v &= ~mask;
|
||||
v |= bits;
|
||||
cm_write_mod_reg(v, module, idx);
|
||||
|
||||
return v;
|
||||
}
|
||||
EXPORT_SYMBOL(cm_rmw_mod_reg_bits);
|
||||
|
||||
void __init omap2_set_globals_prcm(struct omap_globals *omap2_globals)
|
||||
{
|
||||
prm_base = omap2_globals->prm;
|
||||
cm_base = omap2_globals->cm;
|
||||
}
|
||||
|
@@ -38,13 +38,29 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/* Global 24xx registers in GR_MOD (Same as OCP_MOD for 24xx) */
|
||||
#define OMAP24XX_PRCM_VOLTCTRL_OFFSET 0x0050
|
||||
#define OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET 0x0080
|
||||
|
||||
/* 242x GR_MOD registers, use these only for assembly code */
|
||||
#define OMAP242X_PRCM_VOLTCTRL OMAP2420_PRM_REGADDR(OMAP24XX_GR_MOD, \
|
||||
OMAP24XX_PRCM_VOLTCTRL_OFFSET)
|
||||
#define OMAP242X_PRCM_CLKCFG_CTRL OMAP2420_PRM_REGADDR(OMAP24XX_GR_MOD, \
|
||||
OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET)
|
||||
|
||||
/* 243x GR_MOD registers, use these only for assembly code */
|
||||
#define OMAP243X_PRCM_VOLTCTRL OMAP2430_PRM_REGADDR(OMAP24XX_GR_MOD, \
|
||||
OMAP24XX_PRCM_VOLTCTRL_OFFSET)
|
||||
#define OMAP243X_PRCM_CLKCFG_CTRL OMAP2430_PRM_REGADDR(OMAP24XX_GR_MOD, \
|
||||
OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET)
|
||||
|
||||
/* These will disappear */
|
||||
#define OMAP24XX_PRCM_REVISION OMAP_PRM_REGADDR(OCP_MOD, 0x0000)
|
||||
#define OMAP24XX_PRCM_SYSCONFIG OMAP_PRM_REGADDR(OCP_MOD, 0x0010)
|
||||
|
||||
#define OMAP24XX_PRCM_IRQSTATUS_MPU OMAP_PRM_REGADDR(OCP_MOD, 0x0018)
|
||||
#define OMAP24XX_PRCM_IRQENABLE_MPU OMAP_PRM_REGADDR(OCP_MOD, 0x001c)
|
||||
|
||||
#define OMAP24XX_PRCM_VOLTCTRL OMAP_PRM_REGADDR(OCP_MOD, 0x0050)
|
||||
#define OMAP24XX_PRCM_VOLTST OMAP_PRM_REGADDR(OCP_MOD, 0x0054)
|
||||
#define OMAP24XX_PRCM_CLKSRC_CTRL OMAP_PRM_REGADDR(OCP_MOD, 0x0060)
|
||||
#define OMAP24XX_PRCM_CLKOUT_CTRL OMAP_PRM_REGADDR(OCP_MOD, 0x0070)
|
||||
@@ -150,15 +166,19 @@
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
/* Power/reset management domain register get/set */
|
||||
extern u32 prm_read_mod_reg(s16 module, u16 idx);
|
||||
extern void prm_write_mod_reg(u32 val, s16 module, u16 idx);
|
||||
extern u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
|
||||
|
||||
static inline void prm_write_mod_reg(u32 val, s16 module, s16 idx)
|
||||
/* Read-modify-write bits in a PRM register (by domain) */
|
||||
static inline u32 prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
|
||||
{
|
||||
__raw_writel(val, OMAP_PRM_REGADDR(module, idx));
|
||||
return prm_rmw_mod_reg_bits(bits, bits, module, idx);
|
||||
}
|
||||
|
||||
static inline u32 prm_read_mod_reg(s16 module, s16 idx)
|
||||
static inline u32 prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
|
||||
{
|
||||
return __raw_readl(OMAP_PRM_REGADDR(module, idx));
|
||||
return prm_rmw_mod_reg_bits(bits, 0x0, module, idx);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -18,13 +18,11 @@
|
||||
#include <asm/arch/sdrc.h>
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
extern unsigned long omap2_sdrc_base;
|
||||
extern unsigned long omap2_sms_base;
|
||||
extern void __iomem *omap2_sdrc_base;
|
||||
extern void __iomem *omap2_sms_base;
|
||||
|
||||
#define OMAP_SDRC_REGADDR(reg) \
|
||||
(void __iomem *)IO_ADDRESS(omap2_sdrc_base + (reg))
|
||||
#define OMAP_SMS_REGADDR(reg) \
|
||||
(void __iomem *)IO_ADDRESS(omap2_sms_base + (reg))
|
||||
#define OMAP_SDRC_REGADDR(reg) (omap2_sdrc_base + (reg))
|
||||
#define OMAP_SMS_REGADDR(reg) (omap2_sms_base + (reg))
|
||||
|
||||
/* SDRC global register get/set */
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-omap2/sram-fn.S
|
||||
* linux/arch/arm/mach-omap2/sram242x.S
|
||||
*
|
||||
* Omap2 specific functions that need to be run in internal SRAM
|
||||
*
|
||||
@@ -27,22 +27,20 @@
|
||||
#include <asm/arch/io.h>
|
||||
#include <asm/hardware.h>
|
||||
|
||||
#include "sdrc.h"
|
||||
#include "prm.h"
|
||||
#include "cm.h"
|
||||
|
||||
#define TIMER_32KSYNCT_CR_V IO_ADDRESS(OMAP2420_32KSYNCT_BASE + 0x010)
|
||||
#include "sdrc.h"
|
||||
|
||||
.text
|
||||
|
||||
ENTRY(sram_ddr_init)
|
||||
ENTRY(omap242x_sram_ddr_init)
|
||||
stmfd sp!, {r0 - r12, lr} @ save registers on stack
|
||||
|
||||
mov r12, r2 @ capture CS1 vs CS0
|
||||
mov r8, r3 @ capture force parameter
|
||||
|
||||
/* frequency shift down */
|
||||
ldr r2, cm_clksel2_pll @ get address of dpllout reg
|
||||
ldr r2, omap242x_sdi_cm_clksel2_pll @ get address of dpllout reg
|
||||
mov r3, #0x1 @ value for 1x operation
|
||||
str r3, [r2] @ go to L1-freq operation
|
||||
|
||||
@@ -51,7 +49,7 @@ ENTRY(sram_ddr_init)
|
||||
bl voltage_shift @ go drop voltage
|
||||
|
||||
/* dll lock mode */
|
||||
ldr r11, sdrc_dlla_ctrl @ addr of dlla ctrl
|
||||
ldr r11, omap242x_sdi_sdrc_dlla_ctrl @ addr of dlla ctrl
|
||||
ldr r10, [r11] @ get current val
|
||||
cmp r12, #0x1 @ cs1 base (2422 es2.05/1)
|
||||
addeq r11, r11, #0x8 @ if cs1 base, move to DLLB
|
||||
@@ -102,7 +100,7 @@ i_dll_delay:
|
||||
* wait for it to finish, use 32k sync counter, 1tick=31uS.
|
||||
*/
|
||||
voltage_shift:
|
||||
ldr r4, prcm_voltctrl @ get addr of volt ctrl.
|
||||
ldr r4, omap242x_sdi_prcm_voltctrl @ get addr of volt ctrl.
|
||||
ldr r5, [r4] @ get value.
|
||||
ldr r6, prcm_mask_val @ get value of mask
|
||||
and r5, r5, r6 @ apply mask to clear bits
|
||||
@@ -112,7 +110,7 @@ voltage_shift:
|
||||
orr r5, r5, r3 @ build value for force
|
||||
str r5, [r4] @ Force transition to L1
|
||||
|
||||
ldr r3, timer_32ksynct_cr @ get addr of counter
|
||||
ldr r3, omap242x_sdi_timer_32ksynct_cr @ get addr of counter
|
||||
ldr r5, [r3] @ get value
|
||||
add r5, r5, #0x3 @ give it at most 93uS
|
||||
volt_delay:
|
||||
@@ -121,32 +119,31 @@ volt_delay:
|
||||
bhi volt_delay @ not yet->branch
|
||||
mov pc, lr @ back to caller.
|
||||
|
||||
/* relative load constants */
|
||||
cm_clksel2_pll:
|
||||
omap242x_sdi_cm_clksel2_pll:
|
||||
.word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
|
||||
sdrc_dlla_ctrl:
|
||||
omap242x_sdi_sdrc_dlla_ctrl:
|
||||
.word OMAP242X_SDRC_REGADDR(SDRC_DLLA_CTRL)
|
||||
prcm_voltctrl:
|
||||
.word OMAP2420_PRM_REGADDR(OCP_MOD, 0x50)
|
||||
omap242x_sdi_prcm_voltctrl:
|
||||
.word OMAP242X_PRCM_VOLTCTRL
|
||||
prcm_mask_val:
|
||||
.word 0xFFFF3FFC
|
||||
timer_32ksynct_cr:
|
||||
.word TIMER_32KSYNCT_CR_V
|
||||
ENTRY(sram_ddr_init_sz)
|
||||
.word . - sram_ddr_init
|
||||
omap242x_sdi_timer_32ksynct_cr:
|
||||
.word IO_ADDRESS(OMAP2_32KSYNCT_BASE + 0x010)
|
||||
ENTRY(omap242x_sram_ddr_init_sz)
|
||||
.word . - omap242x_sram_ddr_init
|
||||
|
||||
/*
|
||||
* Reprograms memory timings.
|
||||
* r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR]
|
||||
* PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0
|
||||
*/
|
||||
ENTRY(sram_reprogram_sdrc)
|
||||
ENTRY(omap242x_sram_reprogram_sdrc)
|
||||
stmfd sp!, {r0 - r10, lr} @ save registers on stack
|
||||
mov r3, #0x0 @ clear for mrc call
|
||||
mcr p15, 0, r3, c7, c10, 4 @ memory barrier, finish ARM SDR/DDR
|
||||
nop
|
||||
nop
|
||||
ldr r6, ddr_sdrc_rfr_ctrl @ get addr of refresh reg
|
||||
ldr r6, omap242x_srs_sdrc_rfr_ctrl @ get addr of refresh reg
|
||||
ldr r5, [r6] @ get value
|
||||
mov r5, r5, lsr #8 @ isolate rfr field and drop burst
|
||||
|
||||
@@ -160,7 +157,7 @@ ENTRY(sram_reprogram_sdrc)
|
||||
movne r5, r5, lsl #1 @ mult by 2 if to full
|
||||
mov r5, r5, lsl #8 @ put rfr field back into place
|
||||
add r5, r5, #0x1 @ turn on burst of 1
|
||||
ldr r4, ddr_cm_clksel2_pll @ get address of out reg
|
||||
ldr r4, omap242x_srs_cm_clksel2_pll @ get address of out reg
|
||||
ldr r3, [r4] @ get curr value
|
||||
orr r3, r3, #0x3
|
||||
bic r3, r3, #0x3 @ clear lower bits
|
||||
@@ -181,7 +178,7 @@ ENTRY(sram_reprogram_sdrc)
|
||||
bne freq_out @ leave if SDR, no DLL function
|
||||
|
||||
/* With DDR, we need to take care of the DLL for the frequency change */
|
||||
ldr r2, ddr_sdrc_dlla_ctrl @ addr of dlla ctrl
|
||||
ldr r2, omap242x_srs_sdrc_dlla_ctrl @ addr of dlla ctrl
|
||||
str r1, [r2] @ write out new SDRC_DLLA_CTRL
|
||||
add r2, r2, #0x8 @ addr to SDRC_DLLB_CTRL
|
||||
str r1, [r2] @ commit to SDRC_DLLB_CTRL
|
||||
@@ -197,7 +194,7 @@ freq_out:
|
||||
* wait for it to finish, use 32k sync counter, 1tick=31uS.
|
||||
*/
|
||||
voltage_shift_c:
|
||||
ldr r10, ddr_prcm_voltctrl @ get addr of volt ctrl
|
||||
ldr r10, omap242x_srs_prcm_voltctrl @ get addr of volt ctrl
|
||||
ldr r8, [r10] @ get value
|
||||
ldr r7, ddr_prcm_mask_val @ get value of mask
|
||||
and r8, r8, r7 @ apply mask to clear bits
|
||||
@@ -207,7 +204,7 @@ voltage_shift_c:
|
||||
orr r8, r8, r7 @ build value for force
|
||||
str r8, [r10] @ Force transition to L1
|
||||
|
||||
ldr r10, ddr_timer_32ksynct @ get addr of counter
|
||||
ldr r10, omap242x_srs_timer_32ksynct @ get addr of counter
|
||||
ldr r8, [r10] @ get value
|
||||
add r8, r8, #0x2 @ give it at most 62uS (min 31+)
|
||||
volt_delay_c:
|
||||
@@ -216,39 +213,39 @@ volt_delay_c:
|
||||
bhi volt_delay_c @ not yet->branch
|
||||
mov pc, lr @ back to caller
|
||||
|
||||
ddr_cm_clksel2_pll:
|
||||
omap242x_srs_cm_clksel2_pll:
|
||||
.word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
|
||||
ddr_sdrc_dlla_ctrl:
|
||||
omap242x_srs_sdrc_dlla_ctrl:
|
||||
.word OMAP242X_SDRC_REGADDR(SDRC_DLLA_CTRL)
|
||||
ddr_sdrc_rfr_ctrl:
|
||||
omap242x_srs_sdrc_rfr_ctrl:
|
||||
.word OMAP242X_SDRC_REGADDR(SDRC_RFR_CTRL_0)
|
||||
ddr_prcm_voltctrl:
|
||||
.word OMAP2420_PRM_REGADDR(OCP_MOD, 0x50)
|
||||
omap242x_srs_prcm_voltctrl:
|
||||
.word OMAP242X_PRCM_VOLTCTRL
|
||||
ddr_prcm_mask_val:
|
||||
.word 0xFFFF3FFC
|
||||
ddr_timer_32ksynct:
|
||||
.word TIMER_32KSYNCT_CR_V
|
||||
omap242x_srs_timer_32ksynct:
|
||||
.word IO_ADDRESS(OMAP2_32KSYNCT_BASE + 0x010)
|
||||
|
||||
ENTRY(sram_reprogram_sdrc_sz)
|
||||
.word . - sram_reprogram_sdrc
|
||||
ENTRY(omap242x_sram_reprogram_sdrc_sz)
|
||||
.word . - omap242x_sram_reprogram_sdrc
|
||||
|
||||
/*
|
||||
* Set dividers and pll. Also recalculate DLL value for DDR and unlock mode.
|
||||
*/
|
||||
ENTRY(sram_set_prcm)
|
||||
ENTRY(omap242x_sram_set_prcm)
|
||||
stmfd sp!, {r0-r12, lr} @ regs to stack
|
||||
adr r4, pbegin @ addr of preload start
|
||||
adr r8, pend @ addr of preload end
|
||||
mcrr p15, 1, r8, r4, c12 @ preload into icache
|
||||
pbegin:
|
||||
/* move into fast relock bypass */
|
||||
ldr r8, pll_ctl @ get addr
|
||||
ldr r8, omap242x_ssp_pll_ctl @ get addr
|
||||
ldr r5, [r8] @ get val
|
||||
mvn r6, #0x3 @ clear mask
|
||||
and r5, r5, r6 @ clear field
|
||||
orr r7, r5, #0x2 @ fast relock val
|
||||
str r7, [r8] @ go to fast relock
|
||||
ldr r4, pll_stat @ addr of stat
|
||||
ldr r4, omap242x_ssp_pll_stat @ addr of stat
|
||||
block:
|
||||
/* wait for bypass */
|
||||
ldr r8, [r4] @ stat value
|
||||
@@ -257,10 +254,10 @@ block:
|
||||
bne block @ loop if not
|
||||
|
||||
/* set new dpll dividers _after_ in bypass */
|
||||
ldr r4, pll_div @ get addr
|
||||
ldr r4, omap242x_ssp_pll_div @ get addr
|
||||
str r0, [r4] @ set dpll ctrl val
|
||||
|
||||
ldr r4, set_config @ get addr
|
||||
ldr r4, omap242x_ssp_set_config @ get addr
|
||||
mov r8, #1 @ valid cfg msk
|
||||
str r8, [r4] @ make dividers take
|
||||
|
||||
@@ -274,8 +271,8 @@ wait_a_bit:
|
||||
beq pend @ jump over dpll relock
|
||||
|
||||
/* relock DPLL with new vals */
|
||||
ldr r5, pll_stat @ get addr
|
||||
ldr r4, pll_ctl @ get addr
|
||||
ldr r5, omap242x_ssp_pll_stat @ get addr
|
||||
ldr r4, omap242x_ssp_pll_ctl @ get addr
|
||||
orr r8, r7, #0x3 @ val for lock dpll
|
||||
str r8, [r4] @ set val
|
||||
mov r0, #1000 @ dead spin a bit
|
||||
@@ -289,9 +286,9 @@ wait_lock:
|
||||
bne wait_lock @ wait if not
|
||||
pend:
|
||||
/* update memory timings & briefly lock dll */
|
||||
ldr r4, sdrc_rfr @ get addr
|
||||
ldr r4, omap242x_ssp_sdrc_rfr @ get addr
|
||||
str r1, [r4] @ update refresh timing
|
||||
ldr r11, dlla_ctrl @ get addr of DLLA ctrl
|
||||
ldr r11, omap242x_ssp_dlla_ctrl @ get addr of DLLA ctrl
|
||||
ldr r10, [r11] @ get current val
|
||||
mvn r9, #0x4 @ mask to get clear bit2
|
||||
and r10, r10, r9 @ clear bit2 for lock mode
|
||||
@@ -307,18 +304,18 @@ wait_dll_lock:
|
||||
nop
|
||||
ldmfd sp!, {r0-r12, pc} @ restore regs and return
|
||||
|
||||
set_config:
|
||||
.word OMAP2420_PRM_REGADDR(OCP_MOD, 0x80)
|
||||
pll_ctl:
|
||||
.word OMAP2420_CM_REGADDR(PLL_MOD, CM_FCLKEN1)
|
||||
pll_stat:
|
||||
.word OMAP2420_CM_REGADDR(PLL_MOD, CM_IDLEST1)
|
||||
pll_div:
|
||||
.word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKSEL)
|
||||
sdrc_rfr:
|
||||
omap242x_ssp_set_config:
|
||||
.word OMAP242X_PRCM_CLKCFG_CTRL
|
||||
omap242x_ssp_pll_ctl:
|
||||
.word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKEN)
|
||||
omap242x_ssp_pll_stat:
|
||||
.word OMAP2420_CM_REGADDR(PLL_MOD, CM_IDLEST)
|
||||
omap242x_ssp_pll_div:
|
||||
.word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKSEL1)
|
||||
omap242x_ssp_sdrc_rfr:
|
||||
.word OMAP242X_SDRC_REGADDR(SDRC_RFR_CTRL_0)
|
||||
dlla_ctrl:
|
||||
omap242x_ssp_dlla_ctrl:
|
||||
.word OMAP242X_SDRC_REGADDR(SDRC_DLLA_CTRL)
|
||||
|
||||
ENTRY(sram_set_prcm_sz)
|
||||
.word . - sram_set_prcm
|
||||
ENTRY(omap242x_sram_set_prcm_sz)
|
||||
.word . - omap242x_sram_set_prcm
|
321
arch/arm/mach-omap2/sram243x.S
Normal file
321
arch/arm/mach-omap2/sram243x.S
Normal file
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-omap2/sram243x.S
|
||||
*
|
||||
* Omap2 specific functions that need to be run in internal SRAM
|
||||
*
|
||||
* (C) Copyright 2004
|
||||
* Texas Instruments, <www.ti.com>
|
||||
* Richard Woodruff <r-woodruff2@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/arch/io.h>
|
||||
#include <asm/hardware.h>
|
||||
|
||||
#include "prm.h"
|
||||
#include "cm.h"
|
||||
#include "sdrc.h"
|
||||
|
||||
.text
|
||||
|
||||
ENTRY(omap243x_sram_ddr_init)
|
||||
stmfd sp!, {r0 - r12, lr} @ save registers on stack
|
||||
|
||||
mov r12, r2 @ capture CS1 vs CS0
|
||||
mov r8, r3 @ capture force parameter
|
||||
|
||||
/* frequency shift down */
|
||||
ldr r2, omap243x_sdi_cm_clksel2_pll @ get address of dpllout reg
|
||||
mov r3, #0x1 @ value for 1x operation
|
||||
str r3, [r2] @ go to L1-freq operation
|
||||
|
||||
/* voltage shift down */
|
||||
mov r9, #0x1 @ set up for L1 voltage call
|
||||
bl voltage_shift @ go drop voltage
|
||||
|
||||
/* dll lock mode */
|
||||
ldr r11, omap243x_sdi_sdrc_dlla_ctrl @ addr of dlla ctrl
|
||||
ldr r10, [r11] @ get current val
|
||||
cmp r12, #0x1 @ cs1 base (2422 es2.05/1)
|
||||
addeq r11, r11, #0x8 @ if cs1 base, move to DLLB
|
||||
mvn r9, #0x4 @ mask to get clear bit2
|
||||
and r10, r10, r9 @ clear bit2 for lock mode.
|
||||
orr r10, r10, #0x8 @ make sure DLL on (es2 bit pos)
|
||||
orr r10, r10, #0x2 @ 90 degree phase for all below 133Mhz
|
||||
str r10, [r11] @ commit to DLLA_CTRL
|
||||
bl i_dll_wait @ wait for dll to lock
|
||||
|
||||
/* get dll value */
|
||||
add r11, r11, #0x4 @ get addr of status reg
|
||||
ldr r10, [r11] @ get locked value
|
||||
|
||||
/* voltage shift up */
|
||||
mov r9, #0x0 @ shift back to L0-voltage
|
||||
bl voltage_shift @ go raise voltage
|
||||
|
||||
/* frequency shift up */
|
||||
mov r3, #0x2 @ value for 2x operation
|
||||
str r3, [r2] @ go to L0-freq operation
|
||||
|
||||
/* reset entry mode for dllctrl */
|
||||
sub r11, r11, #0x4 @ move from status to ctrl
|
||||
cmp r12, #0x1 @ normalize if cs1 based
|
||||
subeq r11, r11, #0x8 @ possibly back to DLLA
|
||||
cmp r8, #0x1 @ if forced unlock exit
|
||||
orreq r1, r1, #0x4 @ make sure exit with unlocked value
|
||||
str r1, [r11] @ restore DLLA_CTRL high value
|
||||
add r11, r11, #0x8 @ move to DLLB_CTRL addr
|
||||
str r1, [r11] @ set value DLLB_CTRL
|
||||
bl i_dll_wait @ wait for possible lock
|
||||
|
||||
/* set up for return, DDR should be good */
|
||||
str r10, [r0] @ write dll_status and return counter
|
||||
ldmfd sp!, {r0 - r12, pc} @ restore regs and return
|
||||
|
||||
/* ensure the DLL has relocked */
|
||||
i_dll_wait:
|
||||
mov r4, #0x800 @ delay DLL relock, min 0x400 L3 clocks
|
||||
i_dll_delay:
|
||||
subs r4, r4, #0x1
|
||||
bne i_dll_delay
|
||||
mov pc, lr
|
||||
|
||||
/*
|
||||
* shift up or down voltage, use R9 as input to tell level.
|
||||
* wait for it to finish, use 32k sync counter, 1tick=31uS.
|
||||
*/
|
||||
voltage_shift:
|
||||
ldr r4, omap243x_sdi_prcm_voltctrl @ get addr of volt ctrl.
|
||||
ldr r5, [r4] @ get value.
|
||||
ldr r6, prcm_mask_val @ get value of mask
|
||||
and r5, r5, r6 @ apply mask to clear bits
|
||||
orr r5, r5, r9 @ bulld value for L0/L1-volt operation.
|
||||
str r5, [r4] @ set up for change.
|
||||
mov r3, #0x4000 @ get val for force
|
||||
orr r5, r5, r3 @ build value for force
|
||||
str r5, [r4] @ Force transition to L1
|
||||
|
||||
ldr r3, omap243x_sdi_timer_32ksynct_cr @ get addr of counter
|
||||
ldr r5, [r3] @ get value
|
||||
add r5, r5, #0x3 @ give it at most 93uS
|
||||
volt_delay:
|
||||
ldr r7, [r3] @ get timer value
|
||||
cmp r5, r7 @ time up?
|
||||
bhi volt_delay @ not yet->branch
|
||||
mov pc, lr @ back to caller.
|
||||
|
||||
omap243x_sdi_cm_clksel2_pll:
|
||||
.word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
|
||||
omap243x_sdi_sdrc_dlla_ctrl:
|
||||
.word OMAP243X_SDRC_REGADDR(SDRC_DLLA_CTRL)
|
||||
omap243x_sdi_prcm_voltctrl:
|
||||
.word OMAP243X_PRCM_VOLTCTRL
|
||||
prcm_mask_val:
|
||||
.word 0xFFFF3FFC
|
||||
omap243x_sdi_timer_32ksynct_cr:
|
||||
.word IO_ADDRESS(OMAP2_32KSYNCT_BASE + 0x010)
|
||||
ENTRY(omap243x_sram_ddr_init_sz)
|
||||
.word . - omap243x_sram_ddr_init
|
||||
|
||||
/*
|
||||
* Reprograms memory timings.
|
||||
* r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR]
|
||||
* PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0
|
||||
*/
|
||||
ENTRY(omap243x_sram_reprogram_sdrc)
|
||||
stmfd sp!, {r0 - r10, lr} @ save registers on stack
|
||||
mov r3, #0x0 @ clear for mrc call
|
||||
mcr p15, 0, r3, c7, c10, 4 @ memory barrier, finish ARM SDR/DDR
|
||||
nop
|
||||
nop
|
||||
ldr r6, omap243x_srs_sdrc_rfr_ctrl @ get addr of refresh reg
|
||||
ldr r5, [r6] @ get value
|
||||
mov r5, r5, lsr #8 @ isolate rfr field and drop burst
|
||||
|
||||
cmp r0, #0x1 @ going to half speed?
|
||||
movne r9, #0x0 @ if up set flag up for pre up, hi volt
|
||||
|
||||
blne voltage_shift_c @ adjust voltage
|
||||
|
||||
cmp r0, #0x1 @ going to half speed (post branch link)
|
||||
moveq r5, r5, lsr #1 @ divide by 2 if to half
|
||||
movne r5, r5, lsl #1 @ mult by 2 if to full
|
||||
mov r5, r5, lsl #8 @ put rfr field back into place
|
||||
add r5, r5, #0x1 @ turn on burst of 1
|
||||
ldr r4, omap243x_srs_cm_clksel2_pll @ get address of out reg
|
||||
ldr r3, [r4] @ get curr value
|
||||
orr r3, r3, #0x3
|
||||
bic r3, r3, #0x3 @ clear lower bits
|
||||
orr r3, r3, r0 @ new state value
|
||||
str r3, [r4] @ set new state (pll/x, x=1 or 2)
|
||||
nop
|
||||
nop
|
||||
|
||||
moveq r9, #0x1 @ if speed down, post down, drop volt
|
||||
bleq voltage_shift_c
|
||||
|
||||
mcr p15, 0, r3, c7, c10, 4 @ memory barrier
|
||||
str r5, [r6] @ set new RFR_1 value
|
||||
add r6, r6, #0x30 @ get RFR_2 addr
|
||||
str r5, [r6] @ set RFR_2
|
||||
nop
|
||||
cmp r2, #0x1 @ (SDR or DDR) do we need to adjust DLL
|
||||
bne freq_out @ leave if SDR, no DLL function
|
||||
|
||||
/* With DDR, we need to take care of the DLL for the frequency change */
|
||||
ldr r2, omap243x_srs_sdrc_dlla_ctrl @ addr of dlla ctrl
|
||||
str r1, [r2] @ write out new SDRC_DLLA_CTRL
|
||||
add r2, r2, #0x8 @ addr to SDRC_DLLB_CTRL
|
||||
str r1, [r2] @ commit to SDRC_DLLB_CTRL
|
||||
mov r1, #0x2000 @ wait DLL relock, min 0x400 L3 clocks
|
||||
dll_wait:
|
||||
subs r1, r1, #0x1
|
||||
bne dll_wait
|
||||
freq_out:
|
||||
ldmfd sp!, {r0 - r10, pc} @ restore regs and return
|
||||
|
||||
/*
|
||||
* shift up or down voltage, use R9 as input to tell level.
|
||||
* wait for it to finish, use 32k sync counter, 1tick=31uS.
|
||||
*/
|
||||
voltage_shift_c:
|
||||
ldr r10, omap243x_srs_prcm_voltctrl @ get addr of volt ctrl
|
||||
ldr r8, [r10] @ get value
|
||||
ldr r7, ddr_prcm_mask_val @ get value of mask
|
||||
and r8, r8, r7 @ apply mask to clear bits
|
||||
orr r8, r8, r9 @ bulld value for L0/L1-volt operation.
|
||||
str r8, [r10] @ set up for change.
|
||||
mov r7, #0x4000 @ get val for force
|
||||
orr r8, r8, r7 @ build value for force
|
||||
str r8, [r10] @ Force transition to L1
|
||||
|
||||
ldr r10, omap243x_srs_timer_32ksynct @ get addr of counter
|
||||
ldr r8, [r10] @ get value
|
||||
add r8, r8, #0x2 @ give it at most 62uS (min 31+)
|
||||
volt_delay_c:
|
||||
ldr r7, [r10] @ get timer value
|
||||
cmp r8, r7 @ time up?
|
||||
bhi volt_delay_c @ not yet->branch
|
||||
mov pc, lr @ back to caller
|
||||
|
||||
omap243x_srs_cm_clksel2_pll:
|
||||
.word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKSEL2)
|
||||
omap243x_srs_sdrc_dlla_ctrl:
|
||||
.word OMAP243X_SDRC_REGADDR(SDRC_DLLA_CTRL)
|
||||
omap243x_srs_sdrc_rfr_ctrl:
|
||||
.word OMAP243X_SDRC_REGADDR(SDRC_RFR_CTRL_0)
|
||||
omap243x_srs_prcm_voltctrl:
|
||||
.word OMAP243X_PRCM_VOLTCTRL
|
||||
ddr_prcm_mask_val:
|
||||
.word 0xFFFF3FFC
|
||||
omap243x_srs_timer_32ksynct:
|
||||
.word IO_ADDRESS(OMAP2_32KSYNCT_BASE + 0x010)
|
||||
|
||||
ENTRY(omap243x_sram_reprogram_sdrc_sz)
|
||||
.word . - omap243x_sram_reprogram_sdrc
|
||||
|
||||
/*
|
||||
* Set dividers and pll. Also recalculate DLL value for DDR and unlock mode.
|
||||
*/
|
||||
ENTRY(omap243x_sram_set_prcm)
|
||||
stmfd sp!, {r0-r12, lr} @ regs to stack
|
||||
adr r4, pbegin @ addr of preload start
|
||||
adr r8, pend @ addr of preload end
|
||||
mcrr p15, 1, r8, r4, c12 @ preload into icache
|
||||
pbegin:
|
||||
/* move into fast relock bypass */
|
||||
ldr r8, omap243x_ssp_pll_ctl @ get addr
|
||||
ldr r5, [r8] @ get val
|
||||
mvn r6, #0x3 @ clear mask
|
||||
and r5, r5, r6 @ clear field
|
||||
orr r7, r5, #0x2 @ fast relock val
|
||||
str r7, [r8] @ go to fast relock
|
||||
ldr r4, omap243x_ssp_pll_stat @ addr of stat
|
||||
block:
|
||||
/* wait for bypass */
|
||||
ldr r8, [r4] @ stat value
|
||||
and r8, r8, #0x3 @ mask for stat
|
||||
cmp r8, #0x1 @ there yet
|
||||
bne block @ loop if not
|
||||
|
||||
/* set new dpll dividers _after_ in bypass */
|
||||
ldr r4, omap243x_ssp_pll_div @ get addr
|
||||
str r0, [r4] @ set dpll ctrl val
|
||||
|
||||
ldr r4, omap243x_ssp_set_config @ get addr
|
||||
mov r8, #1 @ valid cfg msk
|
||||
str r8, [r4] @ make dividers take
|
||||
|
||||
mov r4, #100 @ dead spin a bit
|
||||
wait_a_bit:
|
||||
subs r4, r4, #1 @ dec loop
|
||||
bne wait_a_bit @ delay done?
|
||||
|
||||
/* check if staying in bypass */
|
||||
cmp r2, #0x1 @ stay in bypass?
|
||||
beq pend @ jump over dpll relock
|
||||
|
||||
/* relock DPLL with new vals */
|
||||
ldr r5, omap243x_ssp_pll_stat @ get addr
|
||||
ldr r4, omap243x_ssp_pll_ctl @ get addr
|
||||
orr r8, r7, #0x3 @ val for lock dpll
|
||||
str r8, [r4] @ set val
|
||||
mov r0, #1000 @ dead spin a bit
|
||||
wait_more:
|
||||
subs r0, r0, #1 @ dec loop
|
||||
bne wait_more @ delay done?
|
||||
wait_lock:
|
||||
ldr r8, [r5] @ get lock val
|
||||
and r8, r8, #3 @ isolate field
|
||||
cmp r8, #2 @ locked?
|
||||
bne wait_lock @ wait if not
|
||||
pend:
|
||||
/* update memory timings & briefly lock dll */
|
||||
ldr r4, omap243x_ssp_sdrc_rfr @ get addr
|
||||
str r1, [r4] @ update refresh timing
|
||||
ldr r11, omap243x_ssp_dlla_ctrl @ get addr of DLLA ctrl
|
||||
ldr r10, [r11] @ get current val
|
||||
mvn r9, #0x4 @ mask to get clear bit2
|
||||
and r10, r10, r9 @ clear bit2 for lock mode
|
||||
orr r10, r10, #0x8 @ make sure DLL on (es2 bit pos)
|
||||
str r10, [r11] @ commit to DLLA_CTRL
|
||||
add r11, r11, #0x8 @ move to dllb
|
||||
str r10, [r11] @ hit DLLB also
|
||||
|
||||
mov r4, #0x800 @ relock time (min 0x400 L3 clocks)
|
||||
wait_dll_lock:
|
||||
subs r4, r4, #0x1
|
||||
bne wait_dll_lock
|
||||
nop
|
||||
ldmfd sp!, {r0-r12, pc} @ restore regs and return
|
||||
|
||||
omap243x_ssp_set_config:
|
||||
.word OMAP243X_PRCM_CLKCFG_CTRL
|
||||
omap243x_ssp_pll_ctl:
|
||||
.word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKEN)
|
||||
omap243x_ssp_pll_stat:
|
||||
.word OMAP2430_CM_REGADDR(PLL_MOD, CM_IDLEST)
|
||||
omap243x_ssp_pll_div:
|
||||
.word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKSEL1)
|
||||
omap243x_ssp_sdrc_rfr:
|
||||
.word OMAP243X_SDRC_REGADDR(SDRC_RFR_CTRL_0)
|
||||
omap243x_ssp_dlla_ctrl:
|
||||
.word OMAP243X_SDRC_REGADDR(SDRC_DLLA_CTRL)
|
||||
|
||||
ENTRY(omap243x_sram_set_prcm_sz)
|
||||
.word . - omap243x_sram_set_prcm
|
@@ -59,8 +59,7 @@ static struct irqaction omap2_gp_timer_irq = {
|
||||
static int omap2_gp_timer_set_next_event(unsigned long cycles,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
omap_dm_timer_set_load(gptimer, 0, 0xffffffff - cycles);
|
||||
omap_dm_timer_start(gptimer);
|
||||
omap_dm_timer_set_load_start(gptimer, 0, 0xffffffff - cycles);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -77,8 +76,7 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
|
||||
period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / HZ;
|
||||
period -= 1;
|
||||
|
||||
omap_dm_timer_set_load(gptimer, 1, 0xffffffff - period);
|
||||
omap_dm_timer_start(gptimer);
|
||||
omap_dm_timer_set_load_start(gptimer, 1, 0xffffffff - period);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
break;
|
||||
@@ -172,8 +170,7 @@ static void __init omap2_gp_clocksource_init(void)
|
||||
tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gpt));
|
||||
tick_period = (tick_rate / HZ) - 1;
|
||||
|
||||
omap_dm_timer_set_load(gpt, 1, 0);
|
||||
omap_dm_timer_start(gpt);
|
||||
omap_dm_timer_set_load_start(gpt, 1, 0);
|
||||
|
||||
clocksource_gpt.mult =
|
||||
clocksource_khz2mult(tick_rate/1000, clocksource_gpt.shift);
|
||||
|
Reference in New Issue
Block a user