xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/boot_mode.c (revision 57e25cf7ea75e107ba3b4033e705e4e6a45dacbc)
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