在驱动程序中经常看到这样使能片上资源的时钟 struct clk *usb_clk; usb_clk = clk_get(&pdev->dev, "usb-host"); clk_enable(usb_clk);
一开始很费解,为什么是名字是“usb-host”,记得之间移植usb驱动时,还写成了"usbhost"导致时钟使能失败
今天特意分析了一番
clk_get(struct device *dev, const char *con_id) const char *dev_id = dev ? dev_name(dev) : NULL; /* dev->init_name */ clk_get_sys(dev_id, con_id); /* 根据dev_id和con_id去找相应的时钟 */ clk_find(dev_id, con_id); list_for_each_entry(p, &clocks, node) list_for_each_entry(p, &clocks, node) /* 遍历clock链表,找到对应的时钟 */ strcmp(p->dev_id, dev_id) strcmp(p->con_id, con_id)
clock是什么呢?
实际上只是定义了一个链表头 static LIST_HEAD(clocks);
通过下面的函数给它添加元素 void __init clkdev_add_table(struct clk_lookup *cl, size_t num) list_add_tail(&cl->node, &clocks); void clkdev_add(struct clk_lookup *cl) list_add_tail(&cl->node, &clocks);
现在需要找到哪里调用了这些函数给clocks添加元素
搜索得到 linux-3.4.2\arch\arm\mach-s5pv210\clock.c void __init s5pv210_register_clocks(void) * clkdev_add_table(s5pv210_clk_lookup, ARRAY_SIZE(s5pv210_clk_lookup)); s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); s3c24xx_register_clock * clkdev_add(&clk->lookup);
在这个文件中定义了很多数组,然后将这些数组项添加到clocks链表中 static struct clk init_clocks_off[] = { { .name= "dma", .devname= "dma-pl330.0", .parent= &clk_hclk_psys.clk, .enable= s5pv210_clk_ip0_ctrl, .ctrlbit= (1 << 3), }, { .name= "fimc", .devname= "s5pv210-fimc.1", .parent= &clk_hclk_dsys.clk, .enable= s5pv210_clk_ip0_ctrl, .ctrlbit= (1 << 25), }, { .name= "dac", .devname= "s5p-sdo", .parent= &clk_hclk_dsys.clk, .enable= s5pv210_clk_ip1_ctrl, .ctrlbit= (1 << 10), }, { .name= "usb-host", .parent= &clk_hclk_psys.clk, .enable= s5pv210_clk_ip1_ctrl, .ctrlbit= (1<<17), }, { .name= "lcd", .parent= &clk_hclk_dsys.clk, .enable= s5pv210_clk_ip1_ctrl, .ctrlbit= (1<<0), }, }; s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); s3c24xx_register_clock(clkp); clk->lookup.dev_id = clk->devname; clk->lookup.con_id = clk->name; clk->lookup.clk = clk; /* clk_get返回的就是这一个 */ clkdev_add(&clk->lookup);
因此如果要使能某一个片上资源额时钟,比如lcd控制器,那么现在这上面找到对应的名字
然后调用下面的函数就可以使能lcd控制器的时钟 struct clk *usb_clk; usb_clk = clk_get(NULL, "lcd"); clk_enable(usb_clk);
下面将一下clk_enable int clk_enable(struct clk *clk) clk_enable(clk->parent); (clk->enable)(clk, 1); /* 调用了对应的enable函数 */