xref: /rk3399_rockchip-uboot/board/samsung/common/misc.c (revision 00e64ab6471e154a06d89bbfffba2bbe6e2150ad)
1 /*
2  * Copyright (C) 2013 Samsung Electronics
3  * Przemyslaw Marczak <p.marczak@samsung.com>
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include <common.h>
9 #include <lcd.h>
10 #include <libtizen.h>
11 #include <samsung/misc.h>
12 #include <errno.h>
13 #include <version.h>
14 #include <asm/sizes.h>
15 #include <asm/arch/cpu.h>
16 #include <asm/arch/gpio.h>
17 #include <asm/gpio.h>
18 #include <linux/input.h>
19 #include <power/pmic.h>
20 #include <mmc.h>
21 
22 DECLARE_GLOBAL_DATA_PTR;
23 
24 #ifdef CONFIG_LCD_MENU
25 static int power_key_pressed(u32 reg)
26 {
27 	struct pmic *pmic;
28 	u32 status;
29 	u32 mask;
30 
31 	pmic = pmic_get(KEY_PWR_PMIC_NAME);
32 	if (!pmic) {
33 		printf("%s: Not found\n", KEY_PWR_PMIC_NAME);
34 		return 0;
35 	}
36 
37 	if (pmic_probe(pmic))
38 		return 0;
39 
40 	if (reg == KEY_PWR_STATUS_REG)
41 		mask = KEY_PWR_STATUS_MASK;
42 	else
43 		mask = KEY_PWR_INTERRUPT_MASK;
44 
45 	if (pmic_reg_read(pmic, reg, &status))
46 		return 0;
47 
48 	return !!(status & mask);
49 }
50 
51 static int key_pressed(int key)
52 {
53 	int value;
54 
55 	switch (key) {
56 	case KEY_POWER:
57 		value = power_key_pressed(KEY_PWR_INTERRUPT_REG);
58 		break;
59 	case KEY_VOLUMEUP:
60 		value = !gpio_get_value(KEY_VOL_UP_GPIO);
61 		break;
62 	case KEY_VOLUMEDOWN:
63 		value = !gpio_get_value(KEY_VOL_DOWN_GPIO);
64 		break;
65 	default:
66 		value = 0;
67 		break;
68 	}
69 
70 	return value;
71 }
72 
73 static int check_keys(void)
74 {
75 	int keys = 0;
76 
77 	if (key_pressed(KEY_POWER))
78 		keys += KEY_POWER;
79 	if (key_pressed(KEY_VOLUMEUP))
80 		keys += KEY_VOLUMEUP;
81 	if (key_pressed(KEY_VOLUMEDOWN))
82 		keys += KEY_VOLUMEDOWN;
83 
84 	return keys;
85 }
86 
87 /*
88  * 0 BOOT_MODE_INFO
89  * 1 BOOT_MODE_THOR
90  * 2 BOOT_MODE_UMS
91  * 3 BOOT_MODE_DFU
92  * 4 BOOT_MODE_EXIT
93  */
94 static char *
95 mode_name[BOOT_MODE_EXIT + 1] = {
96 	"DEVICE",
97 	"THOR",
98 	"UMS",
99 	"DFU",
100 	"EXIT"
101 };
102 
103 static char *
104 mode_info[BOOT_MODE_EXIT + 1] = {
105 	"info",
106 	"downloader",
107 	"mass storage",
108 	"firmware update",
109 	"and run normal boot"
110 };
111 
112 #define MODE_CMD_ARGC	4
113 
114 static char *
115 mode_cmd[BOOT_MODE_EXIT + 1][MODE_CMD_ARGC] = {
116 	{"", "", "", ""},
117 	{"thor", "0", "mmc", "0"},
118 	{"ums", "0", "mmc", "0"},
119 	{"dfu", "0", "mmc", "0"},
120 	{"", "", "", ""},
121 };
122 
123 static void display_board_info(void)
124 {
125 #ifdef CONFIG_GENERIC_MMC
126 	struct mmc *mmc = find_mmc_device(0);
127 #endif
128 	vidinfo_t *vid = &panel_info;
129 
130 	lcd_position_cursor(4, 4);
131 
132 	lcd_printf("%s\n\t", U_BOOT_VERSION);
133 	lcd_puts("\n\t\tBoard Info:\n");
134 #ifdef CONFIG_SYS_BOARD
135 	lcd_printf("\tBoard name: %s\n", CONFIG_SYS_BOARD);
136 #endif
137 #ifdef CONFIG_REVISION_TAG
138 	lcd_printf("\tBoard rev: %u\n", get_board_rev());
139 #endif
140 	lcd_printf("\tDRAM banks: %u\n", CONFIG_NR_DRAM_BANKS);
141 	lcd_printf("\tDRAM size: %u MB\n", gd->ram_size / SZ_1M);
142 
143 #ifdef CONFIG_GENERIC_MMC
144 	if (mmc) {
145 		if (!mmc->capacity)
146 			mmc_init(mmc);
147 
148 		lcd_printf("\teMMC size: %llu MB\n", mmc->capacity / SZ_1M);
149 	}
150 #endif
151 	if (vid)
152 		lcd_printf("\tDisplay resolution: %u x % u\n",
153 			   vid->vl_col, vid->vl_row);
154 
155 	lcd_printf("\tDisplay BPP: %u\n", 1 << vid->vl_bpix);
156 }
157 
158 static int mode_leave_menu(int mode)
159 {
160 	char *exit_option;
161 	char *exit_boot = "boot";
162 	char *exit_back = "back";
163 	cmd_tbl_t *cmd;
164 	int cmd_result;
165 	int cmd_repeatable;
166 	int leave;
167 
168 	lcd_clear();
169 
170 	switch (mode) {
171 	case BOOT_MODE_EXIT:
172 		return 1;
173 	case BOOT_MODE_INFO:
174 		display_board_info();
175 		exit_option = exit_back;
176 		leave = 0;
177 		break;
178 	default:
179 		cmd = find_cmd(mode_cmd[mode][0]);
180 		if (cmd) {
181 			printf("Enter: %s %s\n", mode_name[mode],
182 						 mode_info[mode]);
183 			lcd_printf("\n\n\t%s %s\n", mode_name[mode],
184 						    mode_info[mode]);
185 			lcd_puts("\n\tDo not turn off device before finish!\n");
186 
187 			cmd_result = cmd_process(0, MODE_CMD_ARGC,
188 						 *(mode_cmd + mode),
189 						 &cmd_repeatable, NULL);
190 
191 			if (cmd_result == CMD_RET_SUCCESS) {
192 				printf("Command finished\n");
193 				lcd_clear();
194 				lcd_printf("\n\n\t%s finished\n",
195 					   mode_name[mode]);
196 
197 				exit_option = exit_boot;
198 				leave = 1;
199 			} else {
200 				printf("Command error\n");
201 				lcd_clear();
202 				lcd_printf("\n\n\t%s command error\n",
203 					   mode_name[mode]);
204 
205 				exit_option = exit_back;
206 				leave = 0;
207 			}
208 		} else {
209 			lcd_puts("\n\n\tThis mode is not supported.\n");
210 			exit_option = exit_back;
211 			leave = 0;
212 		}
213 	}
214 
215 	lcd_printf("\n\n\tPress POWER KEY to %s\n", exit_option);
216 
217 	/* Clear PWR button Rising edge interrupt status flag */
218 	power_key_pressed(KEY_PWR_INTERRUPT_REG);
219 
220 	/* Wait for PWR key */
221 	while (!key_pressed(KEY_POWER))
222 		mdelay(1);
223 
224 	lcd_clear();
225 	return leave;
226 }
227 
228 static void display_download_menu(int mode)
229 {
230 	char *selection[BOOT_MODE_EXIT + 1];
231 	int i;
232 
233 	for (i = 0; i <= BOOT_MODE_EXIT; i++)
234 		selection[i] = "[  ]";
235 
236 	selection[mode] = "[=>]";
237 
238 	lcd_clear();
239 	lcd_printf("\n\t\tDownload Mode Menu\n");
240 
241 	for (i = 0; i <= BOOT_MODE_EXIT; i++)
242 		lcd_printf("\t%s  %s - %s\n\n", selection[i],
243 						mode_name[i],
244 						mode_info[i]);
245 }
246 
247 static void download_menu(void)
248 {
249 	int mode = 0;
250 	int last_mode = 0;
251 	int run;
252 	int key;
253 
254 	display_download_menu(mode);
255 
256 	while (1) {
257 		run = 0;
258 
259 		if (mode != last_mode)
260 			display_download_menu(mode);
261 
262 		last_mode = mode;
263 		mdelay(100);
264 
265 		key = check_keys();
266 		switch (key) {
267 		case KEY_POWER:
268 			run = 1;
269 			break;
270 		case KEY_VOLUMEUP:
271 			if (mode > 0)
272 				mode--;
273 			break;
274 		case KEY_VOLUMEDOWN:
275 			if (mode < BOOT_MODE_EXIT)
276 				mode++;
277 			break;
278 		default:
279 			break;
280 		}
281 
282 		if (run) {
283 			if (mode_leave_menu(mode))
284 				break;
285 
286 			display_download_menu(mode);
287 		}
288 	}
289 
290 	lcd_clear();
291 }
292 
293 static void display_mode_info(void)
294 {
295 	lcd_position_cursor(4, 4);
296 	lcd_printf("%s\n", U_BOOT_VERSION);
297 	lcd_puts("\nDownload Mode Menu\n");
298 #ifdef CONFIG_SYS_BOARD
299 	lcd_printf("Board name: %s\n", CONFIG_SYS_BOARD);
300 #endif
301 	lcd_printf("Press POWER KEY to display MENU options.");
302 }
303 
304 static int boot_menu(void)
305 {
306 	int key = 0;
307 	int timeout = 10;
308 
309 	display_mode_info();
310 
311 	while (timeout--) {
312 		lcd_printf("\rNormal boot will start in: %d seconds.", timeout);
313 		mdelay(1000);
314 
315 		key = key_pressed(KEY_POWER);
316 		if (key)
317 			break;
318 	}
319 
320 	lcd_clear();
321 
322 	/* If PWR pressed - show download menu */
323 	if (key) {
324 		printf("Power pressed - go to download menu\n");
325 		download_menu();
326 		printf("Download mode exit.\n");
327 	}
328 
329 	return 0;
330 }
331 
332 void check_boot_mode(void)
333 {
334 	int pwr_key;
335 
336 	pwr_key = power_key_pressed(KEY_PWR_STATUS_REG);
337 	if (!pwr_key)
338 		return;
339 
340 	/* Clear PWR button Rising edge interrupt status flag */
341 	power_key_pressed(KEY_PWR_INTERRUPT_REG);
342 
343 	if (key_pressed(KEY_VOLUMEUP))
344 		boot_menu();
345 	else if (key_pressed(KEY_VOLUMEDOWN))
346 		mode_leave_menu(BOOT_MODE_THOR);
347 }
348 
349 void keys_init(void)
350 {
351 	/* Set direction to input */
352 	gpio_direction_input(KEY_VOL_UP_GPIO);
353 	gpio_direction_input(KEY_VOL_DOWN_GPIO);
354 }
355 #endif /* CONFIG_LCD_MENU */
356 
357 #ifdef CONFIG_CMD_BMP
358 void draw_logo(void)
359 {
360 	int x, y;
361 	ulong addr;
362 
363 	addr = panel_info.logo_addr;
364 	if (!addr) {
365 		error("There is no logo data.");
366 		return;
367 	}
368 
369 	if (panel_info.vl_width >= panel_info.logo_width) {
370 		x = ((panel_info.vl_width - panel_info.logo_width) >> 1);
371 		x += panel_info.logo_x_offset; /* For X center align */
372 	} else {
373 		x = 0;
374 		printf("Warning: image width is bigger than display width\n");
375 	}
376 
377 	if (panel_info.vl_height >= panel_info.logo_height) {
378 		y = ((panel_info.vl_height - panel_info.logo_height) >> 1);
379 		y += panel_info.logo_y_offset; /* For Y center align */
380 	} else {
381 		y = 0;
382 		printf("Warning: image height is bigger than display height\n");
383 	}
384 
385 	bmp_display(addr, x, y);
386 }
387 #endif /* CONFIG_CMD_BMP */
388