您的位置:首页 > 运维架构 > Linux

OK335xS Linux kernel check clock 24M hacking

2016-01-05 16:44 555 查看
/******************************************************************************
*              OK335xS Linux kernel check clock 24M hacking
* 声明:
*     由于需要确认kernel中的时钟和引脚配置的时钟是否一致,于是需要去跟踪内核
* 中的代码是如何对引脚配置时钟进行识别,并对其进行相关配置的额。
*
*                                            2016-1-5 深圳 南山平山村 曾剑锋
*****************************************************************************/

MACHINE_START(AM335XEVM, "am335xevm")
/* Maintainer: Texas Instruments */
.atag_offset    = 0x100,
.map_io         = am335x_evm_map_io,
.init_early     = am33xx_init_early,    ---------------+
.init_irq       = ti81xx_init_irq,                     |
.handle_irq     = omap3_intc_handle_irq,               |
.timer          = &omap3_am33xx_timer,                 |
.init_machine   = am335x_evm_init,                     |
MACHINE_END                                                |
|
void __init am33xx_init_early(void)         <--------------+
{
omap2_set_globals_am33xx();
omap3xxx_check_revision();
am33xx_check_features();
omap_common_init_early();
am33xx_voltagedomains_init();
omap44xx_prminst_init();
am33xx_powerdomains_init();
omap44xx_cminst_init();
am33xx_clockdomains_init();
am33xx_hwmod_init();
omap_hwmod_init_postsetup();
omap3xxx_clk_init();                    --------------+
}                                                         |
|
int __init omap3xxx_clk_init(void)          <-------------+
{
struct omap_clk *c;
u32 cpu_clkflg = 0;

/*
* 3505 must be tested before 3517, since 3517 returns true
* for both AM3517 chips and AM3517 family chips, which
* includes 3505.  Unfortunately there's no obvious family
* test for 3517/3505 :-(
*/
if (cpu_is_omap3505()) {
cpu_mask = RATE_IN_34XX;
cpu_clkflg = CK_3505;
} else if (cpu_is_omap3517()) {
cpu_mask = RATE_IN_34XX;
cpu_clkflg = CK_3517;
} else if (cpu_is_omap3505()) {
cpu_mask = RATE_IN_34XX;
cpu_clkflg = CK_3505;
} else if (cpu_is_omap3630()) {
cpu_mask = (RATE_IN_34XX | RATE_IN_36XX);
cpu_clkflg = CK_36XX;
} else if (cpu_is_ti816x()) {
cpu_mask = RATE_IN_TI816X;
cpu_clkflg = CK_TI816X;
} else if (cpu_is_am33xx()) {
am33xx_clk_init();                      ---------------------------+
return 0;                                                          |
} else if (cpu_is_ti814x()) {                                          |
cpu_mask = RATE_IN_TI814X;                                         |
} else if (cpu_is_omap34xx()) {                                        |
if (omap_rev() == OMAP3430_REV_ES1_0) {                            |
cpu_mask = RATE_IN_3430ES1;                                    |
cpu_clkflg = CK_3430ES1;                                       |
} else {                                                           |
/*                                                             |
* Assume that anything that we haven't matched yet            |
* has 3430ES2-type clocks.                                    |
*/                                                            |
cpu_mask = RATE_IN_3430ES2PLUS;                                |
cpu_clkflg = CK_3430ES2PLUS;                                   |
}                                                                  |
} else {                                                               |
WARN(1, "clock: could not identify OMAP3 variant\n");              |
}                                                                      |
......                                                                 |
}                                                                          |
|
int __init am33xx_clk_init(void)                   <-----------------------+
{
struct omap_clk *c;
u32 cpu_clkflg;

if (cpu_is_am33xx()) {
cpu_mask = RATE_IN_AM33XX;
cpu_clkflg = CK_AM33XX;
}

clk_init(&omap2_clk_functions);                ------------------------+
|
for (c = am33xx_clks; c < am33xx_clks + ARRAY_SIZE(am33xx_clks); c++)--*---+
clk_preinit(c->lk.clk);                                            |   |
|   |
for (c = am33xx_clks; c < am33xx_clks + ARRAY_SIZE(am33xx_clks); c++)  |   |
if (c->cpu & cpu_clkflg) {                                         |   |
clkdev_add(&c->lk);                                            |   |
clk_register(c->lk.clk);                                       |   |
omap2_init_clk_clkdm(c->lk.clk);               ----------------*-+ |
}                                                                  | | |
| | |
recalculate_root_clocks();                                             | | |
| | |
/*                                                                     | | |
* Only enable those clocks we will need, let the drivers              | | |
* enable other clocks as necessary                                    | | |
*/                                                                    | | |
clk_enable_init_clocks();                     -------------------------*-*-*-+
| | | |
return 0;                                                              | | | |
}                                                                          | | | |
| | | |
| | | |
/* 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                                                                     | | | |
};                                                                         | | | |
| | | |
static struct clk_functions *arch_clock;                     --------------*-*-*-*-+
int __init clk_init(struct clk_functions * custom_clocks)    <-------------+ | | | |
{                                                                            | | | |
if (!custom_clocks) {                                                    | | | |
pr_err("No custom clock functions registered\n");                    | | | |
BUG();                                                               | | | |
}                                                                        | | | |
| | | |
arch_clock = custom_clocks;                                              | | | |
| | | |
return 0;                                                                | | | |
}                                                                            | | | |
| | | |
void omap2_init_clk_clkdm(struct clk *clk)        <--------------------------+ | | |
{                                                                              | | |
struct clockdomain *clkdm;                                                 | | |
| | |
if (!clk->clkdm_name)                                                      | | |
return;                                                                | | |
| | |
clkdm = clkdm_lookup(clk->clkdm_name);              -------+               | | |
if (clkdm) {                                               |               | | |
printk("clock: associated clk %s to clkdm %s\n",       |               | | |
clk->name, clk->clkdm_name);                      |               | | |
pr_debug("clock: associated clk %s to clkdm %s\n",     |               | | |
clk->name, clk->clkdm_name);                      |               | | |
clk->clkdm = clkdm;                                    |               | | |
} else {                                                   |               | | |
pr_debug("clock: could not associate clk %s to "       |               | | |
"clkdm %s\n", clk->name, clk->clkdm_name);        |               | | |
}                                                          |               | | |
}                                                              |               | | |
|               | | |
struct clockdomain *clkdm_lookup(const char *name)      <------+               | | |
{                                                                              | | |
struct clockdomain *clkdm, *temp_clkdm;                                    | | |
| | |
if (!name)                                                                 | | |
return NULL;                                                           | | |
| | |
clkdm = NULL;                                                              | | |
| | |
list_for_each_entry(temp_clkdm, &clkdm_list, node) {                       | | |
if (!strcmp(name, temp_clkdm->name)) {                                 | | |
clkdm = temp_clkdm;                                                | | |
break;                                                             | | |
}                                                                      | | |
}                                                                          | | |
| | |
return clkdm;                                                              | | |
}                                                                              | | |
| | |
| | |
/*                                                                             | | |
* clkdev         +----------------------------------------------------------+ | | |
*/               |                                                          | | | |
static struct omap_clk am33xx_clks[] = {                     <---------------*-+ | |
......                                                                   |   | |
CLK(NULL,    "clk_rc32k_ck",        &clk_rc32k_ck,    CK_AM33XX),        |   | |
CLK(NULL,    "virt_19_2m_ck",    &virt_19_2m_ck,    CK_AM33XX),          |   | |
CLK(NULL,    "virt_24m_ck",        &virt_24m_ck,    CK_AM33XX),          |   | |
CLK(NULL,    "virt_25m_ck",        &virt_25m_ck,    CK_AM33XX),          |   | |
CLK(NULL,    "virt_26m_ck",        &virt_26m_ck,    CK_AM33XX),          |   | |
CLK(NULL,    "sys_clkin_ck",        &sys_clkin_ck,    CK_AM33XX),  ----+ |   | |
CLK(NULL,    "tclkin_ck",        &tclkin_ck,    CK_AM33XX),            | |   | |
CLK(NULL,    "dpll_core_ck",        &dpll_core_ck,        CK_AM33XX),  | |   | |
CLK(NULL,    "dpll_core_x2_ck",    &dpll_core_x2_ck,    CK_AM33XX),    | |   | |
CLK(NULL,    "dpll_core_m4_ck",    &dpll_core_m4_ck,    CK_AM33XX),    | |   | |
CLK(NULL,    "dpll_core_m5_ck",    &dpll_core_m5_ck,    CK_AM33XX),    | |   | |
CLK(NULL,    "dpll_core_m6_ck",    &dpll_core_m6_ck,    CK_AM33XX),    | |   | |
CLK(NULL,    "sysclk1_ck",        &sysclk1_ck,    CK_AM33XX),          | |   | |
CLK(NULL,    "sysclk2_ck",        &sysclk2_ck,    CK_AM33XX),          | |   | |
......                                                                 | |   | |
};   |                                                                     | |   | |
+-----------------------------------------+                           | |   | |
struct omap_clk {                              |             <-------------*-+   | |
u16                        cpu;            |                           |     | |
struct clk_lookup        lk;               |                           |     | |
};                                             |                           |     | |
|                           |     | |
#define CLK(dev, con, ck, cp)         \   <----+                           |     | |
{                \                                                     |     | |
.cpu = cp,        \                                               |     | |
.lk = {            \                                               |     | |
.dev_id = dev,    \                                            |     | |
.con_id = con,    \                                            |     | |
.clk = ck,    \                                                |     | |
},            \                                                    |     | |
}                                                                      |     | |
|     | |
/* sys_clk_in */                                                           |     | |
static struct clk sys_clkin_ck = {                      <------------------+     | |
.name        = "sys_clkin_ck",                                               | |
.parent        = &virt_24m_ck,                                               | |
.init        = &omap2_init_clksel_parent,           ----------------------+  | |
/**                                                                           |  | |
* +------------------------------------------------------------------------+ |  | |
* |        Table 9-14. control_status Register Field Descriptions          | |  | |
* +-------+----------+------------+----------------------------------------+ |  | |
* | Bit   | Field    | Type Reset | Description                            | |  | |
* +-------+----------+------------+----------------------------------------+ |  | |
* | 23-22 | sysboot1 | R/W 0h     | Used to select crystal clock frequency.| |  | |
* |       |          |            | See SYSBOOT Configuration Pins.        | |  | |
* |       |          |            | Reset value is from SYSBOOT[15:14].    | |  | |
* +-------+----------+------------+----------------------------------------+ |  | |
*/                                                                           |  | |
.clksel_reg    = AM33XX_CTRL_REGADDR(0x40),    /* CONTROL_STATUS */       |  | |
.clksel_mask    = (0x3 << 22),                                            |  | |
.clksel        = sys_clkin_sel,       -----------+                        |  | |
.ops        = &clkops_null,           -----------*-----+                  |  | |
.recalc        = &omap2_clksel_recalc,           |     |                  |  | |
};                                                   |     |                  |  | |
|     |                  |  | |
/* Oscillator clock */                               |     |                  |  | |
/* 19.2, 24, 25 or 26 MHz */                         |     |                  |  | |
static const struct clksel sys_clkin_sel[] = {  <----+     |                  |  | |
{ .parent = &virt_19_2m_ck, .rates = div_1_0_rates },  |                  |  | |
{ .parent = &virt_24m_ck, .rates = div_1_1_rates },    |   ------+        |  | |
{ .parent = &virt_25m_ck, .rates = div_1_2_rates },    |         |        |  | |
{ .parent = &virt_26m_ck, .rates = div_1_3_rates },    |         |        |  | |
{ .parent = NULL },                  |                 |         |        |  | |
};                                       |                 |         |        |  | |
|                 |         |        |  | |
static struct clk virt_24m_ck = {        |        <--------*---------+        |  | |
.name        = "virt_24m_ck",        |                 |                  |  | |
.rate        = 24000000,             |                 |                  |  | |
.ops        = &clkops_null,          |                 |                  |  | |
};                                       |                 |                  |  | |
v                 |                  |  | |
static const struct clksel_rate div_1_1_rates[] = {        |                  |  | |
{ .div = 1, .val = 1, .flags = RATE_IN_AM33XX },       |                  |  | |
{ .div = 0 },                                          |                  |  | |
};                                                         |                  |  | |
|                  |  | |
const struct clkops clkops_null = {             <----------+                  |  | |
.enable        = clkll_enable_null,                                       |  | |
.disable    = clkll_disable_null,                                         |  | |
};                                                                            |  | |
|  | |
|  | |
// 到目前为止都不知道哪里调用了这个函数,因为这个函数是用来判断系统接入的晶振 |  | |
// 大小的,没跟踪到到底是谁调用了该函数。                                     |  | |
void omap2_init_clksel_parent(struct clk *clk)           <--------------------+  | |
{                                                                                | |
const struct clksel *clks;                                                   | |
const struct clksel_rate *clkr;                                              | |
u32 r, found = 0;                                                            | |
| |
if (!clk->clksel || !clk->clksel_mask)                                       | |
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))                                       | |
continue;                                                        | |
| |
if (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;                                               |       | |
}                                                            |       | |
}                                                                |       | |
}                                                                    |       | |
|       | |
printk("zengjf ckeck function calling [%s].\n", __func__);           |       | |
/* This indicates a data error */                                    |       | |
WARN(!found, "clock: %s: init parent: could not find regval %0x\n",  |       | |
clk->name, r);                                                  |       | |
|       | |
return;                                                              |       | |
}                                                                        |       | |
|       | |
int clk_reparent(struct clk *c, struct clk *parent)          <-----------+       | |
{                                                                                | |
c->parent = parent;                                                          | |
return 0;                                                                    | |
}                                                                                | |
| |
void clk_enable_init_clocks(void)                            <-------------------+ |
{                                                                                  |
struct clk *clkp;                                                              |
|
list_for_each_entry(clkp, &clocks, node) {                                     |
if (clkp->flags & ENABLE_ON_INIT)                                          |
clk_enable(clkp);                                -------+              |
}                                                               |              |
}                                                                   |              |
|              |
/*                                                                  |              |
* Standard clock functions defined in include/linux/clk.h          |              |
*/                                                                 |              |
|              |
int clk_enable(struct clk *clk)                              <------+              |
{                                                                                  |
unsigned long flags;                                                           |
int ret;                                                                       |
|
if (clk == NULL || IS_ERR(clk))                                                |
return -EINVAL;                                                            |
|
if (!arch_clock || !arch_clock->clk_enable)                                    |
return -EINVAL;                                                            |
|
spin_lock_irqsave(&clockfw_lock, flags);                                       |
ret = arch_clock->clk_enable(clk);                      <----------------------+
spin_unlock_irqrestore(&clockfw_lock, flags);

return ret;
}
EXPORT_SYMBOL(clk_enable);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: