xref: /rk3399_rockchip-uboot/arch/arm/mach-rockchip/boot_mode.c (revision ce18b1fcdc0dc15df054d2c1b0970bc555ca56b4)
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 ret;
96 
97 	if (done)
98 		return;
99 
100 #ifdef CONFIG_ROCKCHIP_PRELOADER_ATAGS
101 	struct tag *t;
102 
103 	t = atags_get_tag(ATAG_BOOTDEV);
104 	if (t) {
105 		switch (t->u.bootdev.devtype) {
106 		case BOOT_TYPE_EMMC:
107 			devtype = "mmc";
108 			devnum = "0";
109 			break;
110 		case BOOT_TYPE_SD0:
111 		case BOOT_TYPE_SD1:
112 			devtype = "mmc";
113 			devnum = "1";
114 			break;
115 		case BOOT_TYPE_NAND:
116 			devtype = "rknand";
117 			devnum = "0";
118 			break;
119 		case BOOT_TYPE_SPI_NAND:
120 			devtype = "spinand";
121 			devnum = "0";
122 			break;
123 		case BOOT_TYPE_SPI_NOR:
124 			devtype = "spinor";
125 			devnum = "1";
126 			break;
127 		case BOOT_TYPE_RAM:
128 			devtype = "ramdisk";
129 			devnum = "0";
130 			break;
131 		default:
132 			printf("Unknown bootdev type: 0x%x\n",
133 			       t->u.bootdev.devtype);
134 			break;
135 		}
136 	}
137 
138 	debug("%s: Get bootdev from atags: %s %s\n", __func__, devtype, devnum);
139 
140 	if (devtype && devnum) {
141 		env_set("devtype", devtype);
142 		env_set("devnum", devnum);
143 #ifdef CONFIG_DM_MMC
144 		if (!strcmp("mmc", devtype))
145 			mmc_initialize(gd->bd);
146 #endif
147 		goto finish;
148 	}
149 #endif
150 
151 #ifdef CONFIG_DM_MMC
152 	mmc_initialize(gd->bd);
153 #endif
154 	ret = run_command_list(devtype_num_set, -1, 0);
155 	if (ret) {
156 		/* Set default dev type/num if command not valid */
157 		devtype = "mmc";
158 		devnum = "0";
159 		env_set("devtype", devtype);
160 		env_set("devnum", devnum);
161 	}
162 finish:
163 	done = 1;
164 	printf("Bootdev: %s %s\n", env_get("devtype"), env_get("devnum"));
165 }
166 
167 void rockchip_dnl_mode_check(void)
168 {
169 	if (rockchip_dnl_key_pressed()) {
170 		if (rockchip_u2phy_vbus_detect()) {
171 			printf("download key pressed, entering download mode...\n");
172 			/* If failed, we fall back to bootrom download mode */
173 			run_command_list("rockusb 0 ${devtype} ${devnum}", -1, 0);
174 			set_back_to_bootrom_dnl_flag();
175 			do_reset(NULL, 0, 0, NULL);
176 		} else {
177 #ifdef CONFIG_RKIMG_BOOTLOADER
178 			/* If there is no recovery partition, just boot on */
179 			struct blk_desc *dev_desc;
180 			disk_partition_t part_info;
181 
182 			dev_desc = rockchip_get_bootdev();
183 			if (!dev_desc) {
184 				printf("%s: dev_desc is NULL!\n", __func__);
185 				return;
186 			}
187 			if (part_get_info_by_name(dev_desc, PART_RECOVERY,
188 						  &part_info)) {
189 				debug("%s: no recovery partition\n", __func__);
190 				return;
191 			}
192 #endif
193 			printf("recovery key pressed, entering recovery mode!\n");
194 			env_set("reboot_mode", "recovery");
195 		}
196 	}
197 }
198 
199 int setup_boot_mode(void)
200 {
201 	int boot_mode = BOOT_MODE_NORMAL;
202 	char env_preboot[256] = {0};
203 
204 	boot_devtype_init();
205 	rockchip_dnl_mode_check();
206 #ifdef CONFIG_RKIMG_BOOTLOADER
207 	boot_mode = rockchip_get_boot_mode();
208 #endif
209 	switch (boot_mode) {
210 	case BOOT_MODE_BOOTLOADER:
211 		printf("enter fastboot!\n");
212 #if defined(CONFIG_FASTBOOT_FLASH_MMC_DEV)
213 		snprintf(env_preboot, 256,
214 				"setenv preboot; mmc dev %x; fastboot usb 0; ",
215 				CONFIG_FASTBOOT_FLASH_MMC_DEV);
216 #elif defined(CONFIG_FASTBOOT_FLASH_NAND_DEV)
217 		snprintf(env_preboot, 256,
218 				"setenv preboot; fastboot usb 0; ");
219 #endif
220 		env_set("preboot", env_preboot);
221 		break;
222 	case BOOT_MODE_UMS:
223 		printf("enter UMS!\n");
224 		env_set("preboot", "setenv preboot; ums mmc 0");
225 		break;
226 	case BOOT_MODE_LOADER:
227 		printf("enter Rockusb!\n");
228 		env_set("preboot", "setenv preboot; rockusb 0 ${devtype} ${devnum}");
229 		break;
230 	case BOOT_MODE_CHARGING:
231 		printf("enter charging!\n");
232 		env_set("preboot", "setenv preboot; charge");
233 		break;
234 	case BOOT_MODE_RECOVERY:
235 		printf("enter Recovery mode!\n");
236 		env_set("reboot_mode", "recovery");
237 		break;
238 	}
239 
240 	return 0;
241 }
242 
243 #endif
244