一. clock初始化过程
在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();
-
}
1. 把所有的clk_src添加到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();
-
}
2.把baseclock中的clk添加进链表中
在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;
-
}
CLOCK的类型:
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",
-
};
b. init_clocks_disable
-
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",
-
};
c. clks1与clks
-
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,
-
};
二. clock enable过程
在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;
-
}
2.1 以lcd为例为调用s3c64xx_hclk_ctrl
在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)
-
}
-
}
在arch/arm/plat-samsung/clock.c中
-
static int s3c64xx_hclk_ctrl(struct clk *clk, int enable)
-
{
-
return s3c64xx_gate(S3C_HCLK_GATE, clk, enable);
-
}
#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中
-
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);
阅读(2295) | 评论(0) | 转发(0) |