在linux内核中移植时钟时遇到的问题(4.9)

时间:2017-09-17 08:40:46

标签: linux linux-kernel embedded-linux

我正在尝试将自定义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

1 个答案:

答案 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对帖子的回复。

谢谢。