blob: 2fd104d0fe747d2057dd2feda7e6c9dbc01e0b41 [file] [log] [blame]
Przemyslaw Marczak679549d2014-01-22 11:24:12 +01001/*
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>
Przemyslaw Marczak9d29a682014-01-22 11:24:17 +010012#include <errno.h>
13#include <version.h>
Alexey Brodkin1ace4022014-02-26 17:47:58 +040014#include <linux/sizes.h>
Przemyslaw Marczak9d29a682014-01-22 11:24:17 +010015#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
22DECLARE_GLOBAL_DATA_PTR;
23
Piotr Wilczekeee2fab2014-01-22 15:54:32 +010024#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
25void set_board_info(void)
26{
27 char info[64];
28
29 snprintf(info, ARRAY_SIZE(info), "%d.%d", s5p_cpu_rev & 0x0f,
30 (s5p_cpu_rev & 0xf0) >> 0x04);
31 setenv("soc_rev", info);
32
33 snprintf(info, ARRAY_SIZE(info), "%x", s5p_cpu_id);
34 setenv("soc_id", info);
35
36#ifdef CONFIG_REVISION_TAG
37 snprintf(info, ARRAY_SIZE(info), "%x", get_board_rev());
38 setenv("board_rev", info);
39#endif
40#ifdef CONFIG_OF_LIBFDT
41 snprintf(info, ARRAY_SIZE(info), "%s%x-%s.dtb",
42 CONFIG_SYS_SOC, s5p_cpu_id, CONFIG_SYS_BOARD);
43 setenv("fdtfile", info);
44#endif
45}
46#endif /* CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG */
47
Przemyslaw Marczak9d29a682014-01-22 11:24:17 +010048#ifdef CONFIG_LCD_MENU
49static int power_key_pressed(u32 reg)
50{
51 struct pmic *pmic;
52 u32 status;
53 u32 mask;
54
55 pmic = pmic_get(KEY_PWR_PMIC_NAME);
56 if (!pmic) {
57 printf("%s: Not found\n", KEY_PWR_PMIC_NAME);
58 return 0;
59 }
60
61 if (pmic_probe(pmic))
62 return 0;
63
64 if (reg == KEY_PWR_STATUS_REG)
65 mask = KEY_PWR_STATUS_MASK;
66 else
67 mask = KEY_PWR_INTERRUPT_MASK;
68
69 if (pmic_reg_read(pmic, reg, &status))
70 return 0;
71
72 return !!(status & mask);
73}
74
75static int key_pressed(int key)
76{
77 int value;
78
79 switch (key) {
80 case KEY_POWER:
81 value = power_key_pressed(KEY_PWR_INTERRUPT_REG);
82 break;
83 case KEY_VOLUMEUP:
84 value = !gpio_get_value(KEY_VOL_UP_GPIO);
85 break;
86 case KEY_VOLUMEDOWN:
87 value = !gpio_get_value(KEY_VOL_DOWN_GPIO);
88 break;
89 default:
90 value = 0;
91 break;
92 }
93
94 return value;
95}
96
97static int check_keys(void)
98{
99 int keys = 0;
100
101 if (key_pressed(KEY_POWER))
102 keys += KEY_POWER;
103 if (key_pressed(KEY_VOLUMEUP))
104 keys += KEY_VOLUMEUP;
105 if (key_pressed(KEY_VOLUMEDOWN))
106 keys += KEY_VOLUMEDOWN;
107
108 return keys;
109}
110
111/*
112 * 0 BOOT_MODE_INFO
113 * 1 BOOT_MODE_THOR
114 * 2 BOOT_MODE_UMS
115 * 3 BOOT_MODE_DFU
116 * 4 BOOT_MODE_EXIT
117 */
118static char *
Przemyslaw Marczake6bfe792014-04-30 13:28:06 +0200119mode_name[BOOT_MODE_EXIT + 1][2] = {
120 {"DEVICE", ""},
121 {"THOR", "thor"},
122 {"UMS", "ums"},
123 {"DFU", "dfu"},
Przemyslaw Marczak5c7b8a32014-04-30 13:28:07 +0200124 {"GPT", "gpt"},
Przemyslaw Marczake6bfe792014-04-30 13:28:06 +0200125 {"EXIT", ""},
Przemyslaw Marczak9d29a682014-01-22 11:24:17 +0100126};
127
128static char *
129mode_info[BOOT_MODE_EXIT + 1] = {
130 "info",
131 "downloader",
132 "mass storage",
133 "firmware update",
Przemyslaw Marczak5c7b8a32014-04-30 13:28:07 +0200134 "restore",
Przemyslaw Marczak9d29a682014-01-22 11:24:17 +0100135 "and run normal boot"
136};
137
Przemyslaw Marczak9d29a682014-01-22 11:24:17 +0100138static char *
Przemyslaw Marczake6bfe792014-04-30 13:28:06 +0200139mode_cmd[BOOT_MODE_EXIT + 1] = {
140 "",
141 "thor 0 mmc 0",
142 "ums 0 mmc 0",
143 "dfu 0 mmc 0",
Przemyslaw Marczak5c7b8a32014-04-30 13:28:07 +0200144 "gpt write mmc 0 $partitions",
Przemyslaw Marczake6bfe792014-04-30 13:28:06 +0200145 "",
Przemyslaw Marczak9d29a682014-01-22 11:24:17 +0100146};
147
148static void display_board_info(void)
149{
150#ifdef CONFIG_GENERIC_MMC
151 struct mmc *mmc = find_mmc_device(0);
152#endif
153 vidinfo_t *vid = &panel_info;
154
155 lcd_position_cursor(4, 4);
156
157 lcd_printf("%s\n\t", U_BOOT_VERSION);
158 lcd_puts("\n\t\tBoard Info:\n");
159#ifdef CONFIG_SYS_BOARD
160 lcd_printf("\tBoard name: %s\n", CONFIG_SYS_BOARD);
161#endif
162#ifdef CONFIG_REVISION_TAG
163 lcd_printf("\tBoard rev: %u\n", get_board_rev());
164#endif
165 lcd_printf("\tDRAM banks: %u\n", CONFIG_NR_DRAM_BANKS);
166 lcd_printf("\tDRAM size: %u MB\n", gd->ram_size / SZ_1M);
167
168#ifdef CONFIG_GENERIC_MMC
169 if (mmc) {
170 if (!mmc->capacity)
171 mmc_init(mmc);
172
173 lcd_printf("\teMMC size: %llu MB\n", mmc->capacity / SZ_1M);
174 }
175#endif
176 if (vid)
177 lcd_printf("\tDisplay resolution: %u x % u\n",
178 vid->vl_col, vid->vl_row);
179
180 lcd_printf("\tDisplay BPP: %u\n", 1 << vid->vl_bpix);
181}
182
183static int mode_leave_menu(int mode)
184{
185 char *exit_option;
Przemyslaw Marczake6bfe792014-04-30 13:28:06 +0200186 char *exit_reset = "reset";
Przemyslaw Marczak9d29a682014-01-22 11:24:17 +0100187 char *exit_back = "back";
188 cmd_tbl_t *cmd;
189 int cmd_result;
Przemyslaw Marczak9d29a682014-01-22 11:24:17 +0100190 int leave;
191
192 lcd_clear();
193
194 switch (mode) {
195 case BOOT_MODE_EXIT:
196 return 1;
197 case BOOT_MODE_INFO:
198 display_board_info();
199 exit_option = exit_back;
200 leave = 0;
201 break;
202 default:
Przemyslaw Marczake6bfe792014-04-30 13:28:06 +0200203 cmd = find_cmd(mode_name[mode][1]);
Przemyslaw Marczak9d29a682014-01-22 11:24:17 +0100204 if (cmd) {
Przemyslaw Marczake6bfe792014-04-30 13:28:06 +0200205 printf("Enter: %s %s\n", mode_name[mode][0],
Przemyslaw Marczak9d29a682014-01-22 11:24:17 +0100206 mode_info[mode]);
Przemyslaw Marczake6bfe792014-04-30 13:28:06 +0200207 lcd_printf("\n\n\t%s %s\n", mode_name[mode][0],
Przemyslaw Marczak9d29a682014-01-22 11:24:17 +0100208 mode_info[mode]);
209 lcd_puts("\n\tDo not turn off device before finish!\n");
210
Przemyslaw Marczake6bfe792014-04-30 13:28:06 +0200211 cmd_result = run_command(mode_cmd[mode], 0);
Przemyslaw Marczak9d29a682014-01-22 11:24:17 +0100212
213 if (cmd_result == CMD_RET_SUCCESS) {
214 printf("Command finished\n");
215 lcd_clear();
216 lcd_printf("\n\n\t%s finished\n",
Przemyslaw Marczake6bfe792014-04-30 13:28:06 +0200217 mode_name[mode][0]);
Przemyslaw Marczak9d29a682014-01-22 11:24:17 +0100218
Przemyslaw Marczake6bfe792014-04-30 13:28:06 +0200219 exit_option = exit_reset;
Przemyslaw Marczak9d29a682014-01-22 11:24:17 +0100220 leave = 1;
221 } else {
222 printf("Command error\n");
223 lcd_clear();
224 lcd_printf("\n\n\t%s command error\n",
Przemyslaw Marczake6bfe792014-04-30 13:28:06 +0200225 mode_name[mode][0]);
Przemyslaw Marczak9d29a682014-01-22 11:24:17 +0100226
227 exit_option = exit_back;
228 leave = 0;
229 }
230 } else {
231 lcd_puts("\n\n\tThis mode is not supported.\n");
232 exit_option = exit_back;
233 leave = 0;
234 }
235 }
236
237 lcd_printf("\n\n\tPress POWER KEY to %s\n", exit_option);
238
239 /* Clear PWR button Rising edge interrupt status flag */
240 power_key_pressed(KEY_PWR_INTERRUPT_REG);
241
242 /* Wait for PWR key */
243 while (!key_pressed(KEY_POWER))
244 mdelay(1);
245
246 lcd_clear();
247 return leave;
248}
249
250static void display_download_menu(int mode)
251{
252 char *selection[BOOT_MODE_EXIT + 1];
253 int i;
254
255 for (i = 0; i <= BOOT_MODE_EXIT; i++)
256 selection[i] = "[ ]";
257
258 selection[mode] = "[=>]";
259
260 lcd_clear();
261 lcd_printf("\n\t\tDownload Mode Menu\n");
262
263 for (i = 0; i <= BOOT_MODE_EXIT; i++)
264 lcd_printf("\t%s %s - %s\n\n", selection[i],
Przemyslaw Marczake6bfe792014-04-30 13:28:06 +0200265 mode_name[i][0],
Przemyslaw Marczak9d29a682014-01-22 11:24:17 +0100266 mode_info[i]);
267}
268
269static void download_menu(void)
270{
271 int mode = 0;
272 int last_mode = 0;
273 int run;
274 int key;
275
276 display_download_menu(mode);
277
278 while (1) {
279 run = 0;
280
281 if (mode != last_mode)
282 display_download_menu(mode);
283
284 last_mode = mode;
285 mdelay(100);
286
287 key = check_keys();
288 switch (key) {
289 case KEY_POWER:
290 run = 1;
291 break;
292 case KEY_VOLUMEUP:
293 if (mode > 0)
294 mode--;
295 break;
296 case KEY_VOLUMEDOWN:
297 if (mode < BOOT_MODE_EXIT)
298 mode++;
299 break;
300 default:
301 break;
302 }
303
304 if (run) {
305 if (mode_leave_menu(mode))
Przemyslaw Marczake6bfe792014-04-30 13:28:06 +0200306 run_command("reset", 0);
Przemyslaw Marczak9d29a682014-01-22 11:24:17 +0100307
308 display_download_menu(mode);
309 }
310 }
311
312 lcd_clear();
313}
314
315static void display_mode_info(void)
316{
317 lcd_position_cursor(4, 4);
318 lcd_printf("%s\n", U_BOOT_VERSION);
319 lcd_puts("\nDownload Mode Menu\n");
320#ifdef CONFIG_SYS_BOARD
321 lcd_printf("Board name: %s\n", CONFIG_SYS_BOARD);
322#endif
323 lcd_printf("Press POWER KEY to display MENU options.");
324}
325
326static int boot_menu(void)
327{
328 int key = 0;
329 int timeout = 10;
330
331 display_mode_info();
332
333 while (timeout--) {
334 lcd_printf("\rNormal boot will start in: %d seconds.", timeout);
335 mdelay(1000);
336
337 key = key_pressed(KEY_POWER);
338 if (key)
339 break;
340 }
341
342 lcd_clear();
343
344 /* If PWR pressed - show download menu */
345 if (key) {
346 printf("Power pressed - go to download menu\n");
347 download_menu();
348 printf("Download mode exit.\n");
349 }
350
351 return 0;
352}
353
354void check_boot_mode(void)
355{
356 int pwr_key;
357
358 pwr_key = power_key_pressed(KEY_PWR_STATUS_REG);
359 if (!pwr_key)
360 return;
361
362 /* Clear PWR button Rising edge interrupt status flag */
363 power_key_pressed(KEY_PWR_INTERRUPT_REG);
364
365 if (key_pressed(KEY_VOLUMEUP))
366 boot_menu();
367 else if (key_pressed(KEY_VOLUMEDOWN))
368 mode_leave_menu(BOOT_MODE_THOR);
369}
370
371void keys_init(void)
372{
373 /* Set direction to input */
374 gpio_direction_input(KEY_VOL_UP_GPIO);
375 gpio_direction_input(KEY_VOL_DOWN_GPIO);
376}
377#endif /* CONFIG_LCD_MENU */
Przemyslaw Marczak679549d2014-01-22 11:24:12 +0100378
379#ifdef CONFIG_CMD_BMP
380void draw_logo(void)
381{
382 int x, y;
383 ulong addr;
384
385 addr = panel_info.logo_addr;
386 if (!addr) {
387 error("There is no logo data.");
388 return;
389 }
390
391 if (panel_info.vl_width >= panel_info.logo_width) {
392 x = ((panel_info.vl_width - panel_info.logo_width) >> 1);
Przemyslaw Marczak903afe12013-11-29 18:30:43 +0100393 x += panel_info.logo_x_offset; /* For X center align */
Przemyslaw Marczak679549d2014-01-22 11:24:12 +0100394 } else {
395 x = 0;
396 printf("Warning: image width is bigger than display width\n");
397 }
398
399 if (panel_info.vl_height >= panel_info.logo_height) {
400 y = ((panel_info.vl_height - panel_info.logo_height) >> 1);
Przemyslaw Marczak903afe12013-11-29 18:30:43 +0100401 y += panel_info.logo_y_offset; /* For Y center align */
Przemyslaw Marczak679549d2014-01-22 11:24:12 +0100402 } else {
403 y = 0;
404 printf("Warning: image height is bigger than display height\n");
405 }
406
407 bmp_display(addr, x, y);
408}
409#endif /* CONFIG_CMD_BMP */