exynos4412时钟
定义时钟结构体exynos4x12_clock
clock_init_exynos4.c -->
struct exynos4x12_clock *clk = (struct exynos4x12_clock*)samsung_get_base_clock();
定义了一个exynos4x12_clock 结构体指针clk ,指向时钟基地址。
samsung_get_base_clock()表示获取时钟基地址。定义在/arch/arm/mach-exynos/include/mach/cpu.h
#define EXYNOS4_CLOCK_BASE 0x10030000
#define SAMSUNG_BASE(device, base) \
static inline unsigned long __attribute__((no_instrument_function)) \
samsung_get_base_##device(void) \
{ \
if (cpu_is_exynos4()) { \
if (proid_is_exynos4412()) \
return EXYNOS4X12_##base; \
return EXYNOS4_##base; \
} else if (cpu_is_exynos5()) { \
if (proid_is_exynos5420() || proid_is_exynos5422()) \
return EXYNOS5420_##base; \
return EXYNOS5_##base; \
} \
return 0; \
}
所以samsung_get_base_clock()指的就是0x10030000。
struct exynos4x12_clock结构体的定义在\arch\arm\mach-exynos\include\mach
※内存控制器DMC:DRAM memory controller
设置APLL的参数并使能它后, APLL 并不能立刻输出稳定的时钟 ,它需要经历一个锁定的时间 (lock time) 。APLL的最大锁定时间是: (270 x PDIV) 个周期。 所以 APLL_LOCK 设置为 (270 x PDIV) 就可以了。
简单介绍
本文主要介绍exynos4412芯片的时钟管理单元(CMU)。CMU控制锁相环(PLL)并为Exynos4412芯片中的各个IP、总线和模块产生时钟。它们还与电源管理单元(PMU)通信,以便在进入某个低功耗模式之前停止时钟,以通过时钟切换来降低功耗。
1.Exynos4412芯片的时钟体系介绍
对于PC对于PC机来说,CPU、内存、主板、声卡、显卡等等,这些功能部件由不同的芯片组成,在实体上是相互独立的。在嵌入式系统里,一块芯片往往集成了多种功能,比如Exynos4412上面既有CPU,还有音频/视频接口、LCD接口、GPS等模块。这类芯片被称为SoC,即System on Chip,译为芯片级系统或片上系统。在Exynos 4412芯片中,它以异步方式为功能块提供时钟,以提供更广泛的工作频率选择。它还简化了物理实现。
不同的模块往往工作在不同的频率下,在一个芯片上采用单时钟设计基本上是不可能实现的,在SoC设计中采取多时钟域设计。4412的时钟域有5个,如下图1所示。
![](https://i-blog.csdnimg.cn/blog_migrate/7b103769b1c7a82143b778e6d25ff19a.jpeg)
这5个时钟域名如下(下文中的BLK表示block,模块):
CPU_BLK:内含Cortex-A9 MPCore处理器、L2 cache控制器、CoreSight(调试用)。CMU_CPU用于给这些部件产生时钟。
DMC_BLK:内含DRAM内存控制器(DMC)、安全子系统(Security sub system)、通用中断控制器(Generic Interrupt Controller,GIC)。CMU_DMC用于给这些部件产生时钟。
LEFTBUS_BLK和RIGHTBUS_BLK:它们是全局的数据总线,用于在DRAM和其他子模块之间传输数据。它还包含时钟频率为100MHz的全局外设总线。您可以使用100MHz时钟进行寄存器访问。
CMU_TOP:为剩余的功能块生成时钟,包括G3D,MFC,LCD0,ISP,CAM,TV,FSYS,MFC,GPS,MAUDIO,PERIL和PERIR。它产生的总线时钟工作在400/200/160/133/100MHz频率。它还生成各种特殊时钟来操作Exynos 4412芯片中的IP。
下表描述了Exynos 4412芯片中每个功能模块的典型工作频率。
![](https://i-blog.csdnimg.cn/blog_migrate/e938283d85b47a913e46a372befe8f9d.jpeg)
从原理图上可知,下图2所示。tiny4412开发板外接24MHz的晶振;但是4412的CPU频率可达1.4GHz。可以想象,一定有硬件部件,把24MHZ的频率提升为1.4GHZ,这个部件被称为PLL。4412内部其他部件也要工作于一定频率,比UART、DDR里等,也应该有PLL把24MHZ的频率提高后供给它们使用。
![](https://i-blog.csdnimg.cn/blog_migrate/4b02ff88b873810ba3e66472d2b22f27.jpeg)
4412芯片有3个外部初始时钟源:
- XRTCXTI引脚:接32KHz的晶振,用于实时时钟(RTC)。
- XXTI引脚:接12M~50MHz的晶振,用于向系统提供时钟。也可以不接。
- XUSBXTI引脚:接24MHz的晶振,用于向USB和系统提供时钟。
在tiny4412的开发板中,XRTCXTI上没有外接晶振,系统时钟来源是XUSBXTI引脚上接的24MHz晶振。
Exynos4412有4个PLL:APLL、MPLL、EPLL和VPLL;2个PHY:USB PHY和HDMI PHY(PHY:物理层,一般指与外部信号接口的芯片):
- APLL:用于CPU_BLK;作为MPLL的补充,它也可以给DMC_BLK、LEFTBUS_BLK、RIGHTBUS_BLK和CMU_TOP提供时钟。
- MPLL:用于DMC_BLK、LEFTBUS_BLK、RIGHTBUS_BLK和CMU_TOP。
- EPLL:主要给音频模块提供时钟。
- VPLL:主要给视频系统提供54MHz时钟,给G3D(3D图形加速器)提供时钟。
- USB PHY:给USB子系统提供30MHz和48MHz时钟。
2.Exynos4412中设置PLL的方法
介绍涉及到的概念:
- MUX:多路复用,即从多个输入源中选择一个;
- PLL:把低频率的输入时钟提高后输出;
- DIV:分频器,把高频率的输入时钟降频后输出。
介绍符号:
- 左边深色的:无抖动多路选择器,无抖动意味着在多路选择切换的瞬间,下游时钟就可以稳定下来。需要注意是在切换时要保证上游时钟已经存在并稳定,不然下游时钟状态不确定。
- 右边浅色的:有抖动多路选择器,意味着多路选择切换后,要经历一段时间的不稳定时间,但是有稳定后有相应寄存器标志位标示下游时钟已经稳定,这类指示寄存器器一般以CLK_MUX_STAT开头。
全局约束条件:
- 无抖动多路选择器的时钟源需要存在并且稳定。
- 当某个PLL被设置为关闭状态,是不可以使用它的输出信号的。
时钟源PLL配置
以APLL为例,它的时钟来源可以是XXTI引脚上接的晶振,也可以是XUSBXTI引脚上接的晶振,通过图3中左边的MUX来选择,这个MUX的输出被称为FINPLL。
通过设置APLL的寄存器(根据公式选择参数值,芯片手册上面都有推荐值),可以把FINPLL提高为某个频率输出,假设为1.4GHz,在图上它被命名为FOUTAPLL。
继续往右看图,里面有多个DIV,可以设置对应的寄存器把频率降下来。CPU可以工作于1.4GHz,但是其他模块不能工作于这么高的频率,所以要把频率降下来。
设置PLL的流程如下:
- 设置PLL的P、M、S值,这是根据期望得到的频率用公式计算出来的;
- 设置PLL的其他控制参数;
- 使能PLL;
- PLL会等待一段时间使得时钟稳定;
- 设置MUX,选择PLL所输出的时钟。
简单地说,就是先设置,再启动,后使用。
以下配置步骤参考hyyoxhk的https://blog.csdn.net/hyyoxhk/article/details/81742439博文中的代码。
设置PLL
1、设置分频寄存器CLK_DIV_CPU0 、CLK_DIV_CPU1 、CLK_DIV_DMC0...等,初始化主要模块
以CLK_DIV_CPU0 寄存器为例:
![](https://i-blog.csdnimg.cn/blog_migrate/ae5c257a089b7ee87509658533b7e82e.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/df2c26a58e2e2f0b02fbc200efa824ec.jpeg)
参考上面的APLL时钟流程图,以 CPU 的工作频率 ARMCLK 为例,根据上图计算ARMCLK的频率:
ARMCLK = MUXCORE的输出 / DIVCORE / DIVCORE2
= MOUTCORE / (CORE_RATIO + 1) / DIVCORE2
= MOUTCORE / (CORE_RATIO + 1) / (CORE2_RATIO + 1)
MOUTCORE表示MUXCORE的输出,在MUXAPLL为1、MUXCORE为0时,它等于“MDIV x FIN / (PDIV x 2 ^ SDIV),即APLL的输出FOUT”
再例如计算APLL的频率:
SCLK_APLL = SCLKAPLL = MOUTAPLL/(APLL_RATIO + 1)
2、APLL_CON1 、APLL_CON0 寄存器的初始化,设置 M、P、S的值,配置APLL
APLL_CON1 寄存器的初始化:
该寄存器用于设置 BYPASS 模式,即APLL是直接输出FIN时钟,还是提升频率后再输出时钟;也用于设置AFC(自动频率控制 )功能,暂时无需理会。该寄存器取默认值即可。设置为0,开启AFC模式。
APLL_CON0 寄存器的初始化:
根据 M、P、S的值,可以算出APLL的输出时钟:
FOUT = MDIV x FIN / (PDIV x 2 ^ SDIV)
M、P、S的值不能乱取,需要满足一些限制条件(请参考芯片手册 ),芯片手册里给出了推荐的取值。
如APLL和MPPL的取值和计算
![](https://i-blog.csdnimg.cn/blog_migrate/73f6e3415c4bd8f081d81410399264f0.jpeg)
具体代码分析:
/* Set APLL to 1000MHz */
/** APLL_CON1 */
clr = AFC(31) | LOCK_CON_DLY(31) | LOCK_CON_IN(3) |
LOCK_CON_OUT(3) |FEED_EN(1)| AFC_ENB(1) |
DCC_ENB(1) | BYPASS(1) |RESV0(1) | RESV1(1);
set = AFC(0) | LOCK_CON_DLY(8) | LOCK_CON_IN(3) |
LOCK_CON_OUT(0) |FEED_EN(0)| AFC_ENB(0) |
DCC_ENB(1) | BYPASS(0) |RESV0(0) | RESV1(0);
clrsetbits_le32(&clk->apll_con1, clr, set);
/** APLL_CON0 */
clr_pll_con0 = SDIV(7) | PDIV(63) | MDIV(1023) | FSEL(1) | PLL_ENABLE(1);
set = SDIV(0) | PDIV(3) | MDIV(125) | FSEL(0) | PLL_ENABLE(1);
clrsetbits_le32(&clk->apll_con0, clr_pll_con0, set);
/* Wait for PLL to be locked */
while (!(readl(&clk->apll_con0) & PLL_LOCKED_BIT))
continue;
设置S=0,P=3,M=125。所以FOUTAPLL = 1000MHz
重复第2步配置MPLL、EPLL、VPLL。
3、设置apll_lock寄存器设置锁定时间
设置APLL的参数并使能它后,APLL并不能立刻输出稳定的时钟,它需要经历一个锁定的时间(lock time)。APLL的最大锁定时间是:(270 x PDIV)个周期。所以APLL_LOCK设置为(270xPDIV)就可以了。
PLL频率从小变到指定频率需要一段时间(图中标红框的部分虽然不是PLL实际波形但可以参考着理解),当PLL频率在变化的时候,比如由复位后的初始的400MHz升到1000MHz, 这时,首先把CPU的频率锁定,因这此时CPU的频率是变化的,频率变化,CPU的状态就无法确定,所以,此时用 PLL_LOCKTIME 将CPU频率锁定一段时间,直到频率输出稳定为止。芯片手册上显示APLL最大的锁定时间为100us,如果外部晶振是24MHz,100us换算成tick就是2400个tick,所以
APLL_LOCK(Address:0x1004_4000)寄存器该写入0x960
MPLL_LOCK(Address:0x1004_0008)寄存器该写入0x190
EPLL_LOCK(Address:0x1003_C010)寄存器该写入0xBB8
VPLL_LOCK(Address:0x1003_C020)寄存器该写入0x190。
4、初始化选择时钟寄存器
在锁相环输出时钟稳定后,选择锁相环输出时钟而不是输入参考时钟。一旦PLL时钟开启将不再关闭。初始化选择时钟源寄存器CLK_SRC_CPU、 CLK_SRC_DMC、CLK_SRC_TOP0 等 寄存器:
参考图3时钟流程图:
- BIT[0]控制第1个MUX(即MUXAPLL),用于选择是使用FIN还是APLL的输出时钟,这个输出被称为MOUTAPLL。
- BIT[16]控制第2个MUX(即MUXCORE),用于选择MOUTAPLL还是SCLKMPLL。其中SCLKMPLL由下面的MUXMPLL控制。
- BIT[24]控制第3个MUX(即MUXMPLL),用于选择FINPLL还是FOUTMPLL,这个输出被称为SCLKMPLL。其中,FOUTMPLL来自MPLL的输出。
- BIT[20]控制第4个MUX(即MUXHPM),用于选择MOUTAPLL还是SCLKMPLL。