clk_register

之前写了那么多关于系统时钟的机制,说到底,就那么回事,初始化系统时钟,初始化软中断,

以及初始化那个tvec_base,就这些,其他的也没有什么了,这篇主要关于每个外部设备的时钟的初始化,及获取。

 首先贴上源码

arch/arm/mach-s3c64xx/mach-smdk6410.c

   1145 MACHINE_START(SMDK6410, "SMDK6410")
   1146         /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
   1147         //.phys_io      = S3C_PA_UART & 0xfff00000,
   1148         //.io_pg_offst  = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
   1149         .boot_params    = S3C64XX_PA_SDRAM + 0x100,
   1150
   1151         .init_irq       = s3c6410_init_irq,
   1152         .map_io         = smdk6410_map_io,
   1153         .init_machine   = smdk6410_machine_init,
   1154         .timer          = &s3c24xx_timer,
   1155 MACHINE_END

   1053 static void __init smdk6410_map_io(void)
   1054 {
   1055         u32 tmp;
   1056
   1057         s3c64xx_init_io(smdk6410_iodesc, ARRAY_SIZE(smdk6410_iodesc));
   1058         s3c24xx_init_clocks(12000000);
   1059         s3c24xx_init_uarts(smdk6410_uartcfgs, ARRAY_SIZE(smdk6410_uartcfgs));
   1060
   1061         /* set the LCD type */
   1062
   1063         tmp = __raw_readl(S3C64XX_SPCON);
   1064         tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
   1065         tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
   1066         __raw_writel(tmp, S3C64XX_SPCON);
   1067
   1068         /* remove the lcd bypass */
   1069         tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
   1070         tmp &= ~MIFPCON_LCD_BYPASS;
   1071         __raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
   1072
   1073 #ifdef CONFIG_VIDEO_SAMSUNG

   1074         s3c64xx_reserve_bootmem();
   1075 #endif
   1076 }

void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
{
        unsigned long idcode;

        /* initialise the io descriptors we need for initialisation */
        iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));  //完成地址的虚实转换
        iotable_init(mach_desc, size);    //完成物理地址到虚拟地址的映射

        idcode = __raw_readl(S3C_VA_SYS + 0x118);  //读出本MCU的ID
        if (!idcode) {
                /* S3C6400 has the ID register in a different place,
                 * and needs a write before it can be read. */

                __raw_writel(0x0, S3C_VA_SYS + 0xA1C);
                idcode = __raw_readl(S3C_VA_SYS + 0xA1C);
        }

        s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));  //根据之前读出的ID对CPU进行初始化
}

#define UART_OFFS (S3C_PA_UART & 0xfffff)

static struct map_desc s3c_iodesc[] __initdata = {
        {
                .virtual        = (unsigned long)S3C_VA_SYS,
                .pfn            = __phys_to_pfn(S3C64XX_PA_SYSCON),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S3C_VA_MEM,
                .pfn            = __phys_to_pfn(S3C64XX_PA_SROM),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)(S3C_VA_UART + UART_OFFS),
                .pfn            = __phys_to_pfn(S3C_PA_UART),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)VA_VIC0,
                .pfn            = __phys_to_pfn(S3C64XX_PA_VIC0),

 

                .length         = SZ_16K,
                .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)VA_VIC1,
                .pfn            = __phys_to_pfn(S3C64XX_PA_VIC1),
                .length         = SZ_16K,
                .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S3C_VA_TIMER,
                .pfn            = __phys_to_pfn(S3C_PA_TIMER),
                .length         = SZ_16K,
                .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S3C64XX_VA_GPIO,
                .pfn            = __phys_to_pfn(S3C64XX_PA_GPIO),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S3C64XX_VA_MODEM,
                .pfn            = __phys_to_pfn(S3C64XX_PA_MODEM),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
        }, {

 

                .virtual        = (unsigned long)S3C_VA_WATCHDOG,
                .pfn            = __phys_to_pfn(S3C64XX_PA_WATCHDOG),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S3C_VA_USB_HSPHY,
                .pfn            = __phys_to_pfn(S3C64XX_PA_USB_HSPHY),
                .length         = SZ_1K,
                .type           = MT_DEVICE,
        },
};

 arch/arm/mach-s3c64xx/mach-smdk6410.c

    529 static struct map_desc smdk6410_iodesc[] = {
    530         {
    531                 /* LCD support */
    532                 .virtual    = (unsigned long)S3C_VA_LCD,
    533                 .pfn        = __phys_to_pfn(S3C_PA_FB),
    534                 .length     = SZ_16K,
    535                 .type       = MT_DEVICE,
    536         },
    537 };

arch/arm/mach-s3c64xx/cpu.c

static struct cpu_table cpu_ids[] __initdata = {
        {
                .idcode         = 0x36400000,
                .idmask         = 0xfffff000,
                .map_io         = s3c6400_map_io,
                .init_clocks    = s3c6400_init_clocks,
                .init_uarts     = s3c6400_init_uarts,
                .init           = s3c6400_init,
                .name           = name_s3c6400,
        }, {
                .idcode         = 0x36410100,
                .idmask         = 0xffffff00,
                .map_io         = s3c6410_map_io,       //这里有点搞不清,最后为什么要调用
                .init_clocks    = s3c6410_init_clocks, //初始化外设时钟
                .init_uarts     = s3c6410_init_uarts,
                .init           = s3c6410_init,
                .name           = name_s3c6410,
        },
};
arch/arm/plat-samsung/init.c

void __init s3c_init_cpu(unsigned long idcode,
                         struct cpu_table *cputab, unsigned int cputab_size)
{
        cpu = s3c_lookup_cpu(idcode, cputab, cputab_size);  //寻找与本CPU相同ID的那个玩意

        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();   //这里的东西不是很明白,之前已经调用了map_io.完成了IO口的映射,可这里搞的这玩意,是不清楚了
}

arch/arm/mach-s3c64xx/s3c6410.c

void __init s3c6410_map_io(void)
{
        /* initialise device information early */
        s3c6410_default_sdhci0();
        s3c6410_default_sdhci1();
        s3c6410_default_sdhci2();

        /* the i2c devices are directly compatible with s3c2440 */
        s3c_i2c0_setname("s3c2440-i2c");
        s3c_i2c1_setname("s3c2440-i2c");

        s3c_adc_setname("s3c64xx-adc");
        s3c_device_nand.name = "s3c6410-nand";   // gjl s3c6400-nand
        s3c_onenand_setname("s3c6410-onenand");
        s3c64xx_onenand1_setname("s3c6410-onenand");
        s3c_cfcon_setname("s3c64xx-pata");
}

上面的不是很清楚,希望有懂得人,指点一下,接下来看看他的s3c24xx_init_clocks
   1053 static void __init smdk6410_map_io(void)
   1054 {
   1055         u32 tmp;
   1056
   1057         s3c64xx_init_io(smdk6410_iodesc, ARRAY_SIZE(smdk6410_iodesc));    //找到了和本MCU匹配的cpu列表,然后将寄存器地址进行了重新映射
   1058         s3c24xx_init_clocks(12000000);
   1059         s3c24xx_init_uarts(smdk6410_uartcfgs, ARRAY_SIZE(smdk6410_uartcfgs));
   1060
   1061         /* set the LCD type */
   1062
...............................................................................................................................................................

              }

arch/arm/plat-samsung/init.c

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);       //这里调用的就是下面的s3c6410_init_clocks,在之前的map_io里有一个函数,找到与本地MCU匹配的cpu
}

arch/arm/mach-s3c64xx/s3c6410.c

void __init s3c6410_init_clocks(int xtal)
{
        printk(KERN_DEBUG "%s: initialising clocks\n", __func__);
        s3c64xx_register_clocks(xtal, S3C6410_CLKDIV0_ARM_MASK);
        s3c6400_setup_clocks();
}

arch/arm/mach-s3c64xx/clock.c

void __init s3c64xx_register_clocks(unsigned long xtal,
                                    unsigned armclk_divlimit)
{
        struct clk *clkp;
        int ret;
        int ptr;

        armclk_mask = armclk_divlimit;

        s3c24xx_register_baseclocks(xtal);     //注册主要的时钟,例如HCLK PCLK, MPLL ,DPLL等等
        s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));    //注册了时钟部分

        s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));    //注册了时钟部分

        clkp = init_clocks_disable;
        for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {

                ret = s3c24xx_register_clock(clkp);
                if (ret < 0) {

                        printk(KERN_ERR "Failed to register clock %s (%d)\n",
                               clkp->name, ret);
                }

                (clkp->enable)(clkp, 0);
        }

        s3c24xx_register_clocks(clks1, ARRAY_SIZE(clks1));
        s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
        s3c_pwmclk_init();
}

arch/arm/plat-samsung/clock.c

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

        clk_xtal.rate = xtal;

        /* register our clocks */

        if (s3c24xx_register_clock(&clk_xtal) < 0)
                printk(KERN_ERR "failed to register master xtal\n");

        if (s3c24xx_register_clock(&clk_mpll) < 0)
                printk(KERN_ERR "failed to register mpll clock\n");

        if (s3c24xx_register_clock(&clk_upll) < 0)
                printk(KERN_ERR "failed to register upll clock\n");

        if (s3c24xx_register_clock(&clk_f) < 0)
                printk(KERN_ERR "failed to register cpu fclk\n");

        if (s3c24xx_register_clock(&clk_h) < 0)
                printk(KERN_ERR "failed to register cpu hclk\n");

       if (s3c24xx_register_clock(&clk_p) < 0)
                printk(KERN_ERR "failed to register cpu pclk\n");

        return 0;
}

static struct clk init_clocks[] = {              //要注册的时钟
        {
                .name           = "lcd",
                .id             = -1,
                .parent         = &clk_h,
                .enable         = s3c64xx_hclk_ctrl,
                .ctrlbit        = S3C_CLKCON_HCLK_LCD,
        }, {
                .name           = "gpio",
                .id             = -1,
                .parent         = &clk_p,
                .enable         = s3c64xx_pclk_ctrl,
                .ctrlbit        = S3C_CLKCON_PCLK_GPIO,
        }, {
                .name           = "usb-host",
                .id             = -1,
                .parent         = &clk_h,
                .enable         = s3c64xx_hclk_ctrl,
                .ctrlbit        = S3C_CLKCON_HCLK_UHOST,
        }, {
                .name           = "hsmmc",
                .id             = 0,

                .parent         = &clk_h,
                .enable         = s3c64xx_hclk_ctrl,
                .ctrlbit        = S3C_CLKCON_HCLK_HSMMC0,
        }, {
                .name           = "hsmmc",
                .id             = 1,
                .parent         = &clk_h,
                .enable         = s3c64xx_hclk_ctrl,
                .ctrlbit        = S3C_CLKCON_HCLK_HSMMC1,
        }, {
                .name           = "hsmmc",
                .id             = 2,
                .parent         = &clk_h,
                .enable         = s3c64xx_hclk_ctrl,
                .ctrlbit        = S3C_CLKCON_HCLK_HSMMC2,
        }, {
                .name           = "otg",
                .id             = -1,
                .parent         = &clk_h,
                .enable         = s3c64xx_hclk_ctrl,
                .ctrlbit        = S3C_CLKCON_HCLK_USB,

        }, {
                .name           = "timers",
                .id             = -1,
                .parent         = &clk_p,
                .enable         = s3c64xx_pclk_ctrl,
                .ctrlbit        = S3C_CLKCON_PCLK_PWM,
        }, {
                .name           = "uart",
                .id             = 0,
                .parent         = &clk_p,
                .enable         = s3c64xx_pclk_ctrl,
                .ctrlbit        = S3C_CLKCON_PCLK_UART0,
        }, {
                .name           = "uart",
                .id             = 1,
                .parent         = &clk_p,
                .enable         = s3c64xx_pclk_ctrl,
                .ctrlbit        = S3C_CLKCON_PCLK_UART1,
        }, {
                .name           = "uart",
                .id             = 2,
                .parent         = &clk_p,

                .enable         = s3c64xx_pclk_ctrl,
                .ctrlbit        = S3C_CLKCON_PCLK_UART2,
        }, {
                .name           = "uart",
                .id             = 3,
                .parent         = &clk_p,
                .enable         = s3c64xx_pclk_ctrl,
                .ctrlbit        = S3C_CLKCON_PCLK_UART3,
        }, {
                .name           = "watchdog",
                .id             = -1,
                .parent         = &clk_p,
                .ctrlbit        = S3C_CLKCON_PCLK_WDT,
        }, {
                .name           = "ac97",
                .id             = -1,
                .parent         = &clk_p,
                .ctrlbit        = S3C_CLKCON_PCLK_AC97,
        }, {
                .name           = "cfcon",
                .id             = -1,
                .parent         = &clk_h,
                .enable         = s3c64xx_hclk_ctrl,

                .ctrlbit        = S3C_CLKCON_HCLK_IHOST,
        },

#ifdef CONFIG_VIDEO_SAMSUNG
        {
                .name           = "fimc",
                .id             = -1,
                .parent         = &clk_h,
                .ctrlbit        = S3C_CLKCON_HCLK_CAMIF,
        }, {
                .name           = "hclk_mfc",
                .id             = -1,
                .parent         = &clk_h,
                .enable         = s3c64xx_hclk_ctrl,
                .ctrlbit        = S3C_CLKCON_HCLK_MFC,
        }, {
                .name           = "sclk_mfc",
                .id             = -1,
                .parent         = &clk_h2,
                .enable         = s3c64xx_sclk_ctrl,
                .ctrlbit        = S3C_CLKCON_SCLK_MFC,
                .usage          = 0,
                .rate           = 48*1000*1000,

        }, {
                .name           = "pclk_mfc",
                .id             = -1,
                .parent         = &clk_p,
                .enable         = s3c64xx_pclk_ctrl,
                .ctrlbit        = S3C_CLKCON_PCLK_MFC,
        }, {
                .name           = "hclk_jpeg",
                .id             = -1,
                .parent         = &clk_h,
                .enable         = s3c64xx_hclk_ctrl,
                .ctrlbit        = S3C_CLKCON_HCLK_JPEG,
        }, {
                .name           = "sclk_jpeg",
                .id             = -1,
                .parent         = &clk_h2,
                .enable         = s3c64xx_sclk_ctrl,
                .ctrlbit        = S3C_CLKCON_SCLK_JPEG,
                .usage          = 0,
                .rate           = 48*1000*1000,
        }, {
                .name           = "sclk_cam",

                .id             = -1,
                .parent         = &clk_h2,
                .enable         = s3c64xx_sclk_ctrl,
                .ctrlbit        = S3C_CLKCON_SCLK_CAM,
                .ops        = &(struct clk_ops) {
                        .set_rate       = s3c64xx_setrate_sclk_cam,
                },
        },
#endif
};

int s3c24xx_register_clocks(struct clk **clks, int nr_clks)
{
        int fails = 0;

        for (; nr_clks > 0; nr_clks--, clks++) {
                if (s3c24xx_register_clock(*clks) < 0) {
                        struct clk *clk = *clks;
                        printk(KERN_ERR "%s: failed to register %p: %s\n",
                               __func__, clk, clk->name);
                        fails++;
                }
        }

        return fails;
}

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);
        spin_unlock(&clocks_lock);

        return 0;
}


 

 



 

 

 

 


 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值