S3C2440下clock的源码分析
来源:互联网 发布:传智播客java笔记 编辑:程序博客网 时间:2024/06/08 11:22
s3c2440时钟的体系结构
OM控制使用内部时钟和内部时钟,详细情况可以看数据手册
这里使用的源代码版本是2.6.35.14
初始化时钟代码arch\arm\s3c2440\s3c244x.c
void __init s3c244x_init_clocks(int xtal){/* initialise the clocks here, to allow other things like the * console to use them, and to add new ones after the initialisation */s3c24xx_register_baseclocks(xtal);s3c244x_setup_clocks();s3c2410_baseclk_add();}
首先我们看一下s3c24xx_register_baseclocks(xtal)函数在这里注册时钟arch\arm\plat-samsung\clock.c
/* initalise all the clocks */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;}这里面用到了s3c24xx_register_clock()函数看他是如何实现的
arch\arm\plat-samsung\clock.c
/* initialise the clock system *//** * s3c24xx_register_clock() - register a clock * @clk: The clock to register * * Add the specified clock to the list of clocks known by the system. */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;}接下来我们看一下s3c244x_steup_clocks(xtal)函数
所在目录arch\arm\mach-s3c2440\s3c244x.c
void __init_or_cpufreq s3c244x_setup_clocks(void){struct clk *xtal_clk;unsigned long clkdiv;unsigned long camdiv;unsigned long xtal;unsigned long hclk, fclk, pclk;int hdiv = 1;xtal_clk = clk_get(NULL, "xtal");xtal = clk_get_rate(xtal_clk);clk_put(xtal_clk);fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2;clkdiv = __raw_readl(S3C2410_CLKDIVN);camdiv = __raw_readl(S3C2440_CAMDIVN);/* work out clock scalings */switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {case S3C2440_CLKDIVN_HDIVN_1:hdiv = 1;break;case S3C2440_CLKDIVN_HDIVN_2:hdiv = 2;break;case S3C2440_CLKDIVN_HDIVN_4_8:hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;break;case S3C2440_CLKDIVN_HDIVN_3_6:hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;break;}hclk = fclk / hdiv;pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN) ? 2 : 1);/* print brief summary of clocks, etc */printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n", print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));s3c24xx_setup_clocks(fclk, hclk, pclk);}
再看看s3c24xx_setup_clocks函数arch\arm\plat-s3c24xx\clock.c
/* initalise all the clocks */void __init_or_cpufreq s3c24xx_setup_clocks(unsigned long fclk, unsigned long hclk, unsigned long pclk){clk_upll.rate = s3c24xx_get_pll(__raw_readl(S3C2410_UPLLCON),clk_xtal.rate);clk_mpll.rate = fclk;clk_h.rate = hclk;clk_p.rate = pclk;clk_f.rate = fclk;}
文件目录arch\arm\plat-s3c24xx\s3c2410-clock.c
/* s3c2410_baseclk_add() * * Add all the clocks used by the s3c2410 or compatible CPUs * such as the S3C2440 and S3C2442. * * We cannot use a system device as we are needed before any * of the init-calls that initialise the devices are actually * done.*/int __init s3c2410_baseclk_add(void){unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); //快慢时钟寄存器unsigned long clkcon = __raw_readl(S3C2410_CLKCON); //时钟控制寄存器struct clk *clkp;struct clk *xtal;int ret;int ptr;clk_upll.enable = s3c2410_upll_enable; //记录使能函数if (s3c24xx_register_clock(&clk_usb_bus) < 0) //注册USB时钟printk(KERN_ERR "failed to register usb bus clock\n");/* register clocks from clock array */clkp = init_clocks; //初始化要注册的clock列表for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { /* ensure that we note the clock state */clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0; //判断clock当前的状态ret = s3c24xx_register_clock(clkp); //注册clock列表if (ret < 0) {printk(KERN_ERR "Failed to register clock %s (%d)\n", clkp->name, ret);}}/* We must be careful disabling the clocks we are not intending to * be using at boot time, as subsystems such as the LCD which do * their own DMA requests to the bus can cause the system to lockup * if they where in the middle of requesting bus access. * * Disabling the LCD clock if the LCD is active is very dangerous, * and therefore the bootloader should be careful to not enable * the LCD clock if it is not needed.*//* install (and disable) the clocks we do not need immediately */s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); //注册启动不需要使用的clock列表s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); //禁止clock列表中的各项时钟/* show the clock-slow value */xtal = clk_get(NULL, "xtal"); //获得xtal的时钟printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n", print_mhz(clk_get_rate(xtal) / ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))), (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast", (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on", (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");s3c_pwmclk_init(); //初始化PWM时钟return 0;}
看看init_clocks中都有哪些时钟目录arch\arm\plat-s3c24xx\s3c2410-clock.c
static struct clk init_clocks[] = {{.name= "lcd",.id= -1,.parent= &clk_h,.enable= s3c2410_clkcon_enable,.ctrlbit= S3C2410_CLKCON_LCDC,}, {.name= "gpio",.id= -1,.parent= &clk_p,.enable= s3c2410_clkcon_enable,.ctrlbit= S3C2410_CLKCON_GPIO,}, {.name= "usb-host",.id= -1,.parent= &clk_h,.enable= s3c2410_clkcon_enable,.ctrlbit= S3C2410_CLKCON_USBH,}, {.name= "usb-device",.id= -1,.parent= &clk_h,.enable= s3c2410_clkcon_enable,.ctrlbit= S3C2410_CLKCON_USBD,}, {.name= "timers",.id= -1,.parent= &clk_p,.enable= s3c2410_clkcon_enable,.ctrlbit= S3C2410_CLKCON_PWMT,}, {.name= "uart",.id= 0,.parent= &clk_p,.enable= s3c2410_clkcon_enable,.ctrlbit= S3C2410_CLKCON_UART0,}, {.name= "uart",.id= 1,.parent= &clk_p,.enable= s3c2410_clkcon_enable,.ctrlbit= S3C2410_CLKCON_UART1,}, {.name= "uart",.id= 2,.parent= &clk_p,.enable= s3c2410_clkcon_enable,.ctrlbit= S3C2410_CLKCON_UART2,}, {.name= "rtc",.id= -1,.parent= &clk_p,.enable= s3c2410_clkcon_enable,.ctrlbit= S3C2410_CLKCON_RTC,}, {.name= "watchdog",.id= -1,.parent= &clk_p,.ctrlbit= 0,}, {.name= "usb-bus-host",.id= -1,.parent= &clk_usb_bus,}, {.name= "usb-bus-gadget",.id= -1,.parent= &clk_usb_bus,},};
再看看init_clocks_0ff中都有哪些时钟目录arch\arm\plat-s3c24xx\s3c2410-clock.c
* standard clock definitions */static struct clk init_clocks_off[] = {{.name= "nand",.id= -1,.parent= &clk_h,.enable= s3c2410_clkcon_enable,.ctrlbit= S3C2410_CLKCON_NAND,}, {.name= "sdi",.id= -1,.parent= &clk_p,.enable= s3c2410_clkcon_enable,.ctrlbit= S3C2410_CLKCON_SDI,}, {.name= "adc",.id= -1,.parent= &clk_p,.enable= s3c2410_clkcon_enable,.ctrlbit= S3C2410_CLKCON_ADC,}, {.name= "i2c",.id= -1,.parent= &clk_p,.enable= s3c2410_clkcon_enable,.ctrlbit= S3C2410_CLKCON_IIC,}, {.name= "iis",.id= -1,.parent= &clk_p,.enable= s3c2410_clkcon_enable,.ctrlbit= S3C2410_CLKCON_IIS,}, {.name= "spi",.id= -1,.parent= &clk_p,.enable= s3c2410_clkcon_enable,.ctrlbit= S3C2410_CLKCON_SPI,}};
到此我们已经知道在系统启动后我们的那些时钟已经启动了,那些没有启动。
- S3C2440下clock的源码分析
- 2410下clock源码分析
- 2410下clock源码分析
- S3C2440 对clock的基本认识
- 基于S3c2440的FT5x06 linux触屏驱动源码分析
- S3C2440 clock研究
- S3C2440 clock研究
- keil调试环境下S3C2440.s的分析
- linux2.6.12 下s3c2440 camera接口 源码分析和个人思考之 read方法篇
- S3C2440裸机驱动--MMU源码分析
- S3C2440裸机驱动--MMU源码分析
- S3C2440(1) Clock&Power Management
- uboot根目录下mkconfig分析,基于s3c2440
- 同步电路设计中CLOCK SKEW的分析
- 同步电路设计中clock skew的分析
- OpenRisc-28-ORPSoC的clock子系统分析
- Linux下Clock skew detected的解决办法
- Linux下Clock skew detected的解决办法
- 分集 ->
- 把字符串转换为数字,转换不成功返回NUL
- 后两个月的计划
- Read Config.xml in Perl
- vs2010 标记菜单问题
- S3C2440下clock的源码分析
- c++学习资料库
- debian6 安装及安装ssh
- 光驱HL-DT-ST DVDRAM GSA-T50N(EVEREST)
- 编程之美系列之二——寻找出现频率超过一半的数
- 注册回调机制
- 单片机英文缩写的英文全称及中文名称
- .net知识结构
- Linux下用gcc编译c程序