Merge branch 'for_2.6.34_4f4e65_a' of git://git.pwsan.com/linux-2.6 into omap-for-linus

This commit is contained in:
Tony Lindgren 2010-01-29 11:37:48 -08:00
Родитель 4f4e65d248 98fa3d8aea
Коммит 9ba874506b
55 изменённых файлов: 5203 добавлений и 3845 удалений

Просмотреть файл

@ -52,12 +52,6 @@ const struct clkops clkops_dummy = {
.disable = clk_omap1_dummy_disable,
};
/* XXX can be replaced with a fixed_divisor_recalc */
unsigned long omap1_watchdog_recalc(struct clk *clk)
{
return clk->parent->rate / 14;
}
unsigned long omap1_uart_recalc(struct clk *clk)
{
unsigned int val = __raw_readl(clk->enable_reg);

Просмотреть файл

@ -149,7 +149,8 @@ static struct arm_idlect1_clk armwdt_ck = {
.flags = CLOCK_IDLE_CONTROL,
.enable_reg = OMAP1_IO_ADDRESS(ARM_IDLECT2),
.enable_bit = EN_WDTCK,
.recalc = &omap1_watchdog_recalc,
.fixed_div = 14,
.recalc = &omap_fixed_divisor_recalc,
},
.idlect_shift = 0,
};

Просмотреть файл

@ -6,14 +6,22 @@
obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o
omap-2-3-common = irq.o sdrc.o omap_hwmod.o
omap-3-4-common = dpll.o
omap-3-4-common = dpll3xxx.o
prcm-common = prcm.o powerdomain.o
clock-common = clock.o clock_common_data.o clockdomain.o
clock-common = clock.o clock_common_data.o \
clockdomain.o clkt_dpll.o \
clkt_clksel.o
clock-omap2xxx = clkt2xxx_dpllcore.o \
clkt2xxx_virt_prcm_set.o \
clkt2xxx_apll.o clkt2xxx_osc.o \
clkt2xxx_sys.o
clock-omap3xxx = clkt34xx_dpll3m2.o
obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(prcm-common) $(clock-common)
obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(prcm-common) $(clock-common) \
$(clock-omap2xxx)
obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(prcm-common) $(clock-common) \
$(omap-3-4-common)
obj-$(CONFIG_ARCH_OMAP4) += $(omap-3-4-common) prcm.o clock.o
$(omap-3-4-common) $(clock-omap3xxx)
obj-$(CONFIG_ARCH_OMAP4) += $(omap-3-4-common) $(prcm-common) $(clock-common)
obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o

Просмотреть файл

@ -0,0 +1,120 @@
/*
* OMAP2xxx APLL clock control functions
*
* Copyright (C) 2005-2008 Texas Instruments, Inc.
* Copyright (C) 2004-2010 Nokia Corporation
*
* Contacts:
* Richard Woodruff <r-woodruff2@ti.com>
* Paul Walmsley
*
* Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
* Gordon McNutt and RidgeRun, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#undef DEBUG
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <plat/clock.h>
#include <plat/prcm.h>
#include "clock.h"
#include "clock2xxx.h"
#include "cm.h"
#include "cm-regbits-24xx.h"
/* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */
#define EN_APLL_STOPPED 0
#define EN_APLL_LOCKED 3
/* CM_CLKSEL1_PLL.APLLS_CLKIN options (24XX) */
#define APLLS_CLKIN_19_2MHZ 0
#define APLLS_CLKIN_13MHZ 2
#define APLLS_CLKIN_12MHZ 3
/* Private functions */
/* Enable an APLL if off */
static int omap2_clk_apll_enable(struct clk *clk, u32 status_mask)
{
u32 cval, apll_mask;
apll_mask = EN_APLL_LOCKED << clk->enable_bit;
cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
if ((cval & apll_mask) == apll_mask)
return 0; /* apll already enabled */
cval &= ~apll_mask;
cval |= apll_mask;
cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
omap2_cm_wait_idlest(OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), status_mask,
clk->name);
/*
* REVISIT: Should we return an error code if omap2_wait_clock_ready()
* fails?
*/
return 0;
}
static int omap2_clk_apll96_enable(struct clk *clk)
{
return omap2_clk_apll_enable(clk, OMAP24XX_ST_96M_APLL);
}
static int omap2_clk_apll54_enable(struct clk *clk)
{
return omap2_clk_apll_enable(clk, OMAP24XX_ST_54M_APLL);
}
/* Stop APLL */
static void omap2_clk_apll_disable(struct clk *clk)
{
u32 cval;
cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
cval &= ~(EN_APLL_LOCKED << clk->enable_bit);
cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
}
/* Public data */
const struct clkops clkops_apll96 = {
.enable = omap2_clk_apll96_enable,
.disable = omap2_clk_apll_disable,
};
const struct clkops clkops_apll54 = {
.enable = omap2_clk_apll54_enable,
.disable = omap2_clk_apll_disable,
};
/* Public functions */
u32 omap2xxx_get_apll_clkin(void)
{
u32 aplls, srate = 0;
aplls = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
aplls &= OMAP24XX_APLLS_CLKIN_MASK;
aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT;
if (aplls == APLLS_CLKIN_19_2MHZ)
srate = 19200000;
else if (aplls == APLLS_CLKIN_13MHZ)
srate = 13000000;
else if (aplls == APLLS_CLKIN_12MHZ)
srate = 12000000;
return srate;
}

Просмотреть файл

@ -0,0 +1,173 @@
/*
* DPLL + CORE_CLK composite clock functions
*
* Copyright (C) 2005-2008 Texas Instruments, Inc.
* Copyright (C) 2004-2010 Nokia Corporation
*
* Contacts:
* Richard Woodruff <r-woodruff2@ti.com>
* Paul Walmsley
*
* Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
* Gordon McNutt and RidgeRun, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* XXX The DPLL and CORE clocks should be split into two separate clock
* types.
*/
#undef DEBUG
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <plat/clock.h>
#include <plat/sram.h>
#include <plat/sdrc.h>
#include "clock.h"
#include "clock2xxx.h"
#include "opp2xxx.h"
#include "cm.h"
#include "cm-regbits-24xx.h"
/* #define DOWN_VARIABLE_DPLL 1 */ /* Experimental */
/**
* omap2xxx_clk_get_core_rate - return the CORE_CLK rate
* @clk: pointer to the combined dpll_ck + core_ck (currently "dpll_ck")
*
* Returns the CORE_CLK rate. CORE_CLK can have one of three rate
* sources on OMAP2xxx: the DPLL CLKOUT rate, DPLL CLKOUTX2, or 32KHz
* (the latter is unusual). This currently should be called with
* struct clk *dpll_ck, which is a composite clock of dpll_ck and
* core_ck.
*/
unsigned long omap2xxx_clk_get_core_rate(struct clk *clk)
{
long long core_clk;
u32 v;
core_clk = omap2_get_dpll_rate(clk);
v = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
v &= OMAP24XX_CORE_CLK_SRC_MASK;
if (v == CORE_CLK_SRC_32K)
core_clk = 32768;
else
core_clk *= v;
return core_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 long omap2_dpllcore_round_rate(unsigned long target_rate)
{
u32 high, low, core_clk_src;
core_clk_src = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
core_clk_src &= OMAP24XX_CORE_CLK_SRC_MASK;
if (core_clk_src == CORE_CLK_SRC_DPLL) { /* DPLL clockout */
high = curr_prcm_set->dpll_speed * 2;
low = curr_prcm_set->dpll_speed;
} else { /* DPLL clockout x 2 */
high = curr_prcm_set->dpll_speed;
low = curr_prcm_set->dpll_speed / 2;
}
#ifdef DOWN_VARIABLE_DPLL
if (target_rate > high)
return high;
else
return target_rate;
#else
if (target_rate > low)
return high;
else
return low;
#endif
}
unsigned long omap2_dpllcore_recalc(struct clk *clk)
{
return omap2xxx_clk_get_core_rate(clk);
}
int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
{
u32 cur_rate, low, mult, div, valid_rate, done_rate;
u32 bypass = 0;
struct prcm_config tmpset;
const struct dpll_data *dd;
cur_rate = omap2xxx_clk_get_core_rate(dclk);
mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
mult &= OMAP24XX_CORE_CLK_SRC_MASK;
if ((rate == (cur_rate / 2)) && (mult == 2)) {
omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
} else if ((rate == (cur_rate * 2)) && (mult == 1)) {
omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
} else if (rate != cur_rate) {
valid_rate = omap2_dpllcore_round_rate(rate);
if (valid_rate != rate)
return -EINVAL;
if (mult == 1)
low = curr_prcm_set->dpll_speed;
else
low = curr_prcm_set->dpll_speed / 2;
dd = clk->dpll_data;
if (!dd)
return -EINVAL;
tmpset.cm_clksel1_pll = __raw_readl(dd->mult_div1_reg);
tmpset.cm_clksel1_pll &= ~(dd->mult_mask |
dd->div1_mask);
div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
tmpset.cm_clksel2_pll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
tmpset.cm_clksel2_pll &= ~OMAP24XX_CORE_CLK_SRC_MASK;
if (rate > low) {
tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL_X2;
mult = ((rate / 2) / 1000000);
done_rate = CORE_CLK_SRC_DPLL_X2;
} else {
tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL;
mult = (rate / 1000000);
done_rate = CORE_CLK_SRC_DPLL;
}
tmpset.cm_clksel1_pll |= (div << __ffs(dd->mult_mask));
tmpset.cm_clksel1_pll |= (mult << __ffs(dd->div1_mask));
/* Worst case */
tmpset.base_sdrc_rfr = SDRC_RFR_CTRL_BYPASS;
if (rate == curr_prcm_set->xtal_speed) /* If asking for 1-1 */
bypass = 1;
/* For omap2xxx_sdrc_init_params() */
omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
/* Force dll lock mode */
omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr,
bypass);
/* Errata: ret dll entry state */
omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
omap2xxx_sdrc_reprogram(done_rate, 0);
}
return 0;
}

Просмотреть файл

@ -0,0 +1,62 @@
/*
* OMAP2xxx osc_clk-specific clock code
*
* Copyright (C) 2005-2008 Texas Instruments, Inc.
* Copyright (C) 2004-2010 Nokia Corporation
*
* Contacts:
* Richard Woodruff <r-woodruff2@ti.com>
* Paul Walmsley
*
* Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
* Gordon McNutt and RidgeRun, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#undef DEBUG
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <plat/clock.h>
#include "clock.h"
#include "clock2xxx.h"
#include "prm.h"
#include "prm-regbits-24xx.h"
static int omap2_enable_osc_ck(struct clk *clk)
{
u32 pcc;
pcc = __raw_readl(prcm_clksrc_ctrl);
__raw_writel(pcc & ~OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl);
return 0;
}
static void omap2_disable_osc_ck(struct clk *clk)
{
u32 pcc;
pcc = __raw_readl(prcm_clksrc_ctrl);
__raw_writel(pcc | OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl);
}
const struct clkops clkops_oscck = {
.enable = omap2_enable_osc_ck,
.disable = omap2_disable_osc_ck,
};
unsigned long omap2_osc_clk_recalc(struct clk *clk)
{
return omap2xxx_get_apll_clkin() * omap2xxx_get_sysclkdiv();
}

Просмотреть файл

@ -0,0 +1,50 @@
/*
* OMAP2xxx sys_clk-specific clock code
*
* Copyright (C) 2005-2008 Texas Instruments, Inc.
* Copyright (C) 2004-2010 Nokia Corporation
*
* Contacts:
* Richard Woodruff <r-woodruff2@ti.com>
* Paul Walmsley
*
* Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
* Gordon McNutt and RidgeRun, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#undef DEBUG
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <plat/clock.h>
#include "clock.h"
#include "clock2xxx.h"
#include "prm.h"
#include "prm-regbits-24xx.h"
void __iomem *prcm_clksrc_ctrl;
u32 omap2xxx_get_sysclkdiv(void)
{
u32 div;
div = __raw_readl(prcm_clksrc_ctrl);
div &= OMAP_SYSCLKDIV_MASK;
div >>= OMAP_SYSCLKDIV_SHIFT;
return div;
}
unsigned long omap2xxx_sys_clk_recalc(struct clk *clk)
{
return clk->parent->rate / omap2xxx_get_sysclkdiv();
}

Просмотреть файл

@ -0,0 +1,254 @@
/*
* OMAP2xxx DVFS virtual clock functions
*
* Copyright (C) 2005-2008 Texas Instruments, Inc.
* Copyright (C) 2004-2010 Nokia Corporation
*
* Contacts:
* Richard Woodruff <r-woodruff2@ti.com>
* Paul Walmsley
*
* Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
* Gordon McNutt and RidgeRun, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* XXX Some of this code should be replaceable by the upcoming OPP layer
* code. However, some notion of "rate set" is probably still necessary
* for OMAP2xxx at least. Rate sets should be generalized so they can be
* used for any OMAP chip, not just OMAP2xxx. In particular, Richard Woodruff
* has in the past expressed a preference to use rate sets for OPP changes,
* rather than dynamically recalculating the clock tree, so if someone wants
* this badly enough to write the code to handle it, we should support it
* as an option.
*/
#undef DEBUG
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/cpufreq.h>
#include <plat/clock.h>
#include <plat/sram.h>
#include <plat/sdrc.h>
#include "clock.h"
#include "clock2xxx.h"
#include "opp2xxx.h"
#include "cm.h"
#include "cm-regbits-24xx.h"
const struct prcm_config *curr_prcm_set;
const struct prcm_config *rate_table;
/**
* omap2_table_mpu_recalc - just return the MPU speed
* @clk: virt_prcm_set struct clk
*
* Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
*/
unsigned long omap2_table_mpu_recalc(struct clk *clk)
{
return curr_prcm_set->mpu_speed;
}
/*
* Look for a rate equal or less than the target rate given a configuration set.
*
* What's not entirely clear is "which" field represents the key field.
* Some might argue L3-DDR, others ARM, others IVA. This code is simple and
* just uses the ARM rates.
*/
long omap2_round_to_table_rate(struct clk *clk, unsigned long rate)
{
const struct prcm_config *ptr;
long highest_rate;
long sys_ck_rate;
sys_ck_rate = clk_get_rate(sclk);
highest_rate = -EINVAL;
for (ptr = rate_table; ptr->mpu_speed; ptr++) {
if (!(ptr->flags & cpu_mask))
continue;
if (ptr->xtal_speed != sys_ck_rate)
continue;
highest_rate = ptr->mpu_speed;
/* Can check only after xtal frequency check */
if (ptr->mpu_speed <= rate)
break;
}
return highest_rate;
}
/* Sets basic clocks based on the specified rate */
int omap2_select_table_rate(struct clk *clk, unsigned long rate)
{
u32 cur_rate, done_rate, bypass = 0, tmp;
const struct prcm_config *prcm;
unsigned long found_speed = 0;
unsigned long flags;
long sys_ck_rate;
sys_ck_rate = clk_get_rate(sclk);
for (prcm = rate_table; prcm->mpu_speed; prcm++) {
if (!(prcm->flags & cpu_mask))
continue;
if (prcm->xtal_speed != sys_ck_rate)
continue;
if (prcm->mpu_speed <= rate) {
found_speed = prcm->mpu_speed;
break;
}
}
if (!found_speed) {
printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
rate / 1000000);
return -EINVAL;
}
curr_prcm_set = prcm;
cur_rate = omap2xxx_clk_get_core_rate(dclk);
if (prcm->dpll_speed == cur_rate / 2) {
omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
} else if (prcm->dpll_speed == cur_rate * 2) {
omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
} else if (prcm->dpll_speed != cur_rate) {
local_irq_save(flags);
if (prcm->dpll_speed == prcm->xtal_speed)
bypass = 1;
if ((prcm->cm_clksel2_pll & OMAP24XX_CORE_CLK_SRC_MASK) ==
CORE_CLK_SRC_DPLL_X2)
done_rate = CORE_CLK_SRC_DPLL_X2;
else
done_rate = CORE_CLK_SRC_DPLL;
/* MPU divider */
cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL);
/* dsp + iva1 div(2420), iva2.1(2430) */
cm_write_mod_reg(prcm->cm_clksel_dsp,
OMAP24XX_DSP_MOD, CM_CLKSEL);
cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL);
/* Major subsystem dividers */
tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK;
cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD,
CM_CLKSEL1);
if (cpu_is_omap2430())
cm_write_mod_reg(prcm->cm_clksel_mdm,
OMAP2430_MDM_MOD, CM_CLKSEL);
/* x2 to enter omap2xxx_sdrc_init_params() */
omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
bypass);
omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
omap2xxx_sdrc_reprogram(done_rate, 0);
local_irq_restore(flags);
}
return 0;
}
#ifdef CONFIG_CPU_FREQ
/*
* Walk PRCM rate table and fillout cpufreq freq_table
* XXX This should be replaced by an OPP layer in the near future
*/
static struct cpufreq_frequency_table *freq_table;
void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
{
const struct prcm_config *prcm;
long sys_ck_rate;
int i = 0;
int tbl_sz = 0;
if (!cpu_is_omap24xx())
return;
sys_ck_rate = clk_get_rate(sclk);
for (prcm = rate_table; prcm->mpu_speed; prcm++) {
if (!(prcm->flags & cpu_mask))
continue;
if (prcm->xtal_speed != sys_ck_rate)
continue;
/* don't put bypass rates in table */
if (prcm->dpll_speed == prcm->xtal_speed)
continue;
tbl_sz++;
}
/*
* XXX Ensure that we're doing what CPUFreq expects for this error
* case and the following one
*/
if (tbl_sz == 0) {
pr_warning("%s: no matching entries in rate_table\n",
__func__);
return;
}
/* Include the CPUFREQ_TABLE_END terminator entry */
tbl_sz++;
freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) * tbl_sz,
GFP_ATOMIC);
if (!freq_table) {
pr_err("%s: could not kzalloc frequency table\n", __func__);
return;
}
for (prcm = rate_table; prcm->mpu_speed; prcm++) {
if (!(prcm->flags & cpu_mask))
continue;
if (prcm->xtal_speed != sys_ck_rate)
continue;
/* don't put bypass rates in table */
if (prcm->dpll_speed == prcm->xtal_speed)
continue;
freq_table[i].index = i;
freq_table[i].frequency = prcm->mpu_speed / 1000;
i++;
}
freq_table[i].index = i;
freq_table[i].frequency = CPUFREQ_TABLE_END;
*table = &freq_table[0];
}
void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table)
{
if (!cpu_is_omap24xx())
return;
kfree(freq_table);
}
#endif

Просмотреть файл

@ -0,0 +1,120 @@
/*
* OMAP34xx M2 divider clock code
*
* Copyright (C) 2007-2008 Texas Instruments, Inc.
* Copyright (C) 2007-2010 Nokia Corporation
*
* Paul Walmsley
* Jouni Högander
*
* Parts of this code are based on code written by
* Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu
*
* 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.
*/
#undef DEBUG
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <plat/clock.h>
#include <plat/sram.h>
#include <plat/sdrc.h>
#include "clock.h"
#include "clock34xx.h"
#include "sdrc.h"
#define CYCLES_PER_MHZ 1000000
/*
* CORE DPLL (DPLL3) M2 divider rate programming functions
*
* These call into SRAM code to do the actual CM writes, since the SDRAM
* is clocked from DPLL3.
*/
/**
* omap3_core_dpll_m2_set_rate - set CORE DPLL M2 divider
* @clk: struct clk * of DPLL to set
* @rate: rounded target rate
*
* Program the DPLL M2 divider with the rounded target rate. Returns
* -EINVAL upon error, or 0 upon success.
*/
int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
{
u32 new_div = 0;
u32 unlock_dll = 0;
u32 c;
unsigned long validrate, sdrcrate, _mpurate;
struct omap_sdrc_params *sdrc_cs0;
struct omap_sdrc_params *sdrc_cs1;
int ret;
if (!clk || !rate)
return -EINVAL;
validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
if (validrate != rate)
return -EINVAL;
sdrcrate = sdrc_ick_p->rate;
if (rate > clk->rate)
sdrcrate <<= ((rate / clk->rate) >> 1);
else
sdrcrate >>= ((clk->rate / rate) >> 1);
ret = omap2_sdrc_get_params(sdrcrate, &sdrc_cs0, &sdrc_cs1);
if (ret)
return -EINVAL;
if (sdrcrate < MIN_SDRC_DLL_LOCK_FREQ) {
pr_debug("clock: will unlock SDRC DLL\n");
unlock_dll = 1;
}
/*
* XXX This only needs to be done when the CPU frequency changes
*/
_mpurate = arm_fck_p->rate / CYCLES_PER_MHZ;
c = (_mpurate << SDRC_MPURATE_SCALE) >> SDRC_MPURATE_BASE_SHIFT;
c += 1; /* for safety */
c *= SDRC_MPURATE_LOOPS;
c >>= SDRC_MPURATE_SCALE;
if (c == 0)
c = 1;
pr_debug("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate,
validrate);
pr_debug("clock: SDRC CS0 timing params used:"
" RFR %08x CTRLA %08x CTRLB %08x MR %08x\n",
sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
sdrc_cs0->actim_ctrlb, sdrc_cs0->mr);
if (sdrc_cs1)
pr_debug("clock: SDRC CS1 timing params used: "
" RFR %08x CTRLA %08x CTRLB %08x MR %08x\n",
sdrc_cs1->rfr_ctrl, sdrc_cs1->actim_ctrla,
sdrc_cs1->actim_ctrlb, sdrc_cs1->mr);
if (sdrc_cs1)
omap3_configure_core_dpll(
new_div, unlock_dll, c, rate > clk->rate,
sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
sdrc_cs0->actim_ctrlb, sdrc_cs0->mr,
sdrc_cs1->rfr_ctrl, sdrc_cs1->actim_ctrla,
sdrc_cs1->actim_ctrlb, sdrc_cs1->mr);
else
omap3_configure_core_dpll(
new_div, unlock_dll, c, rate > clk->rate,
sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
sdrc_cs0->actim_ctrlb, sdrc_cs0->mr,
0, 0, 0, 0);
return 0;
}

Просмотреть файл

@ -0,0 +1,417 @@
/*
* clkt_clksel.c - OMAP2/3/4 clksel clock functions
*
* Copyright (C) 2005-2008 Texas Instruments, Inc.
* Copyright (C) 2004-2010 Nokia Corporation
*
* Contacts:
* Richard Woodruff <r-woodruff2@ti.com>
* Paul Walmsley
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* XXX At some point these clksel clocks should be split into
* "divider" clocks and "mux" clocks to better match the hardware.
*
* XXX Currently these clocks are only used in the OMAP2/3/4 code, but
* many of the OMAP1 clocks should be convertible to use this
* mechanism.
*/
#undef DEBUG
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <plat/clock.h>
#include "clock.h"
#include "cm.h"
#include "cm-regbits-24xx.h"
#include "cm-regbits-34xx.h"
/* Private functions */
/**
* _omap2_get_clksel_by_parent - return clksel struct for a given clk & parent
* @clk: OMAP struct clk ptr to inspect
* @src_clk: OMAP struct clk ptr of the parent clk to search for
*
* Scan the struct clksel array associated with the clock to find
* the element associated with the supplied parent clock address.
* Returns a pointer to the struct clksel on success or NULL on error.
*/
static const struct clksel *_omap2_get_clksel_by_parent(struct clk *clk,
struct clk *src_clk)
{
const struct clksel *clks;
if (!clk->clksel)
return NULL;
for (clks = clk->clksel; clks->parent; clks++) {
if (clks->parent == src_clk)
break; /* Found the requested parent */
}
if (!clks->parent) {
printk(KERN_ERR "clock: Could not find parent clock %s in "
"clksel array of clock %s\n", src_clk->name,
clk->name);
return NULL;
}
return clks;
}
/*
* Converts encoded control register address into a full address
* On error, the return value (parent_div) will be 0.
*/
static u32 _omap2_clksel_get_src_field(struct clk *src_clk, struct clk *clk,
u32 *field_val)
{
const struct clksel *clks;
const struct clksel_rate *clkr;
clks = _omap2_get_clksel_by_parent(clk, src_clk);
if (!clks)
return 0;
for (clkr = clks->rates; clkr->div; clkr++) {
if (clkr->flags & cpu_mask && clkr->flags & DEFAULT_RATE)
break; /* Found the default rate for this platform */
}
if (!clkr->div) {
printk(KERN_ERR "clock: Could not find default rate for "
"clock %s parent %s\n", clk->name,
src_clk->parent->name);
return 0;
}
/* Should never happen. Add a clksel mask to the struct clk. */
WARN_ON(clk->clksel_mask == 0);
*field_val = clkr->val;
return clkr->div;
}
/* Public functions */
/**
* omap2_init_clksel_parent - set a clksel clk's parent field from the hardware
* @clk: OMAP clock struct ptr to use
*
* Given a pointer to a source-selectable struct clk, read the hardware
* register and determine what its parent is currently set to. Update the
* clk->parent field with the appropriate clk ptr.
*/
void omap2_init_clksel_parent(struct clk *clk)
{
const struct clksel *clks;
const struct clksel_rate *clkr;
u32 r, found = 0;
if (!clk->clksel)
return;
r = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
r >>= __ffs(clk->clksel_mask);
for (clks = clk->clksel; clks->parent && !found; clks++) {
for (clkr = clks->rates; clkr->div && !found; clkr++) {
if ((clkr->flags & cpu_mask) && (clkr->val == r)) {
if (clk->parent != clks->parent) {
pr_debug("clock: inited %s parent "
"to %s (was %s)\n",
clk->name, clks->parent->name,
((clk->parent) ?
clk->parent->name : "NULL"));
clk_reparent(clk, clks->parent);
};
found = 1;
}
}
}
if (!found)
printk(KERN_ERR "clock: init parent: could not find "
"regval %0x for clock %s\n", r, clk->name);
return;
}
/*
* Used for clocks that are part of CLKSEL_xyz governed clocks.
* REVISIT: Maybe change to use clk->enable() functions like on omap1?
*/
unsigned long omap2_clksel_recalc(struct clk *clk)
{
unsigned long rate;
u32 div = 0;
pr_debug("clock: recalc'ing clksel clk %s\n", clk->name);
div = omap2_clksel_get_divisor(clk);
if (div == 0)
return clk->rate;
rate = clk->parent->rate / div;
pr_debug("clock: new clock rate is %ld (div %d)\n", rate, div);
return rate;
}
/**
* omap2_clksel_round_rate_div - find divisor for the given clock and rate
* @clk: OMAP struct clk to use
* @target_rate: desired clock rate
* @new_div: ptr to where we should store the divisor
*
* Finds 'best' divider value in an array based on the source and target
* rates. The divider array must be sorted with smallest divider first.
* Note that this will not work for clocks which are part of CONFIG_PARTICIPANT,
* they are only settable as part of virtual_prcm set.
*
* Returns the rounded clock rate or returns 0xffffffff on error.
*/
u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
u32 *new_div)
{
unsigned long test_rate;
const struct clksel *clks;
const struct clksel_rate *clkr;
u32 last_div = 0;
pr_debug("clock: clksel_round_rate_div: %s target_rate %ld\n",
clk->name, target_rate);
*new_div = 1;
clks = _omap2_get_clksel_by_parent(clk, clk->parent);
if (!clks)
return ~0;
for (clkr = clks->rates; clkr->div; clkr++) {
if (!(clkr->flags & cpu_mask))
continue;
/* Sanity check */
if (clkr->div <= last_div)
pr_err("clock: clksel_rate table not sorted "
"for clock %s", clk->name);
last_div = clkr->div;
test_rate = clk->parent->rate / clkr->div;
if (test_rate <= target_rate)
break; /* found it */
}
if (!clkr->div) {
pr_err("clock: Could not find divisor for target "
"rate %ld for clock %s parent %s\n", target_rate,
clk->name, clk->parent->name);
return ~0;
}
*new_div = clkr->div;
pr_debug("clock: new_div = %d, new_rate = %ld\n", *new_div,
(clk->parent->rate / clkr->div));
return clk->parent->rate / clkr->div;
}
/**
* omap2_clksel_round_rate - find rounded rate for the given clock and rate
* @clk: OMAP struct clk to use
* @target_rate: desired clock rate
*
* Compatibility wrapper for OMAP clock framework
* Finds best target rate based on the source clock and possible dividers.
* rates. The divider array must be sorted with smallest divider first.
* Note that this will not work for clocks which are part of CONFIG_PARTICIPANT,
* they are only settable as part of virtual_prcm set.
*
* Returns the rounded clock rate or returns 0xffffffff on error.
*/
long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
{
u32 new_div;
return omap2_clksel_round_rate_div(clk, target_rate, &new_div);
}
/* Given a clock and a rate apply a clock specific rounding function */
long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
{
if (clk->round_rate)
return clk->round_rate(clk, rate);
if (clk->flags & RATE_FIXED)
printk(KERN_ERR "clock: generic omap2_clk_round_rate called "
"on fixed-rate clock %s\n", clk->name);
return clk->rate;
}
/**
* omap2_clksel_to_divisor() - turn clksel field value into integer divider
* @clk: OMAP struct clk to use
* @field_val: register field value to find
*
* Given a struct clk of a rate-selectable clksel clock, and a register field
* value to search for, find the corresponding clock divisor. The register
* field value should be pre-masked and shifted down so the LSB is at bit 0
* before calling. Returns 0 on error
*/
u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val)
{
const struct clksel *clks;
const struct clksel_rate *clkr;
clks = _omap2_get_clksel_by_parent(clk, clk->parent);
if (!clks)
return 0;
for (clkr = clks->rates; clkr->div; clkr++) {
if ((clkr->flags & cpu_mask) && (clkr->val == field_val))
break;
}
if (!clkr->div) {
printk(KERN_ERR "clock: Could not find fieldval %d for "
"clock %s parent %s\n", field_val, clk->name,
clk->parent->name);
return 0;
}
return clkr->div;
}
/**
* omap2_divisor_to_clksel() - turn clksel integer divisor into a field value
* @clk: OMAP struct clk to use
* @div: integer divisor to search for
*
* Given a struct clk of a rate-selectable clksel clock, and a clock divisor,
* find the corresponding register field value. The return register value is
* the value before left-shifting. Returns ~0 on error
*/
u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
{
const struct clksel *clks;
const struct clksel_rate *clkr;
/* should never happen */
WARN_ON(div == 0);
clks = _omap2_get_clksel_by_parent(clk, clk->parent);
if (!clks)
return ~0;
for (clkr = clks->rates; clkr->div; clkr++) {
if ((clkr->flags & cpu_mask) && (clkr->div == div))
break;
}
if (!clkr->div) {
printk(KERN_ERR "clock: Could not find divisor %d for "
"clock %s parent %s\n", div, clk->name,
clk->parent->name);
return ~0;
}
return clkr->val;
}
/**
* omap2_clksel_get_divisor - get current divider applied to parent clock.
* @clk: OMAP struct clk to use.
*
* Returns the integer divisor upon success or 0 on error.
*/
u32 omap2_clksel_get_divisor(struct clk *clk)
{
u32 v;
if (!clk->clksel_mask)
return 0;
v = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
v >>= __ffs(clk->clksel_mask);
return omap2_clksel_to_divisor(clk, v);
}
int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
{
u32 v, field_val, validrate, new_div = 0;
if (!clk->clksel_mask)
return -EINVAL;
validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
if (validrate != rate)
return -EINVAL;
field_val = omap2_divisor_to_clksel(clk, new_div);
if (field_val == ~0)
return -EINVAL;
v = __raw_readl(clk->clksel_reg);
v &= ~clk->clksel_mask;
v |= field_val << __ffs(clk->clksel_mask);
__raw_writel(v, clk->clksel_reg);
v = __raw_readl(clk->clksel_reg); /* OCP barrier */
clk->rate = clk->parent->rate / new_div;
omap2xxx_clk_commit(clk);
return 0;
}
int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent)
{
u32 field_val, v, parent_div;
if (!clk->clksel)
return -EINVAL;
parent_div = _omap2_clksel_get_src_field(new_parent, clk, &field_val);
if (!parent_div)
return -EINVAL;
/* Set new source value (previous dividers if any in effect) */
v = __raw_readl(clk->clksel_reg);
v &= ~clk->clksel_mask;
v |= field_val << __ffs(clk->clksel_mask);
__raw_writel(v, clk->clksel_reg);
v = __raw_readl(clk->clksel_reg); /* OCP barrier */
omap2xxx_clk_commit(clk);
clk_reparent(clk, new_parent);
/* CLKSEL clocks follow their parents' rates, divided by a divisor */
clk->rate = new_parent->rate;
if (parent_div > 0)
clk->rate /= parent_div;
pr_debug("clock: set parent of %s to %s (new rate %ld)\n",
clk->name, clk->parent->name, clk->rate);
return 0;
}

Просмотреть файл

@ -0,0 +1,386 @@
/*
* OMAP2/3/4 DPLL clock functions
*
* Copyright (C) 2005-2008 Texas Instruments, Inc.
* Copyright (C) 2004-2010 Nokia Corporation
*
* Contacts:
* Richard Woodruff <r-woodruff2@ti.com>
* Paul Walmsley
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#undef DEBUG
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <asm/div64.h>
#include <plat/clock.h>
#include "clock.h"
#include "cm.h"
#include "cm-regbits-24xx.h"
#include "cm-regbits-34xx.h"
/* 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
/*
* 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))
/* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
#define DPLL_FINT_BAND1_MIN 750000
#define DPLL_FINT_BAND1_MAX 2100000
#define DPLL_FINT_BAND2_MIN 7500000
#define DPLL_FINT_BAND2_MAX 21000000
/* _dpll_test_fint() return codes */
#define DPLL_FINT_UNDERFLOW -1
#define DPLL_FINT_INVALID -2
/* Private functions */
/*
* _dpll_test_fint - test whether an Fint value is valid for the DPLL
* @clk: DPLL struct clk to test
* @n: divider value (N) to test
*
* Tests whether a particular divider @n will result in a valid DPLL
* internal clock frequency Fint. See the 34xx TRM 4.7.6.2 "DPLL Jitter
* Correction". Returns 0 if OK, -1 if the enclosing loop can terminate
* (assuming that it is counting N upwards), or -2 if the enclosing loop
* should skip to the next iteration (again assuming N is increasing).
*/
static int _dpll_test_fint(struct clk *clk, u8 n)
{
struct dpll_data *dd;
long fint;
int ret = 0;
dd = clk->dpll_data;
/* DPLL divider must result in a valid jitter correction val */
fint = clk->parent->rate / (n + 1);
if (fint < DPLL_FINT_BAND1_MIN) {
pr_debug("rejecting n=%d due to Fint failure, "
"lowering max_divider\n", n);
dd->max_divider = n;
ret = DPLL_FINT_UNDERFLOW;
} else if (fint > DPLL_FINT_BAND1_MAX &&
fint < DPLL_FINT_BAND2_MIN) {
pr_debug("rejecting n=%d due to Fint failure\n", n);
ret = DPLL_FINT_INVALID;
} else if (fint > DPLL_FINT_BAND2_MAX) {
pr_debug("rejecting n=%d due to Fint failure, "
"boosting min_divider\n", n);
dd->min_divider = n;
ret = DPLL_FINT_INVALID;
}
return ret;
}
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 r = 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;
r = DPLL_MULT_UNDERFLOW;
}
if (*new_rate == 0)
*new_rate = _dpll_compute_new_rate(parent_rate, *m, n);
return r;
}
/* Public functions */
void omap2_init_dpll_parent(struct clk *clk)
{
u32 v;
struct dpll_data *dd;
dd = clk->dpll_data;
if (!dd)
return;
/* Return bypass rate if DPLL is bypassed */
v = __raw_readl(dd->control_reg);
v &= dd->enable_mask;
v >>= __ffs(dd->enable_mask);
/* Reparent in case the dpll is in bypass */
if (cpu_is_omap24xx()) {
if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
v == OMAP2XXX_EN_DPLL_FRBYPASS)
clk_reparent(clk, dd->clk_bypass);
} else if (cpu_is_omap34xx()) {
if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
v == OMAP3XXX_EN_DPLL_FRBYPASS)
clk_reparent(clk, dd->clk_bypass);
} else if (cpu_is_omap44xx()) {
if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
v == OMAP4XXX_EN_DPLL_FRBYPASS ||
v == OMAP4XXX_EN_DPLL_MNBYPASS)
clk_reparent(clk, dd->clk_bypass);
}
return;
}
/**
* omap2_get_dpll_rate - returns the current DPLL CLKOUT rate
* @clk: struct clk * of a DPLL
*
* DPLLs can be locked or bypassed - basically, enabled or disabled.
* When locked, the DPLL output depends on the M and N values. When
* bypassed, on OMAP2xxx, the output rate is either the 32KiHz clock
* or sys_clk. Bypass rates on OMAP3 depend on the DPLL: DPLLs 1 and
* 2 are bypassed with dpll1_fclk and dpll2_fclk respectively
* (generated by DPLL3), while DPLL 3, 4, and 5 bypass rates are sys_clk.
* Returns the current DPLL CLKOUT rate (*not* CLKOUTX2) if the DPLL is
* locked, or the appropriate bypass rate if the DPLL is bypassed, or 0
* if the clock @clk is not a DPLL.
*/
u32 omap2_get_dpll_rate(struct clk *clk)
{
long long dpll_clk;
u32 dpll_mult, dpll_div, v;
struct dpll_data *dd;
dd = clk->dpll_data;
if (!dd)
return 0;
/* Return bypass rate if DPLL is bypassed */
v = __raw_readl(dd->control_reg);
v &= dd->enable_mask;
v >>= __ffs(dd->enable_mask);
if (cpu_is_omap24xx()) {
if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
v == OMAP2XXX_EN_DPLL_FRBYPASS)
return dd->clk_bypass->rate;
} else if (cpu_is_omap34xx()) {
if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
v == OMAP3XXX_EN_DPLL_FRBYPASS)
return dd->clk_bypass->rate;
} else if (cpu_is_omap44xx()) {
if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
v == OMAP4XXX_EN_DPLL_FRBYPASS ||
v == OMAP4XXX_EN_DPLL_MNBYPASS)
return dd->clk_bypass->rate;
}
v = __raw_readl(dd->mult_div1_reg);
dpll_mult = v & dd->mult_mask;
dpll_mult >>= __ffs(dd->mult_mask);
dpll_div = v & dd->div1_mask;
dpll_div >>= __ffs(dd->div1_mask);
dpll_clk = (long long)dd->clk_ref->rate * dpll_mult;
do_div(dpll_clk, dpll_div + 1);
return dpll_clk;
}
/* 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;
}
/**
* 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;
struct dpll_data *dd;
if (!clk || !clk->dpll_data)
return ~0;
dd = clk->dpll_data;
pr_debug("clock: starting DPLL round_rate for clock %s, target rate "
"%ld\n", clk->name, target_rate);
scaled_rt_rp = target_rate / (dd->clk_ref->rate / DPLL_SCALE_FACTOR);
scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR;
dd->last_rounded_rate = 0;
for (n = dd->min_divider; n <= dd->max_divider; n++) {
/* Is the (input clk, divider) pair valid for the DPLL? */
r = _dpll_test_fint(clk, n);
if (r == DPLL_FINT_UNDERFLOW)
break;
else if (r == DPLL_FINT_INVALID)
continue;
/* Compute the scaled DPLL multiplier, based on the divider */
m = scaled_rt_rp * n;
/*
* Since we're counting n up, a m overflow means we
* can bail out completely (since as n increases in
* the next iteration, there's no way that m can
* increase beyond the current m)
*/
if (m > scaled_max_m)
break;
r = _dpll_test_mult(&m, n, &new_rate, target_rate,
dd->clk_ref->rate);
/* m can't be set low enough for this n - try with a larger n */
if (r == DPLL_MULT_UNDERFLOW)
continue;
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) - dd->rate_tolerance)) {
min_e = e;
min_e_m = m;
min_e_n = n;
pr_debug("clock: found new least error %d\n", min_e);
/* We found good settings -- bail out now */
if (min_e <= dd->rate_tolerance)
break;
}
}
if (min_e < 0) {
pr_debug("clock: error: target rate or tolerance too low\n");
return ~0;
}
dd->last_rounded_m = min_e_m;
dd->last_rounded_n = min_e_n;
dd->last_rounded_rate = _dpll_compute_new_rate(dd->clk_ref->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",
dd->last_rounded_rate, target_rate);
return dd->last_rounded_rate;
}

Просмотреть файл

@ -28,10 +28,7 @@
#include <plat/clockdomain.h>
#include <plat/cpu.h>
#include <plat/prcm.h>
#include <asm/div64.h>
#include <plat/sdrc.h>
#include "sdrc.h"
#include "clock.h"
#include "prm.h"
#include "prm-regbits-24xx.h"
@ -39,81 +36,66 @@
#include "cm-regbits-24xx.h"
#include "cm-regbits-34xx.h"
/* 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
/*
* 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))
/* DPLL valid Fint frequency band limits - from 34xx TRM Section 4.7.6.2 */
#define DPLL_FINT_BAND1_MIN 750000
#define DPLL_FINT_BAND1_MAX 2100000
#define DPLL_FINT_BAND2_MIN 7500000
#define DPLL_FINT_BAND2_MAX 21000000
/* _dpll_test_fint() return codes */
#define DPLL_FINT_UNDERFLOW -1
#define DPLL_FINT_INVALID -2
u8 cpu_mask;
/*-------------------------------------------------------------------------
* OMAP2/3/4 specific clock functions
*-------------------------------------------------------------------------*/
void omap2_init_dpll_parent(struct clk *clk)
{
u32 v;
struct dpll_data *dd;
dd = clk->dpll_data;
if (!dd)
return;
/* Return bypass rate if DPLL is bypassed */
v = __raw_readl(dd->control_reg);
v &= dd->enable_mask;
v >>= __ffs(dd->enable_mask);
/* Reparent in case the dpll is in bypass */
if (cpu_is_omap24xx()) {
if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
v == OMAP2XXX_EN_DPLL_FRBYPASS)
clk_reparent(clk, dd->clk_bypass);
} else if (cpu_is_omap34xx()) {
if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
v == OMAP3XXX_EN_DPLL_FRBYPASS)
clk_reparent(clk, dd->clk_bypass);
} else if (cpu_is_omap44xx()) {
if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
v == OMAP4XXX_EN_DPLL_FRBYPASS ||
v == OMAP4XXX_EN_DPLL_MNBYPASS)
clk_reparent(clk, dd->clk_bypass);
}
return;
}
/* Private functions */
/**
* _omap2xxx_clk_commit - commit clock parent/rate changes in hardware
* _omap2_module_wait_ready - wait for an OMAP module to leave IDLE
* @clk: struct clk * belonging to the module
*
* If the necessary clocks for the OMAP hardware IP block that
* corresponds to clock @clk are enabled, then wait for the module to
* indicate readiness (i.e., to leave IDLE). This code does not
* belong in the clock code and will be moved in the medium term to
* module-dependent code. No return value.
*/
static void _omap2_module_wait_ready(struct clk *clk)
{
void __iomem *companion_reg, *idlest_reg;
u8 other_bit, idlest_bit;
/* Not all modules have multiple clocks that their IDLEST depends on */
if (clk->ops->find_companion) {
clk->ops->find_companion(clk, &companion_reg, &other_bit);
if (!(__raw_readl(companion_reg) & (1 << other_bit)))
return;
}
clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit);
omap2_cm_wait_idlest(idlest_reg, (1 << idlest_bit), clk->name);
}
/* Enables clock without considering parent dependencies or use count
* REVISIT: Maybe change this to use clk->enable like on omap1?
*/
static int _omap2_clk_enable(struct clk *clk)
{
return clk->ops->enable(clk);
}
/* Disables clock without considering parent dependencies or use count */
static void _omap2_clk_disable(struct clk *clk)
{
clk->ops->disable(clk);
}
/* Public functions */
/**
* omap2xxx_clk_commit - commit clock parent/rate changes in hardware
* @clk: struct clk *
*
* If @clk has the DELAYED_APP flag set, meaning that parent/rate changes
* don't take effect until the VALID_CONFIG bit is written, write the
* VALID_CONFIG bit and wait for the write to complete. No return value.
*/
static void _omap2xxx_clk_commit(struct clk *clk)
void omap2xxx_clk_commit(struct clk *clk)
{
if (!cpu_is_omap24xx())
return;
@ -127,52 +109,6 @@ static void _omap2xxx_clk_commit(struct clk *clk)
prm_read_mod_reg(OMAP24XX_GR_MOD, OMAP2_PRCM_CLKCFG_CTRL_OFFSET);
}
/*
* _dpll_test_fint - test whether an Fint value is valid for the DPLL
* @clk: DPLL struct clk to test
* @n: divider value (N) to test
*
* Tests whether a particular divider @n will result in a valid DPLL
* internal clock frequency Fint. See the 34xx TRM 4.7.6.2 "DPLL Jitter
* Correction". Returns 0 if OK, -1 if the enclosing loop can terminate
* (assuming that it is counting N upwards), or -2 if the enclosing loop
* should skip to the next iteration (again assuming N is increasing).
*/
static int _dpll_test_fint(struct clk *clk, u8 n)
{
struct dpll_data *dd;
long fint;
int ret = 0;
dd = clk->dpll_data;
/* DPLL divider must result in a valid jitter correction val */
fint = clk->parent->rate / (n + 1);
if (fint < DPLL_FINT_BAND1_MIN) {
pr_debug("rejecting n=%d due to Fint failure, "
"lowering max_divider\n", n);
dd->max_divider = n;
ret = DPLL_FINT_UNDERFLOW;
} else if (fint > DPLL_FINT_BAND1_MAX &&
fint < DPLL_FINT_BAND2_MIN) {
pr_debug("rejecting n=%d due to Fint failure\n", n);
ret = DPLL_FINT_INVALID;
} else if (fint > DPLL_FINT_BAND2_MAX) {
pr_debug("rejecting n=%d due to Fint failure, "
"boosting min_divider\n", n);
dd->min_divider = n;
ret = DPLL_FINT_INVALID;
}
return ret;
}
/**
* omap2_init_clk_clkdm - look up a clockdomain name, store pointer in clk
* @clk: OMAP clock struct ptr to use
@ -181,7 +117,6 @@ static int _dpll_test_fint(struct clk *clk, u8 n)
* clockdomain pointer, and save it into the struct clk. Intended to be
* called during clk_register(). No return value.
*/
#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdm f/w is in place */
void omap2_init_clk_clkdm(struct clk *clk)
{
struct clockdomain *clkdm;
@ -199,117 +134,6 @@ void omap2_init_clk_clkdm(struct clk *clk)
"clkdm %s\n", clk->name, clk->clkdm_name);
}
}
#endif
/**
* omap2_init_clksel_parent - set a clksel clk's parent field from the hardware
* @clk: OMAP clock struct ptr to use
*
* Given a pointer to a source-selectable struct clk, read the hardware
* register and determine what its parent is currently set to. Update the
* clk->parent field with the appropriate clk ptr.
*/
void omap2_init_clksel_parent(struct clk *clk)
{
const struct clksel *clks;
const struct clksel_rate *clkr;
u32 r, found = 0;
if (!clk->clksel)
return;
r = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
r >>= __ffs(clk->clksel_mask);
for (clks = clk->clksel; clks->parent && !found; clks++) {
for (clkr = clks->rates; clkr->div && !found; clkr++) {
if ((clkr->flags & cpu_mask) && (clkr->val == r)) {
if (clk->parent != clks->parent) {
pr_debug("clock: inited %s parent "
"to %s (was %s)\n",
clk->name, clks->parent->name,
((clk->parent) ?
clk->parent->name : "NULL"));
clk_reparent(clk, clks->parent);
};
found = 1;
}
}
}
if (!found)
printk(KERN_ERR "clock: init parent: could not find "
"regval %0x for clock %s\n", r, clk->name);
return;
}
/**
* omap2_get_dpll_rate - returns the current DPLL CLKOUT rate
* @clk: struct clk * of a DPLL
*
* DPLLs can be locked or bypassed - basically, enabled or disabled.
* When locked, the DPLL output depends on the M and N values. When
* bypassed, on OMAP2xxx, the output rate is either the 32KiHz clock
* or sys_clk. Bypass rates on OMAP3 depend on the DPLL: DPLLs 1 and
* 2 are bypassed with dpll1_fclk and dpll2_fclk respectively
* (generated by DPLL3), while DPLL 3, 4, and 5 bypass rates are sys_clk.
* Returns the current DPLL CLKOUT rate (*not* CLKOUTX2) if the DPLL is
* locked, or the appropriate bypass rate if the DPLL is bypassed, or 0
* if the clock @clk is not a DPLL.
*/
u32 omap2_get_dpll_rate(struct clk *clk)
{
long long dpll_clk;
u32 dpll_mult, dpll_div, v;
struct dpll_data *dd;
dd = clk->dpll_data;
if (!dd)
return 0;
/* Return bypass rate if DPLL is bypassed */
v = __raw_readl(dd->control_reg);
v &= dd->enable_mask;
v >>= __ffs(dd->enable_mask);
if (cpu_is_omap24xx()) {
if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
v == OMAP2XXX_EN_DPLL_FRBYPASS)
return dd->clk_bypass->rate;
} else if (cpu_is_omap34xx()) {
if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
v == OMAP3XXX_EN_DPLL_FRBYPASS)
return dd->clk_bypass->rate;
} else if (cpu_is_omap44xx()) {
if (v == OMAP4XXX_EN_DPLL_LPBYPASS ||
v == OMAP4XXX_EN_DPLL_FRBYPASS ||
v == OMAP4XXX_EN_DPLL_MNBYPASS)
return dd->clk_bypass->rate;
}
v = __raw_readl(dd->mult_div1_reg);
dpll_mult = v & dd->mult_mask;
dpll_mult >>= __ffs(dd->mult_mask);
dpll_div = v & dd->div1_mask;
dpll_div >>= __ffs(dd->div1_mask);
dpll_clk = (long long)dd->clk_ref->rate * dpll_mult;
do_div(dpll_clk, dpll_div + 1);
return dpll_clk;
}
/*
* Used for clocks that have the same value as the parent clock,
* divided by some factor
*/
unsigned long omap2_fixed_divisor_recalc(struct clk *clk)
{
WARN_ON(!clk->fixed_div);
return clk->parent->rate / clk->fixed_div;
}
/**
* omap2_clk_dflt_find_companion - find companion clock to @clk
@ -370,33 +194,6 @@ void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
*idlest_bit = clk->enable_bit;
}
/**
* omap2_module_wait_ready - wait for an OMAP module to leave IDLE
* @clk: struct clk * belonging to the module
*
* If the necessary clocks for the OMAP hardware IP block that
* corresponds to clock @clk are enabled, then wait for the module to
* indicate readiness (i.e., to leave IDLE). This code does not
* belong in the clock code and will be moved in the medium term to
* module-dependent code. No return value.
*/
static void omap2_module_wait_ready(struct clk *clk)
{
void __iomem *companion_reg, *idlest_reg;
u8 other_bit, idlest_bit;
/* Not all modules have multiple clocks that their IDLEST depends on */
if (clk->ops->find_companion) {
clk->ops->find_companion(clk, &companion_reg, &other_bit);
if (!(__raw_readl(companion_reg) & (1 << other_bit)))
return;
}
clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit);
omap2_cm_wait_idlest(idlest_reg, (1 << idlest_bit), clk->name);
}
int omap2_dflt_clk_enable(struct clk *clk)
{
u32 v;
@ -416,7 +213,7 @@ int omap2_dflt_clk_enable(struct clk *clk)
v = __raw_readl(clk->enable_reg); /* OCP barrier */
if (clk->ops->find_idlest)
omap2_module_wait_ready(clk);
_omap2_module_wait_ready(clk);
return 0;
}
@ -456,30 +253,14 @@ const struct clkops clkops_omap2_dflt = {
.disable = omap2_dflt_clk_disable,
};
/* Enables clock without considering parent dependencies or use count
* REVISIT: Maybe change this to use clk->enable like on omap1?
*/
static int _omap2_clk_enable(struct clk *clk)
{
return clk->ops->enable(clk);
}
/* Disables clock without considering parent dependencies or use count */
static void _omap2_clk_disable(struct clk *clk)
{
clk->ops->disable(clk);
}
void omap2_clk_disable(struct clk *clk)
{
if (clk->usecount > 0 && !(--clk->usecount)) {
_omap2_clk_disable(clk);
if (clk->parent)
omap2_clk_disable(clk->parent);
#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdm f/w is in place */
if (clk->clkdm)
omap2_clkdm_clk_disable(clk->clkdm, clk);
#endif
}
}
@ -489,10 +270,8 @@ int omap2_clk_enable(struct clk *clk)
int ret = 0;
if (clk->usecount++ == 0) {
#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdm f/w is in place */
if (clk->clkdm)
omap2_clkdm_clk_enable(clk->clkdm, clk);
#endif
if (clk->parent) {
ret = omap2_clk_enable(clk->parent);
@ -511,282 +290,12 @@ int omap2_clk_enable(struct clk *clk)
return ret;
err:
#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdm f/w is in place */
if (clk->clkdm)
omap2_clkdm_clk_disable(clk->clkdm, clk);
#endif
clk->usecount--;
return ret;
}
/*
* Used for clocks that are part of CLKSEL_xyz governed clocks.
* REVISIT: Maybe change to use clk->enable() functions like on omap1?
*/
unsigned long omap2_clksel_recalc(struct clk *clk)
{
unsigned long rate;
u32 div = 0;
pr_debug("clock: recalc'ing clksel clk %s\n", clk->name);
div = omap2_clksel_get_divisor(clk);
if (div == 0)
return clk->rate;
rate = clk->parent->rate / div;
pr_debug("clock: new clock rate is %ld (div %d)\n", rate, div);
return rate;
}
/**
* omap2_get_clksel_by_parent - return clksel struct for a given clk & parent
* @clk: OMAP struct clk ptr to inspect
* @src_clk: OMAP struct clk ptr of the parent clk to search for
*
* Scan the struct clksel array associated with the clock to find
* the element associated with the supplied parent clock address.
* Returns a pointer to the struct clksel on success or NULL on error.
*/
static const struct clksel *omap2_get_clksel_by_parent(struct clk *clk,
struct clk *src_clk)
{
const struct clksel *clks;
if (!clk->clksel)
return NULL;
for (clks = clk->clksel; clks->parent; clks++) {
if (clks->parent == src_clk)
break; /* Found the requested parent */
}
if (!clks->parent) {
printk(KERN_ERR "clock: Could not find parent clock %s in "
"clksel array of clock %s\n", src_clk->name,
clk->name);
return NULL;
}
return clks;
}
/**
* omap2_clksel_round_rate_div - find divisor for the given clock and rate
* @clk: OMAP struct clk to use
* @target_rate: desired clock rate
* @new_div: ptr to where we should store the divisor
*
* Finds 'best' divider value in an array based on the source and target
* rates. The divider array must be sorted with smallest divider first.
* Note that this will not work for clocks which are part of CONFIG_PARTICIPANT,
* they are only settable as part of virtual_prcm set.
*
* Returns the rounded clock rate or returns 0xffffffff on error.
*/
u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
u32 *new_div)
{
unsigned long test_rate;
const struct clksel *clks;
const struct clksel_rate *clkr;
u32 last_div = 0;
pr_debug("clock: clksel_round_rate_div: %s target_rate %ld\n",
clk->name, target_rate);
*new_div = 1;
clks = omap2_get_clksel_by_parent(clk, clk->parent);
if (!clks)
return ~0;
for (clkr = clks->rates; clkr->div; clkr++) {
if (!(clkr->flags & cpu_mask))
continue;
/* Sanity check */
if (clkr->div <= last_div)
pr_err("clock: clksel_rate table not sorted "
"for clock %s", clk->name);
last_div = clkr->div;
test_rate = clk->parent->rate / clkr->div;
if (test_rate <= target_rate)
break; /* found it */
}
if (!clkr->div) {
pr_err("clock: Could not find divisor for target "
"rate %ld for clock %s parent %s\n", target_rate,
clk->name, clk->parent->name);
return ~0;
}
*new_div = clkr->div;
pr_debug("clock: new_div = %d, new_rate = %ld\n", *new_div,
(clk->parent->rate / clkr->div));
return (clk->parent->rate / clkr->div);
}
/**
* omap2_clksel_round_rate - find rounded rate for the given clock and rate
* @clk: OMAP struct clk to use
* @target_rate: desired clock rate
*
* Compatibility wrapper for OMAP clock framework
* Finds best target rate based on the source clock and possible dividers.
* rates. The divider array must be sorted with smallest divider first.
* Note that this will not work for clocks which are part of CONFIG_PARTICIPANT,
* they are only settable as part of virtual_prcm set.
*
* Returns the rounded clock rate or returns 0xffffffff on error.
*/
long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate)
{
u32 new_div;
return omap2_clksel_round_rate_div(clk, target_rate, &new_div);
}
/* Given a clock and a rate apply a clock specific rounding function */
long omap2_clk_round_rate(struct clk *clk, unsigned long rate)
{
if (clk->round_rate)
return clk->round_rate(clk, rate);
if (clk->flags & RATE_FIXED)
printk(KERN_ERR "clock: generic omap2_clk_round_rate called "
"on fixed-rate clock %s\n", clk->name);
return clk->rate;
}
/**
* omap2_clksel_to_divisor() - turn clksel field value into integer divider
* @clk: OMAP struct clk to use
* @field_val: register field value to find
*
* Given a struct clk of a rate-selectable clksel clock, and a register field
* value to search for, find the corresponding clock divisor. The register
* field value should be pre-masked and shifted down so the LSB is at bit 0
* before calling. Returns 0 on error
*/
u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val)
{
const struct clksel *clks;
const struct clksel_rate *clkr;
clks = omap2_get_clksel_by_parent(clk, clk->parent);
if (!clks)
return 0;
for (clkr = clks->rates; clkr->div; clkr++) {
if ((clkr->flags & cpu_mask) && (clkr->val == field_val))
break;
}
if (!clkr->div) {
printk(KERN_ERR "clock: Could not find fieldval %d for "
"clock %s parent %s\n", field_val, clk->name,
clk->parent->name);
return 0;
}
return clkr->div;
}
/**
* omap2_divisor_to_clksel() - turn clksel integer divisor into a field value
* @clk: OMAP struct clk to use
* @div: integer divisor to search for
*
* Given a struct clk of a rate-selectable clksel clock, and a clock divisor,
* find the corresponding register field value. The return register value is
* the value before left-shifting. Returns ~0 on error
*/
u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
{
const struct clksel *clks;
const struct clksel_rate *clkr;
/* should never happen */
WARN_ON(div == 0);
clks = omap2_get_clksel_by_parent(clk, clk->parent);
if (!clks)
return ~0;
for (clkr = clks->rates; clkr->div; clkr++) {
if ((clkr->flags & cpu_mask) && (clkr->div == div))
break;
}
if (!clkr->div) {
printk(KERN_ERR "clock: Could not find divisor %d for "
"clock %s parent %s\n", div, clk->name,
clk->parent->name);
return ~0;
}
return clkr->val;
}
/**
* omap2_clksel_get_divisor - get current divider applied to parent clock.
* @clk: OMAP struct clk to use.
*
* Returns the integer divisor upon success or 0 on error.
*/
u32 omap2_clksel_get_divisor(struct clk *clk)
{
u32 v;
if (!clk->clksel_mask)
return 0;
v = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
v >>= __ffs(clk->clksel_mask);
return omap2_clksel_to_divisor(clk, v);
}
int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
{
u32 v, field_val, validrate, new_div = 0;
if (!clk->clksel_mask)
return -EINVAL;
validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
if (validrate != rate)
return -EINVAL;
field_val = omap2_divisor_to_clksel(clk, new_div);
if (field_val == ~0)
return -EINVAL;
v = __raw_readl(clk->clksel_reg);
v &= ~clk->clksel_mask;
v |= field_val << __ffs(clk->clksel_mask);
__raw_writel(v, clk->clksel_reg);
v = __raw_readl(clk->clksel_reg); /* OCP barrier */
clk->rate = clk->parent->rate / new_div;
_omap2xxx_clk_commit(clk);
return 0;
}
/* Set the clock rate for a clock source */
int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
{
@ -806,265 +315,15 @@ int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
return ret;
}
/*
* Converts encoded control register address into a full address
* On error, the return value (parent_div) will be 0.
*/
static u32 _omap2_clksel_get_src_field(struct clk *src_clk, struct clk *clk,
u32 *field_val)
{
const struct clksel *clks;
const struct clksel_rate *clkr;
clks = omap2_get_clksel_by_parent(clk, src_clk);
if (!clks)
return 0;
for (clkr = clks->rates; clkr->div; clkr++) {
if (clkr->flags & cpu_mask && clkr->flags & DEFAULT_RATE)
break; /* Found the default rate for this platform */
}
if (!clkr->div) {
printk(KERN_ERR "clock: Could not find default rate for "
"clock %s parent %s\n", clk->name,
src_clk->parent->name);
return 0;
}
/* Should never happen. Add a clksel mask to the struct clk. */
WARN_ON(clk->clksel_mask == 0);
*field_val = clkr->val;
return clkr->div;
}
int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
{
u32 field_val, v, parent_div;
if (clk->flags & CONFIG_PARTICIPANT)
return -EINVAL;
if (!clk->clksel)
return -EINVAL;
parent_div = _omap2_clksel_get_src_field(new_parent, clk, &field_val);
if (!parent_div)
return -EINVAL;
/* Set new source value (previous dividers if any in effect) */
v = __raw_readl(clk->clksel_reg);
v &= ~clk->clksel_mask;
v |= field_val << __ffs(clk->clksel_mask);
__raw_writel(v, clk->clksel_reg);
v = __raw_readl(clk->clksel_reg); /* OCP barrier */
_omap2xxx_clk_commit(clk);
clk_reparent(clk, new_parent);
/* CLKSEL clocks follow their parents' rates, divided by a divisor */
clk->rate = new_parent->rate;
if (parent_div > 0)
clk->rate /= parent_div;
pr_debug("clock: set parent of %s to %s (new rate %ld)\n",
clk->name, clk->parent->name, clk->rate);
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 r = 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;
r = DPLL_MULT_UNDERFLOW;
}
if (*new_rate == 0)
*new_rate = _dpll_compute_new_rate(parent_rate, *m, n);
return r;
}
/**
* 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;
struct dpll_data *dd;
if (!clk || !clk->dpll_data)
return ~0;
dd = clk->dpll_data;
pr_debug("clock: starting DPLL round_rate for clock %s, target rate "
"%ld\n", clk->name, target_rate);
scaled_rt_rp = target_rate / (dd->clk_ref->rate / DPLL_SCALE_FACTOR);
scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR;
dd->last_rounded_rate = 0;
for (n = dd->min_divider; n <= dd->max_divider; n++) {
/* Is the (input clk, divider) pair valid for the DPLL? */
r = _dpll_test_fint(clk, n);
if (r == DPLL_FINT_UNDERFLOW)
break;
else if (r == DPLL_FINT_INVALID)
continue;
/* Compute the scaled DPLL multiplier, based on the divider */
m = scaled_rt_rp * n;
/*
* Since we're counting n up, a m overflow means we
* can bail out completely (since as n increases in
* the next iteration, there's no way that m can
* increase beyond the current m)
*/
if (m > scaled_max_m)
break;
r = _dpll_test_mult(&m, n, &new_rate, target_rate,
dd->clk_ref->rate);
/* m can't be set low enough for this n - try with a larger n */
if (r == DPLL_MULT_UNDERFLOW)
continue;
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) - dd->rate_tolerance)) {
min_e = e;
min_e_m = m;
min_e_n = n;
pr_debug("clock: found new least error %d\n", min_e);
/* We found good settings -- bail out now */
if (min_e <= dd->rate_tolerance)
break;
}
}
if (min_e < 0) {
pr_debug("clock: error: target rate or tolerance too low\n");
return ~0;
}
dd->last_rounded_m = min_e_m;
dd->last_rounded_n = min_e_n;
dd->last_rounded_rate = _dpll_compute_new_rate(dd->clk_ref->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",
dd->last_rounded_rate, target_rate);
return dd->last_rounded_rate;
return omap2_clksel_set_parent(clk, new_parent);
}
/*-------------------------------------------------------------------------
@ -1092,3 +351,20 @@ void omap2_clk_disable_unused(struct clk *clk)
pwrdm_clkdm_state_switch(clk->clkdm);
}
#endif
/* Common data */
struct clk_functions omap2_clk_functions = {
.clk_enable = omap2_clk_enable,
.clk_disable = omap2_clk_disable,
.clk_round_rate = omap2_clk_round_rate,
.clk_set_rate = omap2_clk_set_rate,
.clk_set_parent = omap2_clk_set_parent,
.clk_disable_unused = omap2_clk_disable_unused,
#ifdef CONFIG_CPU_FREQ
/* These will be removed when the OPP code is integrated */
.clk_init_cpufreq_table = omap2_clk_init_cpufreq_table,
.clk_exit_cpufreq_table = omap2_clk_exit_cpufreq_table,
#endif
};

Просмотреть файл

@ -47,7 +47,6 @@
#define DPLL_LOW_POWER_BYPASS 0x5
#define DPLL_LOCKED 0x7
int omap2_clk_init(void);
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);
@ -78,19 +77,19 @@ u32 omap2_clksel_round_rate_div(struct clk *clk, unsigned long target_rate,
u32 *new_div);
u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val);
u32 omap2_divisor_to_clksel(struct clk *clk, u32 div);
unsigned long omap2_fixed_divisor_recalc(struct clk *clk);
long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent);
u32 omap2_get_dpll_rate(struct clk *clk);
void omap2_init_dpll_parent(struct clk *clk);
int omap2_wait_clock_ready(void __iomem *reg, u32 cval, const char *name);
void omap2_clk_prepare_for_reboot(void);
int omap2_dflt_clk_enable(struct clk *clk);
void omap2_dflt_clk_disable(struct clk *clk);
void omap2_clk_dflt_find_companion(struct clk *clk, void __iomem **other_reg,
u8 *other_bit);
void omap2_clk_dflt_find_idlest(struct clk *clk, void __iomem **idlest_reg,
u8 *idlest_bit);
void omap2xxx_clk_commit(struct clk *clk);
extern u8 cpu_mask;
@ -104,5 +103,12 @@ extern const struct clksel_rate gpt_32k_rates[];
extern const struct clksel_rate gpt_sys_rates[];
extern const struct clksel_rate gfx_l3_rates[];
#if defined(CONFIG_ARCH_OMAP24XX) && defined(CONFIG_CPU_FREQ)
extern void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
#else
#define omap2_clk_init_cpufreq_table 0
#define omap2_clk_exit_cpufreq_table 0
#endif
#endif

Просмотреть файл

@ -1,15 +1,15 @@
/*
* linux/arch/arm/mach-omap2/clock.c
* clock2xxx.c - OMAP2xxx-specific clock integration code
*
* Copyright (C) 2005-2008 Texas Instruments, Inc.
* Copyright (C) 2004-2008 Nokia Corporation
* Copyright (C) 2005-2008 Texas Instruments, Inc.
* Copyright (C) 2004-2010 Nokia Corporation
*
* Contacts:
* Richard Woodruff <r-woodruff2@ti.com>
* Paul Walmsley
* Contacts:
* Richard Woodruff <r-woodruff2@ti.com>
* Paul Walmsley
*
* Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
* Gordon McNutt and RidgeRun, Inc.
* Based on earlier work by Tuukka Tikkanen, Tony Lindgren,
* Gordon McNutt and RidgeRun, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -17,55 +17,25 @@
*/
#undef DEBUG
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/cpufreq.h>
#include <linux/bitops.h>
#include <plat/clock.h>
#include <plat/sram.h>
#include <plat/prcm.h>
#include <plat/clkdev_omap.h>
#include <asm/div64.h>
#include <asm/clkdev.h>
#include <plat/sdrc.h>
#include "clock.h"
#include "clock2xxx.h"
#include "opp2xxx.h"
#include "prm.h"
#include "prm-regbits-24xx.h"
#include "cm.h"
#include "cm-regbits-24xx.h"
/* CM_CLKEN_PLL.EN_{54,96}M_PLL options (24XX) */
#define EN_APLL_STOPPED 0
#define EN_APLL_LOCKED 3
/* CM_CLKSEL1_PLL.APLLS_CLKIN options (24XX) */
#define APLLS_CLKIN_19_2MHZ 0
#define APLLS_CLKIN_13MHZ 2
#define APLLS_CLKIN_12MHZ 3
/* #define DOWN_VARIABLE_DPLL 1 */ /* Experimental */
const struct prcm_config *curr_prcm_set;
const struct prcm_config *rate_table;
struct clk *vclk, *sclk, *dclk;
void __iomem *prcm_clksrc_ctrl;
/*-------------------------------------------------------------------------
/*
* Omap24xx specific clock functions
*-------------------------------------------------------------------------*/
*/
#ifdef CONFIG_ARCH_OMAP2430
/**
* omap2430_clk_i2chs_find_idlest - return CM_IDLEST info for 2430 I2CHS
@ -86,6 +56,10 @@ static void omap2430_clk_i2chs_find_idlest(struct clk *clk,
*idlest_bit = clk->enable_bit;
}
#else
#define omap2430_clk_i2chs_find_idlest NULL
#endif
/* 2430 I2CHS has non-standard IDLEST register */
const struct clkops clkops_omap2430_i2chs_wait = {
.enable = omap2_dflt_clk_enable,
@ -94,491 +68,10 @@ const struct clkops clkops_omap2430_i2chs_wait = {
.find_companion = omap2_clk_dflt_find_companion,
};
/**
* omap2xxx_clk_get_core_rate - return the CORE_CLK rate
* @clk: pointer to the combined dpll_ck + core_ck (currently "dpll_ck")
*
* Returns the CORE_CLK rate. CORE_CLK can have one of three rate
* sources on OMAP2xxx: the DPLL CLKOUT rate, DPLL CLKOUTX2, or 32KHz
* (the latter is unusual). This currently should be called with
* struct clk *dpll_ck, which is a composite clock of dpll_ck and
* core_ck.
*/
unsigned long omap2xxx_clk_get_core_rate(struct clk *clk)
{
long long core_clk;
u32 v;
core_clk = omap2_get_dpll_rate(clk);
v = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
v &= OMAP24XX_CORE_CLK_SRC_MASK;
if (v == CORE_CLK_SRC_32K)
core_clk = 32768;
else
core_clk *= v;
return core_clk;
}
static int omap2_enable_osc_ck(struct clk *clk)
{
u32 pcc;
pcc = __raw_readl(prcm_clksrc_ctrl);
__raw_writel(pcc & ~OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl);
return 0;
}
static void omap2_disable_osc_ck(struct clk *clk)
{
u32 pcc;
pcc = __raw_readl(prcm_clksrc_ctrl);
__raw_writel(pcc | OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl);
}
const struct clkops clkops_oscck = {
.enable = omap2_enable_osc_ck,
.disable = omap2_disable_osc_ck,
};
#ifdef OLD_CK
/* Recalculate SYST_CLK */
static void omap2_sys_clk_recalc(struct clk *clk)
{
u32 div = PRCM_CLKSRC_CTRL;
div &= (1 << 7) | (1 << 6); /* Test if ext clk divided by 1 or 2 */
div >>= clk->rate_offset;
clk->rate = (clk->parent->rate / div);
propagate_rate(clk);
}
#endif /* OLD_CK */
/* Enable an APLL if off */
static int omap2_clk_apll_enable(struct clk *clk, u32 status_mask)
{
u32 cval, apll_mask;
apll_mask = EN_APLL_LOCKED << clk->enable_bit;
cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
if ((cval & apll_mask) == apll_mask)
return 0; /* apll already enabled */
cval &= ~apll_mask;
cval |= apll_mask;
cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
omap2_cm_wait_idlest(OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST), status_mask,
clk->name);
/*
* REVISIT: Should we return an error code if omap2_wait_clock_ready()
* fails?
*/
return 0;
}
static int omap2_clk_apll96_enable(struct clk *clk)
{
return omap2_clk_apll_enable(clk, OMAP24XX_ST_96M_APLL);
}
static int omap2_clk_apll54_enable(struct clk *clk)
{
return omap2_clk_apll_enable(clk, OMAP24XX_ST_54M_APLL);
}
/* Stop APLL */
static void omap2_clk_apll_disable(struct clk *clk)
{
u32 cval;
cval = cm_read_mod_reg(PLL_MOD, CM_CLKEN);
cval &= ~(EN_APLL_LOCKED << clk->enable_bit);
cm_write_mod_reg(cval, PLL_MOD, CM_CLKEN);
}
const struct clkops clkops_apll96 = {
.enable = omap2_clk_apll96_enable,
.disable = omap2_clk_apll_disable,
};
const struct clkops clkops_apll54 = {
.enable = omap2_clk_apll54_enable,
.disable = omap2_clk_apll_disable,
};
/*
* Uses the current prcm set to tell if a rate is valid.
* You can go slower, but not faster within a given rate set.
*/
long omap2_dpllcore_round_rate(unsigned long target_rate)
{
u32 high, low, core_clk_src;
core_clk_src = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
core_clk_src &= OMAP24XX_CORE_CLK_SRC_MASK;
if (core_clk_src == CORE_CLK_SRC_DPLL) { /* DPLL clockout */
high = curr_prcm_set->dpll_speed * 2;
low = curr_prcm_set->dpll_speed;
} else { /* DPLL clockout x 2 */
high = curr_prcm_set->dpll_speed;
low = curr_prcm_set->dpll_speed / 2;
}
#ifdef DOWN_VARIABLE_DPLL
if (target_rate > high)
return high;
else
return target_rate;
#else
if (target_rate > low)
return high;
else
return low;
#endif
}
unsigned long omap2_dpllcore_recalc(struct clk *clk)
{
return omap2xxx_clk_get_core_rate(clk);
}
int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
{
u32 cur_rate, low, mult, div, valid_rate, done_rate;
u32 bypass = 0;
struct prcm_config tmpset;
const struct dpll_data *dd;
cur_rate = omap2xxx_clk_get_core_rate(dclk);
mult = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
mult &= OMAP24XX_CORE_CLK_SRC_MASK;
if ((rate == (cur_rate / 2)) && (mult == 2)) {
omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
} else if ((rate == (cur_rate * 2)) && (mult == 1)) {
omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
} else if (rate != cur_rate) {
valid_rate = omap2_dpllcore_round_rate(rate);
if (valid_rate != rate)
return -EINVAL;
if (mult == 1)
low = curr_prcm_set->dpll_speed;
else
low = curr_prcm_set->dpll_speed / 2;
dd = clk->dpll_data;
if (!dd)
return -EINVAL;
tmpset.cm_clksel1_pll = __raw_readl(dd->mult_div1_reg);
tmpset.cm_clksel1_pll &= ~(dd->mult_mask |
dd->div1_mask);
div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
tmpset.cm_clksel2_pll = cm_read_mod_reg(PLL_MOD, CM_CLKSEL2);
tmpset.cm_clksel2_pll &= ~OMAP24XX_CORE_CLK_SRC_MASK;
if (rate > low) {
tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL_X2;
mult = ((rate / 2) / 1000000);
done_rate = CORE_CLK_SRC_DPLL_X2;
} else {
tmpset.cm_clksel2_pll |= CORE_CLK_SRC_DPLL;
mult = (rate / 1000000);
done_rate = CORE_CLK_SRC_DPLL;
}
tmpset.cm_clksel1_pll |= (div << __ffs(dd->mult_mask));
tmpset.cm_clksel1_pll |= (mult << __ffs(dd->div1_mask));
/* Worst case */
tmpset.base_sdrc_rfr = SDRC_RFR_CTRL_BYPASS;
if (rate == curr_prcm_set->xtal_speed) /* If asking for 1-1 */
bypass = 1;
/* For omap2xxx_sdrc_init_params() */
omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
/* Force dll lock mode */
omap2_set_prcm(tmpset.cm_clksel1_pll, tmpset.base_sdrc_rfr,
bypass);
/* Errata: ret dll entry state */
omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
omap2xxx_sdrc_reprogram(done_rate, 0);
}
return 0;
}
/**
* omap2_table_mpu_recalc - just return the MPU speed
* @clk: virt_prcm_set struct clk
*
* Set virt_prcm_set's rate to the mpu_speed field of the current PRCM set.
*/
unsigned long omap2_table_mpu_recalc(struct clk *clk)
{
return curr_prcm_set->mpu_speed;
}
/*
* Look for a rate equal or less than the target rate given a configuration set.
*
* What's not entirely clear is "which" field represents the key field.
* Some might argue L3-DDR, others ARM, others IVA. This code is simple and
* just uses the ARM rates.
*/
long omap2_round_to_table_rate(struct clk *clk, unsigned long rate)
{
const struct prcm_config *ptr;
long highest_rate;
long sys_ck_rate;
sys_ck_rate = clk_get_rate(sclk);
highest_rate = -EINVAL;
for (ptr = rate_table; ptr->mpu_speed; ptr++) {
if (!(ptr->flags & cpu_mask))
continue;
if (ptr->xtal_speed != sys_ck_rate)
continue;
highest_rate = ptr->mpu_speed;
/* Can check only after xtal frequency check */
if (ptr->mpu_speed <= rate)
break;
}
return highest_rate;
}
/* Sets basic clocks based on the specified rate */
int omap2_select_table_rate(struct clk *clk, unsigned long rate)
{
u32 cur_rate, done_rate, bypass = 0, tmp;
const struct prcm_config *prcm;
unsigned long found_speed = 0;
unsigned long flags;
long sys_ck_rate;
sys_ck_rate = clk_get_rate(sclk);
for (prcm = rate_table; prcm->mpu_speed; prcm++) {
if (!(prcm->flags & cpu_mask))
continue;
if (prcm->xtal_speed != sys_ck_rate)
continue;
if (prcm->mpu_speed <= rate) {
found_speed = prcm->mpu_speed;
break;
}
}
if (!found_speed) {
printk(KERN_INFO "Could not set MPU rate to %luMHz\n",
rate / 1000000);
return -EINVAL;
}
curr_prcm_set = prcm;
cur_rate = omap2xxx_clk_get_core_rate(dclk);
if (prcm->dpll_speed == cur_rate / 2) {
omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL, 1);
} else if (prcm->dpll_speed == cur_rate * 2) {
omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
} else if (prcm->dpll_speed != cur_rate) {
local_irq_save(flags);
if (prcm->dpll_speed == prcm->xtal_speed)
bypass = 1;
if ((prcm->cm_clksel2_pll & OMAP24XX_CORE_CLK_SRC_MASK) ==
CORE_CLK_SRC_DPLL_X2)
done_rate = CORE_CLK_SRC_DPLL_X2;
else
done_rate = CORE_CLK_SRC_DPLL;
/* MPU divider */
cm_write_mod_reg(prcm->cm_clksel_mpu, MPU_MOD, CM_CLKSEL);
/* dsp + iva1 div(2420), iva2.1(2430) */
cm_write_mod_reg(prcm->cm_clksel_dsp,
OMAP24XX_DSP_MOD, CM_CLKSEL);
cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL);
/* Major subsystem dividers */
tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK;
cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD,
CM_CLKSEL1);
if (cpu_is_omap2430())
cm_write_mod_reg(prcm->cm_clksel_mdm,
OMAP2430_MDM_MOD, CM_CLKSEL);
/* x2 to enter omap2xxx_sdrc_init_params() */
omap2xxx_sdrc_reprogram(CORE_CLK_SRC_DPLL_X2, 1);
omap2_set_prcm(prcm->cm_clksel1_pll, prcm->base_sdrc_rfr,
bypass);
omap2xxx_sdrc_init_params(omap2xxx_sdrc_dll_is_unlocked());
omap2xxx_sdrc_reprogram(done_rate, 0);
local_irq_restore(flags);
}
return 0;
}
#ifdef CONFIG_CPU_FREQ
/*
* Walk PRCM rate table and fillout cpufreq freq_table
* XXX This should be replaced by an OPP layer in the near future
*/
static struct cpufreq_frequency_table *freq_table;
void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
{
const struct prcm_config *prcm;
long sys_ck_rate;
int i = 0;
int tbl_sz = 0;
sys_ck_rate = clk_get_rate(sclk);
for (prcm = rate_table; prcm->mpu_speed; prcm++) {
if (!(prcm->flags & cpu_mask))
continue;
if (prcm->xtal_speed != sys_ck_rate)
continue;
/* don't put bypass rates in table */
if (prcm->dpll_speed == prcm->xtal_speed)
continue;
tbl_sz++;
}
/*
* XXX Ensure that we're doing what CPUFreq expects for this error
* case and the following one
*/
if (tbl_sz == 0) {
pr_warning("%s: no matching entries in rate_table\n",
__func__);
return;
}
/* Include the CPUFREQ_TABLE_END terminator entry */
tbl_sz++;
freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) * tbl_sz,
GFP_ATOMIC);
if (!freq_table) {
pr_err("%s: could not kzalloc frequency table\n", __func__);
return;
}
for (prcm = rate_table; prcm->mpu_speed; prcm++) {
if (!(prcm->flags & cpu_mask))
continue;
if (prcm->xtal_speed != sys_ck_rate)
continue;
/* don't put bypass rates in table */
if (prcm->dpll_speed == prcm->xtal_speed)
continue;
freq_table[i].index = i;
freq_table[i].frequency = prcm->mpu_speed / 1000;
i++;
}
freq_table[i].index = i;
freq_table[i].frequency = CPUFREQ_TABLE_END;
*table = &freq_table[0];
}
void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table)
{
kfree(freq_table);
}
#endif
struct clk_functions omap2_clk_functions = {
.clk_enable = omap2_clk_enable,
.clk_disable = omap2_clk_disable,
.clk_round_rate = omap2_clk_round_rate,
.clk_set_rate = omap2_clk_set_rate,
.clk_set_parent = omap2_clk_set_parent,
.clk_disable_unused = omap2_clk_disable_unused,
#ifdef CONFIG_CPU_FREQ
.clk_init_cpufreq_table = omap2_clk_init_cpufreq_table,
.clk_exit_cpufreq_table = omap2_clk_exit_cpufreq_table,
#endif
};
static u32 omap2_get_apll_clkin(void)
{
u32 aplls, srate = 0;
aplls = cm_read_mod_reg(PLL_MOD, CM_CLKSEL1);
aplls &= OMAP24XX_APLLS_CLKIN_MASK;
aplls >>= OMAP24XX_APLLS_CLKIN_SHIFT;
if (aplls == APLLS_CLKIN_19_2MHZ)
srate = 19200000;
else if (aplls == APLLS_CLKIN_13MHZ)
srate = 13000000;
else if (aplls == APLLS_CLKIN_12MHZ)
srate = 12000000;
return srate;
}
static u32 omap2_get_sysclkdiv(void)
{
u32 div;
div = __raw_readl(prcm_clksrc_ctrl);
div &= OMAP_SYSCLKDIV_MASK;
div >>= OMAP_SYSCLKDIV_SHIFT;
return div;
}
unsigned long omap2_osc_clk_recalc(struct clk *clk)
{
return omap2_get_apll_clkin() * omap2_get_sysclkdiv();
}
unsigned long omap2_sys_clk_recalc(struct clk *clk)
{
return clk->parent->rate / omap2_get_sysclkdiv();
}
/*
* Set clocks for bypass mode for reboot to work.
*/
void omap2_clk_prepare_for_reboot(void)
void omap2xxx_clk_prepare_for_reboot(void)
{
u32 rate;
@ -593,11 +86,14 @@ void omap2_clk_prepare_for_reboot(void)
* Switch the MPU rate if specified on cmdline.
* We cannot do this early until cmdline is parsed.
*/
static int __init omap2_clk_arch_init(void)
static int __init omap2xxx_clk_arch_init(void)
{
struct clk *virt_prcm_set, *sys_ck, *dpll_ck, *mpu_ck;
unsigned long sys_ck_rate;
if (!cpu_is_omap24xx())
return 0;
if (!mpurate)
return -EINVAL;
@ -621,6 +117,6 @@ static int __init omap2_clk_arch_init(void)
return 0;
}
arch_initcall(omap2_clk_arch_init);
arch_initcall(omap2xxx_clk_arch_init);

Просмотреть файл

@ -11,12 +11,15 @@
unsigned long omap2_table_mpu_recalc(struct clk *clk);
int omap2_select_table_rate(struct clk *clk, unsigned long rate);
long omap2_round_to_table_rate(struct clk *clk, unsigned long rate);
unsigned long omap2_sys_clk_recalc(struct clk *clk);
unsigned long omap2xxx_sys_clk_recalc(struct clk *clk);
unsigned long omap2_osc_clk_recalc(struct clk *clk);
unsigned long omap2_sys_clk_recalc(struct clk *clk);
unsigned long omap2_dpllcore_recalc(struct clk *clk);
int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate);
unsigned long omap2xxx_clk_get_core_rate(struct clk *clk);
u32 omap2xxx_get_apll_clkin(void);
u32 omap2xxx_get_sysclkdiv(void);
void omap2xxx_clk_prepare_for_reboot(void);
int omap2xxx_clk_init(void);
/* REVISIT: These should be set dynamically for CONFIG_MULTI_OMAP2 */
#ifdef CONFIG_ARCH_OMAP2420

Просмотреть файл

@ -79,7 +79,7 @@ static struct clk sys_ck = { /* (*12, *13, 19.2, 26, 38.4)MHz */
.ops = &clkops_null,
.parent = &osc_ck,
.clkdm_name = "wkup_clkdm",
.recalc = &omap2_sys_clk_recalc,
.recalc = &omap2xxx_sys_clk_recalc,
};
static struct clk alt_ck = { /* Typical 54M or 48M, may not exist */
@ -261,7 +261,7 @@ static struct clk func_12m_ck = {
.parent = &func_48m_ck,
.fixed_div = 4,
.clkdm_name = "wkup_clkdm",
.recalc = &omap2_fixed_divisor_recalc,
.recalc = &omap_fixed_divisor_recalc,
};
/* Secure timer, only available in secure mode */
@ -557,7 +557,7 @@ static struct clk iva1_mpu_int_ifck = {
.enable_reg = OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
.enable_bit = OMAP2420_EN_IVA_MPU_SHIFT,
.fixed_div = 2,
.recalc = &omap2_fixed_divisor_recalc,
.recalc = &omap_fixed_divisor_recalc,
};
/*
@ -2238,7 +2238,7 @@ static struct omap_clk omap24xx_clks[] = {
* init code
*/
int __init omap2_clk_init(void)
int __init omap2xxx_clk_init(void)
{
const struct prcm_config *prcm;
struct omap_clk *c;
@ -2264,7 +2264,7 @@ int __init omap2_clk_init(void)
osc_ck.rate = omap2_osc_clk_recalc(&osc_ck);
propagate_rate(&osc_ck);
sys_ck.rate = omap2_sys_clk_recalc(&sys_ck);
sys_ck.rate = omap2xxx_sys_clk_recalc(&sys_ck);
propagate_rate(&sys_ck);
for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++)

Просмотреть файл

@ -2,10 +2,10 @@
* OMAP3-specific clock framework functions
*
* Copyright (C) 2007-2008 Texas Instruments, Inc.
* Copyright (C) 2007-2009 Nokia Corporation
* Copyright (C) 2007-2010 Nokia Corporation
*
* Written by Paul Walmsley
* Testing and integration fixes by Jouni Högander
* Paul Walmsley
* Jouni Högander
*
* Parts of this code are based on code written by
* Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu
@ -16,34 +16,22 @@
*/
#undef DEBUG
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/limits.h>
#include <linux/bitops.h>
#include <plat/cpu.h>
#include <plat/clock.h>
#include <plat/sram.h>
#include <plat/sdrc.h>
#include <asm/div64.h>
#include <asm/clkdev.h>
#include "clock.h"
#include "clock34xx.h"
#include "sdrc.h"
#include "prm.h"
#include "prm-regbits-34xx.h"
#include "cm.h"
#include "cm-regbits-34xx.h"
#define CYCLES_PER_MHZ 1000000
/*
* DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
* that are sourced by DPLL5, and both of these require this clock
@ -162,129 +150,7 @@ int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate)
return omap3_noncore_dpll_set_rate(clk, rate);
}
/*
* CORE DPLL (DPLL3) rate programming functions
*
* These call into SRAM code to do the actual CM writes, since the SDRAM
* is clocked from DPLL3.
*/
/**
* omap3_core_dpll_m2_set_rate - set CORE DPLL M2 divider
* @clk: struct clk * of DPLL to set
* @rate: rounded target rate
*
* Program the DPLL M2 divider with the rounded target rate. Returns
* -EINVAL upon error, or 0 upon success.
*/
int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate)
{
u32 new_div = 0;
u32 unlock_dll = 0;
u32 c;
unsigned long validrate, sdrcrate, _mpurate;
struct omap_sdrc_params *sdrc_cs0;
struct omap_sdrc_params *sdrc_cs1;
int ret;
if (!clk || !rate)
return -EINVAL;
validrate = omap2_clksel_round_rate_div(clk, rate, &new_div);
if (validrate != rate)
return -EINVAL;
sdrcrate = sdrc_ick_p->rate;
if (rate > clk->rate)
sdrcrate <<= ((rate / clk->rate) >> 1);
else
sdrcrate >>= ((clk->rate / rate) >> 1);
ret = omap2_sdrc_get_params(sdrcrate, &sdrc_cs0, &sdrc_cs1);
if (ret)
return -EINVAL;
if (sdrcrate < MIN_SDRC_DLL_LOCK_FREQ) {
pr_debug("clock: will unlock SDRC DLL\n");
unlock_dll = 1;
}
/*
* XXX This only needs to be done when the CPU frequency changes
*/
_mpurate = arm_fck_p->rate / CYCLES_PER_MHZ;
c = (_mpurate << SDRC_MPURATE_SCALE) >> SDRC_MPURATE_BASE_SHIFT;
c += 1; /* for safety */
c *= SDRC_MPURATE_LOOPS;
c >>= SDRC_MPURATE_SCALE;
if (c == 0)
c = 1;
pr_debug("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate,
validrate);
pr_debug("clock: SDRC CS0 timing params used:"
" RFR %08x CTRLA %08x CTRLB %08x MR %08x\n",
sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
sdrc_cs0->actim_ctrlb, sdrc_cs0->mr);
if (sdrc_cs1)
pr_debug("clock: SDRC CS1 timing params used: "
" RFR %08x CTRLA %08x CTRLB %08x MR %08x\n",
sdrc_cs1->rfr_ctrl, sdrc_cs1->actim_ctrla,
sdrc_cs1->actim_ctrlb, sdrc_cs1->mr);
if (sdrc_cs1)
omap3_configure_core_dpll(
new_div, unlock_dll, c, rate > clk->rate,
sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
sdrc_cs0->actim_ctrlb, sdrc_cs0->mr,
sdrc_cs1->rfr_ctrl, sdrc_cs1->actim_ctrla,
sdrc_cs1->actim_ctrlb, sdrc_cs1->mr);
else
omap3_configure_core_dpll(
new_div, unlock_dll, c, rate > clk->rate,
sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
sdrc_cs0->actim_ctrlb, sdrc_cs0->mr,
0, 0, 0, 0);
return 0;
}
/* Common clock code */
/*
* As it is structured now, this will prevent an OMAP2/3 multiboot
* kernel from compiling. This will need further attention.
*/
#if defined(CONFIG_ARCH_OMAP3)
struct clk_functions omap2_clk_functions = {
.clk_enable = omap2_clk_enable,
.clk_disable = omap2_clk_disable,
.clk_round_rate = omap2_clk_round_rate,
.clk_set_rate = omap2_clk_set_rate,
.clk_set_parent = omap2_clk_set_parent,
.clk_disable_unused = omap2_clk_disable_unused,
};
/*
* Set clocks for bypass mode for reboot to work.
*/
void omap2_clk_prepare_for_reboot(void)
{
/* REVISIT: Not ready for 343x */
#if 0
u32 rate;
if (vclk == NULL || sclk == NULL)
return;
rate = clk_get_rate(sclk);
clk_set_rate(vclk, rate);
#endif
}
void omap3_clk_lock_dpll5(void)
void __init omap3_clk_lock_dpll5(void)
{
struct clk *dpll5_clk;
struct clk *dpll5_m2_clk;
@ -306,17 +172,22 @@ void omap3_clk_lock_dpll5(void)
return;
}
/* Common clock code */
/* REVISIT: Move this init stuff out into clock.c */
/*
* Switch the MPU rate if specified on cmdline.
* We cannot do this early until cmdline is parsed.
*/
static int __init omap2_clk_arch_init(void)
static int __init omap3xxx_clk_arch_init(void)
{
struct clk *osc_sys_ck, *dpll1_ck, *arm_fck, *core_ck;
unsigned long osc_sys_rate;
if (!cpu_is_omap34xx())
return 0;
if (!mpurate)
return -EINVAL;
@ -345,9 +216,6 @@ static int __init omap2_clk_arch_init(void)
return 0;
}
arch_initcall(omap2_clk_arch_init);
#endif
arch_initcall(omap3xxx_clk_arch_init);

Просмотреть файл

@ -8,6 +8,7 @@
#ifndef __ARCH_ARM_MACH_OMAP2_CLOCK_34XX_H
#define __ARCH_ARM_MACH_OMAP2_CLOCK_34XX_H
int omap3xxx_clk_init(void);
int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate);
int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate);
void omap3_clk_lock_dpll5(void);

Просмотреть файл

@ -735,7 +735,7 @@ static struct clk omap_12m_fck = {
.ops = &clkops_null,
.parent = &omap_48m_fck,
.fixed_div = 4,
.recalc = &omap2_fixed_divisor_recalc,
.recalc = &omap_fixed_divisor_recalc,
};
/* This virstual clock is the source for dpll4_m4x2_ck */
@ -1588,7 +1588,7 @@ static struct clk ssi_sst_fck_3430es1 = {
.ops = &clkops_null,
.parent = &ssi_ssr_fck_3430es1,
.fixed_div = 2,
.recalc = &omap2_fixed_divisor_recalc,
.recalc = &omap_fixed_divisor_recalc,
};
static struct clk ssi_sst_fck_3430es2 = {
@ -1596,7 +1596,7 @@ static struct clk ssi_sst_fck_3430es2 = {
.ops = &clkops_null,
.parent = &ssi_ssr_fck_3430es2,
.fixed_div = 2,
.recalc = &omap2_fixed_divisor_recalc,
.recalc = &omap_fixed_divisor_recalc,
};
@ -2988,139 +2988,140 @@ static struct clk wdt1_fck = {
* clkdev
*/
static struct omap_clk omap34xx_clks[] = {
CLK(NULL, "omap_32k_fck", &omap_32k_fck, CK_343X),
CLK(NULL, "virt_12m_ck", &virt_12m_ck, CK_343X),
CLK(NULL, "virt_13m_ck", &virt_13m_ck, CK_343X),
CLK(NULL, "virt_16_8m_ck", &virt_16_8m_ck, CK_3430ES2),
CLK(NULL, "virt_19_2m_ck", &virt_19_2m_ck, CK_343X),
CLK(NULL, "virt_26m_ck", &virt_26m_ck, CK_343X),
CLK(NULL, "virt_38_4m_ck", &virt_38_4m_ck, CK_343X),
CLK(NULL, "osc_sys_ck", &osc_sys_ck, CK_343X),
CLK(NULL, "sys_ck", &sys_ck, CK_343X),
CLK(NULL, "sys_altclk", &sys_altclk, CK_343X),
CLK(NULL, "mcbsp_clks", &mcbsp_clks, CK_343X),
CLK(NULL, "sys_clkout1", &sys_clkout1, CK_343X),
CLK(NULL, "dpll1_ck", &dpll1_ck, CK_343X),
CLK(NULL, "dpll1_x2_ck", &dpll1_x2_ck, CK_343X),
CLK(NULL, "dpll1_x2m2_ck", &dpll1_x2m2_ck, CK_343X),
/* XXX At some point we should rename this file to clock3xxx_data.c */
static struct omap_clk omap3xxx_clks[] = {
CLK(NULL, "omap_32k_fck", &omap_32k_fck, CK_3XXX),
CLK(NULL, "virt_12m_ck", &virt_12m_ck, CK_3XXX),
CLK(NULL, "virt_13m_ck", &virt_13m_ck, CK_3XXX),
CLK(NULL, "virt_16_8m_ck", &virt_16_8m_ck, CK_3430ES2 | CK_AM35XX),
CLK(NULL, "virt_19_2m_ck", &virt_19_2m_ck, CK_3XXX),
CLK(NULL, "virt_26m_ck", &virt_26m_ck, CK_3XXX),
CLK(NULL, "virt_38_4m_ck", &virt_38_4m_ck, CK_3XXX),
CLK(NULL, "osc_sys_ck", &osc_sys_ck, CK_3XXX),
CLK(NULL, "sys_ck", &sys_ck, CK_3XXX),
CLK(NULL, "sys_altclk", &sys_altclk, CK_3XXX),
CLK(NULL, "mcbsp_clks", &mcbsp_clks, CK_3XXX),
CLK(NULL, "sys_clkout1", &sys_clkout1, CK_3XXX),
CLK(NULL, "dpll1_ck", &dpll1_ck, CK_3XXX),
CLK(NULL, "dpll1_x2_ck", &dpll1_x2_ck, CK_3XXX),
CLK(NULL, "dpll1_x2m2_ck", &dpll1_x2m2_ck, CK_3XXX),
CLK(NULL, "dpll2_ck", &dpll2_ck, CK_343X),
CLK(NULL, "dpll2_m2_ck", &dpll2_m2_ck, CK_343X),
CLK(NULL, "dpll3_ck", &dpll3_ck, CK_343X),
CLK(NULL, "core_ck", &core_ck, CK_343X),
CLK(NULL, "dpll3_x2_ck", &dpll3_x2_ck, CK_343X),
CLK(NULL, "dpll3_m2_ck", &dpll3_m2_ck, CK_343X),
CLK(NULL, "dpll3_m2x2_ck", &dpll3_m2x2_ck, CK_343X),
CLK(NULL, "dpll3_m3_ck", &dpll3_m3_ck, CK_343X),
CLK(NULL, "dpll3_m3x2_ck", &dpll3_m3x2_ck, CK_343X),
CLK("etb", "emu_core_alwon_ck", &emu_core_alwon_ck, CK_343X),
CLK(NULL, "dpll4_ck", &dpll4_ck, CK_343X),
CLK(NULL, "dpll4_x2_ck", &dpll4_x2_ck, CK_343X),
CLK(NULL, "omap_96m_alwon_fck", &omap_96m_alwon_fck, CK_343X),
CLK(NULL, "omap_96m_fck", &omap_96m_fck, CK_343X),
CLK(NULL, "cm_96m_fck", &cm_96m_fck, CK_343X),
CLK(NULL, "omap_54m_fck", &omap_54m_fck, CK_343X),
CLK(NULL, "omap_48m_fck", &omap_48m_fck, CK_343X),
CLK(NULL, "omap_12m_fck", &omap_12m_fck, CK_343X),
CLK(NULL, "dpll4_m2_ck", &dpll4_m2_ck, CK_343X),
CLK(NULL, "dpll4_m2x2_ck", &dpll4_m2x2_ck, CK_343X),
CLK(NULL, "dpll4_m3_ck", &dpll4_m3_ck, CK_343X),
CLK(NULL, "dpll4_m3x2_ck", &dpll4_m3x2_ck, CK_343X),
CLK(NULL, "dpll4_m4_ck", &dpll4_m4_ck, CK_343X),
CLK(NULL, "dpll4_m4x2_ck", &dpll4_m4x2_ck, CK_343X),
CLK(NULL, "dpll4_m5_ck", &dpll4_m5_ck, CK_343X),
CLK(NULL, "dpll4_m5x2_ck", &dpll4_m5x2_ck, CK_343X),
CLK(NULL, "dpll4_m6_ck", &dpll4_m6_ck, CK_343X),
CLK(NULL, "dpll4_m6x2_ck", &dpll4_m6x2_ck, CK_343X),
CLK("etb", "emu_per_alwon_ck", &emu_per_alwon_ck, CK_343X),
CLK(NULL, "dpll5_ck", &dpll5_ck, CK_3430ES2),
CLK(NULL, "dpll5_m2_ck", &dpll5_m2_ck, CK_3430ES2),
CLK(NULL, "clkout2_src_ck", &clkout2_src_ck, CK_343X),
CLK(NULL, "sys_clkout2", &sys_clkout2, CK_343X),
CLK(NULL, "corex2_fck", &corex2_fck, CK_343X),
CLK(NULL, "dpll1_fck", &dpll1_fck, CK_343X),
CLK(NULL, "mpu_ck", &mpu_ck, CK_343X),
CLK(NULL, "arm_fck", &arm_fck, CK_343X),
CLK("etb", "emu_mpu_alwon_ck", &emu_mpu_alwon_ck, CK_343X),
CLK(NULL, "dpll3_ck", &dpll3_ck, CK_3XXX),
CLK(NULL, "core_ck", &core_ck, CK_3XXX),
CLK(NULL, "dpll3_x2_ck", &dpll3_x2_ck, CK_3XXX),
CLK(NULL, "dpll3_m2_ck", &dpll3_m2_ck, CK_3XXX),
CLK(NULL, "dpll3_m2x2_ck", &dpll3_m2x2_ck, CK_3XXX),
CLK(NULL, "dpll3_m3_ck", &dpll3_m3_ck, CK_3XXX),
CLK(NULL, "dpll3_m3x2_ck", &dpll3_m3x2_ck, CK_3XXX),
CLK("etb", "emu_core_alwon_ck", &emu_core_alwon_ck, CK_3XXX),
CLK(NULL, "dpll4_ck", &dpll4_ck, CK_3XXX),
CLK(NULL, "dpll4_x2_ck", &dpll4_x2_ck, CK_3XXX),
CLK(NULL, "omap_96m_alwon_fck", &omap_96m_alwon_fck, CK_3XXX),
CLK(NULL, "omap_96m_fck", &omap_96m_fck, CK_3XXX),
CLK(NULL, "cm_96m_fck", &cm_96m_fck, CK_3XXX),
CLK(NULL, "omap_54m_fck", &omap_54m_fck, CK_3XXX),
CLK(NULL, "omap_48m_fck", &omap_48m_fck, CK_3XXX),
CLK(NULL, "omap_12m_fck", &omap_12m_fck, CK_3XXX),
CLK(NULL, "dpll4_m2_ck", &dpll4_m2_ck, CK_3XXX),
CLK(NULL, "dpll4_m2x2_ck", &dpll4_m2x2_ck, CK_3XXX),
CLK(NULL, "dpll4_m3_ck", &dpll4_m3_ck, CK_3XXX),
CLK(NULL, "dpll4_m3x2_ck", &dpll4_m3x2_ck, CK_3XXX),
CLK(NULL, "dpll4_m4_ck", &dpll4_m4_ck, CK_3XXX),
CLK(NULL, "dpll4_m4x2_ck", &dpll4_m4x2_ck, CK_3XXX),
CLK(NULL, "dpll4_m5_ck", &dpll4_m5_ck, CK_3XXX),
CLK(NULL, "dpll4_m5x2_ck", &dpll4_m5x2_ck, CK_3XXX),
CLK(NULL, "dpll4_m6_ck", &dpll4_m6_ck, CK_3XXX),
CLK(NULL, "dpll4_m6x2_ck", &dpll4_m6x2_ck, CK_3XXX),
CLK("etb", "emu_per_alwon_ck", &emu_per_alwon_ck, CK_3XXX),
CLK(NULL, "dpll5_ck", &dpll5_ck, CK_3430ES2 | CK_AM35XX),
CLK(NULL, "dpll5_m2_ck", &dpll5_m2_ck, CK_3430ES2 | CK_AM35XX),
CLK(NULL, "clkout2_src_ck", &clkout2_src_ck, CK_3XXX),
CLK(NULL, "sys_clkout2", &sys_clkout2, CK_3XXX),
CLK(NULL, "corex2_fck", &corex2_fck, CK_3XXX),
CLK(NULL, "dpll1_fck", &dpll1_fck, CK_3XXX),
CLK(NULL, "mpu_ck", &mpu_ck, CK_3XXX),
CLK(NULL, "arm_fck", &arm_fck, CK_3XXX),
CLK("etb", "emu_mpu_alwon_ck", &emu_mpu_alwon_ck, CK_3XXX),
CLK(NULL, "dpll2_fck", &dpll2_fck, CK_343X),
CLK(NULL, "iva2_ck", &iva2_ck, CK_343X),
CLK(NULL, "l3_ick", &l3_ick, CK_343X),
CLK(NULL, "l4_ick", &l4_ick, CK_343X),
CLK(NULL, "rm_ick", &rm_ick, CK_343X),
CLK(NULL, "l3_ick", &l3_ick, CK_3XXX),
CLK(NULL, "l4_ick", &l4_ick, CK_3XXX),
CLK(NULL, "rm_ick", &rm_ick, CK_3XXX),
CLK(NULL, "gfx_l3_ck", &gfx_l3_ck, CK_3430ES1),
CLK(NULL, "gfx_l3_fck", &gfx_l3_fck, CK_3430ES1),
CLK(NULL, "gfx_l3_ick", &gfx_l3_ick, CK_3430ES1),
CLK(NULL, "gfx_cg1_ck", &gfx_cg1_ck, CK_3430ES1),
CLK(NULL, "gfx_cg2_ck", &gfx_cg2_ck, CK_3430ES1),
CLK(NULL, "sgx_fck", &sgx_fck, CK_3430ES2),
CLK(NULL, "sgx_ick", &sgx_ick, CK_3430ES2),
CLK(NULL, "sgx_fck", &sgx_fck, CK_3430ES2 | CK_3517),
CLK(NULL, "sgx_ick", &sgx_ick, CK_3430ES2 | CK_3517),
CLK(NULL, "d2d_26m_fck", &d2d_26m_fck, CK_3430ES1),
CLK(NULL, "modem_fck", &modem_fck, CK_343X),
CLK(NULL, "sad2d_ick", &sad2d_ick, CK_343X),
CLK(NULL, "mad2d_ick", &mad2d_ick, CK_343X),
CLK(NULL, "gpt10_fck", &gpt10_fck, CK_343X),
CLK(NULL, "gpt11_fck", &gpt11_fck, CK_343X),
CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2),
CLK(NULL, "ts_fck", &ts_fck, CK_3430ES2),
CLK(NULL, "usbtll_fck", &usbtll_fck, CK_3430ES2),
CLK(NULL, "core_96m_fck", &core_96m_fck, CK_343X),
CLK("mmci-omap-hs.2", "fck", &mmchs3_fck, CK_3430ES2),
CLK("mmci-omap-hs.1", "fck", &mmchs2_fck, CK_343X),
CLK(NULL, "gpt10_fck", &gpt10_fck, CK_3XXX),
CLK(NULL, "gpt11_fck", &gpt11_fck, CK_3XXX),
CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2 | CK_AM35XX),
CLK(NULL, "ts_fck", &ts_fck, CK_3430ES2 | CK_AM35XX),
CLK(NULL, "usbtll_fck", &usbtll_fck, CK_3430ES2 | CK_AM35XX),
CLK(NULL, "core_96m_fck", &core_96m_fck, CK_3XXX),
CLK("mmci-omap-hs.2", "fck", &mmchs3_fck, CK_3430ES2 | CK_AM35XX),
CLK("mmci-omap-hs.1", "fck", &mmchs2_fck, CK_3XXX),
CLK(NULL, "mspro_fck", &mspro_fck, CK_343X),
CLK("mmci-omap-hs.0", "fck", &mmchs1_fck, CK_343X),
CLK("i2c_omap.3", "fck", &i2c3_fck, CK_343X),
CLK("i2c_omap.2", "fck", &i2c2_fck, CK_343X),
CLK("i2c_omap.1", "fck", &i2c1_fck, CK_343X),
CLK("omap-mcbsp.5", "fck", &mcbsp5_fck, CK_343X),
CLK("omap-mcbsp.1", "fck", &mcbsp1_fck, CK_343X),
CLK(NULL, "core_48m_fck", &core_48m_fck, CK_343X),
CLK("omap2_mcspi.4", "fck", &mcspi4_fck, CK_343X),
CLK("omap2_mcspi.3", "fck", &mcspi3_fck, CK_343X),
CLK("omap2_mcspi.2", "fck", &mcspi2_fck, CK_343X),
CLK("omap2_mcspi.1", "fck", &mcspi1_fck, CK_343X),
CLK(NULL, "uart2_fck", &uart2_fck, CK_343X),
CLK(NULL, "uart1_fck", &uart1_fck, CK_343X),
CLK("mmci-omap-hs.0", "fck", &mmchs1_fck, CK_3XXX),
CLK("i2c_omap.3", "fck", &i2c3_fck, CK_3XXX),
CLK("i2c_omap.2", "fck", &i2c2_fck, CK_3XXX),
CLK("i2c_omap.1", "fck", &i2c1_fck, CK_3XXX),
CLK("omap-mcbsp.5", "fck", &mcbsp5_fck, CK_3XXX),
CLK("omap-mcbsp.1", "fck", &mcbsp1_fck, CK_3XXX),
CLK(NULL, "core_48m_fck", &core_48m_fck, CK_3XXX),
CLK("omap2_mcspi.4", "fck", &mcspi4_fck, CK_3XXX),
CLK("omap2_mcspi.3", "fck", &mcspi3_fck, CK_3XXX),
CLK("omap2_mcspi.2", "fck", &mcspi2_fck, CK_3XXX),
CLK("omap2_mcspi.1", "fck", &mcspi1_fck, CK_3XXX),
CLK(NULL, "uart2_fck", &uart2_fck, CK_3XXX),
CLK(NULL, "uart1_fck", &uart1_fck, CK_3XXX),
CLK(NULL, "fshostusb_fck", &fshostusb_fck, CK_3430ES1),
CLK(NULL, "core_12m_fck", &core_12m_fck, CK_343X),
CLK("omap_hdq.0", "fck", &hdq_fck, CK_343X),
CLK(NULL, "core_12m_fck", &core_12m_fck, CK_3XXX),
CLK("omap_hdq.0", "fck", &hdq_fck, CK_3XXX),
CLK(NULL, "ssi_ssr_fck", &ssi_ssr_fck_3430es1, CK_3430ES1),
CLK(NULL, "ssi_ssr_fck", &ssi_ssr_fck_3430es2, CK_3430ES2),
CLK(NULL, "ssi_sst_fck", &ssi_sst_fck_3430es1, CK_3430ES1),
CLK(NULL, "ssi_sst_fck", &ssi_sst_fck_3430es2, CK_3430ES2),
CLK(NULL, "core_l3_ick", &core_l3_ick, CK_343X),
CLK(NULL, "core_l3_ick", &core_l3_ick, CK_3XXX),
CLK("musb_hdrc", "ick", &hsotgusb_ick_3430es1, CK_3430ES1),
CLK("musb_hdrc", "ick", &hsotgusb_ick_3430es2, CK_3430ES2),
CLK(NULL, "sdrc_ick", &sdrc_ick, CK_343X),
CLK(NULL, "gpmc_fck", &gpmc_fck, CK_343X),
CLK(NULL, "sdrc_ick", &sdrc_ick, CK_3XXX),
CLK(NULL, "gpmc_fck", &gpmc_fck, CK_3XXX),
CLK(NULL, "security_l3_ick", &security_l3_ick, CK_343X),
CLK(NULL, "pka_ick", &pka_ick, CK_343X),
CLK(NULL, "core_l4_ick", &core_l4_ick, CK_343X),
CLK(NULL, "usbtll_ick", &usbtll_ick, CK_3430ES2),
CLK("mmci-omap-hs.2", "ick", &mmchs3_ick, CK_3430ES2),
CLK(NULL, "core_l4_ick", &core_l4_ick, CK_3XXX),
CLK(NULL, "usbtll_ick", &usbtll_ick, CK_3430ES2 | CK_AM35XX),
CLK("mmci-omap-hs.2", "ick", &mmchs3_ick, CK_3430ES2 | CK_AM35XX),
CLK(NULL, "icr_ick", &icr_ick, CK_343X),
CLK(NULL, "aes2_ick", &aes2_ick, CK_343X),
CLK(NULL, "sha12_ick", &sha12_ick, CK_343X),
CLK(NULL, "des2_ick", &des2_ick, CK_343X),
CLK("mmci-omap-hs.1", "ick", &mmchs2_ick, CK_343X),
CLK("mmci-omap-hs.0", "ick", &mmchs1_ick, CK_343X),
CLK("mmci-omap-hs.1", "ick", &mmchs2_ick, CK_3XXX),
CLK("mmci-omap-hs.0", "ick", &mmchs1_ick, CK_3XXX),
CLK(NULL, "mspro_ick", &mspro_ick, CK_343X),
CLK("omap_hdq.0", "ick", &hdq_ick, CK_343X),
CLK("omap2_mcspi.4", "ick", &mcspi4_ick, CK_343X),
CLK("omap2_mcspi.3", "ick", &mcspi3_ick, CK_343X),
CLK("omap2_mcspi.2", "ick", &mcspi2_ick, CK_343X),
CLK("omap2_mcspi.1", "ick", &mcspi1_ick, CK_343X),
CLK("i2c_omap.3", "ick", &i2c3_ick, CK_343X),
CLK("i2c_omap.2", "ick", &i2c2_ick, CK_343X),
CLK("i2c_omap.1", "ick", &i2c1_ick, CK_343X),
CLK(NULL, "uart2_ick", &uart2_ick, CK_343X),
CLK(NULL, "uart1_ick", &uart1_ick, CK_343X),
CLK(NULL, "gpt11_ick", &gpt11_ick, CK_343X),
CLK(NULL, "gpt10_ick", &gpt10_ick, CK_343X),
CLK("omap-mcbsp.5", "ick", &mcbsp5_ick, CK_343X),
CLK("omap-mcbsp.1", "ick", &mcbsp1_ick, CK_343X),
CLK("omap_hdq.0", "ick", &hdq_ick, CK_3XXX),
CLK("omap2_mcspi.4", "ick", &mcspi4_ick, CK_3XXX),
CLK("omap2_mcspi.3", "ick", &mcspi3_ick, CK_3XXX),
CLK("omap2_mcspi.2", "ick", &mcspi2_ick, CK_3XXX),
CLK("omap2_mcspi.1", "ick", &mcspi1_ick, CK_3XXX),
CLK("i2c_omap.3", "ick", &i2c3_ick, CK_3XXX),
CLK("i2c_omap.2", "ick", &i2c2_ick, CK_3XXX),
CLK("i2c_omap.1", "ick", &i2c1_ick, CK_3XXX),
CLK(NULL, "uart2_ick", &uart2_ick, CK_3XXX),
CLK(NULL, "uart1_ick", &uart1_ick, CK_3XXX),
CLK(NULL, "gpt11_ick", &gpt11_ick, CK_3XXX),
CLK(NULL, "gpt10_ick", &gpt10_ick, CK_3XXX),
CLK("omap-mcbsp.5", "ick", &mcbsp5_ick, CK_3XXX),
CLK("omap-mcbsp.1", "ick", &mcbsp1_ick, CK_3XXX),
CLK(NULL, "fac_ick", &fac_ick, CK_3430ES1),
CLK(NULL, "mailboxes_ick", &mailboxes_ick, CK_343X),
CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_343X),
CLK(NULL, "omapctrl_ick", &omapctrl_ick, CK_3XXX),
CLK(NULL, "ssi_l4_ick", &ssi_l4_ick, CK_343X),
CLK(NULL, "ssi_ick", &ssi_ick_3430es1, CK_3430ES1),
CLK(NULL, "ssi_ick", &ssi_ick_3430es2, CK_3430ES2),
@ -3131,96 +3132,100 @@ static struct omap_clk omap34xx_clks[] = {
CLK(NULL, "sha11_ick", &sha11_ick, CK_343X),
CLK(NULL, "des1_ick", &des1_ick, CK_343X),
CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es1, CK_3430ES1),
CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2),
CLK("omapdss", "tv_fck", &dss_tv_fck, CK_343X),
CLK("omapdss", "video_fck", &dss_96m_fck, CK_343X),
CLK("omapdss", "dss2_fck", &dss2_alwon_fck, CK_343X),
CLK("omapdss", "dss1_fck", &dss1_alwon_fck_3430es2, CK_3430ES2 | CK_AM35XX),
CLK("omapdss", "tv_fck", &dss_tv_fck, CK_3XXX),
CLK("omapdss", "video_fck", &dss_96m_fck, CK_3XXX),
CLK("omapdss", "dss2_fck", &dss2_alwon_fck, CK_3XXX),
CLK("omapdss", "ick", &dss_ick_3430es1, CK_3430ES1),
CLK("omapdss", "ick", &dss_ick_3430es2, CK_3430ES2),
CLK("omapdss", "ick", &dss_ick_3430es2, CK_3430ES2 | CK_AM35XX),
CLK(NULL, "cam_mclk", &cam_mclk, CK_343X),
CLK(NULL, "cam_ick", &cam_ick, CK_343X),
CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_343X),
CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2),
CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2),
CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2),
CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2 | CK_AM35XX),
CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2 | CK_AM35XX),
CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2 | CK_AM35XX),
CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2),
CLK(NULL, "gpt1_fck", &gpt1_fck, CK_343X),
CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_343X),
CLK(NULL, "gpio1_dbck", &gpio1_dbck, CK_343X),
CLK("omap_wdt", "fck", &wdt2_fck, CK_343X),
CLK(NULL, "gpt1_fck", &gpt1_fck, CK_3XXX),
CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_3XXX),
CLK(NULL, "gpio1_dbck", &gpio1_dbck, CK_3XXX),
CLK("omap_wdt", "fck", &wdt2_fck, CK_3XXX),
CLK(NULL, "wkup_l4_ick", &wkup_l4_ick, CK_343X),
CLK(NULL, "usim_ick", &usim_ick, CK_3430ES2),
CLK("omap_wdt", "ick", &wdt2_ick, CK_343X),
CLK(NULL, "wdt1_ick", &wdt1_ick, CK_343X),
CLK(NULL, "gpio1_ick", &gpio1_ick, CK_343X),
CLK(NULL, "omap_32ksync_ick", &omap_32ksync_ick, CK_343X),
CLK(NULL, "gpt12_ick", &gpt12_ick, CK_343X),
CLK(NULL, "gpt1_ick", &gpt1_ick, CK_343X),
CLK(NULL, "per_96m_fck", &per_96m_fck, CK_343X),
CLK(NULL, "per_48m_fck", &per_48m_fck, CK_343X),
CLK(NULL, "uart3_fck", &uart3_fck, CK_343X),
CLK(NULL, "gpt2_fck", &gpt2_fck, CK_343X),
CLK(NULL, "gpt3_fck", &gpt3_fck, CK_343X),
CLK(NULL, "gpt4_fck", &gpt4_fck, CK_343X),
CLK(NULL, "gpt5_fck", &gpt5_fck, CK_343X),
CLK(NULL, "gpt6_fck", &gpt6_fck, CK_343X),
CLK(NULL, "gpt7_fck", &gpt7_fck, CK_343X),
CLK(NULL, "gpt8_fck", &gpt8_fck, CK_343X),
CLK(NULL, "gpt9_fck", &gpt9_fck, CK_343X),
CLK(NULL, "per_32k_alwon_fck", &per_32k_alwon_fck, CK_343X),
CLK(NULL, "gpio6_dbck", &gpio6_dbck, CK_343X),
CLK(NULL, "gpio5_dbck", &gpio5_dbck, CK_343X),
CLK(NULL, "gpio4_dbck", &gpio4_dbck, CK_343X),
CLK(NULL, "gpio3_dbck", &gpio3_dbck, CK_343X),
CLK(NULL, "gpio2_dbck", &gpio2_dbck, CK_343X),
CLK(NULL, "wdt3_fck", &wdt3_fck, CK_343X),
CLK(NULL, "per_l4_ick", &per_l4_ick, CK_343X),
CLK(NULL, "gpio6_ick", &gpio6_ick, CK_343X),
CLK(NULL, "gpio5_ick", &gpio5_ick, CK_343X),
CLK(NULL, "gpio4_ick", &gpio4_ick, CK_343X),
CLK(NULL, "gpio3_ick", &gpio3_ick, CK_343X),
CLK(NULL, "gpio2_ick", &gpio2_ick, CK_343X),
CLK(NULL, "wdt3_ick", &wdt3_ick, CK_343X),
CLK(NULL, "uart3_ick", &uart3_ick, CK_343X),
CLK(NULL, "gpt9_ick", &gpt9_ick, CK_343X),
CLK(NULL, "gpt8_ick", &gpt8_ick, CK_343X),
CLK(NULL, "gpt7_ick", &gpt7_ick, CK_343X),
CLK(NULL, "gpt6_ick", &gpt6_ick, CK_343X),
CLK(NULL, "gpt5_ick", &gpt5_ick, CK_343X),
CLK(NULL, "gpt4_ick", &gpt4_ick, CK_343X),
CLK(NULL, "gpt3_ick", &gpt3_ick, CK_343X),
CLK(NULL, "gpt2_ick", &gpt2_ick, CK_343X),
CLK("omap-mcbsp.2", "ick", &mcbsp2_ick, CK_343X),
CLK("omap-mcbsp.3", "ick", &mcbsp3_ick, CK_343X),
CLK("omap-mcbsp.4", "ick", &mcbsp4_ick, CK_343X),
CLK("omap-mcbsp.2", "fck", &mcbsp2_fck, CK_343X),
CLK("omap-mcbsp.3", "fck", &mcbsp3_fck, CK_343X),
CLK("omap-mcbsp.4", "fck", &mcbsp4_fck, CK_343X),
CLK("etb", "emu_src_ck", &emu_src_ck, CK_343X),
CLK(NULL, "pclk_fck", &pclk_fck, CK_343X),
CLK(NULL, "pclkx2_fck", &pclkx2_fck, CK_343X),
CLK(NULL, "atclk_fck", &atclk_fck, CK_343X),
CLK(NULL, "traceclk_src_fck", &traceclk_src_fck, CK_343X),
CLK(NULL, "traceclk_fck", &traceclk_fck, CK_343X),
CLK("omap_wdt", "ick", &wdt2_ick, CK_3XXX),
CLK(NULL, "wdt1_ick", &wdt1_ick, CK_3XXX),
CLK(NULL, "gpio1_ick", &gpio1_ick, CK_3XXX),
CLK(NULL, "omap_32ksync_ick", &omap_32ksync_ick, CK_3XXX),
CLK(NULL, "gpt12_ick", &gpt12_ick, CK_3XXX),
CLK(NULL, "gpt1_ick", &gpt1_ick, CK_3XXX),
CLK(NULL, "per_96m_fck", &per_96m_fck, CK_3XXX),
CLK(NULL, "per_48m_fck", &per_48m_fck, CK_3XXX),
CLK(NULL, "uart3_fck", &uart3_fck, CK_3XXX),
CLK(NULL, "gpt2_fck", &gpt2_fck, CK_3XXX),
CLK(NULL, "gpt3_fck", &gpt3_fck, CK_3XXX),
CLK(NULL, "gpt4_fck", &gpt4_fck, CK_3XXX),
CLK(NULL, "gpt5_fck", &gpt5_fck, CK_3XXX),
CLK(NULL, "gpt6_fck", &gpt6_fck, CK_3XXX),
CLK(NULL, "gpt7_fck", &gpt7_fck, CK_3XXX),
CLK(NULL, "gpt8_fck", &gpt8_fck, CK_3XXX),
CLK(NULL, "gpt9_fck", &gpt9_fck, CK_3XXX),
CLK(NULL, "per_32k_alwon_fck", &per_32k_alwon_fck, CK_3XXX),
CLK(NULL, "gpio6_dbck", &gpio6_dbck, CK_3XXX),
CLK(NULL, "gpio5_dbck", &gpio5_dbck, CK_3XXX),
CLK(NULL, "gpio4_dbck", &gpio4_dbck, CK_3XXX),
CLK(NULL, "gpio3_dbck", &gpio3_dbck, CK_3XXX),
CLK(NULL, "gpio2_dbck", &gpio2_dbck, CK_3XXX),
CLK(NULL, "wdt3_fck", &wdt3_fck, CK_3XXX),
CLK(NULL, "per_l4_ick", &per_l4_ick, CK_3XXX),
CLK(NULL, "gpio6_ick", &gpio6_ick, CK_3XXX),
CLK(NULL, "gpio5_ick", &gpio5_ick, CK_3XXX),
CLK(NULL, "gpio4_ick", &gpio4_ick, CK_3XXX),
CLK(NULL, "gpio3_ick", &gpio3_ick, CK_3XXX),
CLK(NULL, "gpio2_ick", &gpio2_ick, CK_3XXX),
CLK(NULL, "wdt3_ick", &wdt3_ick, CK_3XXX),
CLK(NULL, "uart3_ick", &uart3_ick, CK_3XXX),
CLK(NULL, "gpt9_ick", &gpt9_ick, CK_3XXX),
CLK(NULL, "gpt8_ick", &gpt8_ick, CK_3XXX),
CLK(NULL, "gpt7_ick", &gpt7_ick, CK_3XXX),
CLK(NULL, "gpt6_ick", &gpt6_ick, CK_3XXX),
CLK(NULL, "gpt5_ick", &gpt5_ick, CK_3XXX),
CLK(NULL, "gpt4_ick", &gpt4_ick, CK_3XXX),
CLK(NULL, "gpt3_ick", &gpt3_ick, CK_3XXX),
CLK(NULL, "gpt2_ick", &gpt2_ick, CK_3XXX),
CLK("omap-mcbsp.2", "ick", &mcbsp2_ick, CK_3XXX),
CLK("omap-mcbsp.3", "ick", &mcbsp3_ick, CK_3XXX),
CLK("omap-mcbsp.4", "ick", &mcbsp4_ick, CK_3XXX),
CLK("omap-mcbsp.2", "fck", &mcbsp2_fck, CK_3XXX),
CLK("omap-mcbsp.3", "fck", &mcbsp3_fck, CK_3XXX),
CLK("omap-mcbsp.4", "fck", &mcbsp4_fck, CK_3XXX),
CLK("etb", "emu_src_ck", &emu_src_ck, CK_3XXX),
CLK(NULL, "pclk_fck", &pclk_fck, CK_3XXX),
CLK(NULL, "pclkx2_fck", &pclkx2_fck, CK_3XXX),
CLK(NULL, "atclk_fck", &atclk_fck, CK_3XXX),
CLK(NULL, "traceclk_src_fck", &traceclk_src_fck, CK_3XXX),
CLK(NULL, "traceclk_fck", &traceclk_fck, CK_3XXX),
CLK(NULL, "sr1_fck", &sr1_fck, CK_343X),
CLK(NULL, "sr2_fck", &sr2_fck, CK_343X),
CLK(NULL, "sr_l4_ick", &sr_l4_ick, CK_343X),
CLK(NULL, "secure_32k_fck", &secure_32k_fck, CK_343X),
CLK(NULL, "gpt12_fck", &gpt12_fck, CK_343X),
CLK(NULL, "wdt1_fck", &wdt1_fck, CK_343X),
CLK(NULL, "secure_32k_fck", &secure_32k_fck, CK_3XXX),
CLK(NULL, "gpt12_fck", &gpt12_fck, CK_3XXX),
CLK(NULL, "wdt1_fck", &wdt1_fck, CK_3XXX),
};
int __init omap2_clk_init(void)
int __init omap3xxx_clk_init(void)
{
/* struct prcm_config *prcm; */
struct omap_clk *c;
/* u32 clkrate; */
u32 cpu_clkflg;
u32 cpu_clkflg = CK_3XXX;
if (cpu_is_omap34xx()) {
if (cpu_is_omap3517()) {
cpu_mask = RATE_IN_343X | RATE_IN_3430ES2;
cpu_clkflg |= CK_3517;
} else if (cpu_is_omap3505()) {
cpu_mask = RATE_IN_343X | RATE_IN_3430ES2;
cpu_clkflg |= CK_3505;
} else if (cpu_is_omap34xx()) {
cpu_mask = RATE_IN_343X;
cpu_clkflg = CK_343X;
cpu_clkflg |= CK_343X;
/*
* Update this if there are further clock changes between ES2
@ -3237,31 +3242,16 @@ int __init omap2_clk_init(void)
clk_init(&omap2_clk_functions);
for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++)
for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks); c++)
clk_preinit(c->lk.clk);
for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++)
for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks); c++)
if (c->cpu & cpu_clkflg) {
clkdev_add(&c->lk);
clk_register(c->lk.clk);
omap2_init_clk_clkdm(c->lk.clk);
}
/* REVISIT: Not yet ready for OMAP3 */
#if 0
/* Check the MPU rate set by bootloader */
clkrate = omap2_get_dpll_rate_24xx(&dpll_ck);
for (prcm = rate_table; prcm->mpu_speed; prcm++) {
if (!(prcm->flags & cpu_mask))
continue;
if (prcm->xtal_speed != sys_ck.rate)
continue;
if (prcm->dpll_speed <= clkrate)
break;
}
curr_prcm_set = prcm;
#endif
recalculate_root_clocks();
printk(KERN_INFO "Clocking rate (Crystal/Core/MPU): "

Просмотреть файл

@ -13,21 +13,7 @@
#include <linux/errno.h>
#include "clock.h"
struct clk_functions omap2_clk_functions = {
.clk_enable = omap2_clk_enable,
.clk_disable = omap2_clk_disable,
.clk_round_rate = omap2_clk_round_rate,
.clk_set_rate = omap2_clk_set_rate,
.clk_set_parent = omap2_clk_set_parent,
.clk_disable_unused = omap2_clk_disable_unused,
};
const struct clkops clkops_noncore_dpll_ops = {
.enable = &omap3_noncore_dpll_enable,
.disable = &omap3_noncore_dpll_disable,
};
void omap2_clk_prepare_for_reboot(void)
{
return;
}

Просмотреть файл

@ -10,6 +10,8 @@
#define OMAP4430_MAX_DPLL_MULT 2048
#define OMAP4430_MAX_DPLL_DIV 128
int omap4xxx_clk_init(void);
extern const struct clkops clkops_noncore_dpll_ops;
#endif

Просмотреть файл

@ -2726,11 +2726,9 @@ static struct omap_clk omap44xx_clks[] = {
CLK(NULL, "utmi_p2_gfclk_ck", &utmi_p2_gfclk_ck, CK_443X),
};
int __init omap2_clk_init(void)
int __init omap4xxx_clk_init(void)
{
/* struct prcm_config *prcm; */
struct omap_clk *c;
/* u32 clkrate; */
u32 cpu_clkflg;
if (cpu_is_omap44xx()) {
@ -2749,9 +2747,7 @@ int __init omap2_clk_init(void)
if (c->cpu & cpu_clkflg) {
clkdev_add(&c->lk);
clk_register(c->lk.clk);
/* TODO
omap2_init_clk_clkdm(c->lk.clk);
*/
}
recalculate_root_clocks();

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,16 +1,420 @@
/*
* OMAP2/3 clockdomains
*
* Copyright (C) 2008 Texas Instruments, Inc.
* Copyright (C) 2008 Nokia Corporation
* Copyright (C) 2008-2009 Texas Instruments, Inc.
* Copyright (C) 2008-2010 Nokia Corporation
*
* Written by Paul Walmsley
* Written by Paul Walmsley and Jouni Högander
*
* This file contains clockdomains and clockdomain wakeup/sleep
* dependencies for the OMAP2/3 chips. Some notes:
*
* A useful validation rule for struct clockdomain: Any clockdomain
* referenced by a wkdep_srcs or sleepdep_srcs array must have a
* dep_bit assigned. So wkdep_srcs/sleepdep_srcs are really just
* software-controllable dependencies. Non-software-controllable
* dependencies do exist, but they are not encoded below (yet).
*
* 24xx does not support programmable sleep dependencies (SLEEPDEP)
*
* The overly-specific dep_bit names are due to a bit name collision
* with CM_FCLKEN_{DSP,IVA2}. The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
* value are the same for all powerdomains: 2
*
* XXX should dep_bit be a mask, so we can test to see if it is 0 as a
* sanity check?
* XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
*/
/*
* To-Do List
* -> Port the Sleep/Wakeup dependencies for the domains
* from the Power domain framework
*/
#ifndef __ARCH_ARM_MACH_OMAP2_CLOCKDOMAINS_H
#define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAINS_H
#include <plat/clockdomain.h>
#include "cm.h"
#include "prm.h"
/*
* Clockdomain dependencies for wkdeps/sleepdeps
*
* XXX Hardware dependencies (e.g., dependencies that cannot be
* changed in software) are not included here yet, but should be.
*/
/* OMAP2/3-common wakeup dependencies */
/*
* 2420/2430 PM_WKDEP_GFX: CORE, MPU, WKUP
* 3430ES1 PM_WKDEP_GFX: adds IVA2, removes CORE
* 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE
* These can share data since they will never be present simultaneously
* on the same device.
*/
static struct clkdm_dep gfx_sgx_wkdeps[] = {
{
.clkdm_name = "core_l3_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.clkdm_name = "core_l4_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.clkdm_name = "iva2_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "mpu_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
CHIP_IS_OMAP3430)
},
{
.clkdm_name = "wkup_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
CHIP_IS_OMAP3430)
},
{ NULL },
};
/* 24XX-specific possible dependencies */
#ifdef CONFIG_ARCH_OMAP24XX
/* Wakeup dependency source arrays */
/* 2420/2430 PM_WKDEP_DSP: CORE, MPU, WKUP */
static struct clkdm_dep dsp_24xx_wkdeps[] = {
{
.clkdm_name = "core_l3_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.clkdm_name = "core_l4_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.clkdm_name = "mpu_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.clkdm_name = "wkup_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{ NULL },
};
/*
* 2420 PM_WKDEP_MPU: CORE, DSP, WKUP
* 2430 adds MDM
*/
static struct clkdm_dep mpu_24xx_wkdeps[] = {
{
.clkdm_name = "core_l3_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.clkdm_name = "core_l4_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.clkdm_name = "dsp_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.clkdm_name = "wkup_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.clkdm_name = "mdm_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
},
{ NULL },
};
/*
* 2420 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP
* 2430 adds MDM
*/
static struct clkdm_dep core_24xx_wkdeps[] = {
{
.clkdm_name = "dsp_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.clkdm_name = "gfx_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.clkdm_name = "mpu_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.clkdm_name = "wkup_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.clkdm_name = "mdm_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
},
{ NULL },
};
#endif
/* 2430-specific possible wakeup dependencies */
#ifdef CONFIG_ARCH_OMAP2430
/* 2430 PM_WKDEP_MDM: CORE, MPU, WKUP */
static struct clkdm_dep mdm_2430_wkdeps[] = {
{
.clkdm_name = "core_l3_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.clkdm_name = "core_l4_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.clkdm_name = "mpu_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.clkdm_name = "wkup_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{ NULL },
};
#endif /* CONFIG_ARCH_OMAP2430 */
/* OMAP3-specific possible dependencies */
#ifdef CONFIG_ARCH_OMAP3
/* 3430: PM_WKDEP_PER: CORE, IVA2, MPU, WKUP */
static struct clkdm_dep per_wkdeps[] = {
{
.clkdm_name = "core_l3_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "core_l4_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "iva2_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "mpu_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "wkup_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{ NULL },
};
/* 3430ES2: PM_WKDEP_USBHOST: CORE, IVA2, MPU, WKUP */
static struct clkdm_dep usbhost_wkdeps[] = {
{
.clkdm_name = "core_l3_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "core_l4_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "iva2_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "mpu_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "wkup_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{ NULL },
};
/* 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER */
static struct clkdm_dep mpu_3xxx_wkdeps[] = {
{
.clkdm_name = "core_l3_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "core_l4_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "iva2_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "dss_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "per_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{ NULL },
};
/* 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER */
static struct clkdm_dep iva2_wkdeps[] = {
{
.clkdm_name = "core_l3_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "core_l4_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "mpu_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "wkup_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "dss_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "per_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{ NULL },
};
/* 3430 PM_WKDEP_CAM: IVA2, MPU, WKUP */
static struct clkdm_dep cam_wkdeps[] = {
{
.clkdm_name = "iva2_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "mpu_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "wkup_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{ NULL },
};
/* 3430 PM_WKDEP_DSS: IVA2, MPU, WKUP */
static struct clkdm_dep dss_wkdeps[] = {
{
.clkdm_name = "iva2_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "mpu_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "wkup_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{ NULL },
};
/* 3430: PM_WKDEP_NEON: MPU */
static struct clkdm_dep neon_wkdeps[] = {
{
.clkdm_name = "mpu_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{ NULL },
};
/* Sleep dependency source arrays for OMAP3-specific clkdms */
/* 3430: CM_SLEEPDEP_DSS: MPU, IVA */
static struct clkdm_dep dss_sleepdeps[] = {
{
.clkdm_name = "mpu_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "iva2_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{ NULL },
};
/* 3430: CM_SLEEPDEP_PER: MPU, IVA */
static struct clkdm_dep per_sleepdeps[] = {
{
.clkdm_name = "mpu_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "iva2_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{ NULL },
};
/* 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA */
static struct clkdm_dep usbhost_sleepdeps[] = {
{
.clkdm_name = "mpu_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.clkdm_name = "iva2_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{ NULL },
};
/* 3430: CM_SLEEPDEP_CAM: MPU */
static struct clkdm_dep cam_sleepdeps[] = {
{
.clkdm_name = "mpu_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{ NULL },
};
/*
* 3430ES1: CM_SLEEPDEP_GFX: MPU
* 3430ES2: CM_SLEEPDEP_SGX: MPU
* These can share data since they will never be present simultaneously
* on the same device.
*/
static struct clkdm_dep gfx_sgx_sleepdeps[] = {
{
.clkdm_name = "mpu_clkdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{ NULL },
};
#endif /* CONFIG_ARCH_OMAP3 */
/*
* OMAP2/3-common clockdomains
@ -21,10 +425,13 @@
* sys_clkout/sys_clkout2.
*/
#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
/* This is an implicit clockdomain - it is never defined as such in TRM */
static struct clockdomain wkup_clkdm = {
.name = "wkup_clkdm",
.pwrdm = { .name = "wkup_pwrdm" },
.dep_bit = OMAP_EN_WKUP_SHIFT,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
};
@ -40,6 +447,8 @@ static struct clockdomain cm_clkdm = {
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
};
#endif
/*
* 2420-only clockdomains
*/
@ -50,6 +459,8 @@ static struct clockdomain mpu_2420_clkdm = {
.name = "mpu_clkdm",
.pwrdm = { .name = "mpu_pwrdm" },
.flags = CLKDM_CAN_HWSUP,
.clkstctrl_reg = OMAP2420_CM_REGADDR(MPU_MOD, OMAP2_CM_CLKSTCTRL),
.wkdep_srcs = mpu_24xx_wkdeps,
.clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
@ -58,11 +469,64 @@ static struct clockdomain iva1_2420_clkdm = {
.name = "iva1_clkdm",
.pwrdm = { .name = "dsp_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.clkstctrl_reg = OMAP2420_CM_REGADDR(OMAP24XX_DSP_MOD,
OMAP2_CM_CLKSTCTRL),
.dep_bit = OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
.wkdep_srcs = dsp_24xx_wkdeps,
.clktrctrl_mask = OMAP2420_AUTOSTATE_IVA_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
#endif /* CONFIG_ARCH_OMAP2420 */
static struct clockdomain dsp_2420_clkdm = {
.name = "dsp_clkdm",
.pwrdm = { .name = "dsp_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.clkstctrl_reg = OMAP2420_CM_REGADDR(OMAP24XX_DSP_MOD,
OMAP2_CM_CLKSTCTRL),
.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
static struct clockdomain gfx_2420_clkdm = {
.name = "gfx_clkdm",
.pwrdm = { .name = "gfx_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.clkstctrl_reg = OMAP2420_CM_REGADDR(GFX_MOD, OMAP2_CM_CLKSTCTRL),
.wkdep_srcs = gfx_sgx_wkdeps,
.clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
static struct clockdomain core_l3_2420_clkdm = {
.name = "core_l3_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.flags = CLKDM_CAN_HWSUP,
.clkstctrl_reg = OMAP2420_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
.wkdep_srcs = core_24xx_wkdeps,
.clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
static struct clockdomain core_l4_2420_clkdm = {
.name = "core_l4_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.flags = CLKDM_CAN_HWSUP,
.clkstctrl_reg = OMAP2420_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
.wkdep_srcs = core_24xx_wkdeps,
.clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
static struct clockdomain dss_2420_clkdm = {
.name = "dss_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.flags = CLKDM_CAN_HWSUP,
.clkstctrl_reg = OMAP2420_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
};
#endif /* CONFIG_ARCH_OMAP2420 */
/*
@ -75,80 +539,105 @@ static struct clockdomain mpu_2430_clkdm = {
.name = "mpu_clkdm",
.pwrdm = { .name = "mpu_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.clkstctrl_reg = OMAP2430_CM_REGADDR(MPU_MOD,
OMAP2_CM_CLKSTCTRL),
.wkdep_srcs = mpu_24xx_wkdeps,
.clktrctrl_mask = OMAP24XX_AUTOSTATE_MPU_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/* Another case of bit name collisions between several registers: EN_MDM */
static struct clockdomain mdm_clkdm = {
.name = "mdm_clkdm",
.pwrdm = { .name = "mdm_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.clkstctrl_reg = OMAP2430_CM_REGADDR(OMAP2430_MDM_MOD,
OMAP2_CM_CLKSTCTRL),
.dep_bit = OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT,
.wkdep_srcs = mdm_2430_wkdeps,
.clktrctrl_mask = OMAP2430_AUTOSTATE_MDM_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
static struct clockdomain dsp_2430_clkdm = {
.name = "dsp_clkdm",
.pwrdm = { .name = "dsp_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.clkstctrl_reg = OMAP2430_CM_REGADDR(OMAP24XX_DSP_MOD,
OMAP2_CM_CLKSTCTRL),
.dep_bit = OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
.wkdep_srcs = dsp_24xx_wkdeps,
.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
static struct clockdomain gfx_2430_clkdm = {
.name = "gfx_clkdm",
.pwrdm = { .name = "gfx_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.clkstctrl_reg = OMAP2430_CM_REGADDR(GFX_MOD, OMAP2_CM_CLKSTCTRL),
.wkdep_srcs = gfx_sgx_wkdeps,
.clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/*
* XXX add usecounting for clkdm dependencies, otherwise the presence
* of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
* could cause trouble
*/
static struct clockdomain core_l3_2430_clkdm = {
.name = "core_l3_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.flags = CLKDM_CAN_HWSUP,
.clkstctrl_reg = OMAP2430_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
.dep_bit = OMAP24XX_EN_CORE_SHIFT,
.wkdep_srcs = core_24xx_wkdeps,
.clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
/*
* XXX add usecounting for clkdm dependencies, otherwise the presence
* of a single dep bit for core_l3_24xx_clkdm and core_l4_24xx_clkdm
* could cause trouble
*/
static struct clockdomain core_l4_2430_clkdm = {
.name = "core_l4_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.flags = CLKDM_CAN_HWSUP,
.clkstctrl_reg = OMAP2430_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
.dep_bit = OMAP24XX_EN_CORE_SHIFT,
.wkdep_srcs = core_24xx_wkdeps,
.clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
static struct clockdomain dss_2430_clkdm = {
.name = "dss_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.flags = CLKDM_CAN_HWSUP,
.clkstctrl_reg = OMAP2430_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
};
#endif /* CONFIG_ARCH_OMAP2430 */
/*
* 24XX-only clockdomains
* OMAP3 clockdomains
*/
#if defined(CONFIG_ARCH_OMAP24XX)
#if defined(CONFIG_ARCH_OMAP3)
static struct clockdomain dsp_clkdm = {
.name = "dsp_clkdm",
.pwrdm = { .name = "dsp_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSP_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
};
static struct clockdomain gfx_24xx_clkdm = {
.name = "gfx_clkdm",
.pwrdm = { .name = "gfx_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.clktrctrl_mask = OMAP24XX_AUTOSTATE_GFX_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
};
static struct clockdomain core_l3_24xx_clkdm = {
.name = "core_l3_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.flags = CLKDM_CAN_HWSUP,
.clktrctrl_mask = OMAP24XX_AUTOSTATE_L3_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
};
static struct clockdomain core_l4_24xx_clkdm = {
.name = "core_l4_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.flags = CLKDM_CAN_HWSUP,
.clktrctrl_mask = OMAP24XX_AUTOSTATE_L4_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
};
static struct clockdomain dss_24xx_clkdm = {
.name = "dss_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.flags = CLKDM_CAN_HWSUP,
.clktrctrl_mask = OMAP24XX_AUTOSTATE_DSS_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
};
#endif /* CONFIG_ARCH_OMAP24XX */
/*
* 34xx clockdomains
*/
#if defined(CONFIG_ARCH_OMAP34XX)
static struct clockdomain mpu_34xx_clkdm = {
static struct clockdomain mpu_3xxx_clkdm = {
.name = "mpu_clkdm",
.pwrdm = { .name = "mpu_pwrdm" },
.flags = CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP,
.clkstctrl_reg = OMAP34XX_CM_REGADDR(MPU_MOD, OMAP2_CM_CLKSTCTRL),
.dep_bit = OMAP3430_EN_MPU_SHIFT,
.wkdep_srcs = mpu_3xxx_wkdeps,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
@ -157,6 +646,9 @@ static struct clockdomain neon_clkdm = {
.name = "neon_clkdm",
.pwrdm = { .name = "neon_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.clkstctrl_reg = OMAP34XX_CM_REGADDR(OMAP3430_NEON_MOD,
OMAP2_CM_CLKSTCTRL),
.wkdep_srcs = neon_wkdeps,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_NEON_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
@ -165,6 +657,10 @@ static struct clockdomain iva2_clkdm = {
.name = "iva2_clkdm",
.pwrdm = { .name = "iva2_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.clkstctrl_reg = OMAP34XX_CM_REGADDR(OMAP3430_IVA2_MOD,
OMAP2_CM_CLKSTCTRL),
.dep_bit = OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,
.wkdep_srcs = iva2_wkdeps,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_IVA2_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
@ -173,6 +669,9 @@ static struct clockdomain gfx_3430es1_clkdm = {
.name = "gfx_clkdm",
.pwrdm = { .name = "gfx_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.clkstctrl_reg = OMAP34XX_CM_REGADDR(GFX_MOD, OMAP2_CM_CLKSTCTRL),
.wkdep_srcs = gfx_sgx_wkdeps,
.sleepdep_srcs = gfx_sgx_sleepdeps,
.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_GFX_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1),
};
@ -181,6 +680,10 @@ static struct clockdomain sgx_clkdm = {
.name = "sgx_clkdm",
.pwrdm = { .name = "sgx_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.clkstctrl_reg = OMAP34XX_CM_REGADDR(OMAP3430ES2_SGX_MOD,
OMAP2_CM_CLKSTCTRL),
.wkdep_srcs = gfx_sgx_wkdeps,
.sleepdep_srcs = gfx_sgx_sleepdeps,
.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
};
@ -196,30 +699,51 @@ static struct clockdomain d2d_clkdm = {
.name = "d2d_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.clkstctrl_reg = OMAP34XX_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
.clktrctrl_mask = OMAP3430ES1_CLKTRCTRL_D2D_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
static struct clockdomain core_l3_34xx_clkdm = {
/*
* XXX add usecounting for clkdm dependencies, otherwise the presence
* of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
* could cause trouble
*/
static struct clockdomain core_l3_3xxx_clkdm = {
.name = "core_l3_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.flags = CLKDM_CAN_HWSUP,
.clkstctrl_reg = OMAP34XX_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
.dep_bit = OMAP3430_EN_CORE_SHIFT,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_L3_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
static struct clockdomain core_l4_34xx_clkdm = {
/*
* XXX add usecounting for clkdm dependencies, otherwise the presence
* of a single dep bit for core_l3_3xxx_clkdm and core_l4_3xxx_clkdm
* could cause trouble
*/
static struct clockdomain core_l4_3xxx_clkdm = {
.name = "core_l4_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.flags = CLKDM_CAN_HWSUP,
.clkstctrl_reg = OMAP34XX_CM_REGADDR(CORE_MOD, OMAP2_CM_CLKSTCTRL),
.dep_bit = OMAP3430_EN_CORE_SHIFT,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_L4_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
static struct clockdomain dss_34xx_clkdm = {
/* Another case of bit name collisions between several registers: EN_DSS */
static struct clockdomain dss_3xxx_clkdm = {
.name = "dss_clkdm",
.pwrdm = { .name = "dss_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.clkstctrl_reg = OMAP34XX_CM_REGADDR(OMAP3430_DSS_MOD,
OMAP2_CM_CLKSTCTRL),
.dep_bit = OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,
.wkdep_srcs = dss_wkdeps,
.sleepdep_srcs = dss_sleepdeps,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
@ -228,6 +752,10 @@ static struct clockdomain cam_clkdm = {
.name = "cam_clkdm",
.pwrdm = { .name = "cam_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.clkstctrl_reg = OMAP34XX_CM_REGADDR(OMAP3430_CAM_MOD,
OMAP2_CM_CLKSTCTRL),
.wkdep_srcs = cam_wkdeps,
.sleepdep_srcs = cam_sleepdeps,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_CAM_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
@ -236,6 +764,10 @@ static struct clockdomain usbhost_clkdm = {
.name = "usbhost_clkdm",
.pwrdm = { .name = "usbhost_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.clkstctrl_reg = OMAP34XX_CM_REGADDR(OMAP3430ES2_USBHOST_MOD,
OMAP2_CM_CLKSTCTRL),
.wkdep_srcs = usbhost_wkdeps,
.sleepdep_srcs = usbhost_sleepdeps,
.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
};
@ -244,6 +776,11 @@ static struct clockdomain per_clkdm = {
.name = "per_clkdm",
.pwrdm = { .name = "per_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.clkstctrl_reg = OMAP34XX_CM_REGADDR(OMAP3430_PER_MOD,
OMAP2_CM_CLKSTCTRL),
.dep_bit = OMAP3430_EN_PER_SHIFT,
.wkdep_srcs = per_wkdeps,
.sleepdep_srcs = per_sleepdeps,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
@ -256,6 +793,8 @@ static struct clockdomain emu_clkdm = {
.name = "emu_clkdm",
.pwrdm = { .name = "emu_pwrdm" },
.flags = /* CLKDM_CAN_ENABLE_AUTO | */CLKDM_CAN_SWSUP,
.clkstctrl_reg = OMAP34XX_CM_REGADDR(OMAP3430_EMU_MOD,
OMAP2_CM_CLKSTCTRL),
.clktrctrl_mask = OMAP3430_CLKTRCTRL_EMU_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
};
@ -290,64 +829,70 @@ static struct clockdomain dpll5_clkdm = {
.omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
};
#endif /* CONFIG_ARCH_OMAP34XX */
#endif /* CONFIG_ARCH_OMAP3 */
#include "clockdomains44xx.h"
/*
* Clockdomain-powerdomain hwsup dependencies (34XX only)
* Clockdomain hwsup dependencies (OMAP3 only)
*/
static struct clkdm_pwrdm_autodep clkdm_pwrdm_autodeps[] = {
static struct clkdm_autodep clkdm_autodeps[] = {
{
.pwrdm = { .name = "mpu_pwrdm" },
.clkdm = { .name = "mpu_clkdm" },
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.pwrdm = { .name = "iva2_pwrdm" },
.clkdm = { .name = "iva2_clkdm" },
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.pwrdm = { .name = NULL },
.clkdm = { .name = NULL },
}
};
/*
*
* List of clockdomain pointers per platform
*/
static struct clockdomain *clockdomains_omap[] = {
#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
&wkup_clkdm,
&cm_clkdm,
&prm_clkdm,
#endif
#ifdef CONFIG_ARCH_OMAP2420
&mpu_2420_clkdm,
&iva1_2420_clkdm,
&dsp_2420_clkdm,
&gfx_2420_clkdm,
&core_l3_2420_clkdm,
&core_l4_2420_clkdm,
&dss_2420_clkdm,
#endif
#ifdef CONFIG_ARCH_OMAP2430
&mpu_2430_clkdm,
&mdm_clkdm,
&dsp_2430_clkdm,
&gfx_2430_clkdm,
&core_l3_2430_clkdm,
&core_l4_2430_clkdm,
&dss_2430_clkdm,
#endif
#ifdef CONFIG_ARCH_OMAP24XX
&dsp_clkdm,
&gfx_24xx_clkdm,
&core_l3_24xx_clkdm,
&core_l4_24xx_clkdm,
&dss_24xx_clkdm,
#endif
#ifdef CONFIG_ARCH_OMAP34XX
&mpu_34xx_clkdm,
#ifdef CONFIG_ARCH_OMAP3
&mpu_3xxx_clkdm,
&neon_clkdm,
&iva2_clkdm,
&gfx_3430es1_clkdm,
&sgx_clkdm,
&d2d_clkdm,
&core_l3_34xx_clkdm,
&core_l4_34xx_clkdm,
&dss_34xx_clkdm,
&core_l3_3xxx_clkdm,
&core_l4_3xxx_clkdm,
&dss_3xxx_clkdm,
&cam_clkdm,
&usbhost_clkdm,
&per_clkdm,
@ -359,6 +904,33 @@ static struct clockdomain *clockdomains_omap[] = {
&dpll5_clkdm,
#endif
#ifdef CONFIG_ARCH_OMAP4
&l4_cefuse_44xx_clkdm,
&l4_cfg_44xx_clkdm,
&tesla_44xx_clkdm,
&l3_gfx_44xx_clkdm,
&ivahd_44xx_clkdm,
&l4_secure_44xx_clkdm,
&l4_per_44xx_clkdm,
&abe_44xx_clkdm,
&l3_instr_44xx_clkdm,
&l3_init_44xx_clkdm,
&mpuss_44xx_clkdm,
&mpu0_44xx_clkdm,
&mpu1_44xx_clkdm,
&l3_emif_44xx_clkdm,
&l4_ao_44xx_clkdm,
&ducati_44xx_clkdm,
&l3_2_44xx_clkdm,
&l3_1_44xx_clkdm,
&l3_d2d_44xx_clkdm,
&iss_44xx_clkdm,
&l3_dss_44xx_clkdm,
&l4_wkup_44xx_clkdm,
&emu_sys_44xx_clkdm,
&l3_dma_44xx_clkdm,
#endif
NULL,
};

Просмотреть файл

@ -0,0 +1,250 @@
/*
* OMAP4 Clock domains framework
*
* Copyright (C) 2009 Texas Instruments, Inc.
* Copyright (C) 2009 Nokia Corporation
*
* Abhijit Pagare (abhijitpagare@ti.com)
* Benoit Cousson (b-cousson@ti.com)
*
* This file is automatically generated from the OMAP hardware databases.
* We respectfully ask that any modifications to this file be coordinated
* with the public linux-omap@vger.kernel.org mailing list and the
* authors above to ensure that the autogeneration scripts are kept
* up-to-date with the file contents.
*
* 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.
*/
/*
* To-Do List
* -> Populate the Sleep/Wakeup dependencies for the domains
*/
#ifndef __ARCH_ARM_MACH_OMAP2_CLOCKDOMAINS44XX_H
#define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAINS44XX_H
#include <plat/clockdomain.h>
#if defined(CONFIG_ARCH_OMAP4)
static struct clockdomain l4_cefuse_44xx_clkdm = {
.name = "l4_cefuse_clkdm",
.pwrdm = { .name = "cefuse_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_CEFUSE_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l4_cfg_44xx_clkdm = {
.name = "l4_cfg_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_L4CFG_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_HWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain tesla_44xx_clkdm = {
.name = "tesla_clkdm",
.pwrdm = { .name = "tesla_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_TESLA_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_HWSUP_SWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l3_gfx_44xx_clkdm = {
.name = "l3_gfx_clkdm",
.pwrdm = { .name = "gfx_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_GFX_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_HWSUP_SWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain ivahd_44xx_clkdm = {
.name = "ivahd_clkdm",
.pwrdm = { .name = "ivahd_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_IVAHD_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_HWSUP_SWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l4_secure_44xx_clkdm = {
.name = "l4_secure_clkdm",
.pwrdm = { .name = "l4per_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_L4SEC_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_HWSUP_SWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l4_per_44xx_clkdm = {
.name = "l4_per_clkdm",
.pwrdm = { .name = "l4per_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_L4PER_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_HWSUP_SWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain abe_44xx_clkdm = {
.name = "abe_clkdm",
.pwrdm = { .name = "abe_pwrdm" },
.clkstctrl_reg = OMAP4430_CM1_ABE_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_HWSUP_SWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l3_instr_44xx_clkdm = {
.name = "l3_instr_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_L3INSTR_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l3_init_44xx_clkdm = {
.name = "l3_init_clkdm",
.pwrdm = { .name = "l3init_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_L3INIT_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_HWSUP_SWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain mpuss_44xx_clkdm = {
.name = "mpuss_clkdm",
.pwrdm = { .name = "mpu_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_MPU_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain mpu0_44xx_clkdm = {
.name = "mpu0_clkdm",
.pwrdm = { .name = "cpu0_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_PDA_CPU0_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain mpu1_44xx_clkdm = {
.name = "mpu1_clkdm",
.pwrdm = { .name = "cpu1_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_PDA_CPU1_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l3_emif_44xx_clkdm = {
.name = "l3_emif_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_MEMIF_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l4_ao_44xx_clkdm = {
.name = "l4_ao_clkdm",
.pwrdm = { .name = "always_on_core_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_ALWON_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain ducati_44xx_clkdm = {
.name = "ducati_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_DUCATI_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_HWSUP_SWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l3_2_44xx_clkdm = {
.name = "l3_2_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_L3_2_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_HWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l3_1_44xx_clkdm = {
.name = "l3_1_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_L3_1_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_HWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l3_d2d_44xx_clkdm = {
.name = "l3_d2d_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_D2D_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain iss_44xx_clkdm = {
.name = "iss_clkdm",
.pwrdm = { .name = "cam_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_CAM_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_HWSUP_SWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l3_dss_44xx_clkdm = {
.name = "l3_dss_clkdm",
.pwrdm = { .name = "dss_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_DSS_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_HWSUP_SWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l4_wkup_44xx_clkdm = {
.name = "l4_wkup_clkdm",
.pwrdm = { .name = "wkup_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_WKUP_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_HWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain emu_sys_44xx_clkdm = {
.name = "emu_sys_clkdm",
.pwrdm = { .name = "emu_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_EMU_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_HWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
static struct clockdomain l3_dma_44xx_clkdm = {
.name = "l3_dma_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.clkstctrl_reg = OMAP4430_CM_SDMA_CLKSTCTRL,
.clktrctrl_mask = OMAP4430_CLKTRCTRL_MASK,
.flags = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
};
#endif
#endif

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -67,7 +67,8 @@
#define CM_CLKSEL 0x0040
#define CM_CLKSEL1 CM_CLKSEL
#define CM_CLKSEL2 0x0044
#define CM_CLKSTCTRL 0x0048
#define OMAP2_CM_CLKSTCTRL 0x0048
#define OMAP4_CM_CLKSTCTRL 0x0000
/* Architecture-specific registers */
@ -88,7 +89,7 @@
#define OMAP3430_CM_CLKSEL1_PLL CM_CLKSEL
#define OMAP3430_CM_CLKSEL2_PLL CM_CLKSEL2
#define OMAP3430_CM_SLEEPDEP CM_CLKSEL2
#define OMAP3430_CM_CLKSEL3 CM_CLKSTCTRL
#define OMAP3430_CM_CLKSEL3 OMAP2_CM_CLKSTCTRL
#define OMAP3430_CM_CLKSTST 0x004c
#define OMAP3430ES2_CM_CLKSEL4 0x004c
#define OMAP3430ES2_CM_CLKSEL5 0x0050

Просмотреть файл

@ -44,17 +44,7 @@
#define MAX_DPLL_WAIT_TRIES 1000000
/**
* omap3_dpll_recalc - recalculate DPLL rate
* @clk: DPLL struct clk
*
* Recalculate and propagate the DPLL rate.
*/
unsigned long omap3_dpll_recalc(struct clk *clk)
{
return omap2_get_dpll_rate(clk);
}
/* Private functions */
/* _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)
@ -136,8 +126,6 @@ static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n)
return f;
}
/* 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
@ -237,6 +225,63 @@ static int _omap3_noncore_dpll_stop(struct clk *clk)
return 0;
}
/*
* _omap3_noncore_dpll_program - set non-core DPLL M,N values directly
* @clk: struct clk * of DPLL to set
* @m: DPLL multiplier to set
* @n: DPLL divider to set
* @freqsel: FREQSEL value to set
*
* Program the DPLL with the supplied M, N values, and wait for the DPLL to
* lock.. Returns -EINVAL upon error, or 0 upon success.
*/
static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
{
struct dpll_data *dd = clk->dpll_data;
u32 v;
/* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */
_omap3_noncore_dpll_bypass(clk);
/* Set jitter correction */
if (!cpu_is_omap44xx()) {
v = __raw_readl(dd->control_reg);
v &= ~dd->freqsel_mask;
v |= freqsel << __ffs(dd->freqsel_mask);
__raw_writel(v, dd->control_reg);
}
/* Set DPLL multiplier, divider */
v = __raw_readl(dd->mult_div1_reg);
v &= ~(dd->mult_mask | dd->div1_mask);
v |= m << __ffs(dd->mult_mask);
v |= (n - 1) << __ffs(dd->div1_mask);
__raw_writel(v, dd->mult_div1_reg);
/* We let the clock framework set the other output dividers later */
/* REVISIT: Set ramp-up delay? */
_omap3_noncore_dpll_lock(clk);
return 0;
}
/* Public functions */
/**
* omap3_dpll_recalc - recalculate DPLL rate
* @clk: DPLL struct clk
*
* Recalculate and propagate the DPLL rate.
*/
unsigned long omap3_dpll_recalc(struct clk *clk)
{
return omap2_get_dpll_rate(clk);
}
/* Non-CORE DPLL (e.g., DPLLs that do not control SDRC) clock functions */
/**
* omap3_noncore_dpll_enable - instruct a DPLL to enter bypass or lock mode
* @clk: pointer to a DPLL struct clk
@ -292,48 +337,6 @@ void omap3_noncore_dpll_disable(struct clk *clk)
/* Non-CORE DPLL rate set code */
/*
* omap3_noncore_dpll_program - set non-core DPLL M,N values directly
* @clk: struct clk * of DPLL to set
* @m: DPLL multiplier to set
* @n: DPLL divider to set
* @freqsel: FREQSEL value to set
*
* Program the DPLL with the supplied M, N values, and wait for the DPLL to
* lock.. Returns -EINVAL upon error, or 0 upon success.
*/
int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
{
struct dpll_data *dd = clk->dpll_data;
u32 v;
/* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */
_omap3_noncore_dpll_bypass(clk);
/* Set jitter correction */
if (!cpu_is_omap44xx()) {
v = __raw_readl(dd->control_reg);
v &= ~dd->freqsel_mask;
v |= freqsel << __ffs(dd->freqsel_mask);
__raw_writel(v, dd->control_reg);
}
/* Set DPLL multiplier, divider */
v = __raw_readl(dd->mult_div1_reg);
v &= ~(dd->mult_mask | dd->div1_mask);
v |= m << __ffs(dd->mult_mask);
v |= (n - 1) << __ffs(dd->div1_mask);
__raw_writel(v, dd->mult_div1_reg);
/* We let the clock framework set the other output dividers later */
/* REVISIT: Set ramp-up delay? */
_omap3_noncore_dpll_lock(clk);
return 0;
}
/**
* omap3_noncore_dpll_set_rate - set non-core DPLL rate
* @clk: struct clk * of DPLL to set

Просмотреть файл

@ -281,6 +281,7 @@ void __init omap4_check_revision(void)
if ((hawkeye == 0xb852) && (rev == 0x0)) {
omap_revision = OMAP4430_REV_ES1_0;
omap_chip.oc |= CHIP_IS_OMAP4430ES1;
pr_info("OMAP%04x %s\n", omap_rev() >> 16, rev_name);
return;
}

Просмотреть файл

@ -35,7 +35,9 @@
#include <plat/serial.h>
#include <plat/vram.h>
#include "clock.h"
#include "clock2xxx.h"
#include "clock34xx.h"
#include "clock44xx.h"
#include <plat/omap-pm.h>
#include <plat/powerdomain.h>
@ -312,15 +314,24 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
else if (cpu_is_omap34xx())
hwmods = omap34xx_hwmods;
pwrdm_init(powerdomains_omap);
clkdm_init(clockdomains_omap, clkdm_autodeps);
#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once the clkdev is ready */
/* The OPP tables have to be registered before a clk init */
omap_hwmod_init(hwmods);
omap2_mux_init();
omap_pm_if_early_init(mpu_opps, dsp_opps, l3_opps);
pwrdm_init(powerdomains_omap);
clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps);
#endif
omap2_clk_init();
if (cpu_is_omap24xx())
omap2xxx_clk_init();
else if (cpu_is_omap34xx())
omap3xxx_clk_init();
else if (cpu_is_omap44xx())
omap4xxx_clk_init();
else
pr_err("Could not init clock framework - unknown CPU\n");
omap_serial_early_init();
#ifndef CONFIG_ARCH_OMAP4
omap_hwmod_late_init();

Просмотреть файл

@ -299,15 +299,14 @@ static int _disable_wakeup(struct omap_hwmod *oh)
* be accessed by the IVA, there should be a sleepdep between the IVA
* initiator and the module). Only applies to modules in smart-idle
* mode. Returns -EINVAL upon error or passes along
* pwrdm_add_sleepdep() value upon success.
* clkdm_add_sleepdep() value upon success.
*/
static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
{
if (!oh->_clk)
return -EINVAL;
return pwrdm_add_sleepdep(oh->_clk->clkdm->pwrdm.ptr,
init_oh->_clk->clkdm->pwrdm.ptr);
return clkdm_add_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm);
}
/**
@ -320,15 +319,14 @@ static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
* be accessed by the IVA, there should be no sleepdep between the IVA
* initiator and the module). Only applies to modules in smart-idle
* mode. Returns -EINVAL upon error or passes along
* pwrdm_add_sleepdep() value upon success.
* clkdm_del_sleepdep() value upon success.
*/
static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
{
if (!oh->_clk)
return -EINVAL;
return pwrdm_del_sleepdep(oh->_clk->clkdm->pwrdm.ptr,
init_oh->_clk->clkdm->pwrdm.ptr);
return clkdm_del_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm);
}
/**
@ -994,6 +992,23 @@ void omap_hwmod_writel(u32 v, struct omap_hwmod *oh, u16 reg_offs)
__raw_writel(v, oh->_rt_va + reg_offs);
}
int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode)
{
u32 v;
int retval = 0;
if (!oh)
return -EINVAL;
v = oh->_sysc_cache;
retval = _set_slave_idlemode(oh, idlemode, &v);
if (!retval)
_write_sysconfig(v, oh);
return retval;
}
/**
* omap_hwmod_register - register a struct omap_hwmod
* @oh: struct omap_hwmod *

Просмотреть файл

@ -67,9 +67,9 @@ void omap2_pm_dump(int mode, int resume, unsigned int us)
#if 0
/* MPU */
DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRM_IRQENABLE_MPU_OFFSET);
DUMP_CM_MOD_REG(MPU_MOD, CM_CLKSTCTRL);
DUMP_PRM_MOD_REG(MPU_MOD, PM_PWSTCTRL);
DUMP_PRM_MOD_REG(MPU_MOD, PM_PWSTST);
DUMP_CM_MOD_REG(MPU_MOD, OMAP2_CM_CLKSTCTRL);
DUMP_PRM_MOD_REG(MPU_MOD, OMAP2_PM_PWSTCTRL);
DUMP_PRM_MOD_REG(MPU_MOD, OMAP2_PM_PWSTST);
DUMP_PRM_MOD_REG(MPU_MOD, PM_WKDEP);
#endif
#if 0
@ -93,7 +93,7 @@ void omap2_pm_dump(int mode, int resume, unsigned int us)
DUMP_CM_MOD_REG(WKUP_MOD, CM_ICLKEN);
DUMP_CM_MOD_REG(PLL_MOD, CM_CLKEN);
DUMP_CM_MOD_REG(PLL_MOD, CM_AUTOIDLE);
DUMP_PRM_MOD_REG(CORE_MOD, PM_PWSTST);
DUMP_PRM_MOD_REG(CORE_MOD, OMAP2_PM_PWSTST);
#endif
#if 0
/* DSP */
@ -103,11 +103,11 @@ void omap2_pm_dump(int mode, int resume, unsigned int us)
DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_IDLEST);
DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_AUTOIDLE);
DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSEL);
DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSTCTRL);
DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, RM_RSTCTRL);
DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, RM_RSTST);
DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, PM_PWSTCTRL);
DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, PM_PWSTST);
DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_CM_CLKSTCTRL);
DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_RM_RSTCTRL);
DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_RM_RSTST);
DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_PM_PWSTCTRL);
DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, OMAP2_PM_PWSTST);
}
#endif
} else {
@ -577,7 +577,7 @@ static int __init pm_dbg_init(void)
(void) debugfs_create_file("time", S_IRUGO,
d, (void *)DEBUG_FILE_TIMERS, &debug_fops);
pwrdm_for_each_nolock(pwrdms_setup, (void *)d);
pwrdm_for_each(pwrdms_setup, (void *)d);
pm_dbg_dir = debugfs_create_dir("registers", d);
if (IS_ERR(pm_dbg_dir))

Просмотреть файл

@ -57,11 +57,8 @@ static void (*omap2_sram_idle)(void);
static void (*omap2_sram_suspend)(u32 dllctrl, void __iomem *sdrc_dlla_ctrl,
void __iomem *sdrc_power);
static struct powerdomain *mpu_pwrdm;
static struct powerdomain *core_pwrdm;
static struct clockdomain *dsp_clkdm;
static struct clockdomain *gfx_clkdm;
static struct powerdomain *mpu_pwrdm, *core_pwrdm;
static struct clockdomain *dsp_clkdm, *mpu_clkdm, *wkup_clkdm, *gfx_clkdm;
static struct clk *osc_ck, *emul_ck;
@ -219,11 +216,12 @@ static void omap2_enter_mpu_retention(void)
/* Try to enter MPU retention */
prm_write_mod_reg((0x01 << OMAP_POWERSTATE_SHIFT) |
OMAP_LOGICRETSTATE,
MPU_MOD, PM_PWSTCTRL);
MPU_MOD, OMAP2_PM_PWSTCTRL);
} else {
/* Block MPU retention */
prm_write_mod_reg(OMAP_LOGICRETSTATE, MPU_MOD, PM_PWSTCTRL);
prm_write_mod_reg(OMAP_LOGICRETSTATE, MPU_MOD,
OMAP2_PM_PWSTCTRL);
only_idle = 1;
}
@ -333,9 +331,17 @@ static struct platform_suspend_ops omap_pm_ops = {
.valid = suspend_valid_only_mem,
};
static int _pm_clkdm_enable_hwsup(struct clockdomain *clkdm, void *unused)
/* XXX This function should be shareable between OMAP2xxx and OMAP3 */
static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
{
omap2_clkdm_allow_idle(clkdm);
clkdm_clear_all_wkdeps(clkdm);
clkdm_clear_all_sleepdeps(clkdm);
if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
omap2_clkdm_allow_idle(clkdm);
else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
atomic_read(&clkdm->usecount) == 0)
omap2_clkdm_sleep(clkdm);
return 0;
}
@ -348,14 +354,6 @@ static void __init prcm_setup_regs(void)
prm_write_mod_reg(OMAP24XX_AUTOIDLE, OCP_MOD,
OMAP2_PRCM_SYSCONFIG_OFFSET);
/* Set all domain wakeup dependencies */
prm_write_mod_reg(OMAP_EN_WKUP_MASK, MPU_MOD, PM_WKDEP);
prm_write_mod_reg(0, OMAP24XX_DSP_MOD, PM_WKDEP);
prm_write_mod_reg(0, GFX_MOD, PM_WKDEP);
prm_write_mod_reg(0, CORE_MOD, PM_WKDEP);
if (cpu_is_omap2430())
prm_write_mod_reg(0, OMAP2430_MDM_MOD, PM_WKDEP);
/*
* Set CORE powerdomain memory banks to retain their contents
* during RETENTION
@ -384,8 +382,12 @@ static void __init prcm_setup_regs(void)
pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
omap2_clkdm_sleep(gfx_clkdm);
/* Enable clockdomain hardware-supervised control for all clkdms */
clkdm_for_each(_pm_clkdm_enable_hwsup, NULL);
/*
* Clear clockdomain wakeup dependencies and enable
* hardware-supervised idle for all clkdms
*/
clkdm_for_each(clkdms_setup, NULL);
clkdm_add_wkdep(mpu_clkdm, wkup_clkdm);
/* Enable clock autoidle for all domains */
cm_write_mod_reg(OMAP24XX_AUTO_CAM |
@ -481,7 +483,7 @@ static int __init omap2_pm_init(void)
l = prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_REVISION_OFFSET);
printk(KERN_INFO "PRCM revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
/* Look up important powerdomains, clockdomains */
/* Look up important powerdomains */
mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
if (!mpu_pwrdm)
@ -491,9 +493,19 @@ static int __init omap2_pm_init(void)
if (!core_pwrdm)
pr_err("PM: core_pwrdm not found\n");
/* Look up important clockdomains */
mpu_clkdm = clkdm_lookup("mpu_clkdm");
if (!mpu_clkdm)
pr_err("PM: mpu_clkdm not found\n");
wkup_clkdm = clkdm_lookup("wkup_clkdm");
if (!wkup_clkdm)
pr_err("PM: wkup_clkdm not found\n");
dsp_clkdm = clkdm_lookup("dsp_clkdm");
if (!dsp_clkdm)
pr_err("PM: mpu_clkdm not found\n");
pr_err("PM: dsp_clkdm not found\n");
gfx_clkdm = clkdm_lookup("gfx_clkdm");
if (!gfx_clkdm)

Просмотреть файл

@ -685,7 +685,7 @@ static void __init omap3_iva_idle(void)
prm_write_mod_reg(OMAP3430_RST1_IVA2 |
OMAP3430_RST2_IVA2 |
OMAP3430_RST3_IVA2,
OMAP3430_IVA2_MOD, RM_RSTCTRL);
OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
/* Enable IVA2 clock */
cm_write_mod_reg(OMAP3430_CM_FCLKEN_IVA2_EN_IVA2,
@ -696,7 +696,7 @@ static void __init omap3_iva_idle(void)
OMAP343X_CONTROL_IVA2_BOOTMOD);
/* Un-reset IVA2 */
prm_write_mod_reg(0, OMAP3430_IVA2_MOD, RM_RSTCTRL);
prm_write_mod_reg(0, OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
/* Disable IVA2 clock */
cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN);
@ -705,7 +705,7 @@ static void __init omap3_iva_idle(void)
prm_write_mod_reg(OMAP3430_RST1_IVA2 |
OMAP3430_RST2_IVA2 |
OMAP3430_RST3_IVA2,
OMAP3430_IVA2_MOD, RM_RSTCTRL);
OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
}
static void __init omap3_d2d_idle(void)
@ -728,8 +728,8 @@ static void __init omap3_d2d_idle(void)
/* reset modem */
prm_write_mod_reg(OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON |
OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RST,
CORE_MOD, RM_RSTCTRL);
prm_write_mod_reg(0, CORE_MOD, RM_RSTCTRL);
CORE_MOD, OMAP2_RM_RSTCTRL);
prm_write_mod_reg(0, CORE_MOD, OMAP2_RM_RSTCTRL);
}
static void __init prcm_setup_regs(void)
@ -916,13 +916,13 @@ static void __init prcm_setup_regs(void)
prm_write_mod_reg(0, OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL);
/* Clear any pending 'reset' flags */
prm_write_mod_reg(0xffffffff, MPU_MOD, RM_RSTST);
prm_write_mod_reg(0xffffffff, CORE_MOD, RM_RSTST);
prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, RM_RSTST);
prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, RM_RSTST);
prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, RM_RSTST);
prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, RM_RSTST);
prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, RM_RSTST);
prm_write_mod_reg(0xffffffff, MPU_MOD, OMAP2_RM_RSTST);
prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP2_RM_RSTST);
prm_write_mod_reg(0xffffffff, OMAP3430_PER_MOD, OMAP2_RM_RSTST);
prm_write_mod_reg(0xffffffff, OMAP3430_EMU_MOD, OMAP2_RM_RSTST);
prm_write_mod_reg(0xffffffff, OMAP3430_NEON_MOD, OMAP2_RM_RSTST);
prm_write_mod_reg(0xffffffff, OMAP3430_DSS_MOD, OMAP2_RM_RSTST);
prm_write_mod_reg(0xffffffff, OMAP3430ES2_USBHOST_MOD, OMAP2_RM_RSTST);
/* Clear any pending PRCM interrupts */
prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
@ -998,6 +998,9 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
*/
static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
{
clkdm_clear_all_wkdeps(clkdm);
clkdm_clear_all_sleepdeps(clkdm);
if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
omap2_clkdm_allow_idle(clkdm);
else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
@ -1018,6 +1021,7 @@ void omap_push_sram_idle(void)
static int __init omap3_pm_init(void)
{
struct power_state *pwrst, *tmp;
struct clockdomain *neon_clkdm, *per_clkdm, *mpu_clkdm, *core_clkdm;
int ret;
if (!cpu_is_omap34xx())
@ -1057,6 +1061,11 @@ static int __init omap3_pm_init(void)
core_pwrdm = pwrdm_lookup("core_pwrdm");
cam_pwrdm = pwrdm_lookup("cam_pwrdm");
neon_clkdm = clkdm_lookup("neon_clkdm");
mpu_clkdm = clkdm_lookup("mpu_clkdm");
per_clkdm = clkdm_lookup("per_clkdm");
core_clkdm = clkdm_lookup("core_clkdm");
omap_push_sram_idle();
#ifdef CONFIG_SUSPEND
suspend_set_ops(&omap_pm_ops);
@ -1065,14 +1074,14 @@ static int __init omap3_pm_init(void)
pm_idle = omap3_pm_idle;
omap3_idle_init();
pwrdm_add_wkdep(neon_pwrdm, mpu_pwrdm);
clkdm_add_wkdep(neon_clkdm, mpu_clkdm);
/*
* REVISIT: This wkdep is only necessary when GPIO2-6 are enabled for
* IO-pad wakeup. Otherwise it will unnecessarily waste power
* waking up PER with every CORE wakeup - see
* http://marc.info/?l=linux-omap&m=121852150710062&w=2
*/
pwrdm_add_wkdep(per_pwrdm, core_pwrdm);
clkdm_add_wkdep(per_clkdm, core_clkdm);
if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
omap3_secure_ram_storage =

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,8 +1,8 @@
/*
* OMAP2/3 common powerdomain definitions
*
* Copyright (C) 2007-8 Texas Instruments, Inc.
* Copyright (C) 2007-8 Nokia Corporation
* Copyright (C) 2007-2008 Texas Instruments, Inc.
* Copyright (C) 2007-2009 Nokia Corporation
*
* Written by Paul Walmsley
* Debugging and integration fixes by Jouni Högander
@ -12,26 +12,21 @@
* published by the Free Software Foundation.
*/
/*
* To Do List
* -> Move the Sleep/Wakeup dependencies from Power Domain framework to
* Clock Domain Framework
*/
#ifndef ARCH_ARM_MACH_OMAP2_POWERDOMAINS
#define ARCH_ARM_MACH_OMAP2_POWERDOMAINS
/*
* This file contains all of the powerdomains that have some element
* of software control for the OMAP24xx and OMAP34XX chips.
*
* A few notes:
* of software control for the OMAP24xx and OMAP34xx chips.
*
* This is not an exhaustive listing of powerdomains on the chips; only
* powerdomains that can be controlled in software.
*
* A useful validation rule for struct powerdomain:
* Any powerdomain referenced by a wkdep_srcs or sleepdep_srcs array
* must have a dep_bit assigned. So wkdep_srcs/sleepdep_srcs are really
* just software-controllable dependencies. Non-software-controllable
* dependencies do exist, but they are not encoded below (yet).
*
* 24xx does not support programmable sleep dependencies (SLEEPDEP)
*
*/
/*
@ -41,26 +36,17 @@
*
* On the 2420, this is a 'C55 DSP called, simply, the DSP. Its
* powerdomain is called the "DSP power domain." On the 2430, the
* on-board DSP is a 'C64 DSP, now called the IVA2 or IVA2.1. Its
* powerdomain is still called the "DSP power domain." On the 3430,
* the DSP is a 'C64 DSP like the 2430, also known as the IVA2; but
* its powerdomain is now called the "IVA2 power domain."
* on-board DSP is a 'C64 DSP, now called (along with its hardware
* accelerators) the IVA2 or IVA2.1. Its powerdomain is still called
* the "DSP power domain." On the 3430, the DSP is a 'C64 DSP like the
* 2430, also known as the IVA2; but its powerdomain is now called the
* "IVA2 power domain."
*
* The 2420 also has something called the IVA, which is a separate ARM
* core, and has nothing to do with the DSP/IVA2.
*
* Ideally the DSP/IVA2 could just be the same powerdomain, but the PRCM
* address offset is different between the C55 and C64 DSPs.
*
* The overly-specific dep_bit names are due to a bit name collision
* with CM_FCLKEN_{DSP,IVA2}. The DSP/IVA2 PM_WKDEP and CM_SLEEPDEP shift
* value are the same for all powerdomains: 2
*/
/*
* XXX should dep_bit be a mask, so we can test to see if it is 0 as a
* sanity check?
* XXX encode hardware fixed wakeup dependencies -- esp. for 3430 CORE
*/
#include <plat/powerdomain.h>
@ -68,69 +54,23 @@
#include "prcm-common.h"
#include "prm.h"
#include "cm.h"
/* OMAP2/3-common powerdomains and wakeup dependencies */
/*
* 2420/2430 PM_WKDEP_GFX: CORE, MPU, WKUP
* 3430ES1 PM_WKDEP_GFX: adds IVA2, removes CORE
* 3430ES2 PM_WKDEP_SGX: adds IVA2, removes CORE
*/
static struct pwrdm_dep gfx_sgx_wkdeps[] = {
{
.pwrdm_name = "core_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.pwrdm_name = "iva2_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.pwrdm_name = "mpu_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
CHIP_IS_OMAP3430)
},
{
.pwrdm_name = "wkup_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
CHIP_IS_OMAP3430)
},
{ NULL },
};
/*
* 3430: CM_SLEEPDEP_CAM: MPU
* 3430ES1: CM_SLEEPDEP_GFX: MPU
* 3430ES2: CM_SLEEPDEP_SGX: MPU
*/
static struct pwrdm_dep cam_gfx_sleepdeps[] = {
{
.pwrdm_name = "mpu_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{ NULL },
};
#include "powerdomains24xx.h"
#include "powerdomains34xx.h"
#include "powerdomains44xx.h"
/* OMAP2/3-common powerdomains */
/*
* OMAP2/3 common powerdomains
*/
#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
/*
* The GFX powerdomain is not present on 3430ES2, but currently we do not
* have a macro to filter it out at compile-time.
*/
static struct powerdomain gfx_pwrdm = {
static struct powerdomain gfx_omap2_pwrdm = {
.name = "gfx_pwrdm",
.prcm_offs = GFX_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
CHIP_IS_OMAP3430ES1),
.wkdep_srcs = gfx_sgx_wkdeps,
.sleepdep_srcs = cam_gfx_sleepdeps,
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRDM_POWER_RET,
.banks = 1,
@ -142,22 +82,24 @@ static struct powerdomain gfx_pwrdm = {
},
};
static struct powerdomain wkup_pwrdm = {
static struct powerdomain wkup_omap2_pwrdm = {
.name = "wkup_pwrdm",
.prcm_offs = WKUP_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
.dep_bit = OMAP_EN_WKUP_SHIFT,
};
#endif
/* As powerdomains are added or removed above, this list must also be changed */
static struct powerdomain *powerdomains_omap[] __initdata = {
&gfx_pwrdm,
&wkup_pwrdm,
#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
&wkup_omap2_pwrdm,
&gfx_omap2_pwrdm,
#endif
#ifdef CONFIG_ARCH_OMAP24XX
#ifdef CONFIG_ARCH_OMAP2
&dsp_pwrdm,
&mpu_24xx_pwrdm,
&core_24xx_pwrdm,
@ -167,12 +109,12 @@ static struct powerdomain *powerdomains_omap[] __initdata = {
&mdm_pwrdm,
#endif
#ifdef CONFIG_ARCH_OMAP34XX
#ifdef CONFIG_ARCH_OMAP3
&iva2_pwrdm,
&mpu_34xx_pwrdm,
&mpu_3xxx_pwrdm,
&neon_pwrdm,
&core_34xx_pre_es3_1_pwrdm,
&core_34xx_es3_1_pwrdm,
&core_3xxx_pre_es3_1_pwrdm,
&core_3xxx_es3_1_pwrdm,
&cam_pwrdm,
&dss_pwrdm,
&per_pwrdm,
@ -186,6 +128,24 @@ static struct powerdomain *powerdomains_omap[] __initdata = {
&dpll5_pwrdm,
#endif
#ifdef CONFIG_ARCH_OMAP4
&core_44xx_pwrdm,
&gfx_44xx_pwrdm,
&abe_44xx_pwrdm,
&dss_44xx_pwrdm,
&tesla_44xx_pwrdm,
&wkup_44xx_pwrdm,
&cpu0_44xx_pwrdm,
&cpu1_44xx_pwrdm,
&emu_44xx_pwrdm,
&mpu_44xx_pwrdm,
&ivahd_44xx_pwrdm,
&cam_44xx_pwrdm,
&l3init_44xx_pwrdm,
&l4per_44xx_pwrdm,
&always_on_core_44xx_pwrdm,
&cefuse_44xx_pwrdm,
#endif
NULL
};

Просмотреть файл

@ -2,7 +2,7 @@
* OMAP24XX powerdomain definitions
*
* Copyright (C) 2007-2008 Texas Instruments, Inc.
* Copyright (C) 2007-2008 Nokia Corporation
* Copyright (C) 2007-2009 Nokia Corporation
*
* Written by Paul Walmsley
* Debugging and integration fixes by Jouni Högander
@ -32,90 +32,12 @@
#ifdef CONFIG_ARCH_OMAP24XX
/* Wakeup dependency source arrays */
/*
* 2420/2430 PM_WKDEP_DSP: CORE, MPU, WKUP
* 2430 PM_WKDEP_MDM: same as above
*/
static struct pwrdm_dep dsp_mdm_24xx_wkdeps[] = {
{
.pwrdm_name = "core_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.pwrdm_name = "mpu_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.pwrdm_name = "wkup_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{ NULL },
};
/*
* 2420 PM_WKDEP_MPU: CORE, DSP, WKUP
* 2430 adds MDM
*/
static struct pwrdm_dep mpu_24xx_wkdeps[] = {
{
.pwrdm_name = "core_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.pwrdm_name = "dsp_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.pwrdm_name = "wkup_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.pwrdm_name = "mdm_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
},
{ NULL },
};
/*
* 2420 PM_WKDEP_CORE: DSP, GFX, MPU, WKUP
* 2430 adds MDM
*/
static struct pwrdm_dep core_24xx_wkdeps[] = {
{
.pwrdm_name = "dsp_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.pwrdm_name = "gfx_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.pwrdm_name = "mpu_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.pwrdm_name = "wkup_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX)
},
{
.pwrdm_name = "mdm_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
},
{ NULL },
};
/* Powerdomains */
static struct powerdomain dsp_pwrdm = {
.name = "dsp_pwrdm",
.prcm_offs = OMAP24XX_DSP_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
.dep_bit = OMAP24XX_PM_WKDEP_MPU_EN_DSP_SHIFT,
.wkdep_srcs = dsp_mdm_24xx_wkdeps,
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRDM_POWER_RET,
.banks = 1,
@ -131,8 +53,6 @@ static struct powerdomain mpu_24xx_pwrdm = {
.name = "mpu_pwrdm",
.prcm_offs = MPU_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
.dep_bit = OMAP24XX_EN_MPU_SHIFT,
.wkdep_srcs = mpu_24xx_wkdeps,
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 1,
@ -148,9 +68,7 @@ static struct powerdomain core_24xx_pwrdm = {
.name = "core_pwrdm",
.prcm_offs = CORE_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
.wkdep_srcs = core_24xx_wkdeps,
.pwrsts = PWRSTS_OFF_RET_ON,
.dep_bit = OMAP24XX_EN_CORE_SHIFT,
.banks = 3,
.pwrsts_mem_ret = {
[0] = PWRSTS_OFF_RET, /* MEM1RETSTATE */
@ -176,13 +94,10 @@ static struct powerdomain core_24xx_pwrdm = {
/* XXX 2430 KILLDOMAINWKUP bit? No current users apparently */
/* Another case of bit name collisions between several registers: EN_MDM */
static struct powerdomain mdm_pwrdm = {
.name = "mdm_pwrdm",
.prcm_offs = OMAP2430_MDM_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
.dep_bit = OMAP2430_PM_WKDEP_MPU_EN_MDM_SHIFT,
.wkdep_srcs = dsp_mdm_24xx_wkdeps,
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRDM_POWER_RET,
.banks = 1,

Просмотреть файл

@ -1,8 +1,8 @@
/*
* OMAP34XX powerdomain definitions
* OMAP3 powerdomain definitions
*
* Copyright (C) 2007-2008 Texas Instruments, Inc.
* Copyright (C) 2007-2008 Nokia Corporation
* Copyright (C) 2007-2010 Nokia Corporation
*
* Written by Paul Walmsley
* Debugging and integration fixes by Jouni Högander
@ -32,128 +32,7 @@
* 34XX-specific powerdomains, dependencies
*/
#ifdef CONFIG_ARCH_OMAP34XX
/*
* 3430: PM_WKDEP_{PER,USBHOST}: CORE, IVA2, MPU, WKUP
* (USBHOST is ES2 only)
*/
static struct pwrdm_dep per_usbhost_wkdeps[] = {
{
.pwrdm_name = "core_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.pwrdm_name = "iva2_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.pwrdm_name = "mpu_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.pwrdm_name = "wkup_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{ NULL },
};
/*
* 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER
*/
static struct pwrdm_dep mpu_34xx_wkdeps[] = {
{
.pwrdm_name = "core_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.pwrdm_name = "iva2_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.pwrdm_name = "dss_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.pwrdm_name = "per_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{ NULL },
};
/*
* 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER
*/
static struct pwrdm_dep iva2_wkdeps[] = {
{
.pwrdm_name = "core_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.pwrdm_name = "mpu_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.pwrdm_name = "wkup_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.pwrdm_name = "dss_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.pwrdm_name = "per_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{ NULL },
};
/* 3430 PM_WKDEP_{CAM,DSS}: IVA2, MPU, WKUP */
static struct pwrdm_dep cam_dss_wkdeps[] = {
{
.pwrdm_name = "iva2_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.pwrdm_name = "mpu_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.pwrdm_name = "wkup_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{ NULL },
};
/* 3430: PM_WKDEP_NEON: MPU */
static struct pwrdm_dep neon_wkdeps[] = {
{
.pwrdm_name = "mpu_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{ NULL },
};
/* Sleep dependency source arrays for 34xx-specific pwrdms - 34XX only */
/*
* 3430: CM_SLEEPDEP_{DSS,PER}: MPU, IVA
* 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA
*/
static struct pwrdm_dep dss_per_usbhost_sleepdeps[] = {
{
.pwrdm_name = "mpu_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{
.pwrdm_name = "iva2_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
},
{ NULL },
};
#ifdef CONFIG_ARCH_OMAP3
/*
* Powerdomains
@ -163,8 +42,6 @@ static struct powerdomain iva2_pwrdm = {
.name = "iva2_pwrdm",
.prcm_offs = OMAP3430_IVA2_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.dep_bit = OMAP3430_PM_WKDEP_MPU_EN_IVA2_SHIFT,
.wkdep_srcs = iva2_wkdeps,
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 4,
@ -182,12 +59,10 @@ static struct powerdomain iva2_pwrdm = {
},
};
static struct powerdomain mpu_34xx_pwrdm = {
static struct powerdomain mpu_3xxx_pwrdm = {
.name = "mpu_pwrdm",
.prcm_offs = MPU_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.dep_bit = OMAP3430_EN_MPU_SHIFT,
.wkdep_srcs = mpu_34xx_wkdeps,
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.flags = PWRDM_HAS_MPU_QUIRK,
@ -200,15 +75,13 @@ static struct powerdomain mpu_34xx_pwrdm = {
},
};
/* No wkdeps or sleepdeps for 34xx core apparently */
static struct powerdomain core_34xx_pre_es3_1_pwrdm = {
static struct powerdomain core_3xxx_pre_es3_1_pwrdm = {
.name = "core_pwrdm",
.prcm_offs = CORE_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
CHIP_IS_OMAP3430ES2 |
CHIP_IS_OMAP3430ES3_0),
.pwrsts = PWRSTS_OFF_RET_ON,
.dep_bit = OMAP3430_EN_CORE_SHIFT,
.banks = 2,
.pwrsts_mem_ret = {
[0] = PWRSTS_OFF_RET, /* MEM1RETSTATE */
@ -220,13 +93,11 @@ static struct powerdomain core_34xx_pre_es3_1_pwrdm = {
},
};
/* No wkdeps or sleepdeps for 34xx core apparently */
static struct powerdomain core_34xx_es3_1_pwrdm = {
static struct powerdomain core_3xxx_es3_1_pwrdm = {
.name = "core_pwrdm",
.prcm_offs = CORE_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES3_1),
.pwrsts = PWRSTS_OFF_RET_ON,
.dep_bit = OMAP3430_EN_CORE_SHIFT,
.flags = PWRDM_HAS_HDWR_SAR, /* for USBTLL only */
.banks = 2,
.pwrsts_mem_ret = {
@ -239,14 +110,10 @@ static struct powerdomain core_34xx_es3_1_pwrdm = {
},
};
/* Another case of bit name collisions between several registers: EN_DSS */
static struct powerdomain dss_pwrdm = {
.name = "dss_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.prcm_offs = OMAP3430_DSS_MOD,
.dep_bit = OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,
.wkdep_srcs = cam_dss_wkdeps,
.sleepdep_srcs = dss_per_usbhost_sleepdeps,
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRDM_POWER_RET,
.banks = 1,
@ -267,8 +134,6 @@ static struct powerdomain sgx_pwrdm = {
.name = "sgx_pwrdm",
.prcm_offs = OMAP3430ES2_SGX_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
.wkdep_srcs = gfx_sgx_wkdeps,
.sleepdep_srcs = cam_gfx_sleepdeps,
/* XXX This is accurate for 3430 SGX, but what about GFX? */
.pwrsts = PWRSTS_OFF_ON,
.pwrsts_logic_ret = PWRDM_POWER_RET,
@ -285,8 +150,6 @@ static struct powerdomain cam_pwrdm = {
.name = "cam_pwrdm",
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.prcm_offs = OMAP3430_CAM_MOD,
.wkdep_srcs = cam_dss_wkdeps,
.sleepdep_srcs = cam_gfx_sleepdeps,
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRDM_POWER_RET,
.banks = 1,
@ -302,9 +165,6 @@ static struct powerdomain per_pwrdm = {
.name = "per_pwrdm",
.prcm_offs = OMAP3430_PER_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.dep_bit = OMAP3430_EN_PER_SHIFT,
.wkdep_srcs = per_usbhost_wkdeps,
.sleepdep_srcs = dss_per_usbhost_sleepdeps,
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 1,
@ -326,7 +186,6 @@ static struct powerdomain neon_pwrdm = {
.name = "neon_pwrdm",
.prcm_offs = OMAP3430_NEON_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
.wkdep_srcs = neon_wkdeps,
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRDM_POWER_RET,
};
@ -335,8 +194,6 @@ static struct powerdomain usbhost_pwrdm = {
.name = "usbhost_pwrdm",
.prcm_offs = OMAP3430ES2_USBHOST_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
.wkdep_srcs = per_usbhost_wkdeps,
.sleepdep_srcs = dss_per_usbhost_sleepdeps,
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRDM_POWER_RET,
/*
@ -386,7 +243,7 @@ static struct powerdomain dpll5_pwrdm = {
};
#endif /* CONFIG_ARCH_OMAP34XX */
#endif /* CONFIG_ARCH_OMAP3 */
#endif

Просмотреть файл

@ -0,0 +1,310 @@
/*
* OMAP4 Power domains framework
*
* Copyright (C) 2009 Texas Instruments, Inc.
* Copyright (C) 2009 Nokia Corporation
*
* Abhijit Pagare (abhijitpagare@ti.com)
* Benoit Cousson (b-cousson@ti.com)
* Paul Walmsley
*
* This file is automatically generated from the OMAP hardware databases.
* We respectfully ask that any modifications to this file be coordinated
* with the public linux-omap@vger.kernel.org mailing list and the
* authors above to ensure that the autogeneration scripts are kept
* up-to-date with the file contents.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __ARCH_ARM_MACH_OMAP2_POWERDOMAINS44XX_H
#define __ARCH_ARM_MACH_OMAP2_POWERDOMAINS44XX_H
#include <plat/powerdomain.h>
#include "prcm-common.h"
#include "cm.h"
#include "cm-regbits-44xx.h"
#include "prm.h"
#include "prm-regbits-44xx.h"
#if defined(CONFIG_ARCH_OMAP4)
/* core_44xx_pwrdm: CORE power domain */
static struct powerdomain core_44xx_pwrdm = {
.name = "core_pwrdm",
.prcm_offs = OMAP4430_PRM_CORE_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 5,
.pwrsts_mem_ret = {
[0] = PWRDM_POWER_OFF, /* core_nret_bank */
[1] = PWRSTS_OFF_RET, /* core_ocmram */
[2] = PWRDM_POWER_RET, /* core_other_bank */
[3] = PWRSTS_OFF_RET, /* ducati_l2ram */
[4] = PWRSTS_OFF_RET, /* ducati_unicache */
},
.pwrsts_mem_on = {
[0] = PWRDM_POWER_ON, /* core_nret_bank */
[1] = PWRSTS_OFF_RET, /* core_ocmram */
[2] = PWRDM_POWER_ON, /* core_other_bank */
[3] = PWRDM_POWER_ON, /* ducati_l2ram */
[4] = PWRDM_POWER_ON, /* ducati_unicache */
},
};
/* gfx_44xx_pwrdm: 3D accelerator power domain */
static struct powerdomain gfx_44xx_pwrdm = {
.name = "gfx_pwrdm",
.prcm_offs = OMAP4430_PRM_GFX_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_ON,
.banks = 1,
.pwrsts_mem_ret = {
[0] = PWRDM_POWER_OFF, /* gfx_mem */
},
.pwrsts_mem_on = {
[0] = PWRDM_POWER_ON, /* gfx_mem */
},
};
/* abe_44xx_pwrdm: Audio back end power domain */
static struct powerdomain abe_44xx_pwrdm = {
.name = "abe_pwrdm",
.prcm_offs = OMAP4430_PRM_ABE_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRDM_POWER_OFF,
.banks = 2,
.pwrsts_mem_ret = {
[0] = PWRDM_POWER_RET, /* aessmem */
[1] = PWRDM_POWER_OFF, /* periphmem */
},
.pwrsts_mem_on = {
[0] = PWRDM_POWER_ON, /* aessmem */
[1] = PWRDM_POWER_ON, /* periphmem */
},
};
/* dss_44xx_pwrdm: Display subsystem power domain */
static struct powerdomain dss_44xx_pwrdm = {
.name = "dss_pwrdm",
.prcm_offs = OMAP4430_PRM_DSS_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 1,
.pwrsts_mem_ret = {
[0] = PWRDM_POWER_OFF, /* dss_mem */
},
.pwrsts_mem_on = {
[0] = PWRDM_POWER_ON, /* dss_mem */
},
};
/* tesla_44xx_pwrdm: Tesla processor power domain */
static struct powerdomain tesla_44xx_pwrdm = {
.name = "tesla_pwrdm",
.prcm_offs = OMAP4430_PRM_TESLA_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 3,
.pwrsts_mem_ret = {
[0] = PWRDM_POWER_RET, /* tesla_edma */
[1] = PWRSTS_OFF_RET, /* tesla_l1 */
[2] = PWRSTS_OFF_RET, /* tesla_l2 */
},
.pwrsts_mem_on = {
[0] = PWRDM_POWER_ON, /* tesla_edma */
[1] = PWRDM_POWER_ON, /* tesla_l1 */
[2] = PWRDM_POWER_ON, /* tesla_l2 */
},
};
/* wkup_44xx_pwrdm: Wake-up power domain */
static struct powerdomain wkup_44xx_pwrdm = {
.name = "wkup_pwrdm",
.prcm_offs = OMAP4430_PRM_WKUP_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRDM_POWER_ON,
.banks = 1,
.pwrsts_mem_ret = {
[0] = PWRDM_POWER_OFF, /* wkup_bank */
},
.pwrsts_mem_on = {
[0] = PWRDM_POWER_ON, /* wkup_bank */
},
};
/* cpu0_44xx_pwrdm: MPU0 processor and Neon coprocessor power domain */
static struct powerdomain cpu0_44xx_pwrdm = {
.name = "cpu0_pwrdm",
.prcm_offs = OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 1,
.pwrsts_mem_ret = {
[0] = PWRSTS_OFF_RET, /* cpu0_l1 */
},
.pwrsts_mem_on = {
[0] = PWRDM_POWER_ON, /* cpu0_l1 */
},
};
/* cpu1_44xx_pwrdm: MPU1 processor and Neon coprocessor power domain */
static struct powerdomain cpu1_44xx_pwrdm = {
.name = "cpu1_pwrdm",
.prcm_offs = OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 1,
.pwrsts_mem_ret = {
[0] = PWRSTS_OFF_RET, /* cpu1_l1 */
},
.pwrsts_mem_on = {
[0] = PWRDM_POWER_ON, /* cpu1_l1 */
},
};
/* emu_44xx_pwrdm: Emulation power domain */
static struct powerdomain emu_44xx_pwrdm = {
.name = "emu_pwrdm",
.prcm_offs = OMAP4430_PRM_EMU_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_ON,
.banks = 1,
.pwrsts_mem_ret = {
[0] = PWRDM_POWER_OFF, /* emu_bank */
},
.pwrsts_mem_on = {
[0] = PWRDM_POWER_ON, /* emu_bank */
},
};
/* mpu_44xx_pwrdm: Modena processor and the Neon coprocessor power domain */
static struct powerdomain mpu_44xx_pwrdm = {
.name = "mpu_pwrdm",
.prcm_offs = OMAP4430_PRM_MPU_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 3,
.pwrsts_mem_ret = {
[0] = PWRSTS_OFF_RET, /* mpu_l1 */
[1] = PWRSTS_OFF_RET, /* mpu_l2 */
[2] = PWRDM_POWER_RET, /* mpu_ram */
},
.pwrsts_mem_on = {
[0] = PWRDM_POWER_ON, /* mpu_l1 */
[1] = PWRDM_POWER_ON, /* mpu_l2 */
[2] = PWRDM_POWER_ON, /* mpu_ram */
},
};
/* ivahd_44xx_pwrdm: IVA-HD power domain */
static struct powerdomain ivahd_44xx_pwrdm = {
.name = "ivahd_pwrdm",
.prcm_offs = OMAP4430_PRM_IVAHD_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRDM_POWER_OFF,
.banks = 4,
.pwrsts_mem_ret = {
[0] = PWRDM_POWER_OFF, /* hwa_mem */
[1] = PWRSTS_OFF_RET, /* sl2_mem */
[2] = PWRSTS_OFF_RET, /* tcm1_mem */
[3] = PWRSTS_OFF_RET, /* tcm2_mem */
},
.pwrsts_mem_on = {
[0] = PWRDM_POWER_ON, /* hwa_mem */
[1] = PWRDM_POWER_ON, /* sl2_mem */
[2] = PWRDM_POWER_ON, /* tcm1_mem */
[3] = PWRDM_POWER_ON, /* tcm2_mem */
},
};
/* cam_44xx_pwrdm: Camera subsystem power domain */
static struct powerdomain cam_44xx_pwrdm = {
.name = "cam_pwrdm",
.prcm_offs = OMAP4430_PRM_CAM_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_ON,
.banks = 1,
.pwrsts_mem_ret = {
[0] = PWRDM_POWER_OFF, /* cam_mem */
},
.pwrsts_mem_on = {
[0] = PWRDM_POWER_ON, /* cam_mem */
},
};
/* l3init_44xx_pwrdm: L3 initators pheripherals power domain */
static struct powerdomain l3init_44xx_pwrdm = {
.name = "l3init_pwrdm",
.prcm_offs = OMAP4430_PRM_L3INIT_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 1,
.pwrsts_mem_ret = {
[0] = PWRDM_POWER_OFF, /* l3init_bank1 */
},
.pwrsts_mem_on = {
[0] = PWRDM_POWER_ON, /* l3init_bank1 */
},
};
/* l4per_44xx_pwrdm: Target peripherals power domain */
static struct powerdomain l4per_44xx_pwrdm = {
.name = "l4per_pwrdm",
.prcm_offs = OMAP4430_PRM_L4PER_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_RET_ON,
.pwrsts_logic_ret = PWRSTS_OFF_RET,
.banks = 2,
.pwrsts_mem_ret = {
[0] = PWRDM_POWER_OFF, /* nonretained_bank */
[1] = PWRDM_POWER_RET, /* retained_bank */
},
.pwrsts_mem_on = {
[0] = PWRDM_POWER_ON, /* nonretained_bank */
[1] = PWRDM_POWER_ON, /* retained_bank */
},
};
/*
* always_on_core_44xx_pwrdm: Always ON logic that sits in VDD_CORE voltage
* domain
*/
static struct powerdomain always_on_core_44xx_pwrdm = {
.name = "always_on_core_pwrdm",
.prcm_offs = OMAP4430_PRM_ALWAYS_ON_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRDM_POWER_ON,
};
/* cefuse_44xx_pwrdm: Customer efuse controller power domain */
static struct powerdomain cefuse_44xx_pwrdm = {
.name = "cefuse_pwrdm",
.prcm_offs = OMAP4430_PRM_CEFUSE_MOD,
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
.pwrsts = PWRSTS_OFF_ON,
};
/*
* The following power domains are not under SW control
*
* always_on_iva
* always_on_mpu
* stdefuse
*/
#endif
#endif

Просмотреть файл

@ -119,6 +119,15 @@
#define OMAP4430_CHIRONSS_CHIRONSS_CPU0_MOD 0x0400
#define OMAP4430_CHIRONSS_CHIRONSS_CPU1_MOD 0x0800
/* Base Addresses for the OMAP4 */
#define OMAP4430_CM1_BASE 0x4a004000
#define OMAP4430_CM2_BASE 0x4a008000
#define OMAP4430_PRM_BASE 0x4a306000
#define OMAP4430_SCRM_BASE 0x4a30a000
#define OMAP4430_CHIRONSS_BASE 0x48243000
/* 24XX register bits shared between CM & PRM registers */
/* CM_FCLKEN1_CORE, CM_ICLKEN1_CORE, PM_WKEN1_CORE shared bits */

Просмотреть файл

@ -11,6 +11,7 @@
* Rajendra Nayak <rnayak@ti.com>
*
* Some pieces of code Copyright (C) 2005 Texas Instruments, Inc.
* Upgraded with OMAP4 support by Abhijit Pagare <abhijitpagare@ti.com>
*
* 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
@ -28,6 +29,7 @@
#include <plat/control.h>
#include "clock.h"
#include "clock2xxx.h"
#include "cm.h"
#include "prm.h"
#include "prm-regbits-24xx.h"
@ -121,7 +123,10 @@ struct omap3_prcm_regs prcm_context;
u32 omap_prcm_get_reset_sources(void)
{
/* XXX This presumably needs modification for 34XX */
return prm_read_mod_reg(WKUP_MOD, RM_RSTST) & 0x7f;
if (cpu_is_omap24xx() | cpu_is_omap34xx())
return prm_read_mod_reg(WKUP_MOD, OMAP2_RM_RSTST) & 0x7f;
if (cpu_is_omap44xx())
return prm_read_mod_reg(WKUP_MOD, OMAP4_RM_RSTST) & 0x7f;
}
EXPORT_SYMBOL(omap_prcm_get_reset_sources);
@ -129,11 +134,12 @@ EXPORT_SYMBOL(omap_prcm_get_reset_sources);
void omap_prcm_arch_reset(char mode)
{
s16 prcm_offs;
omap2_clk_prepare_for_reboot();
if (cpu_is_omap24xx())
if (cpu_is_omap24xx()) {
omap2xxx_clk_prepare_for_reboot();
prcm_offs = WKUP_MOD;
else if (cpu_is_omap34xx()) {
} else if (cpu_is_omap34xx()) {
u32 l;
prcm_offs = OMAP3430_GR_MOD;
@ -144,10 +150,17 @@ void omap_prcm_arch_reset(char mode)
* cf. OMAP34xx TRM, Initialization / Software Booting
* Configuration. */
omap_writel(l, OMAP343X_SCRATCHPAD + 4);
} else
} else if (cpu_is_omap44xx())
prcm_offs = OMAP4430_PRM_DEVICE_MOD;
else
WARN_ON(1);
prm_set_mod_reg_bits(OMAP_RST_DPLL3, prcm_offs, RM_RSTCTRL);
if (cpu_is_omap24xx() | cpu_is_omap34xx())
prm_set_mod_reg_bits(OMAP_RST_DPLL3, prcm_offs,
OMAP2_RM_RSTCTRL);
if (cpu_is_omap44xx())
prm_set_mod_reg_bits(OMAP_RST_DPLL3, prcm_offs,
OMAP4_RM_RSTCTRL);
}
static inline u32 __omap_prcm_read(void __iomem *base, s16 module, u16 reg)
@ -188,6 +201,18 @@ u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx)
return v;
}
/* Read a PRM register, AND it, and shift the result down to bit 0 */
u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
{
u32 v;
v = prm_read_mod_reg(domain, idx);
v &= mask;
v >>= __ffs(mask);
return v;
}
/* Read a register in a CM module */
u32 cm_read_mod_reg(s16 module, u16 idx)
{
@ -280,7 +305,7 @@ void omap3_prcm_save_context(void)
prcm_context.emu_cm_clksel =
cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1);
prcm_context.emu_cm_clkstctrl =
cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSTCTRL);
cm_read_mod_reg(OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL);
prcm_context.pll_cm_autoidle2 =
cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2);
prcm_context.pll_cm_clksel4 =
@ -333,23 +358,25 @@ void omap3_prcm_save_context(void)
prcm_context.mpu_cm_autoidle2 =
cm_read_mod_reg(MPU_MOD, CM_AUTOIDLE2);
prcm_context.iva2_cm_clkstctrl =
cm_read_mod_reg(OMAP3430_IVA2_MOD, CM_CLKSTCTRL);
cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP2_CM_CLKSTCTRL);
prcm_context.mpu_cm_clkstctrl =
cm_read_mod_reg(MPU_MOD, CM_CLKSTCTRL);
cm_read_mod_reg(MPU_MOD, OMAP2_CM_CLKSTCTRL);
prcm_context.core_cm_clkstctrl =
cm_read_mod_reg(CORE_MOD, CM_CLKSTCTRL);
cm_read_mod_reg(CORE_MOD, OMAP2_CM_CLKSTCTRL);
prcm_context.sgx_cm_clkstctrl =
cm_read_mod_reg(OMAP3430ES2_SGX_MOD, CM_CLKSTCTRL);
cm_read_mod_reg(OMAP3430ES2_SGX_MOD,
OMAP2_CM_CLKSTCTRL);
prcm_context.dss_cm_clkstctrl =
cm_read_mod_reg(OMAP3430_DSS_MOD, CM_CLKSTCTRL);
cm_read_mod_reg(OMAP3430_DSS_MOD, OMAP2_CM_CLKSTCTRL);
prcm_context.cam_cm_clkstctrl =
cm_read_mod_reg(OMAP3430_CAM_MOD, CM_CLKSTCTRL);
cm_read_mod_reg(OMAP3430_CAM_MOD, OMAP2_CM_CLKSTCTRL);
prcm_context.per_cm_clkstctrl =
cm_read_mod_reg(OMAP3430_PER_MOD, CM_CLKSTCTRL);
cm_read_mod_reg(OMAP3430_PER_MOD, OMAP2_CM_CLKSTCTRL);
prcm_context.neon_cm_clkstctrl =
cm_read_mod_reg(OMAP3430_NEON_MOD, CM_CLKSTCTRL);
cm_read_mod_reg(OMAP3430_NEON_MOD, OMAP2_CM_CLKSTCTRL);
prcm_context.usbhost_cm_clkstctrl =
cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, CM_CLKSTCTRL);
cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD,
OMAP2_CM_CLKSTCTRL);
prcm_context.core_cm_autoidle1 =
cm_read_mod_reg(CORE_MOD, CM_AUTOIDLE1);
prcm_context.core_cm_autoidle2 =
@ -432,7 +459,7 @@ void omap3_prcm_restore_context(void)
cm_write_mod_reg(prcm_context.emu_cm_clksel, OMAP3430_EMU_MOD,
CM_CLKSEL1);
cm_write_mod_reg(prcm_context.emu_cm_clkstctrl, OMAP3430_EMU_MOD,
CM_CLKSTCTRL);
OMAP2_CM_CLKSTCTRL);
cm_write_mod_reg(prcm_context.pll_cm_autoidle2, PLL_MOD,
CM_AUTOIDLE2);
cm_write_mod_reg(prcm_context.pll_cm_clksel4, PLL_MOD,
@ -478,22 +505,23 @@ void omap3_prcm_restore_context(void)
CM_AUTOIDLE2);
cm_write_mod_reg(prcm_context.mpu_cm_autoidle2, MPU_MOD, CM_AUTOIDLE2);
cm_write_mod_reg(prcm_context.iva2_cm_clkstctrl, OMAP3430_IVA2_MOD,
CM_CLKSTCTRL);
cm_write_mod_reg(prcm_context.mpu_cm_clkstctrl, MPU_MOD, CM_CLKSTCTRL);
OMAP2_CM_CLKSTCTRL);
cm_write_mod_reg(prcm_context.mpu_cm_clkstctrl, MPU_MOD,
OMAP2_CM_CLKSTCTRL);
cm_write_mod_reg(prcm_context.core_cm_clkstctrl, CORE_MOD,
CM_CLKSTCTRL);
OMAP2_CM_CLKSTCTRL);
cm_write_mod_reg(prcm_context.sgx_cm_clkstctrl, OMAP3430ES2_SGX_MOD,
CM_CLKSTCTRL);
OMAP2_CM_CLKSTCTRL);
cm_write_mod_reg(prcm_context.dss_cm_clkstctrl, OMAP3430_DSS_MOD,
CM_CLKSTCTRL);
OMAP2_CM_CLKSTCTRL);
cm_write_mod_reg(prcm_context.cam_cm_clkstctrl, OMAP3430_CAM_MOD,
CM_CLKSTCTRL);
OMAP2_CM_CLKSTCTRL);
cm_write_mod_reg(prcm_context.per_cm_clkstctrl, OMAP3430_PER_MOD,
CM_CLKSTCTRL);
OMAP2_CM_CLKSTCTRL);
cm_write_mod_reg(prcm_context.neon_cm_clkstctrl, OMAP3430_NEON_MOD,
CM_CLKSTCTRL);
OMAP2_CM_CLKSTCTRL);
cm_write_mod_reg(prcm_context.usbhost_cm_clkstctrl,
OMAP3430ES2_USBHOST_MOD, CM_CLKSTCTRL);
OMAP3430ES2_USBHOST_MOD, OMAP2_CM_CLKSTCTRL);
cm_write_mod_reg(prcm_context.core_cm_autoidle1, CORE_MOD,
CM_AUTOIDLE1);
cm_write_mod_reg(prcm_context.core_cm_autoidle2, CORE_MOD,

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -179,9 +179,11 @@
/* Registers appearing on both 24xx and 34xx */
#define RM_RSTCTRL 0x0050
#define RM_RSTTIME 0x0054
#define RM_RSTST 0x0058
#define OMAP2_RM_RSTCTRL 0x0050
#define OMAP2_RM_RSTTIME 0x0054
#define OMAP2_RM_RSTST 0x0058
#define OMAP2_PM_PWSTCTRL 0x00e0
#define OMAP2_PM_PWSTST 0x00e4
#define PM_WKEN 0x00a0
#define PM_WKEN1 PM_WKEN
@ -191,8 +193,6 @@
#define PM_EVGENCTRL 0x00d4
#define PM_EVGENONTIM 0x00d8
#define PM_EVGENOFFTIM 0x00dc
#define PM_PWSTCTRL 0x00e0
#define PM_PWSTST 0x00e4
/* Omap2 specific registers */
#define OMAP24XX_PM_WKEN2 0x00a4
@ -220,6 +220,13 @@
#define OMAP3430_PRM_IRQSTATUS_IVA2 0x00f8
#define OMAP3430_PRM_IRQENABLE_IVA2 0x00fc
/* Omap4 specific registers */
#define OMAP4_RM_RSTCTRL 0x0000
#define OMAP4_RM_RSTTIME 0x0004
#define OMAP4_RM_RSTST 0x0008
#define OMAP4_PM_PWSTCTRL 0x0000
#define OMAP4_PM_PWSTST 0x0004
#ifndef __ASSEMBLER__

Просмотреть файл

@ -38,7 +38,7 @@
#define PM_PREPWSTST_CORE_P 0x48306AE8
#define PM_PREPWSTST_MPU_V OMAP34XX_PRM_REGADDR(MPU_MOD, \
OMAP3430_PM_PREPWSTST)
#define PM_PWSTCTRL_MPU_P OMAP3430_PRM_BASE + MPU_MOD + PM_PWSTCTRL
#define PM_PWSTCTRL_MPU_P OMAP3430_PRM_BASE + MPU_MOD + OMAP2_PM_PWSTCTRL
#define CM_IDLEST1_CORE_V OMAP34XX_CM_REGADDR(CORE_MOD, CM_IDLEST1)
#define SRAM_BASE_P 0x40200000
#define CONTROL_STAT 0x480022F0

Просмотреть файл

@ -173,7 +173,7 @@ EXPORT_SYMBOL(clk_get_parent);
* OMAP specific clock functions shared between omap1 and omap2
*-------------------------------------------------------------------------*/
unsigned int __initdata mpurate;
int __initdata mpurate;
/*
* By default we use the rate set by the bootloader.
@ -199,6 +199,17 @@ unsigned long followparent_recalc(struct clk *clk)
return clk->parent->rate;
}
/*
* Used for clocks that have the same value as the parent clock,
* divided by some factor
*/
unsigned long omap_fixed_divisor_recalc(struct clk *clk)
{
WARN_ON(!clk->fixed_div);
return clk->parent->rate / clk->fixed_div;
}
void clk_reparent(struct clk *child, struct clk *parent)
{
list_del_init(&child->sibling);

Просмотреть файл

@ -25,17 +25,25 @@ struct omap_clk {
}, \
}
/* Platform flags for the clkdev-OMAP integration code */
#define CK_310 (1 << 0)
#define CK_7XX (1 << 1)
#define CK_7XX (1 << 1) /* 7xx, 850 */
#define CK_1510 (1 << 2)
#define CK_16XX (1 << 3)
#define CK_243X (1 << 4)
#define CK_242X (1 << 5)
#define CK_343X (1 << 6)
#define CK_3430ES1 (1 << 7)
#define CK_3430ES2 (1 << 8)
#define CK_443X (1 << 9)
#define CK_16XX (1 << 3) /* 16xx, 17xx, 5912 */
#define CK_242X (1 << 4)
#define CK_243X (1 << 5)
#define CK_3XXX (1 << 6) /* OMAP3 + AM3 common clocks*/
#define CK_343X (1 << 7) /* OMAP34xx common clocks */
#define CK_3430ES1 (1 << 8) /* 34xxES1 only */
#define CK_3430ES2 (1 << 9) /* 34xxES2, ES3, non-Sitara 35xx only */
#define CK_3505 (1 << 10)
#define CK_3517 (1 << 11)
#define CK_36XX (1 << 12) /* OMAP36xx/37xx-specific clocks */
#define CK_443X (1 << 13)
#define CK_AM35XX (CK_3505 | CK_3517) /* all Sitara AM35xx */
#endif

Просмотреть файл

@ -88,9 +88,9 @@ struct clk {
void (*init)(struct clk *);
__u8 enable_bit;
__s8 usecount;
u8 fixed_div;
#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \
defined(CONFIG_ARCH_OMAP4)
u8 fixed_div;
void __iomem *clksel_reg;
u32 clksel_mask;
const struct clksel *clksel;
@ -123,7 +123,7 @@ struct clk_functions {
#endif
};
extern unsigned int mpurate;
extern int mpurate;
extern int clk_init(struct clk_functions *custom_clocks);
extern void clk_preinit(struct clk *clk);
@ -134,6 +134,7 @@ extern void propagate_rate(struct clk *clk);
extern void recalculate_root_clocks(void);
extern unsigned long followparent_recalc(struct clk *clk);
extern void clk_enable_init_clocks(void);
unsigned long omap_fixed_divisor_recalc(struct clk *clk);
#ifdef CONFIG_CPU_FREQ
extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
extern void clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);

Просмотреть файл

@ -4,7 +4,7 @@
* OMAP2/3 clockdomain framework functions
*
* Copyright (C) 2008 Texas Instruments, Inc.
* Copyright (C) 2008 Nokia Corporation
* Copyright (C) 2008-2009 Nokia Corporation
*
* Written by Paul Walmsley
*
@ -40,65 +40,95 @@
#define OMAP34XX_CLKSTCTRL_FORCE_WAKEUP 0x2
#define OMAP34XX_CLKSTCTRL_ENABLE_AUTO 0x3
/*
* struct clkdm_pwrdm_autodep - a powerdomain that should have wkdeps
* and sleepdeps added when a powerdomain should stay active in hwsup mode;
* and conversely, removed when the powerdomain should be allowed to go
* inactive in hwsup mode.
/**
* struct clkdm_autodep - clkdm deps to add when entering/exiting hwsup mode
* @clkdm: clockdomain to add wkdep+sleepdep on - set name member only
* @omap_chip: OMAP chip types that this autodep is valid on
*
* A clockdomain that should have wkdeps and sleepdeps added when a
* clockdomain should stay active in hwsup mode; and conversely,
* removed when the clockdomain should be allowed to go inactive in
* hwsup mode.
*
* Autodeps are deprecated and should be removed after
* omap_hwmod-based fine-grained module idle control is added.
*/
struct clkdm_pwrdm_autodep {
struct clkdm_autodep {
union {
/* Name of the powerdomain to add a wkdep/sleepdep on */
const char *name;
/* Powerdomain pointer (looked up at clkdm_init() time) */
struct powerdomain *ptr;
} pwrdm;
/* OMAP chip types that this clockdomain dep is valid on */
struct clockdomain *ptr;
} clkdm;
const struct omap_chip_id omap_chip;
};
/**
* struct clkdm_dep - encode dependencies between clockdomains
* @clkdm_name: clockdomain name
* @clkdm: pointer to the struct clockdomain of @clkdm_name
* @omap_chip: OMAP chip types that this dependency is valid on
* @wkdep_usecount: Number of wakeup dependencies causing this clkdm to wake
* @sleepdep_usecount: Number of sleep deps that could prevent clkdm from idle
*
* Statically defined. @clkdm is resolved from @clkdm_name at runtime and
* should not be pre-initialized.
*
* XXX Should also include hardware (fixed) dependencies.
*/
struct clkdm_dep {
const char *clkdm_name;
struct clockdomain *clkdm;
atomic_t wkdep_usecount;
atomic_t sleepdep_usecount;
const struct omap_chip_id omap_chip;
};
/**
* struct clockdomain - OMAP clockdomain
* @name: clockdomain name
* @pwrdm: powerdomain containing this clockdomain
* @clktrctrl_reg: CLKSTCTRL reg for the given clock domain
* @clktrctrl_mask: CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg
* @flags: Clockdomain capability flags
* @dep_bit: Bit shift of this clockdomain's PM_WKDEP/CM_SLEEPDEP bit
* @wkdep_srcs: Clockdomains that can be told to wake this powerdomain up
* @sleepdep_srcs: Clockdomains that can be told to keep this clkdm from inact
* @omap_chip: OMAP chip types that this clockdomain is valid on
* @usecount: Usecount tracking
* @node: list_head to link all clockdomains together
*/
struct clockdomain {
/* Clockdomain name */
const char *name;
union {
/* Powerdomain enclosing this clockdomain */
const char *name;
/* Powerdomain pointer assigned at clkdm_register() */
struct powerdomain *ptr;
} pwrdm;
/* CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg */
void __iomem *clkstctrl_reg;
const u16 clktrctrl_mask;
/* Clockdomain capability flags */
const u8 flags;
/* OMAP chip types that this clockdomain is valid on */
const u8 dep_bit;
struct clkdm_dep *wkdep_srcs;
struct clkdm_dep *sleepdep_srcs;
const struct omap_chip_id omap_chip;
/* Usecount tracking */
atomic_t usecount;
struct list_head node;
};
void clkdm_init(struct clockdomain **clkdms, struct clkdm_pwrdm_autodep *autodeps);
int clkdm_register(struct clockdomain *clkdm);
int clkdm_unregister(struct clockdomain *clkdm);
void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps);
struct clockdomain *clkdm_lookup(const char *name);
int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
void *user);
struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm);
int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
int clkdm_clear_all_wkdeps(struct clockdomain *clkdm);
int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm);
void omap2_clkdm_allow_idle(struct clockdomain *clkdm);
void omap2_clkdm_deny_idle(struct clockdomain *clkdm);

Просмотреть файл

@ -160,6 +160,14 @@
#define OMAP343X_CONTROL_SRAMLDO5 (OMAP2_CONTROL_GENERAL + 0x02C0)
#define OMAP343X_CONTROL_CSI (OMAP2_CONTROL_GENERAL + 0x02C4)
/* AM35XX only CONTROL_GENERAL register offsets */
#define AM35XX_CONTROL_MSUSPENDMUX_6 (OMAP2_CONTROL_GENERAL + 0x0038)
#define AM35XX_CONTROL_DEVCONF2 (OMAP2_CONTROL_GENERAL + 0x0310)
#define AM35XX_CONTROL_DEVCONF3 (OMAP2_CONTROL_GENERAL + 0x0314)
#define AM35XX_CONTROL_CBA_PRIORITY (OMAP2_CONTROL_GENERAL + 0x0320)
#define AM35XX_CONTROL_LVL_INTR_CLEAR (OMAP2_CONTROL_GENERAL + 0x0324)
#define AM35XX_CONTROL_IP_SW_RESET (OMAP2_CONTROL_GENERAL + 0x0328)
#define AM35XX_CONTROL_IPSS_CLK_CTRL (OMAP2_CONTROL_GENERAL + 0x032C)
/* 34xx PADCONF register offsets */
#define OMAP343X_PADCONF_ETK(i) (OMAP2_CONTROL_PADCONFS + 0x5a8 + \
@ -257,6 +265,15 @@
#define OMAP343X_SCRATCHPAD (OMAP343X_CTRL_BASE + 0x910)
#define OMAP343X_SCRATCHPAD_ROM_OFFSET 0x19C
/* AM35XX_CONTROL_IPSS_CLK_CTRL bits */
#define AM35XX_USBOTG_VBUSP_CLK_SHIFT 0
#define AM35XX_CPGMAC_VBUSP_CLK_SHIFT 1
#define AM35XX_VPFE_VBUSP_CLK_SHIFT 2
#define AM35XX_HECC_VBUSP_CLK_SHIFT 3
#define AM35XX_USBOTG_FCLK_SHIFT 8
#define AM35XX_CPGMAC_FCLK_SHIFT 9
#define AM35XX_VPFE_FCLK_SHIFT 10
/*
* CONTROL OMAP STATUS register to identify OMAP3 features
*/

Просмотреть файл

@ -44,7 +44,7 @@
int omap_type(void);
struct omap_chip_id {
u8 oc;
u16 oc;
u8 type;
};
@ -154,6 +154,7 @@ unsigned int omap_rev(void);
* cpu_is_omap242x(): True for OMAP2420, OMAP2422, OMAP2423
* cpu_is_omap243x(): True for OMAP2430
* cpu_is_omap343x(): True for OMAP3430
* cpu_is_omap443x(): True for OMAP4430
*/
#define GET_OMAP_CLASS (omap_rev() & 0xff)
@ -286,6 +287,7 @@ IS_OMAP_SUBCLASS(443x, 0x443)
* cpu_is_omap2423(): True for OMAP2423
* cpu_is_omap2430(): True for OMAP2430
* cpu_is_omap3430(): True for OMAP3430
* cpu_is_omap4430(): True for OMAP4430
* cpu_is_omap3505(): True for OMAP3505
* cpu_is_omap3517(): True for OMAP3517
*/
@ -334,6 +336,7 @@ IS_OMAP_TYPE(3517, 0x3517)
#define cpu_is_omap3505() 0
#define cpu_is_omap3517() 0
#define cpu_is_omap3430() 0
#define cpu_is_omap4430() 0
#define cpu_is_omap3630() 0
/*
@ -471,9 +474,12 @@ IS_OMAP_TYPE(3517, 0x3517)
#define CHIP_IS_OMAP3430ES3_0 (1 << 5)
#define CHIP_IS_OMAP3430ES3_1 (1 << 6)
#define CHIP_IS_OMAP3630ES1 (1 << 7)
#define CHIP_IS_OMAP4430ES1 (1 << 8)
#define CHIP_IS_OMAP24XX (CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430)
#define CHIP_IS_OMAP4430 (CHIP_IS_OMAP4430ES1)
/*
* "GE" here represents "greater than or equal to" in terms of ES
* levels. So CHIP_GE_OMAP3430ES2 is intended to match all OMAP3430

Просмотреть файл

@ -131,11 +131,15 @@ int omap_device_enable_clocks(struct omap_device *od);
*/
struct omap_device_pm_latency {
u32 deactivate_lat;
u32 deactivate_lat_worst;
int (*deactivate_func)(struct omap_device *od);
u32 activate_lat;
u32 activate_lat_worst;
int (*activate_func)(struct omap_device *od);
u32 flags;
};
#define OMAP_DEVICE_LATENCY_AUTO_ADJUST BIT(1)
/* Get omap_device pointer from platform_device pointer */
#define to_omap_device(x) container_of((x), struct omap_device, pdev)

Просмотреть файл

@ -441,6 +441,8 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh);
int omap_hwmod_enable_clocks(struct omap_hwmod *oh);
int omap_hwmod_disable_clocks(struct omap_hwmod *oh);
int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode);
int omap_hwmod_reset(struct omap_hwmod *oh);
void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);

Просмотреть файл

@ -1,8 +1,8 @@
/*
* OMAP2/3 powerdomain control
*
* Copyright (C) 2007-8 Texas Instruments, Inc.
* Copyright (C) 2007-8 Nokia Corporation
* Copyright (C) 2007-2008 Texas Instruments, Inc.
* Copyright (C) 2007-2009 Nokia Corporation
*
* Written by Paul Walmsley
*
@ -37,6 +37,9 @@
#define PWRSTS_OFF_RET ((1 << PWRDM_POWER_OFF) | \
(1 << PWRDM_POWER_RET))
#define PWRSTS_RET_ON ((1 << PWRDM_POWER_RET) | \
(1 << PWRDM_POWER_ON))
#define PWRSTS_OFF_RET_ON (PWRSTS_OFF_RET | (1 << PWRDM_POWER_ON))
@ -48,16 +51,16 @@
*/
/*
* Number of memory banks that are power-controllable. On OMAP3430, the
* maximum is 4.
* Number of memory banks that are power-controllable. On OMAP4430, the
* maximum is 5.
*/
#define PWRDM_MAX_MEM_BANKS 4
#define PWRDM_MAX_MEM_BANKS 5
/*
* Maximum number of clockdomains that can be associated with a powerdomain.
* CORE powerdomain on OMAP3 is the worst case
* CORE powerdomain on OMAP4 is the worst case
*/
#define PWRDM_MAX_CLKDMS 4
#define PWRDM_MAX_CLKDMS 9
/* XXX A completely arbitrary number. What is reasonable here? */
#define PWRDM_TRANSITION_BAILOUT 100000
@ -65,63 +68,36 @@
struct clockdomain;
struct powerdomain;
/* Encodes dependencies between powerdomains - statically defined */
struct pwrdm_dep {
/* Powerdomain name */
const char *pwrdm_name;
/* Powerdomain pointer - resolved by the powerdomain code */
struct powerdomain *pwrdm;
/* Flags to mark OMAP chip restrictions, etc. */
const struct omap_chip_id omap_chip;
};
/**
* struct powerdomain - OMAP powerdomain
* @name: Powerdomain name
* @omap_chip: represents the OMAP chip types containing this pwrdm
* @prcm_offs: the address offset from CM_BASE/PRM_BASE
* @pwrsts: Possible powerdomain power states
* @pwrsts_logic_ret: Possible logic power states when pwrdm in RETENTION
* @flags: Powerdomain flags
* @banks: Number of software-controllable memory banks in this powerdomain
* @pwrsts_mem_ret: Possible memory bank pwrstates when pwrdm in RETENTION
* @pwrsts_mem_on: Possible memory bank pwrstates when pwrdm in ON
* @pwrdm_clkdms: Clockdomains in this powerdomain
* @node: list_head linking all powerdomains
* @state:
* @state_counter:
* @timer:
* @state_timer:
*/
struct powerdomain {
/* Powerdomain name */
const char *name;
/* the address offset from CM_BASE/PRM_BASE */
const s16 prcm_offs;
/* Used to represent the OMAP chip types containing this pwrdm */
const struct omap_chip_id omap_chip;
/* Powerdomains that can be told to wake this powerdomain up */
struct pwrdm_dep *wkdep_srcs;
/* Powerdomains that can be told to keep this pwrdm from inactivity */
struct pwrdm_dep *sleepdep_srcs;
/* Bit shift of this powerdomain's PM_WKDEP/CM_SLEEPDEP bit */
const u8 dep_bit;
/* Possible powerdomain power states */
const s16 prcm_offs;
const u8 pwrsts;
/* Possible logic power states when pwrdm in RETENTION */
const u8 pwrsts_logic_ret;
/* Powerdomain flags */
const u8 flags;
/* Number of software-controllable memory banks in this powerdomain */
const u8 banks;
/* Possible memory bank pwrstates when pwrdm in RETENTION */
const u8 pwrsts_mem_ret[PWRDM_MAX_MEM_BANKS];
/* Possible memory bank pwrstates when pwrdm is ON */
const u8 pwrsts_mem_on[PWRDM_MAX_MEM_BANKS];
/* Clockdomains in this powerdomain */
struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS];
struct list_head node;
int state;
unsigned state_counter[PWRDM_MAX_PWRSTS];
@ -134,8 +110,6 @@ struct powerdomain {
void pwrdm_init(struct powerdomain **pwrdm_list);
int pwrdm_register(struct powerdomain *pwrdm);
int pwrdm_unregister(struct powerdomain *pwrdm);
struct powerdomain *pwrdm_lookup(const char *name);
int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user),
@ -149,13 +123,6 @@ int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,
int (*fn)(struct powerdomain *pwrdm,
struct clockdomain *clkdm));
int pwrdm_add_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
int pwrdm_del_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
int pwrdm_read_wkdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
int pwrdm_add_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
int pwrdm_del_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
int pwrdm_read_sleepdep(struct powerdomain *pwrdm1, struct powerdomain *pwrdm2);
int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm);
int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst);

Просмотреть файл

@ -33,6 +33,14 @@ int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, const char *name);
void omap3_prcm_save_context(void);
void omap3_prcm_restore_context(void);
u32 prm_read_mod_reg(s16 module, u16 idx);
void prm_write_mod_reg(u32 val, s16 module, u16 idx);
u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask);
u32 cm_read_mod_reg(s16 module, u16 idx);
void cm_write_mod_reg(u32 val, s16 module, u16 idx);
u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
#endif

Просмотреть файл

@ -148,10 +148,22 @@ static int _omap_device_activate(struct omap_device *od, u8 ignore_lat)
"%llu nsec\n", od->pdev.name, od->pm_lat_level,
act_lat);
WARN(act_lat > odpl->activate_lat, "omap_device: %s.%d: "
"activate step %d took longer than expected (%llu > %d)\n",
od->pdev.name, od->pdev.id, od->pm_lat_level,
act_lat, odpl->activate_lat);
if (act_lat > odpl->activate_lat) {
odpl->activate_lat_worst = act_lat;
if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
odpl->activate_lat = act_lat;
pr_warning("omap_device: %s.%d: new worst case "
"activate latency %d: %llu\n",
od->pdev.name, od->pdev.id,
od->pm_lat_level, act_lat);
} else
pr_warning("omap_device: %s.%d: activate "
"latency %d higher than exptected. "
"(%llu > %d)\n",
od->pdev.name, od->pdev.id,
od->pm_lat_level, act_lat,
odpl->activate_lat);
}
od->dev_wakeup_lat -= odpl->activate_lat;
}
@ -204,10 +216,23 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat)
"%llu nsec\n", od->pdev.name, od->pm_lat_level,
deact_lat);
WARN(deact_lat > odpl->deactivate_lat, "omap_device: %s.%d: "
"deactivate step %d took longer than expected "
"(%llu > %d)\n", od->pdev.name, od->pdev.id,
od->pm_lat_level, deact_lat, odpl->deactivate_lat);
if (deact_lat > odpl->deactivate_lat) {
odpl->deactivate_lat_worst = deact_lat;
if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
odpl->deactivate_lat = deact_lat;
pr_warning("omap_device: %s.%d: new worst case "
"deactivate latency %d: %llu\n",
od->pdev.name, od->pdev.id,
od->pm_lat_level, deact_lat);
} else
pr_warning("omap_device: %s.%d: deactivate "
"latency %d higher than exptected. "
"(%llu > %d)\n",
od->pdev.name, od->pdev.id,
od->pm_lat_level, deact_lat,
odpl->deactivate_lat);
}
od->dev_wakeup_lat += odpl->activate_lat;