Chinaunix首页 | 论坛 | 博客
  • 博客访问: 89789
  • 博文数量: 24
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 15
  • 用 户 组: 普通用户
  • 注册时间: 2013-12-30 18:07
个人简介

peaceful

文章分类
文章存档

2017年(1)

2015年(2)

2014年(20)

2013年(1)

我的朋友

分类: LINUX

2014-04-10 16:40:36

原文地址:smdkv210_map_io 作者:shushi0123



点击(此处)折叠或打开

  1. static void __init smdkv210_map_io(void)
  2. {
  3.     s5p_init_io(NULL, 0, S5P_VA_CHIPID);
  4.     s3c24xx_init_clocks(24000000);
  5.     s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs));
  6.     s5p_set_timer_source(S5P_PWM2, S5P_PWM4);
  7. }

点击(此处)折叠或打开

  1. void __init s5p_init_io(struct map_desc *mach_desc,
  2.             int size, void __iomem *cpuid_addr)
  3. {
  4.     unsigned long idcode;

  5.     /* initialize the io descriptors we need for initialization */
  6.     iotable_init(s5p_iodesc, ARRAY_SIZE(s5p_iodesc));
  7.     if (mach_desc)
  8.         iotable_init(mach_desc, size);

  9.     idcode = __raw_readl(cpuid_addr);
  10.     s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));//从CPUids中查找开发板自己的cpu
  11. }

点击(此处)折叠或打开

  1. void __init s3c_init_cpu(unsigned long idcode,
  2.              struct cpu_table *cputab, unsigned int cputab_size)
  3. {
  4.     cpu = s3c_lookup_cpu(idcode, cputab, cputab_size);//在cputable中查询,查找的结果存放在cpu全局变量中

  5.     if (cpu == NULL) {
  6.         printk(KERN_ERR "Unknown CPU type 0x%08lx\n", idcode);
  7.         panic("Unknown S3C24XX CPU");
  8.     }

  9.     printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);

  10.     if (cpu->map_io == NULL || cpu->init == NULL) {
  11.         printk(KERN_ERR "CPU %s support not enabled\n", cpu->name);
  12.         panic("Unsupported Samsung CPU");
  13.     }

  14.     cpu->map_io(); //执行 如下 cpu_ids[] 中的s5pv210_map_io
  15. }

 点击(此处)折叠或打开

  1. static struct cpu_table cpu_ids[] __initdata = {
  2.     {
  3.         .idcode        = 0x56440100,
  4.         .idmask        = 0xfffff000,
  5.         .map_io        = s5p6440_map_io,
  6.         .init_clocks    = s5p6440_init_clocks,
  7.         .init_uarts    = s5p6440_init_uarts,
  8.         .init        = s5p64x0_init,
  9.         .name        = name_s5p6440,
  10.     }, {
  11.         .idcode        = 0x36450000,
  12.         .idmask        = 0xfffff000,
  13.         .map_io        = s5p6450_map_io,
  14.         .init_clocks    = s5p6450_init_clocks,
  15.         .init_uarts    = s5p6450_init_uarts,
  16.         .init        = s5p64x0_init,
  17.         .name        = name_s5p6450,
  18.     }, {
  19.         .idcode        = 0x43100000,
  20.         .idmask        = 0xfffff000,
  21.         .map_io        = s5pc100_map_io,
  22.         .init_clocks    = s5pc100_init_clocks,
  23.         .init_uarts    = s5pc100_init_uarts,
  24.         .init        = s5pc100_init,
  25.         .name        = name_s5pc100,
  26.     }, {
  27.         .idcode        = 0x43110000,
  28.         .idmask        = 0xfffff000,
  29.         .map_io        = s5pv210_map_io,
  30.         .init_clocks    = s5pv210_init_clocks,
  31.         .init_uarts    = s5pv210_init_uarts,
  32.         .init        = s5pv210_init,
  33.         .name        = name_s5pv210,
  34.     }, {
  35.         .idcode        = 0x43210000,
  36.         .idmask        = 0xfffe0000,
  37.         .map_io        = exynos4_map_io,
  38.         .init_clocks    = exynos4_init_clocks,
  39.         .init_uarts    = exynos4_init_uarts,
  40.         .init        = exynos4_init,
  41.         .name        = name_exynos4210,
  42.     },
  43. };


点击(此处)折叠或打开

  1. void __init s5pv210_map_io(void)
  2. {
  3. iotable_init(s5pv210_iodesc, ARRAY_SIZE(s5pv210_iodesc));
  4. /* initialise device information early */
  5. s5pv210_default_sdhci0();
  6. s5pv210_default_sdhci1();
  7. s5pv210_default_sdhci2();
  8. s5pv210_default_sdhci3();
  9. s3c_adc_setname("s3c64xx-adc");
  10. s3c_cfcon_setname("s5pv210-pata");
  11. s3c_fimc_setname(0, "s5pv210-fimc");
  12. s3c_fimc_setname(1, "s5pv210-fimc");
  13. s3c_fimc_setname(2, "s5pv210-fimc");
  14. /* the i2c devices are directly compatible with s3c2440 */
  15. s3c_i2c0_setname("s3c2440-i2c");
  16. s3c_i2c1_setname("s3c2440-i2c");
  17. s3c_i2c2_setname("s3c2440-i2c");
  18. s3c_fb_setname("s5pv210-fb");
  19. /* Use s5pv210-keypad instead of samsung-keypad */
  20. samsung_keypad_setname("s5pv210-keypad");
  21. }
完成s5p_init_io(NULL, 0, S5P_VA_CHIPID);后继续执行s3c24xx_init_clocks(24000000)如下所示

点击(此处)折叠或打开

  1. void __init s3c24xx_init_clocks(int xtal)
  2. {
  3.     if (xtal == 0)
  4.         xtal = 12*1000*1000;

  5.     if (cpu == NULL)
  6.         panic("s3c24xx_init_clocks: no cpu setup?\n");

  7.     if (cpu->init_clocks == NULL)
  8.         panic("s3c24xx_init_clocks: cpu has no clock init\n");
  9.     else
  10.         (cpu->init_clocks)(xtal);  //由于在之前填充了cpu全局变量,实际就是执行 s5pv210_init_clocks ( .init_clocks    = s5pv210_init_clocks
  11. }
s5pv210_init_clocks如下:

点击(此处)折叠或打开

  1. void __init s5pv210_init_clocks(int xtal)
  2. {
  3.     printk(KERN_DEBUG "%s: initializing clocks\n", __func__);

  4.     s3c24xx_register_baseclocks(xtal); //注册基本时钟,24XX
  5.     s5p_register_clocks(xtal);  //都是注册时钟
  6.     s5pv210_register_clocks(); //都是注册时钟
  7.     s5pv210_setup_clocks();
  8. }

点击(此处)折叠或打开

  1. int __init s3c24xx_register_baseclocks(unsigned long xtal)
  2. {
  3.     printk(KERN_INFO "S3C24XX Clocks, Copyright 2004 Simtec Electronics\n");

  4.     clk_xtal.rate = xtal; // 设置 clk_xtal.rate时钟速率,clk_xtal是struct clk类型,这个clk类型包含了控制位和控制函数,还有一个链表头,能够和其他clk构成链表机构

  5.     /* register our clocks */

  6.     if (s3c24xx_register_clock(&clk_xtal) < 0)//注册 clk_xtal到链表中
  7.         printk(KERN_ERR "failed to register master xtal\n");

  8.     if (s3c24xx_register_clock(&clk_mpll) < 0) //注册  clk_mpll 到链表中
  9.         printk(KERN_ERR "failed to register mpll clock\n");

  10.     if (s3c24xx_register_clock(&clk_upll) < 0) //注册  clk_upll 到链表中
  11.         printk(KERN_ERR "failed to register upll clock\n");

  12.     if (s3c24xx_register_clock(&clk_f) < 0) //注册  clk_f 到链表中
  13.         printk(KERN_ERR "failed to register cpu fclk\n");

  14.     if (s3c24xx_register_clock(&clk_h) < 0) //注册  clk_h 到链表中
  15.         printk(KERN_ERR "failed to register cpu hclk\n");

  16.     if (s3c24xx_register_clock(&clk_p) < 0) //注册  clk_p 到链表中
  17.         printk(KERN_ERR "failed to register cpu pclk\n");

  18.     return 0;
  19. }

点击(此处)折叠或打开

  1. int s3c24xx_register_clock(struct clk *clk)
  2. {
  3.     if (clk->enable == NULL)
  4.         clk->enable = clk_null_enable;

  5.     /* add to the list of available clocks */

  6.     /* Quick check to see if this clock has already been registered. */
  7.     BUG_ON(clk->list.prev != clk->list.next);

  8.     spin_lock(&clocks_lock);  //操作链表时获得自旋锁
  9.     list_add(&clk->list, &clocks);  //将本clk插入到以clocks为链表头的链表中
  10.     spin_unlock(&clocks_lock);

  11.     return 0;
  12. }

 点击(此处)折叠或打开

  1. struct clk {
  2.     struct list_head list;  
  3.     struct module *owner;
  4.     struct clk *parent;
  5.     const char *name;
  6.     int         id;
  7.     int         usage;
  8.     unsigned long rate;
  9.     unsigned long ctrlbit;

  10.     struct clk_ops        *ops;
  11.     int         (*enable)(struct clk *, int enable);
  12. #if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
  13.     struct dentry        *dent;    /* For visible tree hierarchy */
  14. #endif
  15. };


点击(此处)折叠或打开

  1. static LIST_HEAD(clocks);

  2. //include/linux/list.h中
  3. #define LIST_HEAD_INIT(name) { &(name), &(name) }

  4. #define LIST_HEAD(name) \
  5.     struct list_head name = LIST_HEAD_INIT(name)

  6. static inline void INIT_LIST_HEAD(struct list_head *list)
  7. {
  8.     list->next = list;
  9.     list->prev = list;
  10. }

  11. 通过上面,有了static LIST_HEAD(clocks)之后,其实就有一个clocks的list_head结构实体,其链表的next和prev 均指向了自己。

  12. spinlock_t clocks_lock  //操作时钟链表对应的自旋锁

阅读(1378) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~