OK335xS Linux kernel check clock 24M hacking

/******************************************************************************
 *              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);

 

时间: 2024-10-01 15:26:57

OK335xS Linux kernel check clock 24M hacking的相关文章

FL2440 Linux kernel + yaffs2根文件移植过程(一)

本文全过程为自己亲自试验,成功移植了一个最基本功能的Kernel.根文件系统,现在将这个一耗时.耗精力 的过程写下来,希望对遇到相同问题的朋友们有所帮助! 平台:飞凌FL2440             windows xp sp2             vmware 6.5.build-203739              ubuntu 9.10              交叉编译器: 4.3.2              内核:linux-2.6.28.7.tar.bz2        

The Linux Kernel Module Programming Guide

The Linux Kernel Module Programming Guide Peter Jay SalzmanMichael BurianOri Pomerantz Copyright 2001 Peter Jay Salzman The Linux Kernel Module Programming Guide is a free book; you may reproduce and/or modify it under the terms of the Open Software

linux kernel的中断子系统之(三):IRQ number和中断描述符【转】

转自:http://www.wowotech.net/linux_kenrel/interrupt_descriptor.html 一.前言 本文主要围绕IRQ number和中断描述符(interrupt descriptor)这两个概念描述通用中断处理过程.第二章主要描述基本概念,包括什么是IRQ number,什么是中断描述符等.第三章描述中断描述符数据结构的各个成员.第四章描述了初始化中断描述符相关的接口API.第五章描述中断描述符相关的接口API. 二.基本概念 1.通用中断的代码处理

Linux kernel suspend resume学习:2.6.35与3.0.35比较【转】

转自:http://blog.csdn.net/njuitjf/article/details/18317149 Linux kernel suspend resume学习:2.6.35与3.0.35比较 最近在学习linux kernel中suspend和resume的处理.只是一味的看代码,有点枯燥,刚好有两个项目使用了不同的内核版本,就以比较这两个间的处理差别为线索进行学习.由于列举了很多代码,为了保持连续性,整篇文章还是放到了一个blog中. 首先看看公开出去的接口,都是文件/sys/p

在Ubuntu上编译 emulat Android avd内核源代码(Linux Kernel)

因为我没有真机的环境  所以需要在模拟器中进行模拟进行,所以要下载支持模拟器的源代码版本,而goldfish这个源代码版本就是专门为模拟器环境而提供的. The goldfish project contains the kernel sources for the emulated platforms. 一.首先,到 git clone https://android.googlesource.com/kernel/goldfish.git下载Linux Kernel for Android

Kprobe在Linux kernel debug中的应用

一直在做kernel开发方面的工作,也一直苦于kernel debug的困惑,到底如何进行kernel开发的debug的工作?今天经美国同事的推荐,我认为kprobe是一个非常好的debug工具.其本质原理就是在你需要probe的地方放入断点指令,然后在断点处调用你的调试/测试程序,从而可以实现对kernel程序的调试/测试. Kprobe只是提供了一种机制,使得用户可以在系统运行时调试/测试内核程序.使用Kprobe需要做如下几件事情: 1,需要找到测试点所对应的内存地址.这件工作可能是最麻烦

Linux Kernel 4.5在3月15日发布最终版

  今天Linus Torvalds和辛苦工作的内核团队非常自豪的宣布了Linux Kernel 4.5版本,并已经开放下载.自2016年1月25日首个候选版本发布,经历了长达两个多月的不懈更新,在3月6日发布最后一个候选版本之后,Linux Kernel 4.5终于在今天获得了最终版本. Linux Kernel 4.5的突出特性包括部署了AMD的PowerPlay电池管理技术,针对Radeon 显卡添加的AMD GPU开源驱动带来了更高的性能输出,同时在处理Brtfs文件系统中改善了空闲空间

如何通过Git在本地建立Linux Kernel的版本库镜像

在本地Git的版本库根目录下执行以下命令,将会同步Linux Kernel版本库到本地,进行镜像. git clone --bare git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 当然,该命令只会在本地建立版本库镜像.那么如何保持和Linux Kernel版本库的更新呢? 建议参考以下项目,使用git-mirror进行定时同步更新版本库. https://github.com/ndechesne/git-mirr

nginx conf by linux kernel

#nginx conf by linux kernel net.ipv4.tcp_max_tw_buckets = 6000 net.ipv4.ip_local_port_range = 1024 65000 net.ipv4.tcp_tw_recycle=1 net_ipv4.tcp_tw_reuse=1 net_ipv4.tcp_syncookies=1 net.core.somaxconn=262144 net.core.netdev_max_backlog=262144 net.ipv4