xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/boot_mode.c (revision d4eae7f5feecb47401382e92cf7d3e5430b9dd44)
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/rk_atags.h>
12 #include <cli.h>
13 #include <dm.h>
14 #include <fdtdec.h>
15 #include <boot_rkimg.h>
16 #include <linux/usb/phy-rockchip-inno-usb2.h>
17 #include <key.h>
18 #ifdef CONFIG_DM_RAMDISK
19 #include <ramdisk.h>
20 #endif
21 #include <mmc.h>
22 
23 DECLARE_GLOBAL_DATA_PTR;
24 
25 #if (CONFIG_ROCKCHIP_BOOT_MODE_REG == 0)
26 
27 int setup_boot_mode(void)
28 {
29 	return 0;
30 }
31 
32 #else
33 
34 void set_back_to_bootrom_dnl_flag(void)
35 {
36 	writel(BOOT_BROM_DOWNLOAD, CONFIG_ROCKCHIP_BOOT_MODE_REG);
37 }
38 
39 /*
40  * detect download key status by adc, most rockchip
41  * based boards use adc sample the download key status,
42  * but there are also some use gpio. So it's better to
43  * make this a weak function that can be override by
44  * some special boards.
45  */
46 #define KEY_DOWN_MIN_VAL	0
47 #define KEY_DOWN_MAX_VAL	30
48 
49 __weak int rockchip_dnl_key_pressed(void)
50 {
51 	int keyval = false;
52 
53 /*
54  * This is a generic interface to read key
55  */
56 #if defined(CONFIG_DM_KEY)
57 	keyval = key_read(KEY_VOLUMEUP);
58 
59 	return key_is_pressed(keyval);
60 
61 #elif defined(CONFIG_ADC)
62 	const void *blob = gd->fdt_blob;
63 	unsigned int val;
64 	int channel = 1;
65 	int node;
66 	int ret;
67 	u32 chns[2];
68 
69 	node = fdt_node_offset_by_compatible(blob, 0, "adc-keys");
70 	if (node >= 0) {
71 	       if (!fdtdec_get_int_array(blob, node, "io-channels", chns, 2))
72 		       channel = chns[1];
73 	}
74 
75 	ret = adc_channel_single_shot("saradc", channel, &val);
76 	if (ret) {
77 		printf("%s adc_channel_single_shot fail! ret=%d\n", __func__, ret);
78 		return false;
79 	}
80 
81 	if ((val >= KEY_DOWN_MIN_VAL) && (val <= KEY_DOWN_MAX_VAL))
82 		return true;
83 	else
84 		return false;
85 #endif
86 
87 	return keyval;
88 }
89 
90 void boot_devtype_init(void)
91 {
92 	const char *devtype_num_set = "run rkimg_bootdev";
93 	char *devtype = NULL, *devnum = NULL;
94 	static int done = 0;
95 	int atags_en = 0;
96 	int ret;
97 
98 	if (done)
99 		return;
100 
101 	/*
102 	 * New way: get bootdev from preloader atags info.
103 	 */
104 #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
105 	struct tag *t;
106 
107 	t = atags_get_tag(ATAG_BOOTDEV);
108 	if (t) {
109 		atags_en = 1;
110 		switch (t->u.bootdev.devtype) {
111 		case BOOT_TYPE_EMMC:
112 			devtype = "mmc";
113 			devnum = "0";
114 			break;
115 		case BOOT_TYPE_SD0:
116 		case BOOT_TYPE_SD1:
117 			devtype = "mmc";
118 			devnum = "1";
119 			break;
120 		case BOOT_TYPE_NAND:
121 			devtype = "rknand";
122 			devnum = "0";
123 			break;
124 		case BOOT_TYPE_SPI_NAND:
125 			devtype = "spinand";
126 			devnum = "0";
127 			break;
128 		case BOOT_TYPE_SPI_NOR:
129 			devtype = "spinor";
130 			devnum = "1";
131 			break;
132 		case BOOT_TYPE_RAM:
133 			devtype = "ramdisk";
134 			devnum = "0";
135 			break;
136 		default:
137 			printf("Unknown bootdev type: 0x%x\n",
138 			       t->u.bootdev.devtype);
139 			goto fallback;
140 		}
141 	}
142 
143 	debug("%s: Get bootdev from atags: %s %s\n", __func__, devtype, devnum);
144 
145 	if (devtype && devnum) {
146 		env_set("devtype", devtype);
147 		env_set("devnum", devnum);
148 #ifdef CONFIG_DM_MMC
149 		if (!strcmp("mmc", devtype))
150 			mmc_initialize(gd->bd);
151 #endif
152 		goto finish;
153 	}
154 #endif
155 
156 	/*
157 	 * Legacy way: get bootdev by going through all boot media.
158 	 */
159 fallback:
160 #ifdef CONFIG_DM_MMC
161 	mmc_initialize(gd->bd);
162 #endif
163 	ret = run_command_list(devtype_num_set, -1, 0);
164 	if (ret) {
165 		/* Set default dev type/num if command not valid */
166 		devtype = "mmc";
167 		devnum = "0";
168 		env_set("devtype", devtype);
169 		env_set("devnum", devnum);
170 	}
171 finish:
172 	done = 1;
173 	printf("Bootdev%s: %s %s\n", atags_en ? "(atags)" : "",
174 	       env_get("devtype"), env_get("devnum"));
175 }
176 
177 void rockchip_dnl_mode_check(void)
178 {
179 	if (rockchip_dnl_key_pressed()) {
180 		printf("download key pressed... ");
181 		if (rockchip_u2phy_vbus_detect() > 0) {
182 			printf("entering download mode...\n");
183 			/* If failed, we fall back to bootrom download mode */
184 			run_command_list("rockusb 0 ${devtype} ${devnum}", -1, 0);
185 			set_back_to_bootrom_dnl_flag();
186 			do_reset(NULL, 0, 0, NULL);
187 		} else {
188 			printf("\n");
189 #ifdef CONFIG_RKIMG_BOOTLOADER
190 			/* If there is no recovery partition, just boot on */
191 			struct blk_desc *dev_desc;
192 			disk_partition_t part_info;
193 
194 			dev_desc = rockchip_get_bootdev();
195 			if (!dev_desc) {
196 				printf("%s: dev_desc is NULL!\n", __func__);
197 				return;
198 			}
199 			if (part_get_info_by_name(dev_desc, PART_RECOVERY,
200 						  &part_info)) {
201 				debug("%s: no recovery partition\n", __func__);
202 				return;
203 			}
204 #endif
205 			printf("recovery key pressed, entering recovery mode!\n");
206 			env_set("reboot_mode", "recovery");
207 		}
208 	}
209 }
210 
211 int setup_boot_mode(void)
212 {
213 	int boot_mode = BOOT_MODE_NORMAL;
214 	char env_preboot[256] = {0};
215 
216 	boot_devtype_init();
217 	rockchip_dnl_mode_check();
218 #ifdef CONFIG_RKIMG_BOOTLOADER
219 	boot_mode = rockchip_get_boot_mode();
220 #endif
221 	switch (boot_mode) {
222 	case BOOT_MODE_BOOTLOADER:
223 		printf("enter fastboot!\n");
224 #if defined(CONFIG_FASTBOOT_FLASH_MMC_DEV)
225 		snprintf(env_preboot, 256,
226 				"setenv preboot; mmc dev %x; fastboot usb 0; ",
227 				CONFIG_FASTBOOT_FLASH_MMC_DEV);
228 #elif defined(CONFIG_FASTBOOT_FLASH_NAND_DEV)
229 		snprintf(env_preboot, 256,
230 				"setenv preboot; fastboot usb 0; ");
231 #endif
232 		env_set("preboot", env_preboot);
233 		break;
234 	case BOOT_MODE_UMS:
235 		printf("enter UMS!\n");
236 		env_set("preboot", "setenv preboot; ums mmc 0");
237 		break;
238 	case BOOT_MODE_LOADER:
239 		printf("enter Rockusb!\n");
240 		env_set("preboot", "setenv preboot; rockusb 0 ${devtype} ${devnum}");
241 		break;
242 	case BOOT_MODE_CHARGING:
243 		printf("enter charging!\n");
244 		env_set("preboot", "setenv preboot; charge");
245 		break;
246 	case BOOT_MODE_RECOVERY:
247 		printf("enter Recovery mode!\n");
248 		env_set("reboot_mode", "recovery");
249 		break;
250 	}
251 
252 	return 0;
253 }
254 
255 #endif
256