DM8148平台的定时器的时钟源配置



通过函数omap_dm_timer_set_source()来为定时器指定时钟源。由代码可以知道,source的取值只能在1~3之间。

arch/arm/plat-omap/dmtimer.c

int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)

{

       int ret = -EINVAL;

 

       if (source < 0 || source >= 3)

              return -EINVAL;

 

       clk_disable(timer->fclk);

       ret = clk_set_parent(timer->fclk, dm_source_clocks[source]);

       clk_enable(timer->fclk);

 

       /*

        * When the functional clock disappears, too quick writes seem

        * to cause an abort. XXX Is this still necessary?

        */

       __delay(300000);

 

       return ret;

}

即在头文件arch/arm/plat-omap/include/plat/dmtimer.h中所定义的宏:

arch/arm/plat-omap/include/plat/dmtimer.h

/* clock sources */

#define OMAP_TIMER_SRC_SYS_CLK                  0x00

#define OMAP_TIMER_SRC_32_KHZ                     0x01

#define OMAP_TIMER_SRC_EXT_CLK                  0x02

通过函数omap_dm_timer_init来设置dm_source_clocks的值。具体的代码如下所示:

 

static struct clk **dm_source_clocks

/* FIXME: Currently set_source only allows selecting form first three sources */

static const char *ti814x_dm_source_names[] __initdata = {

       "osc0_clkin_ck",

       "sysclk18_ck",

       "tclkin_ck",

       "osc1_clkin_ck",

       "xref0_ck",

       "xref1_ck",

       "xref2_ck",

       NULL

};

。。。

dm_source_names = ti814x_dm_source_names;

。。。

int __init omap_dm_timer_init(void)

{

。。。

if (cpu_class_is_omap2())

              for (i = 0; dm_source_names[i] != NULL; i++)

                     dm_source_clocks[i] = clk_get(NULL, dm_source_names[i]);

。。。

}

clk_get 的原型为如下,用来查找并获取一个时钟源struct clk *clk,注意:不可在中断上下文调用,同时时钟也是禁止的。其中dev可以为NULL。由如下代码可知,现在已经将参数struct device *转换为了char *。分析到这一步已经足以说明定时器的时钟源是如何来的。clk_get_sys就不向下展开了,否则就没完没了了。

arch/arm/common/clkdev.c

struct clk *clk_get(struct device *dev, const char *con_id)

{

       const char *dev_id = dev ? dev_name(dev) : NULL;

 

       return clk_get_sys(dev_id, con_id);

}

 

include/linux/device.h

static inline const char *dev_name(const struct device *dev)

{

       /* Use the init name until the kobject becomes available */

       if (dev->init_name)

              return dev->init_name;

 

       return kobject_name(&dev->kobj);

}

static inline const char *kobject_name(const struct kobject *kobj)

{

       return kobj->name;

}

可以参考arch/arm/mach-omap2/clock814x_data.c来查看一个时钟设备的dev_nameNULL或是合法的字符串。查看数组ti814x_clks[],在数组中,第一个域为dev_id,第三个域为struct clk结构。可以通过源代码查看:

arch/arm/mach-omap2/clock814x_data.c

#define CLK(dev, con, ck, cp)            \

       {                          \

               .cpu = cp,            \

              .lk = {                   \

                     .dev_id = dev, \

                     .con_id = con, \

                     .clk = ck, \

              },                  \

       }

struct clk_lookup {

       struct list_head       node;

       const char              *dev_id;

       const char              *con_id;

       struct clk        *clk;

};

struct omap_clk {

       u16                       cpu;

       struct clk_lookup           lk;

};

 

static struct omap_clk ti814x_clks[] = {

。。。

CLK(NULL,"tclkin_ck",&tclkin_ck,CK_TI814X | CK_DM385),

CLK(NULL,"osc0_clkin_ck",&osc0_clkin_ck,CK_TI814X | CK_DM385),

。。。

CLK(NULL,"sysclk18_ck",&sysclk18_ck,CK_TI814X | CK_DM385),

。。。

CLK(NULL,"rcosc_32k_ck", &rcosc_32k_ck,CK_TI814X),

CLK(NULL,"sys_32k_clkin_ck",&sys_32k_clkin_ck, CK_TI814X),

...

CLK("cpsw.0",NULL,&cpsw_ick, CK_TI814X),

...

};

例子

struct clk *clkp;

clkp=clk_get(NULL,”gem_fck”);

if(!clkp)

       pr_err(“clk_get failed for gem_fck!\n”);

然后将ti814x_clks[]结构添加到一个链表中,方便clk_get_sys()时根据具体的devcon_id来获取时钟。下面则是struct clk结构的具体定义。

arch/arm/mach-omap2/clock814x_data.c

static struct clk osc0_clkin_ck = {

       .name             = "osc0_clkin_ck",

       .ops        = &clkops_null,

       .rate        = 20000000,

       .flags             = RATE_IN_TI814X,

};

static struct clk tclkin_ck = {

       .name             = "tclkin_ck",

       .ops        = &clkops_null,

       .rate        = 32768, /* TODO: Check */

       .flags             = RATE_IN_TI814X,

};

static struct clk sysclk18_ck = {

       .name             = "sysclk18_ck",

       .init        = &omap2_init_clksel_parent,

       .clksel            = sysclk18_mux_sel,

       .clksel_reg      = TI81XX_CM_DPLL_SYSCLK18_CLKSEL,

       .clksel_mask   = TI81XX_CLKSEL_0_0_MASK,

       .ops        = &clkops_null,

       .recalc            = &omap2_clksel_recalc,

};

总结:

1、为DM814x指定时钟源时,可以有三个选择,分别是:OMAP_TIMER_SRC_SYS_CLK对应于struct clk结构的osc0_clkin_ckOMAP_TIMER_SRC_32_KHZ对应于struct clk结构的sysclk18_ckOMAP_TIMER_SRC_EXT_CLK 对应于struct clk结构的tclkin_ck

2、通过struct clk *clk_get(struct device *dev, const char *con_id)来获取时钟时,可以结合devkboj->namecon_idarch/arm/mach-omap2/clock814x_data.c中查找即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值