1 /* 2 * (C) Copyright 2016 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <adc.h> 9 #include <asm/io.h> 10 #include <asm/arch/boot_mode.h> 11 #include <asm/arch/hotkey.h> 12 #include <asm/arch/param.h> 13 #include <cli.h> 14 #include <dm.h> 15 #include <fdtdec.h> 16 #include <boot_rkimg.h> 17 #include <stdlib.h> 18 #include <linux/usb/phy-rockchip-inno-usb2.h> 19 #include <key.h> 20 #ifdef CONFIG_DM_RAMDISK 21 #include <ramdisk.h> 22 #endif 23 #include <mmc.h> 24 #include <console.h> 25 26 DECLARE_GLOBAL_DATA_PTR; 27 28 #if (CONFIG_ROCKCHIP_BOOT_MODE_REG == 0) 29 30 int setup_boot_mode(void) 31 { 32 return 0; 33 } 34 35 #else 36 37 void set_back_to_bootrom_dnl_flag(void) 38 { 39 writel(BOOT_BROM_DOWNLOAD, CONFIG_ROCKCHIP_BOOT_MODE_REG); 40 } 41 42 /* 43 * detect download key status by adc, most rockchip 44 * based boards use adc sample the download key status, 45 * but there are also some use gpio. So it's better to 46 * make this a weak function that can be override by 47 * some special boards. 48 */ 49 #define KEY_DOWN_MIN_VAL 0 50 #define KEY_DOWN_MAX_VAL 30 51 52 __weak int rockchip_dnl_key_pressed(void) 53 { 54 int keyval = false; 55 56 /* 57 * This is a generic interface to read key 58 */ 59 #if defined(CONFIG_DM_KEY) 60 keyval = key_read(KEY_VOLUMEUP); 61 62 return key_is_pressed(keyval); 63 64 #elif defined(CONFIG_ADC) 65 const void *blob = gd->fdt_blob; 66 unsigned int val; 67 int channel = 1; 68 int node; 69 int ret; 70 u32 chns[2]; 71 72 node = fdt_node_offset_by_compatible(blob, 0, "adc-keys"); 73 if (node >= 0) { 74 if (!fdtdec_get_int_array(blob, node, "io-channels", chns, 2)) 75 channel = chns[1]; 76 } 77 78 ret = adc_channel_single_shot("saradc", channel, &val); 79 if (ret) { 80 printf("%s adc_channel_single_shot fail! ret=%d\n", __func__, ret); 81 return false; 82 } 83 84 if ((val >= KEY_DOWN_MIN_VAL) && (val <= KEY_DOWN_MAX_VAL)) 85 return true; 86 else 87 return false; 88 #endif 89 90 return keyval; 91 } 92 93 void boot_devtype_init(void) 94 { 95 const char *devtype_num_set = "run rkimg_bootdev"; 96 char *devtype = NULL, *devnum = NULL; 97 static int done = 0; 98 int atags_en = 0; 99 int ret; 100 101 if (done) 102 return; 103 104 ret = param_parse_bootdev(&devtype, &devnum); 105 if (!ret) { 106 atags_en = 1; 107 env_set("devtype", devtype); 108 env_set("devnum", devnum); 109 110 #ifdef CONFIG_DM_MMC 111 if (!strcmp("mmc", devtype)) 112 mmc_initialize(gd->bd); 113 #endif 114 /* 115 * For example, the pre-loader do not have mtd device, 116 * and pass devtype is nand. Then U-Boot can not get 117 * dev_desc when use mtd driver to read firmware. So 118 * test the block dev is exist or not here. 119 * 120 * And the devtype & devnum maybe wrong sometimes, it 121 * is better to test first. 122 */ 123 if (blk_get_devnum_by_typename(devtype, atoi(devnum))) 124 goto finish; 125 } 126 127 /* If not find valid bootdev by atags, scan all possible */ 128 #ifdef CONFIG_DM_MMC 129 mmc_initialize(gd->bd); 130 #endif 131 ret = run_command_list(devtype_num_set, -1, 0); 132 if (ret) { 133 /* Set default dev type/num if command not valid */ 134 devtype = "mmc"; 135 devnum = "0"; 136 env_set("devtype", devtype); 137 env_set("devnum", devnum); 138 } 139 140 finish: 141 done = 1; 142 printf("Bootdev%s: %s %s\n", atags_en ? "(atags)" : "", 143 env_get("devtype"), env_get("devnum")); 144 } 145 146 void rockchip_dnl_mode_check(void) 147 { 148 /* recovery key or "ctrl+d" */ 149 if (rockchip_dnl_key_pressed() || 150 is_hotkey(HK_ROCKUSB_DNL)) { 151 printf("download key pressed... "); 152 if (rockchip_u2phy_vbus_detect() > 0) { 153 printf("entering download mode...\n"); 154 /* If failed, we fall back to bootrom download mode */ 155 run_command_list("rockusb 0 ${devtype} ${devnum}", -1, 0); 156 set_back_to_bootrom_dnl_flag(); 157 do_reset(NULL, 0, 0, NULL); 158 } else { 159 printf("\n"); 160 #ifdef CONFIG_RKIMG_BOOTLOADER 161 /* If there is no recovery partition, just boot on */ 162 struct blk_desc *dev_desc; 163 disk_partition_t part_info; 164 int ret; 165 166 dev_desc = rockchip_get_bootdev(); 167 if (!dev_desc) { 168 printf("%s: dev_desc is NULL!\n", __func__); 169 return; 170 } 171 172 ret = part_get_info_by_name(dev_desc, 173 PART_RECOVERY, 174 &part_info); 175 if (ret < 0) { 176 debug("%s: no recovery partition\n", __func__); 177 return; 178 } 179 #endif 180 printf("recovery key pressed, entering recovery mode!\n"); 181 env_set("reboot_mode", "recovery"); 182 } 183 } else if (is_hotkey(HK_FASTBOOT)) { 184 env_set("reboot_mode", "fastboot"); 185 } 186 } 187 188 int setup_boot_mode(void) 189 { 190 int boot_mode = BOOT_MODE_NORMAL; 191 char env_preboot[256] = {0}; 192 193 boot_devtype_init(); 194 rockchip_dnl_mode_check(); 195 #ifdef CONFIG_RKIMG_BOOTLOADER 196 boot_mode = rockchip_get_boot_mode(); 197 #endif 198 switch (boot_mode) { 199 case BOOT_MODE_BOOTLOADER: 200 printf("enter fastboot!\n"); 201 #if defined(CONFIG_FASTBOOT_FLASH_MMC_DEV) 202 snprintf(env_preboot, 256, 203 "setenv preboot; mmc dev %x; fastboot usb 0; ", 204 CONFIG_FASTBOOT_FLASH_MMC_DEV); 205 #elif defined(CONFIG_FASTBOOT_FLASH_NAND_DEV) 206 snprintf(env_preboot, 256, 207 "setenv preboot; fastboot usb 0; "); 208 #endif 209 env_set("preboot", env_preboot); 210 break; 211 case BOOT_MODE_UMS: 212 printf("enter UMS!\n"); 213 env_set("preboot", "setenv preboot; ums mmc 0"); 214 break; 215 case BOOT_MODE_LOADER: 216 printf("enter Rockusb!\n"); 217 env_set("preboot", "setenv preboot; rockusb 0 ${devtype} ${devnum}"); 218 break; 219 case BOOT_MODE_CHARGING: 220 printf("enter charging!\n"); 221 env_set("preboot", "setenv preboot; charge"); 222 break; 223 case BOOT_MODE_RECOVERY: 224 printf("enter Recovery mode!\n"); 225 env_set("reboot_mode", "recovery"); 226 break; 227 } 228 229 return 0; 230 } 231 232 #endif 233