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