clk学习

目录

[一,clk-fixed and clk-pll](#一,clk-fixed and clk-pll)

1,clk-fixed

2,clk-pll

[二,clk时钟数 divider/factor/gate/mux/ratio/link介绍](#二,clk时钟数 divider/factor/gate/mux/ratio/link介绍)

1,clk-divider分频器

2,clk-gate开关控制

3,clk-mux多路选择器

[4,clk-ratio 分频比](#4,clk-ratio 分频比)

5,clk-link仅仅做父子绑定,通路使用

6,divider和ratio的区别

7,clk-factor

[三,clk配置,包含配置parent rate和使能](#三,clk配置,包含配置parent rate和使能)


一,clk-fixed and clk-pll

1,clk-fixed

fixed:{ "name": "xtal", "rate": 24000000 }

没啥内容,就是套在时钟树里面,作为后续的parent,实现get_rate可以作为后续clk节点的计算参考。

2,clk-pll

{"parent":"xtal","name":"apll","channel":0},

{"parent":"xtal","name":"dpll","channel":1},

{"parent":"xtal","name":"cpll","channel":2},

{"parent":"xtal","name":"gpll","channel":3},

{"parent":"xtal","name":"npll","channel":4},

val = (read32(CRU_MODE_CON) >> ((pdat->channel == 4) ? 14 : pdat->channel * 4)) & 0x3;

npll的bit位特殊,所以4单独处理,

if(val == 0x1)

{

val = read32(pdat->channel * 0x10);

no = ((val >> 0) & 0x0f) + 1;

nr = ((val >> 8) & 0x3f) + 1;

val = read32((pdat->channel * 0x10 + 0x4));

nf = ((val >> 0) & 0x1fff) + 1;

rate = (24 * nf / (nr * no)) * 1000000;

}

else if(val == 0x2)

{

rate = 32768;

}

else

{

rate = 24000000;

}

以npll为例,con0和con1存放这锁相环nr no nf值,当cru_mode_con寄存器npll值为0x01时

rate = (24 * nf / (nr * no)) * 1000000;

二,clk时钟数 divider/factor/gate/mux/ratio/link介绍

1,clk-divider分频器

执行分频功能的‌硬件电路‌

在Linux内核的通用时钟框架(CCF)中,CLK_DIVIDER_ONE_BASED 是一个用于时钟分频器(clk divider)的标志位,它定义了分频寄存器值与实际分频系数之间的映射关系。

当一个分频器时钟被设置为 CLK_DIVIDER_ONE_BASED 模式时,‌分频寄存器中的值直接等于实际的分频系数‌。例如,如果寄存器中存储的值是 5,那么输出时钟频率就是父时钟频率除以 5。

这与另一种常见的模式(非 ONE_BASED)形成对比:在非 ONE_BASED 模式下,寄存器值为 0 通常表示分频系数为 1(即不分频),寄存器值为 1 表示分频系数为 2,以此类推。而在 ONE_BASED 模式下,寄存器值 0 会被视为无效或特殊状态(通常避免使用),而 1 就代表分频系数为 1

clk_divider_set_rate

{

div = prate / rate;获取分频系数

if(pdat->onebased)

div--;

if(div > mask)

div = mask;

val = read32(pdat->virt);

val &= ~(mask << pdat->shift);

val |= div << pdat->shift;

val |= mask << (pdat->shift + 16);

write32(pdat->virt, val);

}

2,clk-gate开关控制

clk_gate_set_enable

{

val = read32(pdat->virt);

val &= ~(0x1 << pdat->shift);

if(enable)

val |= (pdat->invert ? 0x0 : 0x1) << pdat->shift;

else

val |= (pdat->invert ? 0x1 : 0x0) << pdat->shift;

val |= 0x1 << (pdat->shift + 16);

write32(pdat->virt, val);

}

3,clk-mux多路选择器

clk_mux_set_parent

{

for(i = 0; i < pdat->nparent; i++)

{

if(strcmp(pdat->parent[i].name, pname) == 0)

{

val = read32(pdat->virt);

val &= ~(((1 << pdat->width) - 1) << pdat->shift);

val |= pdat->parent[i].value << pdat->shift;

val |= ((1 << pdat->width) - 1) << (pdat->shift + 16);

write32(pdat->virt, val);

break;

}

}

}

4,clk-ratio 分频比

Clk Ratio(时钟分频比)‌:这是一个‌数值参数或配置项‌,用于‌定义分频器的行为‌。它指明了输出时钟频率与输入时钟频率之间的比例关系。通常用一个整数 N 表示,表示输出频率是输入频率的 1/N。例如,当 clk_ratio 设置为10时,意味着分频器需要将输入时钟频率降低为原来的十分之一,此时分频器的分频系数 N 就是10。‌‌

peri_hclk_div_con

Control the divider ratio between aclk_periph

and hclk_periph

2'b00: aclk_periph:hclk_periph = 1:1

2'b01: aclk_periph:hclk_periph = 2:1

2'b10: aclk_periph:hclk_periph = 4:1

clk_ratio_set_rate

{

div = prate / rate;

if(div > mask)

div = mask;

val = read32(pdat->virt);

val &= ~(mask << pdat->shift);

/* fls - find last (most-significant) bit set,Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32*/

val |= fls(div) << pdat->shift;

val |= mask << (pdat->shift + 16);

write32(pdat->virt, val);

}

5,clk-link仅仅做父子绑定,通路使用

比如G0_3作为aclk_bus_pre的parent做一个link

6,divider和ratio的区别

两者的区别可以类比为:‌

‌Divider‌ 是"‌做什么‌"------ 它是执行分频功能的‌硬件电路‌本身。

‌Clk Ratio‌ 是"‌怎么做‌"------ 它是控制这个电路如何工作的‌配置参数‌。

简单理解,‌分频器(divider)是实现分频功能的模块,而分频比(clk ratio)是这个模块的一个关键设定值,决定了分频的倍数

7,clk-factor

clk-factor分数分频时钟‌(Fractional Divider Clock),这是一种能够产生非整数倍分频时钟信号的技术。与只能输出整数分频(如2分频、5分频)的简单计数器不同,分数分频器可以实现如3.5分频、13/3分频等精确的非整数分频比,这对于需要高精度时钟频率的系统(如通信、音频处理、高速串行接口)至关重要,比如图中S17

clk_gcd 求prate和rate的最大公因数

{

u64_t c;

while(b != 0)

{

c = a % b;

a = b;

b = c;

}

return a;

}

clk_factor_set_rate

{

cdiv = clk_gcd(prate, rate);求prate和rate的最大公因数

div = (prate / cdiv) & 0xffff;

mult = (rate / cdiv) & 0xffff;

write32(pdat->virt, (mult << 16) | (div << 0));

}

三,clk配置,包含配置parent rate和使能

在dts中分散在各个node中

比如

{ "name": "mux-dclk-vop0", "parent": "gpll", "enable": true },

{ "name": "div-dclk-vop0", "rate": 45000000, "enable": true },

关联这几个函数,就是配置和使能

clk_set_parent(name, parent);有些多路选择指定parent

clk_set_rate(name, rate);配置帧率

clk_enable(name)或clk_disable(name);使能

相关推荐
夏日听雨眠2 小时前
LInux(逻辑地址与物理地址的区别,文件描述符,lseek函数)
linux·运维·网络
时空自由民.3 小时前
STM32配置Timer+DMA读取ADC数据
stm32·单片机·嵌入式硬件
华普微HOPERF3 小时前
数字隔离器,如何确保MCU不受储能系统中的高电压、大电流影响?
单片机·嵌入式硬件
qq_542515414 小时前
Ubuntu 22.04.4 LTS安装ToDesk最新版打不开,无响应?旧版本4.7.2_277版本分享
linux·ubuntu·todesk
火车叼位4 小时前
替代 Tiny Win10 的 Linux 方案:Debian XFCE 精简桌面搭建
linux·运维
小麦嵌入式4 小时前
FPGA入门(四):时序逻辑计数器原理与 LED 闪烁实现
linux·驱动开发·stm32·嵌入式硬件·fpga开发·硬件工程·dsp开发
搁浅小泽5 小时前
常用电子元器件
单片机·嵌入式硬件·可靠性工程师
皮卡蛋炒饭.5 小时前
传输层协议UDP
linux·网络协议·udp
zhaoshuzhaoshu5 小时前
嵌入式开发之时钟树解析-SMT32平台
嵌入式硬件
syagain_zsx5 小时前
Linux指令初识(实用篇)
linux·运维·服务器