掌機 - Gaviar (小志掌機) - 解決CLK UNUSED END: pll-cpux-div問題



Kernel Crash問題已經解決,但是從Log的結果來看,Kernel並沒有進入到最後的階段,因為我們尚未描述rootfs位置,理應有VFS Crash的Log才對,所以我們還要繼續追問題

ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
sunxi-ehci: EHCI SUNXI driver
get ehci0-controller wakeup-source is fail.
sunxi ehci0-controller don't init wakeup source
[sunxi-ehci0]: probe, pdev->name: 4101000.ehci0-controller, sunxi_ehci: 0xffffffe00051a130, 0x:ffffffd004078000, irq_no:2e
[sunxi-ehci0]: Not init ehci0
get ehci1-controller wakeup-source is fail.
sunxi ehci1-controller don't init wakeup source
[sunxi-ehci1]: probe, pdev->name: 4200000.ehci1-controller, sunxi_ehci: 0xffffffe00051a8c0, 0x:ffffffd00407c000, irq_no:31
sunxi-ehci 4200000.ehci1-controller: 4200000.ehci1-controller supply drvvbus not found, using dummy regulator
sunxi-ehci 4200000.ehci1-controller: 4200000.ehci1-controller supply hci not found, using dummy regulator
sunxi-ehci 4200000.ehci1-controller: EHCI Host Controller
sunxi-ehci 4200000.ehci1-controller: new USB bus registered, assigned bus number 1
sunxi-ehci 4200000.ehci1-controller: irq 49, io mem 0x04200000

先把USB的DTS描述進行關閉來定位問題

&ehci0 {
    status = "disabled";
};

&ohci0 {
    status = "disabled";
};

關閉後的Kernel Log

ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
sunxi-ehci: EHCI SUNXI driver
ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
sunxi-ohci: OHCI SUNXI driver
usbcore: registered new interface driver uas
usbcore: registered new interface driver usb-storage
sunxi-rtc 7090000.rtc: errata__fix_alarm_day_reg_default_value(): ALARM0_DAY_REG=0, set it to 1
sunxi-rtc 7090000.rtc: Warning: Using internal RC 16M clock source. Time may be inaccurate!
sunxi-rtc 7090000.rtc: Warning: Using internal RC 16M clock source. Time may be inaccurate!
sunxi-rtc 7090000.rtc: Warning: Using internal RC 16M clock source. Time may be inaccurate!
sunxi-rtc 7090000.rtc: registered as rtc0
sunxi-rtc 7090000.rtc: Warning: Using internal RC 16M clock source. Time may be inaccurate!
sunxi-rtc 7090000.rtc: setting system clock to 1970-01-01T00:00:11 UTC (11)
sunxi-rtc 7090000.rtc: sunxi rtc probed
i2c /dev entries driver
sunxi-mmc 4020000.sdmmc: SD/MMC/SDIO Host Controller Driver(v4.25 2022-6-21 13:40)
sunxi-mmc 4020000.sdmmc: ***ctl-spec-caps*** 8
sunxi-mmc 4020000.sdmmc: No vmmc regulator found
sunxi-mmc 4020000.sdmmc: No vqmmc regulator found
sunxi-mmc 4020000.sdmmc: No vdmmc regulator found
sunxi-mmc 4020000.sdmmc: No vd33sw regulator found
sunxi-mmc 4020000.sdmmc: No vd18sw regulator found
sunxi-mmc 4020000.sdmmc: No vq33sw regulator found
sunxi-mmc 4020000.sdmmc: No vq18sw regulator found
sunxi-mmc 4020000.sdmmc: Got CD GPIO
sunxi-mmc 4020000.sdmmc: set cd-gpios as 24M fail
sunxi-mmc 4020000.sdmmc: sdc set ios:clk 0Hz bm PP pm UP vdd 21 width 1 timing LEGACY(SDR12) dt B
sunxi-mmc 4020000.sdmmc: no vqmmc,Check if there is regulator

接著在Kernel menuconfig也將MMC關閉,DTS裡面除了UART4的SDC也關閉

misc dump reg init
brd: module loaded
loop: module loaded
i2c /dev entries driver
ashmem: initialized

但是Kernel還是沒有進入載入init的階段,因此,從initcall印出Log

$ vim init/main.c
    1012 static void __init do_initcall_level(int level)
    1013 {
    1014     int ret = 0;
    1015     initcall_entry_t *fn;
    1016 
    1017     strcpy(initcall_command_line, saved_command_line);
    1018     parse_args(initcall_level_names[level],
    1019            initcall_command_line, __start___param,
    1020            __stop___param - __start___param,
    1021            level, level,
    1022            NULL, &repair_env_string);
    1023 
    1024     trace_initcall_level(initcall_level_names[level]);
    1025     for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++) {
    1026         printk("### INITCALL BEGIN: level=%d fn=%ps ###\n", level, initcall_from_entry(fn));
    1027         do_one_initcall(initcall_from_entry(fn));
    1028         printk("### INITCALL END: level=%d fn=%ps ret=%d ###\n", level, initcall_from_entry(fn), ret);
    1029     }
    1030 }

最後出問題的地方在clk_disable_unused

### INITCALL END: level=6 fn=i2c_dev_init ret=0 ###
### INITCALL BEGIN: level=6 fn=sunxi_led_driver_init ###
### INITCALL END: level=6 fn=sunxi_led_driver_init ret=0 ###
### INITCALL BEGIN: level=6 fn=timer_led_trigger_init ###
### INITCALL END: level=6 fn=timer_led_trigger_init ret=0 ###
### INITCALL BEGIN: level=6 fn=defon_led_trigger_init ###
### INITCALL END: level=6 fn=defon_led_trigger_init ret=0 ###
### INITCALL BEGIN: level=6 fn=ashmem_init ###
### INITCALL END: level=6 fn=ashmem_init ret=0 ###
### INITCALL BEGIN: level=6 fn=sunxi_sid_driver_init ###
### INITCALL END: level=6 fn=sunxi_sid_driver_init ret=0 ###
### INITCALL BEGIN: level=7 fn=init_oops_id ###
### INITCALL END: level=7 fn=init_oops_id ret=0 ###
### INITCALL BEGIN: level=7 fn=pm_qos_power_init ###
### INITCALL END: level=7 fn=pm_qos_power_init ret=0 ###
### INITCALL BEGIN: level=7 fn=pm_debugfs_init ###
### INITCALL END: level=7 fn=pm_debugfs_init ret=0 ###
### INITCALL BEGIN: level=7 fn=wakeup_reason_init ###
### INITCALL END: level=7 fn=wakeup_reason_init ret=0 ###
### INITCALL BEGIN: level=7 fn=printk_late_init ###
### INITCALL END: level=7 fn=printk_late_init ret=0 ###
### INITCALL BEGIN: level=7 fn=init_srcu_module_notifier ###
### INITCALL END: level=7 fn=init_srcu_module_notifier ret=0 ###
### INITCALL BEGIN: level=7 fn=tk_debug_sleep_time_init ###
### INITCALL END: level=7 fn=tk_debug_sleep_time_init ret=0 ###
### INITCALL BEGIN: level=7 fn=fault_around_debugfs ###
### INITCALL END: level=7 fn=fault_around_debugfs ret=0 ###
### INITCALL BEGIN: level=7 fn=max_swapfiles_check ###
### INITCALL END: level=7 fn=max_swapfiles_check ret=0 ###
### INITCALL BEGIN: level=7 fn=prandom_reseed ###
### INITCALL END: level=7 fn=prandom_reseed ret=0 ###
### INITCALL BEGIN: level=7 fn=clk_debug_init ###
### INITCALL END: level=7 fn=clk_debug_init ret=0 ###
### INITCALL BEGIN: level=7 fn=sync_state_resume_initcall ###
### INITCALL END: level=7 fn=sync_state_resume_initcall ret=0 ###
### INITCALL BEGIN: level=7 fn=deferred_probe_initcall ###
### INITCALL END: level=7 fn=deferred_probe_initcall ret=0 ###
### INITCALL BEGIN: level=7 fn=ubi_init ###
### INITCALL END: level=7 fn=ubi_init ret=0 ###
### INITCALL BEGIN: level=7 fn=of_fdt_raw_init ###
### INITCALL END: level=7 fn=of_fdt_raw_init ret=0 ###
### INITCALL BEGIN: level=7 fn=clk_disable_unused ###

忽略CLK錯誤檢查

chosen {
    bootargs = "console=ttyS4,115200n8 earlycon=sbi ignore_loglevel loglevel=8 init=/init clk_ignore_unused";
};

終於進入載入init的階段,這才是Kernel完成開機的階段,當然中間忽略的問題還要一一找出來

Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
CPU: 0 PID: 1 Comm: swapper Not tainted 5.4.61 #5
Call Trace:
[<ffffffe0000211c4>] walk_stackframe+0x0/0x98
[<ffffffe00002137c>] show_stack+0x2a/0x34
[<ffffffe000287892>] dump_stack+0x20/0x28
[<ffffffe000025882>] panic+0xec/0x27a
[<ffffffe000000f22>] mount_block_root+0x214/0x27a
[<ffffffe00000110a>] mount_root+0x86/0x90
[<ffffffe000001288>] prepare_namespace+0x174/0x17e
[<ffffffe000000b62>] kernel_init_freeable+0x174/0x1c8
[<ffffffe000297ff8>] kernel_init+0x12/0xee
[<ffffffe00001ff30>] ret_from_exception+0x0/0xc
---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) ]---

移除CLK錯誤檢查

chosen {
    bootargs = "console=ttyS4,115200n8 earlycon=sbi ignore_loglevel loglevel=8 init=/init";
};

在CLK裡面添加Debug Log

1230 static void clk_disable_unused_subtree(struct clk_core *core)
1231 {
1232     struct clk_core *child;
1233     unsigned long flags;
1234 
1235     printk(
1236         "CLK %s: prepare=%d enable=%d protect=%d parent=%s\n",
1237         core->name,
1238         core->prepare_count,
1239         core->enable_count,
1240         core->protect_count,
1241         core->parent ? core->parent->name : "NULL");

定位到PLL-CPU問題

### CLK UNUSED END: pll-ddr0 ###
CLK pll-cpux: prepare=0 enable=0 protect=0 parent=dcxo24M
CLK riscv: prepare=0 enable=0 protect=0 parent=pll-cpux
CLK riscv-axi: prepare=0 enable=0 protect=0 parent=riscv
### CLK UNUSED END: riscv-axi ###
### CLK UNUSED END: riscv ###
CLK pll-cpux-div: prepare=0 enable=0 protect=0 parent=pll-cpux
### CLK UNUSED END: pll-cpux-div ###

將SUN8IW20_PLL_CPUX_REG設定成CLK_IS_CRITICAL

$ vim drivers/clk/sunxi-ng/ccu-sun8iw20.c
    37 #define SUN8IW20_PLL_CPUX_REG       0x000
    38 static struct ccu_mult pll_cpux_clk = {
    39     .enable     = BIT(27),
    40     .lock       = BIT(28),
    41     .mult       = _SUNXI_CCU_MULT_MIN(8, 8, 12),
    42     .common     = {       
    43         .reg        = 0x000,
    44         .hw.init    = CLK_HW_INIT("pll-cpux", "dcxo24M",
    45                           &ccu_mult_ops,
    46                           CLK_SET_RATE_UNGATE | CLK_IS_CRITICAL),
    47     },
    48 };

添加BOOT開機選項,然後使用rootwait故意讓Kernel停在等待rootfs Ready的狀態

chosen {
    bootargs = "console=ttyS4,115200n8 earlycon=sbi ignore_loglevel loglevel=8 root=/dev/mmcblk0p1 rootwait rw rootfstype=fat init=/init";
};

Kernel已經可以正常開機

printk: console [ttyS4] enabled
printk: bootconsole [sbi0] disabled
printk: bootconsole [sbi0] disabled
misc dump reg init
brd: module loaded
loop: module loaded
i2c /dev entries driver
ashmem: initialized
Waiting for root device /dev/mmcblk0p1...