]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/samsung/common/misc.c
samsung: misc: Add LCD download menu.
[karo-tx-uboot.git] / board / samsung / common / misc.c
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 */