一. clock初始化过程
在arch/arm/mach-s3c64xx/s3c6410.c中
1. 把所有的clk_src添加到clocks链表中
在arch/arm/mach-s3c64xx/clock.c中
2.把baseclock中的clk添加进链表中
在arch/arm/plat-samsung/clock.c中
3.将clk结构体添加到clocks链表中
在arch/arm/plat-samsung/clock.c中
CLOCK的类型:
a. init_clocks
b. init_clocks_disable
c. clks1与clks
二. clock enable过程
在drivers/video/s3c-fb.c中
1. 从clocks链表中查找lcd的clk结构体
在arch/arm/plat-samsung/clock.c中
2. 具体的enable过程
在arch/arm/plat-samsung/clock.c中
2.1 以lcd为例为调用
s3c64xx_hclk_ctrl
在arch/arm/plat-samsung/clock.c中
在arch/arm/plat-samsung/clock.c中
#define S3C_HCLK_GATE S3C_CLKREG(0x30)
#define S3C_CLKREG(x) (S3C_VA_SYS + (x))
HCLK_GATE 0x7E00_F030
2.2 修改gate寄存器,使能或禁止clock
在arch/arm/plat-samsung/clock.c中
附录:
1. 获取clk的值
clk_get_rate(struct clk);
在arch/arm/mach-s3c64xx/s3c6410.c中
- void __init s3c6410_init_clocks(int xtal)
- {
- s3c64xx_register_clocks(xtal, S3C6410_CLKDIV0_ARM_MASK); //1.将clk_src添加到clocks链表中
- s3c6400_setup_clocks();
- }
在arch/arm/mach-s3c64xx/clock.c中
- void __init s3c64xx_register_clocks(unsigned long xtal, unsigned armclk_divlimit)
- {
- armclk_mask = armclk_divlimit;
- //把xtal mpll upll clk_f clk_h clk_p添加到clocks链表中
- s3c24xx_register_baseclocks(xtal);
- //把 ext, epll, 27m, 48m, h2, xusbxti,添加到clocks链表中
- s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
- //把init_clocks区的clk添加到clokcs链表中
- s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
- //放在init_clocks_disable区内的clk,先添加进链表然后调用enable(0),禁止clk生效
- clkp = init_clocks_disable;
- for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
- ret = s3c24xx_register_clock(clkp);
- (clkp->enable)(clkp, 0);
- }
- //把cks1区的clk添加到clokcs链表中
- s3c24xx_register_clocks(clks1, ARRAY_SIZE(clks1));
- //把clksrcs区的clk添加到clokcs链表中
- s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
- s3c_pwmclk_init();
- }
在arch/arm/plat-samsung/clock.c中
- int __init s3c24xx_register_baseclocks(unsigned long xtal)
- {
- clk_xtal.rate = xtal;
- s3c24xx_register_clock(&clk_xtal)
- s3c24xx_register_clock(&clk_mpll)
- s3c24xx_register_clock(&clk_upll)
- s3c24xx_register_clock(&clk_f)
- s3c24xx_register_clock(&clk_h)
- s3c24xx_register_clock(&clk_p)
- }
3.将clk结构体添加到clocks链表中
在arch/arm/plat-samsung/clock.c中
- int s3c24xx_register_clock(struct clk *clk)
- {
- if (clk->enable == NULL)
- clk->enable = clk_null_enable;
-
- spin_lock(&clocks_lock);
- list_add(&clk->list, &clocks); //把参数中的clk结构体添加到clocks链表中
- spin_unlock(&clocks_lock);
- return 0;
- }
a. init_clocks
- static struct clk init_clocks[] = {
- .name = "lcd",
- .name = "gpio",
- .name = "usb-host",
- .name = "hsmmc",
- .name = "hsmmc",
- .name = "hsmmc",
- .name = "otg",
- .name = "timers",
- .name = "uart",
- .name = "uart",
- .name = "uart",
- .name = "uart",
- .name = "watchdog",
- .name = "ac97",
- .name = "cfcon",
- .name = "fimc",
- .name = "hclk_mfc",
- .name = "sclk_mfc",
- .name = "pclk_mfc",
- .name = "hclk_jpeg",
- .name = "sclk_jpeg",
- .name = "sclk_cam",
- };
- static struct clk init_clocks_disable[] = {
- .name = "nand",
- .name = "rtc",
- .name = "adc",
- .name = "i2c",
- .name = "iis",
- .name = "iis",
- .name = "iis",
- .name = "keypad",
- .name = "spi",
- .name = "spi",
- .name = "spi_48m",
- .name = "spi_48m",
- .name = "48m",
- .name = "48m",
- .name = "48m",
- .name = "dma0",
- .name = "dma1",
- };
- static struct clk *clks1[] __initdata = {
- &clk_ext_xtal_mux,
- &clk_iis_cd0,
- &clk_iis_cd1,
- &clk_iisv4_cd,
- &clk_pcm_cd,
- &clk_mout_epll.clk,
- &clk_mout_mpll.clk,
- &clk_dout_mpll,
- &clk_arm,
- };
-
- static struct clk *clks[] __initdata = {
- &clk_ext,
- &clk_epll,
- &clk_27m,
- &clk_48m,
- &clk_h2,
- &clk_xusbxti,
- };
在drivers/video/s3c-fb.c中
- static int __devinit s3c_fb_probe(struct platform_device *pdev)
- {
- sfb->bus_clk = clk_get(dev, "lcd"); //1.从clocks链表中查找lcd的clk结构体
- clk_enable(sfb->bus_clk); //2.调用clk的enableb函数
- }
1. 从clocks链表中查找lcd的clk结构体
在arch/arm/plat-samsung/clock.c中
- struct clk *clk_get(struct device *dev, const char *id)
- {
- spin_lock(&clocks_lock);
- //从clocks中查找id与name都与参数相同的clk结构体
- list_for_each_entry(p, &clocks, list) {
- if (p->id == idno && strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
- clk = p;
- break;
- }
- }
- spin_unlock(&clocks_lock);
- return clk;
- }
2. 具体的enable过程
在arch/arm/plat-samsung/clock.c中
- int clk_enable(struct clk *clk)
- {
- clk_enable(clk->parent); //先调用parent的enable
-
- spin_lock(&clocks_lock);
-
- if ((clk->usage++) == 0)
- (clk->enable)(clk, 1); //2.1 再调用具体的enable
-
- spin_unlock(&clocks_lock);
- return 0;
- }
在arch/arm/plat-samsung/clock.c中
- static struct clk init_clocks[] = {
- {
- .name = "lcd",
- .id = -1,
- .parent = &clk_h,
- .enable = s3c64xx_hclk_ctrl,
- .ctrlbit = S3C_CLKCON_HCLK_LCD, //S3C_CLKCON_HCLK_LCD (1<<3)
- }
- }
- static int s3c64xx_hclk_ctrl(struct clk *clk, int enable)
- {
- return s3c64xx_gate(S3C_HCLK_GATE, clk, enable);
- }
#define S3C_CLKREG(x) (S3C_VA_SYS + (x))
HCLK_GATE 0x7E00_F030
2.2 修改gate寄存器,使能或禁止clock
在arch/arm/plat-samsung/clock.c中
- static int inline s3c64xx_gate(void __iomem *reg, struct clk *clk, int enable)
- {
- unsigned int ctrlbit = clk->ctrlbit;
- u32 con;
-
- con = __raw_readl(reg); //读取寄存器的值
-
- if (enable) //如果是enable,将这位清0
- con |= ctrlbit;
- else //如果是disable,将这位清0
- con &= ~ctrlbit;
-
- __raw_writel(con, reg); //修改后,写入到寄存器中
- return 0;
- }
1. 获取clk的值
clk_get_rate(struct clk);