1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * (C) Copyright 2021 Rockchip Electronics Co., Ltd
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <boot_rkimg.h>
9*4882a593Smuzhiyun #include <malloc.h>
10*4882a593Smuzhiyun #include <asm/io.h>
11*4882a593Smuzhiyun #include <asm/arch/boot_mode.h>
12*4882a593Smuzhiyun
misc_require_recovery(struct blk_desc * dev_desc,u32 bcb_offset)13*4882a593Smuzhiyun static int misc_require_recovery(struct blk_desc *dev_desc, u32 bcb_offset)
14*4882a593Smuzhiyun {
15*4882a593Smuzhiyun struct bootloader_message *bmsg;
16*4882a593Smuzhiyun disk_partition_t part;
17*4882a593Smuzhiyun int cnt, recovery;
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun if (!dev_desc)
20*4882a593Smuzhiyun return 0;
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun if (part_get_info_by_name(dev_desc, PART_MISC, &part) < 0) {
23*4882a593Smuzhiyun printf("No misc partition\n");
24*4882a593Smuzhiyun return 0;
25*4882a593Smuzhiyun }
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun cnt = DIV_ROUND_UP(sizeof(struct bootloader_message), dev_desc->blksz);
28*4882a593Smuzhiyun bmsg = memalign(ARCH_DMA_MINALIGN, cnt * dev_desc->blksz);
29*4882a593Smuzhiyun if (!bmsg)
30*4882a593Smuzhiyun return 0;
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun if (blk_dread(dev_desc, part.start + bcb_offset, cnt, bmsg) != cnt)
33*4882a593Smuzhiyun return 0;
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun recovery = !strcmp(bmsg->command, "boot-recovery");
36*4882a593Smuzhiyun free(bmsg);
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun return recovery;
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun
rockchip_get_boot_mode(struct blk_desc * dev_desc,u32 bcb_sector_offset)41*4882a593Smuzhiyun int rockchip_get_boot_mode(struct blk_desc *dev_desc, u32 bcb_sector_offset)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun uint32_t reg_boot_mode;
44*4882a593Smuzhiyun int boot_mode;
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun /*
47*4882a593Smuzhiyun * Boot mode priority
48*4882a593Smuzhiyun *
49*4882a593Smuzhiyun * Anyway, we should set download boot mode as the highest priority, so:
50*4882a593Smuzhiyun * reboot loader/bootloader/fastboot > misc partition "recovery" > reboot xxx.
51*4882a593Smuzhiyun */
52*4882a593Smuzhiyun reg_boot_mode = readl((void *)CONFIG_ROCKCHIP_BOOT_MODE_REG);
53*4882a593Smuzhiyun if (reg_boot_mode == BOOT_LOADER) {
54*4882a593Smuzhiyun printf("boot mode: loader\n");
55*4882a593Smuzhiyun boot_mode = BOOT_MODE_LOADER;
56*4882a593Smuzhiyun } else if (reg_boot_mode == BOOT_DFU) {
57*4882a593Smuzhiyun printf("boot mode: dfu\n");
58*4882a593Smuzhiyun boot_mode = BOOT_MODE_DFU;
59*4882a593Smuzhiyun } else if (reg_boot_mode == BOOT_FASTBOOT) {
60*4882a593Smuzhiyun printf("boot mode: bootloader\n");
61*4882a593Smuzhiyun boot_mode = BOOT_MODE_BOOTLOADER;
62*4882a593Smuzhiyun } else if (misc_require_recovery(dev_desc, bcb_sector_offset)) {
63*4882a593Smuzhiyun printf("boot mode: recovery (misc)\n");
64*4882a593Smuzhiyun boot_mode = BOOT_MODE_RECOVERY;
65*4882a593Smuzhiyun } else {
66*4882a593Smuzhiyun switch (reg_boot_mode) {
67*4882a593Smuzhiyun case BOOT_NORMAL:
68*4882a593Smuzhiyun printf("boot mode: normal\n");
69*4882a593Smuzhiyun boot_mode = BOOT_MODE_NORMAL;
70*4882a593Smuzhiyun break;
71*4882a593Smuzhiyun case BOOT_RECOVERY:
72*4882a593Smuzhiyun printf("boot mode: recovery (cmd)\n");
73*4882a593Smuzhiyun boot_mode = BOOT_MODE_RECOVERY;
74*4882a593Smuzhiyun break;
75*4882a593Smuzhiyun case BOOT_UMS:
76*4882a593Smuzhiyun printf("boot mode: ums\n");
77*4882a593Smuzhiyun boot_mode = BOOT_MODE_UMS;
78*4882a593Smuzhiyun break;
79*4882a593Smuzhiyun case BOOT_CHARGING:
80*4882a593Smuzhiyun printf("boot mode: charging\n");
81*4882a593Smuzhiyun boot_mode = BOOT_MODE_CHARGING;
82*4882a593Smuzhiyun break;
83*4882a593Smuzhiyun case BOOT_PANIC:
84*4882a593Smuzhiyun printf("boot mode: panic\n");
85*4882a593Smuzhiyun boot_mode = BOOT_MODE_PANIC;
86*4882a593Smuzhiyun break;
87*4882a593Smuzhiyun case BOOT_WATCHDOG:
88*4882a593Smuzhiyun printf("boot mode: watchdog\n");
89*4882a593Smuzhiyun boot_mode = BOOT_MODE_WATCHDOG;
90*4882a593Smuzhiyun break;
91*4882a593Smuzhiyun default:
92*4882a593Smuzhiyun printf("boot mode: None\n");
93*4882a593Smuzhiyun boot_mode = BOOT_MODE_UNDEFINE;
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun return boot_mode;
98*4882a593Smuzhiyun }
99