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