赞
踩
- Bootdev(atags): mmc 0
- MMC0: HS200, 200Mhz
- PartType: EFI
- boot mode: None
- FIT: no signed, no conf required
- DTB: rk-kernel.dtb
- HASH(c): OK
- I2c0 speed: 100000Hz
- vsel-gpios- not found! Error: -2
- vdd_cpu init 900000 uV
- PMIC: RK8170 (on=0x10, off=0x00)
- vdd_logic init 900000 uV
- vdd_gpu init 900000 uV
- 4200000 uV is too high from LDO_REG5
- io-domain: OK
- Warn: can't find connect driver
- Could not find baseparameter partition
- Model: Rockchip RK3566 RK817 BDTTS402 LP4X Board
- rk8xx_read: read reg 0x4d failed, ret=-121
- rk8xx_write: write reg 0x4d failed, ret=-121
- __virq_enable: Clear status register 0x4d failed, ret=-121
- 此时液晶屏无logo显示。
- 停留1分钟
- 继续输出如下日志:
- Rockchip UBOOT DRM driver version: v1.0.1
- VOP have 1 active VP
- vp0 have layer nr:6[0 2 4 1 3 5 ], primary plane: 4
- vp1 have layer nr:0[], primary plane: 0
- vp2 have layer nr:0[], primary plane: 0
- Using display timing dts
- dsi@fe060000: detailed mode clock 29000 kHz, flags[8000000a]
- H: 0480 0508 0512 0540
- V: 0854 0882 0886 0914
- bus_format: 100e
- VOP update mode to: 480x854p0, type: MIPI0 for VP0
- VOP VP0 enable Smart0[480x854->480x854@0x0] fmt[1] addr[0x7df00036]
- final DSI-Link bandwidth: 384 Mbps x 2
- CLK: (sync kernel. arm: enter 816000 KHz, init 816000 KHz, kernel 0N/A)
- apll 1416000 KHz
- dpll 460000 KHz
- gpll 1188000 KHz
- cpll 1000000 KHz
- npll 1200000 KHz
- vpll 24000 KHz
- hpll 29000 KHz
- ppll 200000 KHz
- armclk 1416000 KHz
- aclk_bus 150000 KHz
- pclk_bus 100000 KHz
- aclk_top_high 500000 KHz
- aclk_top_low 400000 KHz
- hclk_top 150000 KHz
- pclk_top 100000 KHz
- aclk_perimid 300000 KHz
- hclk_perimid 150000 KHz
- pclk_pmu 100000 KHz
- Net: eth1: ethernet@fe010000
- Hit key to stop autoboot('CTRL+C'): 0
- ## Booting FIT Image at 0x7a317f80 with size 0x014dfc00
- Fdt Ramdisk skip relocation
- ## Loading kernel from FIT Image at 7a317f80 ...
- Using 'conf' configuration
- optee api revision: 2.0
- TEEC: Waring: Could not find security partition
- 此时液晶屏可以显示logo。
烧写厂家提供的android镜像则不会存在此问题。把linux镜像中的uboot.img换为android下的uboot.img也不会存在此问题,不过会出现另一个问题,就是内核启动后液晶就无显示了,如果没有这个问题其实可以直接用android下的u-boot源码替换linux下的u-boot源码。也尝试对比两个u-boot源码的差异,发现很多文件都不同。
通过在..\x3566_linux_v1.2.0\u-boot\arch\arm\mach-rockchip\board.c文件的board_late_init()函数中加入一些日志,发现是执行setup_download_mode()函数返回的错误,屏蔽此函数后则硬件复位后系统能正常启动。不过android源码中也调用了此函数。屏蔽此函数后启动时无法通过按下recovery按键进入loader模式。
通过搜索setup_download_mode()函数的实现在..\x3566_linux_v1.2.0\u-boot\arch\arm\mach-rockchip\boot_rkimg.c文件中:
- void setup_download_mode(void)
- {
- int vbus = 1; /* Assumed 1 in case of no rockusb */
-
- boot_devtype_init();
-
- /*
- * rockchip_dnl_key_pressed():
- *
- * (1) volume-up key (default)
- * (2) menu key (If no rockusb)
- *
- * It's possible that USB is disabled due to developer needs
- * a critial size of u-boot.bin.
- *
- * Disabling USB makes vbus can't be detected any more, so that
- * we add menu key. The events trigger are changed:
- *
- * - rockusb mode(actually fallback to bootrom mode):
- * "volume-up pressed + vbus=1" replaced with "menu pressed"
- * - recovery mode:
- * "volume-up pressed + vbus=0" replaced with "volume-up pressed"
- *
- * At the most time, USB is enabled and this feature is not applied.
- */
- if (rockchip_dnl_key_pressed() || is_hotkey(HK_ROCKUSB_DNL)) {
- printf("download %skey pressed... ",
- is_hotkey(HK_ROCKUSB_DNL) ? "hot" : "");
- #ifdef CONFIG_CMD_ROCKUSB
- vbus = rockchip_u2phy_vbus_detect();
- #endif
- if (vbus > 0) {
- printf("%sentering download mode...\n",
- IS_ENABLED(CONFIG_CMD_ROCKUSB) ?
- "" : "no rockusb, ");
-
- /* try rockusb download and brom download */
- run_command("download", 0);
- } else {
- printf("entering recovery mode!\n");
- env_set("reboot_mode", "recovery-key");
- }
- } else if (is_hotkey(HK_FASTBOOT)) {
- env_set("reboot_mode", "fastboot");
- }
- }
进一步探索,发现是uboot卡死在rockchip_dnl_key_pressed()函数的return key_is_pressed(key_read(KEY_VOLUMEUP));语句中:
- __weak int rockchip_dnl_key_pressed(void)
- {
- #if defined(CONFIG_DM_KEY)
- #ifdef CONFIG_CMD_ROCKUSB
- printf("key_is_pressed VOLUMEUP\n");
- return key_is_pressed(key_read(KEY_VOLUMEUP));
- #else
- printf("key_is_pressed MENU\n");
- return key_is_pressed(key_read(KEY_MENU));
- #endif
-
- #elif defined(CONFIG_ADC)
- const void *blob = gd->fdt_blob;
- int node, ret, channel = 1;
- u32 val, chns[2];
-
- node = fdt_node_offset_by_compatible(blob, 0, "adc-keys");
-
- printf("fdt_node_offset_by_compatible\n");
- if (node >= 0) {
- if (!fdtdec_get_int_array(blob, node, "io-channels", chns, 2))
- channel = chns[1];
- }
-
- ret = adc_channel_single_shot("saradc", channel, &val);
- if (ret) {
- printf("%s: Failed to read saradc, ret=%d\n", __func__, ret);
- return 0;
- }
-
- printf("adc_channel_single_shot\n");
-
- return ((val >= KEY_DOWN_MIN_VAL) && (val <= KEY_DOWN_MAX_VAL));
- #endif
-
- return 0;
- }
继续深入到..\x3566_linux_v1.2.0\u-boot\drivers\input\key-uclass.c文件,此文件实现了int key_read(int code)函数:
- int key_read(int code)
- {
- struct dm_key_uclass_platdata *uc_key;
- struct udevice *dev;
- struct uclass *uc;
- bool allow_pre_reloc = false;
- int ret, event = KEY_NOT_EXIST;
-
- ret = uclass_get(UCLASS_KEY, &uc);
- if (ret)
- return ret;
-
- try_again:
- for (uclass_first_device(UCLASS_KEY, &dev);
- dev;
- uclass_next_device(&dev)) {
- uc_key = dev_get_uclass_platdata(dev);
-
- if (!allow_pre_reloc && uc_key->pre_reloc)
- continue;
-
- if (uc_key->code != code)
- continue;
-
- event = key_core_read(uc_key);
- if (key_is_pressed(event))
- return event;
- }
-
- /* If not find valid key node from kernel, try from u-boot */
- if (event == KEY_NOT_EXIST && !allow_pre_reloc) {
- allow_pre_reloc = true;
- goto try_again;
- }
-
- return event;
- }
dev_get_uclass_platdata()函数的实现在..\x3566_linux_v1.2.0\u-boot\drivers\core\device.c文件中。
- rk8xx_read: read reg 0x4d failed, ret=-121
- rk8xx_write: write reg 0x4d failed, ret=-121
- __virq_enable: Clear status register 0x4d failed, ret=-121
根据以上日志,猜测应该是PMIC产生了中断事件,处理器读取PMIC INT寄存器时出错,也没有清除掉PMIC的中断,导致中断一直存在,程序卡死。
从日志看出当前是在读取0x04寄存器,而RK817的INT MASK寄存器为0xf9,RK805、RK808、RK818的INT MASK寄存器为0x4d。
怀疑是某个过程PMIC的ID传错了,通过加日志排查,int rk8xx_irq_chip_init(struct udevice *dev)函数中PMIC的ID为RK808,所以注册的中断相关的寄存器也是RK808的,导致读取错误。
修改int rk8xx_probe(struct udevice *dev)函数,给priv->variant赋值:
- static int rk8xx_probe(struct udevice *dev)
- {
- ...
- -- show_variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
- ++ priv->variant = ((msb << 8) | lsb) & RK8XX_ID_MSK;
- ++ show_variant = priv->variant;
- ...
- }
修改之后运行还是报错,只是寄存器变了:
- rk8xx_read: read reg 0xf9 failed, ret=-121
- rk8xx_write: write reg 0xf9 failed, ret=-121
- __virq_enable: Clear status register 0xf9 failed, ret=-121
从此现象可以得出错误的主要原因不是寄存器配置错误,而是其它未知的原因。
目前将rk8xx_pwrkey.c文件中的中断使能函数屏蔽,即可避免此问题:
- static int rk8xx_pwrkey_probe(struct udevice *dev)
- {
- printf("rk8xx_pwrkey_probe\n");
- struct rk8xx_priv *rk8xx = dev_get_priv(dev->parent);
- struct dm_key_uclass_platdata *key = dev_get_uclass_platdata(dev);
- int fall_irq, rise_irq;
-
- if (!rk8xx->irq_chip) {
- printf("Failed to get parent irq chip\n");
- return -ENOENT;
- }
-
- fall_irq = virq_to_irq(rk8xx->irq_chip, RK8XX_IRQ_PWRON_FALL);
- if (fall_irq < 0) {
- printf("Failed to register pwron fall irq, ret=%d\n", fall_irq);
- return fall_irq;
- }
-
- rise_irq = virq_to_irq(rk8xx->irq_chip, RK8XX_IRQ_PWRON_RISE);
- if (rise_irq < 0) {
- printf("Failed to register pwron rise irq, ret=%d\n", rise_irq);
- return rise_irq;
- }
-
- key->name = "rk8xx_pwr";
- key->type = GPIO_KEY;
- key->code = KEY_POWER;
- key->skip_irq_init = 1;
-
- irq_install_handler(fall_irq, rk8xx_pwron_fall_handler, dev);
- irq_install_handler(rise_irq, rk8xx_pwron_rise_handler, dev);
- // irq_handler_enable(fall_irq);
- // irq_handler_enable(rise_irq);
-
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。