- static void __init smdkv210_map_io(void)
- {
- s5p_init_io(NULL, 0, S5P_VA_CHIPID);
- s3c24xx_init_clocks(24000000);
- s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs));
- s5p_set_timer_source(S5P_PWM2, S5P_PWM4);
- }
- void __init s5p_init_io(struct map_desc *mach_desc,
- int size, void __iomem *cpuid_addr)
- {
- unsigned long idcode;
- /* initialize the io descriptors we need for initialization */
- iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc));
- if (mach_desc)
- iotable_init(mach_desc, size);
- idcode = __raw_readl(cpuid_addr);
- s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));//从CPUids中查找开发板自己的cpu
- }
- void __init s3c_init_cpu(unsigned long idcode,
- struct cpu_table *cputab, unsigned int cputab_size)
- {
- cpu = s3c_lookup_cpu(idcode, cputab, cputab_size);//在cputable中查询,查找的结果存放在cpu全局变量中
- if (cpu == NULL) {
- printk(KERN_ERR "Unknown CPU type 0x%08lx\n", idcode);
- panic("Unknown S3C24XX CPU");
- }
- printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
- if (cpu->map_io == NULL || cpu->init == NULL) {
- printk(KERN_ERR "CPU %s support not enabled\n", cpu->name);
- panic("Unsupported Samsung CPU");
- }
- cpu->map_io(); //执行 如下
cpu_ids[] 中的s5pv210_map_io
- }
- static struct cpu_table cpu_ids[] __initdata = {
- {
- .idcode = 0x56440100,
- .idmask = 0xfffff000,
- .map_io = s5p6440_map_io,
- .init_clocks = s5p6440_init_clocks,
- .init_uarts = s5p6440_init_uarts,
- .init = s5p64x0_init,
- .name = name_s5p6440,
- }, {
- .idcode = 0x36450000,
- .idmask = 0xfffff000,
- .map_io = s5p6450_map_io,
- .init_clocks = s5p6450_init_clocks,
- .init_uarts = s5p6450_init_uarts,
- .init = s5p64x0_init,
- .name = name_s5p6450,
- }, {
- .idcode = 0x43100000,
- .idmask = 0xfffff000,
- .map_io = s5pc100_map_io,
- .init_clocks = s5pc100_init_clocks,
- .init_uarts = s5pc100_init_uarts,
- .init = s5pc100_init,
- .name = name_s5pc100,
- }, {
- .idcode = 0x43110000,
- .idmask = 0xfffff000,
- .map_io = s5pv210_map_io,
- .init_clocks = s5pv210_init_clocks,
- .init_uarts = s5pv210_init_uarts,
- .init = s5pv210_init,
- .name = name_s5pv210,
- }, {
- .idcode = 0x43210000,
- .idmask = 0xfffe0000,
- .map_io = exynos4_map_io,
- .init_clocks = exynos4_init_clocks,
- .init_uarts = exynos4_init_uarts,
- .init = exynos4_init,
- .name = name_exynos4210,
- },
- };
- void __init s5pv210_map_io(void)
- {
- iotable_init(s5pv210_iodesc, ARRAY_SIZE(s5pv210_iodesc));
- /* initialise device information early */
- s5pv210_default_sdhci0();
- s5pv210_default_sdhci1();
- s5pv210_default_sdhci2();
- s5pv210_default_sdhci3();
- s3c_adc_setname("s3c64xx-adc");
- s3c_cfcon_setname("s5pv210-pata");
- s3c_fimc_setname(0, "s5pv210-fimc");
- s3c_fimc_setname(1, "s5pv210-fimc");
- s3c_fimc_setname(2, "s5pv210-fimc");
- /* the i2c devices are directly compatible with s3c2440 */
- s3c_i2c0_setname("s3c2440-i2c");
- s3c_i2c1_setname("s3c2440-i2c");
- s3c_i2c2_setname("s3c2440-i2c");
- s3c_fb_setname("s5pv210-fb");
- /* Use s5pv210-keypad instead of samsung-keypad */
- samsung_keypad_setname("s5pv210-keypad");
- }
完成
s5p_init_io(NULL, 0, S5P_VA_CHIPID);后继续执行s3c24xx_init_clocks(24000000)如下所示- void __init s3c24xx_init_clocks(int xtal)
- {
- if (xtal == 0)
- xtal = 12*1000*1000;
- if (cpu == NULL)
- panic("s3c24xx_init_clocks: no cpu setup?\n");
- if (cpu->init_clocks == NULL)
- panic("s3c24xx_init_clocks: cpu has no clock init\n");
- else
- (cpu->init_clocks)(xtal); //由于在之前填充了cpu全局变量,实际就是执行
s5pv210_init_clocks ( .init_clocks = s5pv210_init_clocks)
- }
s5pv210_init_clocks如下:- void __init s5pv210_init_clocks(int xtal)
- {
- printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
- s3c24xx_register_baseclocks(xtal); //注册基本时钟,24XX
- s5p_register_clocks(xtal); //都是注册时钟
- s5pv210_register_clocks();
//都是注册时钟
- s5pv210_setup_clocks();
- }
- int __init s3c24xx_register_baseclocks(unsigned long xtal)
- {
- printk(KERN_INFO "S3C24XX Clocks, Copyright 2004 Simtec Electronics\n");
- clk_xtal.rate = xtal; // 设置
clk_xtal.rate时钟速率,clk_xtal是struct clk类型,这个clk类型包含了控制位和控制函数,还有一个链表头,能够和其他clk构成链表机构
- /* register our clocks */
- if (s3c24xx_register_clock(&clk_xtal) < 0)//注册
clk_xtal到链表中
- printk(KERN_ERR "failed to register master xtal\n");
- if (s3c24xx_register_clock(&clk_mpll) < 0)
//注册
clk_mpll 到链表中
- printk(KERN_ERR "failed to register mpll clock\n");
- if (s3c24xx_register_clock(&clk_upll) < 0)
//注册
clk_upll 到链表中
- printk(KERN_ERR "failed to register upll clock\n");
- if (s3c24xx_register_clock(&clk_f) < 0)
//注册
clk_f 到链表中
- printk(KERN_ERR "failed to register cpu fclk\n");
- if (s3c24xx_register_clock(&clk_h) < 0)
//注册
clk_h 到链表中
- printk(KERN_ERR "failed to register cpu hclk\n");
- if (s3c24xx_register_clock(&clk_p) < 0)
//注册
clk_p 到链表中
- printk(KERN_ERR "failed to register cpu pclk\n");
- return 0;
- }
- int s3c24xx_register_clock(struct clk *clk)
- {
- if (clk->enable == NULL)
- clk->enable = clk_null_enable;
- /* add to the list of available clocks */
- /* Quick check to see if this clock has already been registered. */
- BUG_ON(clk->list.prev != clk->list.next);
- spin_lock(&clocks_lock); //操作链表时获得自旋锁
- list_add(&clk->list, &clocks); //将本clk插入到以clocks为链表头的链表中
- spin_unlock(&clocks_lock);
- return 0;
- }
- struct clk {
- struct list_head list;
- struct module *owner;
- struct clk *parent;
- const char *name;
- int id;
- int usage;
- unsigned long rate;
- unsigned long ctrlbit;
- struct clk_ops *ops;
- int (*enable)(struct clk *, int enable);
- #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
- struct dentry *dent; /* For visible tree hierarchy */
- #endif
- };
- static LIST_HEAD(clocks);
- //include/linux/list.h中
- #define LIST_HEAD_INIT(name) { &(name), &(name) }
- #define LIST_HEAD(name) \
- struct list_head name = LIST_HEAD_INIT(name)
- static inline void INIT_LIST_HEAD(struct list_head *list)
- {
- list->next = list;
- list->prev = list;
- }
- 通过上面,有了static LIST_HEAD(clocks)之后,其实就有一个clocks的list_head结构实体,其链表的next和prev 均指向了自己。
- spinlock_t clocks_lock //操作时钟链表对应的自旋锁
阅读(1378) | 评论(0) | 转发(0) |