我正在尝试将自定义SoC的系统时钟移植到linux内核(4.9)。我设置了一个带有晶体Osc,pll和amp的最小查找表。 spi如下:
static struct clk_lookup clocks[] = {
CLKDEV_INIT(NULL, "ref", &ref_clk),
CLKDEV_INIT(NULL, "pll1", &pll1_clk),
CLKDEV_INIT(NULL, "apb_pclk", &apb_clk),
CLKDEV_INIT("spi0", NULL, &spi_clk),
};
我试图使用func添加时钟:
int __init clocks_init(void)
{
clkdev_add_table(clocks, ARRAY_SIZE(clocks));
};
但是在尝试设置时钟时我的启动失败了。 以下是错误:
Unable to handle kernel NULL pointer dereference at virtual address 00000008
[ 0.000000]` pgd = c0004000
[ 0.000000] [00000008] *pgd=00000000
[ 0.000000] Internal error: Oops: 5 [#1] ARM
[ 0.000000] Modules linked in:
[ 0.000000] CPU: 0 PID: 1 Comm: swapper Not tainted 4.9.22+ #22
[ 0.000000] Hardware name: CUSTOMSOC
[ 0.000000] task: c6898000 task.stack: c688e000
[ 0.000000] PC is at __clk_get_hw+0x1c/0x24
[ 0.000000] LR is at clkdev_add_table+0x40/0x78
[ 0.000000] pc : [<c025ce40>] lr : [<c025cda8>] psr: a0000053
[ 0.000000] sp : c688fe58 ip : c688fe68 fp : c688fe64
[ 0.000000] r10: 00000000 r9 : 0000003d r8 : c04867f0
[ 0.000000] r7 : c04ea720 r6 : c04ea714 r5 : 00000004 r4 : c04cbf50
[ 0.000000] r3 : 00000000 r2 : 00000000 r1 : 00000004 r0 : c04cbf98
[ 0.000000] Flags: NzCv IRQs on FIQs off Mode SVC_32 ISA ARM Segment user
[ 0.000000] Control: 00c5387d Table: c0004008 DAC: 00000055
[ 0.000000] Process swapper (pid: 1, stack limit = 0xc688e188)
[ 0.000000] Stack: (0xc688fe58 to 0xc6890000)
[ 0.000000] fe40: c688fe84 c688fe68
[ 0.000000] fe60: c025cda8 c025ce30 00000000 c8905000 c0501020 c04ae820 c688fea4 c688fe88
[ 0.000000] fe80: c048a6d8 c025cd74 00000000 c03004d4 c04ca798 c04cd718 c688febc c688fea8
[ 0.000000] fea0: c048a4a8 c048a62c c04c27f8 00000003 c688fecc c688fec0 c0486814 c048a49c
[ 0.000000] fec0: c688ff4c c688fed0 c0009a6c c04867fc c0483614 c02268b8 00000000 c0434e84
[ 0.000000] fee0: c6fffe00 c032ca2c c688ff4c c688fef8 c003e5f4 c0483604 c0050050 c00bb438
[ 0.000000] ff00: 00000000 c030f938 00000003 00000003 00000000 c04349c0 c03d2654 00000000
[ 0.000000] ff20: c688ff4c c04c27f8 00000003 c0501020 c04ae820 00000000 0000003d c04ae838
[ 0.000000] ff40: c688ff94 c688ff50 c0483ec0 c0009a2c 00000003 00000003 00000000 c04835f8
[ 0.000000] ff60: 9d322010 62802229 20a41903 00000000 c030cc94 00000000 00000000 00000000
[ 0.000000] ff80: 00000000 00000000 c688ffac c688ff98 c030ccac c0483d48 ffffffff 00000000
[ 0.000000] ffa0: 00000000 c688ffb0 c00107c8 c030cca0 00000000 00000000 00000000 00000000
[ 0.000000] ffc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 0.000000] ffe0: 00000000 00000000 00000000 00000000 00000013 00000000 0114212a 8dce8aa8
[ 0.000000] [<c025ce40>] (__clk_get_hw) from [<c025cda8>] (clkdev_add_table+0x40/0x78)
[ 0.000000] [<c025cda8>] (clkdev_add_table) from [<c048a6d8>] (bbsoc_clocks_init+0xb8/0xec)
[ 0.000000] [<c048a6d8>] (clocks_init) from [<c048a4a8>] (bcm2835_init+0x18/0x74)
[ 0.000000] [<c048a4a8>] (board_init) from [<c0486814>] (customize_machine+0x24/0x30)
[ 0.000000] [<c0486814>] (customize_machine) from [<c0009a6c>] (do_one_initcall+0x4c/0x180)
[ 0.000000] [<c0009a6c>] (do_one_initcall) from [<c0483ec0>] (kernel_init_freeable+0x184/0x254)
[ 0.000000] [<c0483ec0>] (kernel_init_freeable) from [<c030ccac>] (kernel_init+0x18/0x114)
[ 0.000000] [<c030ccac>] (kernel_init) from [<c00107c8>] (ret_from_fork+0x14/0x2c)
[ 0.000000] Code: e52de004 e8bd4000 e3500000 15903000 (15930008)
[ 0.000000] ---[ end trace 671b49261be9dc6a ]---
[ 0.000000] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
经过调查func:__ clk_get_hw(cl-&gt; clk); 正试图访问clk-&gt; core-&gt; hw(这就是它失败的地方!)
struct clk_hw *__clk_get_hw(struct clk *clk)
{
return !clk ? NULL : clk->core->hw;
}
EXPORT_SYMBOL_GPL(__clk_get_hw);
有关在Linux内核中设置时钟配置的任何建议都非常有用。 谢谢, 的Vivek
答案 0 :(得分:0)
在对特定于SoC的完整时钟驱动器进行编程后,问题得到解决。 1.首先要记录总线时钟,它取决于输入PLL时钟以及遇到的分频器或乘法器。有关分频器和乘法器的信息,请参见sys-control寄存器。一旦所有公交车(例如:ahb,apb)都已注册。
hw = clk_hw_register_fixed_rate(NULL, "ref", NULL, 0, 40MHZ); //setting
if (IS_ERR(hw))
pr_err("xtal clock not registered\n");
hw = clk_hw_register_fixed_rate(NULL, "pll_clk", "ref", 0, 800MHZ);
if (IS_ERR(hw))
pr_err("pll_clk not registered\n");
hw = clk_hw_register_fixed_rate(NULL, "ahb_clk", "pll_clk", 0, 100MHZ);
if (IS_ERR(hw))
pr_err("ahb_clk not registered\n");
可以将面向外围的时钟指定为,这里我正在尝试注册dma时钟。安装在AHB总线上。
static struct clk dma1_clk = {
.name = "xyz.dma",
.parent = &ahb_clk,
.rate = FREQ_200MHZ,
};
以后关于外设的时钟结构可以注册为
hw = clk_hw_register_fixed_rate(NULL, c->dev_id, "ahb_clk", 0, temp_clk->rate);
if (IS_ERR(hw))
pr_err("Device Hw:%s not registered\n", c->dev_id);
ret = clk_hw_register_clkdev(hw, NULL, c->dev_id);
if (ret)
pr_err("Device:%s not registered\n", c->dev_id);
SoC外围设备的时钟基础设施设置也可以通过设备树来完成。
感谢@ 0andriy对帖子的回复。
谢谢。