S3C2440下clock的源码分析
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的源码分析相关推荐
- 【学习笔记】Keras库下的resnet源码分析
Keras库下的resnet源码应用及解读 其实我也不知道这种东西有没有写下来的必要,但是跑代码的时候总摸鱼总归是不好的.虽然很简单,不过我也大概做个学习记录,写给小白看的.源码来自keras文档,大 ...
- Unidbg-Linker部分源码分析(下)
Unidbg-Linker部分源码分析(下) Unidbg-Linker部分源码分析(下) 概要 align resolveLibrary VirtualModule initFunctions ca ...
- S3C24XX DMA框架源码分析
基于S3C2440 的DMA 框架源码分析 基于S3C2440 的DMA 框架源码分析 二寻根溯源 1 设备类的注册 2 s3c2410_dma_init 3 s3c24xx_dma_order_se ...
- 【源码分析】Android触摸事件的分发拦截
Android中View的分发拦截机制是一块重要的内容,网上也有很多大神进行过相关的分析. 在这篇文章里我将以自己的理解尽量全面地分析整个流程,有些分析结果是很多文章没有提及的. 整个分析过程将通过d ...
- 视频教程-经典Vue从入门到案例到源码分析教程(含资料)-Vue
经典Vue从入门到案例到源码分析教程(含资料) 张长志技术全才.擅长领域:区块链.大数据.Java等.10余年软件研发及企业培训经验,曾为多家大型企业提供企业内训如中石化,中国联通,中国移动等知名企业 ...
- AndroidVideoCache简单使用及源码分析
对于视频播放,如果需要用到缓存,AndroidVideoCach是一个不错的选择,该项目地址: https://github.com/danikula/AndroidVideoCache 优缺点: 优 ...
- eos源码分析和应用(一)调试环境搭建
转载自 http://www.limerence2017.com/2018/09/02/eos1/#more eos基于区块链技术实现的开源引擎,开发人员可以基于该引擎开发DAPP(分布式应用).下面 ...
- celery源码分析-worker初始化分析(下)
celery源码分析 本文环境python3.5.2,celery4.0.2,django1.10.x系列 celery的worker启动 在上文中分析到了Hub类的初始化,接下来继续分析Pool类的 ...
- Linux下USB suspend/resume源码分析【转】
转自:http://blog.csdn.net/aaronychen/article/details/3928479 Linux下USB suspend/resume源码分析 Author:aaron ...
最新文章
- 3. Swift 数组|字典|集合
- 用于python环境下的数据操作_数据分析(一):环境搭建,以及初步操作文件
- Jpeglib使用指南, 各种压缩包的压缩和解压方法, 开源社区分裂史
- C++实现AOE网中的关键路径算法(邻接表存储)
- 理解至上:二叉堆与优先队列详细用法
- MAC系统下 win7虚拟机上网应该怎么设置啊
- NSSet与NSArray区别
- VIM插件——vimplus安装(centos 7)
- 一次防火墙无法重启的排查过程和总结
- html设置word页脚,Word页码从任意页开始如何设置?
- 关于安卓/苹果H5移动端上传视频
- 从开发平台到智能供应链,AI技术如何推动企业智能化升级?
- 谷歌软件工程师是怎样写设计文档的?
- nginx限速_NGINX限速简而言之
- 笔记本外接显示屏,FPS下降严重的解决办法
- SH7218T拆解手记(4)修改外屏大时钟
- 第三方开发者平台地址整理
- Vue.js下载与使用
- 安卓音乐播放时微信视频微信语音电话进来音乐暂停播放
- WebBrowser and Cookies
热门文章
- 旭日x3派个人配置总结(ubuntu server + xrdp)
- 安卓手机状态栏显示秒_免Root让安卓状态栏时间精确到秒
- python 三个点‘...’、Ellipsis符号
- c语言链表拆分,P2 拆分链表
- java秒转换为年月日_java时间转化为年月日以及将秒转化为天小时分秒字符串显示总结...
- 【p4】perforce命令笔记
- Python:SM2
- 最长的英文单词十大排行榜
- Lake Shore PT-100铂电阻温度传感器
- 英国AI初创企业OKRA获416万美元A轮融资