【问题标题】:issues while porting clocks in linux kernel (4.9)在 linux 内核 (4.9) 中移植时钟时的问题
【发布时间】:2019-01-24 13:20:05
【问题描述】:

我正在尝试将自定义 SoC 的系统时钟移植到 linux 内核 (4.9) 中。我已经设置了一个带有晶体振荡器、pll 和 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->clk); 正在尝试访问 clk->core->hw (这正是它失败的地方!)

struct clk_hw *__clk_get_hw(struct clk *clk)
{               
        return !clk ? NULL : clk->core->hw;
}
EXPORT_SYMBOL_GPL(__clk_get_hw);

任何关于在 linux 内核中设置时钟配置的建议都会非常有帮助。 谢谢, 维韦克

【问题讨论】:

  • 您首先需要有一个合适的时钟驱动程序。你是否有一个?检查其他 ARM 平台和板如何执行此操作。您需要所有描述的设备树。平台代码是当今大多数板的遗留物。

标签: linux linux-kernel embedded-linux


【解决方案1】:

在编写特定于 SoC 的完整时钟驱动程序后,问题得到解决。 1. 首先要注册的总线时钟,取决于输入的 PLL 时钟和它遇到的分频器或乘法器。有关除法器和乘法器的信息可以在系统控制寄存器中找到。一旦所有总线(例如: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 对帖子的回复。

谢谢。

【讨论】:

    猜你喜欢
    • 2019-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-27
    • 2020-10-07
    • 2013-10-20
    • 1970-01-01
    相关资源
    最近更新 更多