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 <malloc.h> 15 #include <linux/sizes.h> 16 #include <asm/arch/cpu.h> 17 #include <asm/arch/gpio.h> 18 #include <asm/gpio.h> 19 #include <linux/input.h> 20 #include <power/pmic.h> 21 #include <mmc.h> 22 23 DECLARE_GLOBAL_DATA_PTR; 24 25 #ifdef CONFIG_SET_DFU_ALT_INFO 26 void set_dfu_alt_info(void) 27 { 28 size_t buf_size = CONFIG_SET_DFU_ALT_BUF_LEN; 29 ALLOC_CACHE_ALIGN_BUFFER(char, buf, buf_size); 30 char *alt_info = "Settings not found!"; 31 char *status = "error!\n"; 32 char *alt_setting; 33 char *alt_sep; 34 int offset = 0; 35 36 puts("DFU alt info setting: "); 37 38 alt_setting = get_dfu_alt_boot(); 39 if (alt_setting) { 40 setenv("dfu_alt_boot", alt_setting); 41 offset = snprintf(buf, buf_size, "%s", alt_setting); 42 } 43 44 alt_setting = get_dfu_alt_system(); 45 if (alt_setting) { 46 if (offset) 47 alt_sep = ";"; 48 else 49 alt_sep = ""; 50 51 offset += snprintf(buf + offset, buf_size - offset, 52 "%s%s", alt_sep, alt_setting); 53 } 54 55 if (offset) { 56 alt_info = buf; 57 status = "done\n"; 58 } 59 60 setenv("dfu_alt_info", alt_info); 61 puts(status); 62 } 63 #endif 64 65 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG 66 void set_board_info(void) 67 { 68 char info[64]; 69 70 snprintf(info, ARRAY_SIZE(info), "%u.%u", (s5p_cpu_rev & 0xf0) >> 4, 71 s5p_cpu_rev & 0xf); 72 setenv("soc_rev", info); 73 74 snprintf(info, ARRAY_SIZE(info), "%x", s5p_cpu_id); 75 setenv("soc_id", info); 76 77 #ifdef CONFIG_REVISION_TAG 78 snprintf(info, ARRAY_SIZE(info), "%x", get_board_rev()); 79 setenv("board_rev", info); 80 #endif 81 #ifdef CONFIG_OF_LIBFDT 82 snprintf(info, ARRAY_SIZE(info), "%s%x-%s.dtb", 83 CONFIG_SYS_SOC, s5p_cpu_id, CONFIG_SYS_BOARD); 84 setenv("fdtfile", info); 85 #endif 86 } 87 #endif /* CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG */ 88 89 #ifdef CONFIG_LCD_MENU 90 static int power_key_pressed(u32 reg) 91 { 92 struct pmic *pmic; 93 u32 status; 94 u32 mask; 95 96 pmic = pmic_get(KEY_PWR_PMIC_NAME); 97 if (!pmic) { 98 printf("%s: Not found\n", KEY_PWR_PMIC_NAME); 99 return 0; 100 } 101 102 if (pmic_probe(pmic)) 103 return 0; 104 105 if (reg == KEY_PWR_STATUS_REG) 106 mask = KEY_PWR_STATUS_MASK; 107 else 108 mask = KEY_PWR_INTERRUPT_MASK; 109 110 if (pmic_reg_read(pmic, reg, &status)) 111 return 0; 112 113 return !!(status & mask); 114 } 115 116 static int key_pressed(int key) 117 { 118 int value; 119 120 switch (key) { 121 case KEY_POWER: 122 value = power_key_pressed(KEY_PWR_INTERRUPT_REG); 123 break; 124 case KEY_VOLUMEUP: 125 value = !gpio_get_value(KEY_VOL_UP_GPIO); 126 break; 127 case KEY_VOLUMEDOWN: 128 value = !gpio_get_value(KEY_VOL_DOWN_GPIO); 129 break; 130 default: 131 value = 0; 132 break; 133 } 134 135 return value; 136 } 137 138 static int check_keys(void) 139 { 140 int keys = 0; 141 142 if (key_pressed(KEY_POWER)) 143 keys += KEY_POWER; 144 if (key_pressed(KEY_VOLUMEUP)) 145 keys += KEY_VOLUMEUP; 146 if (key_pressed(KEY_VOLUMEDOWN)) 147 keys += KEY_VOLUMEDOWN; 148 149 return keys; 150 } 151 152 /* 153 * 0 BOOT_MODE_INFO 154 * 1 BOOT_MODE_THOR 155 * 2 BOOT_MODE_UMS 156 * 3 BOOT_MODE_DFU 157 * 4 BOOT_MODE_EXIT 158 */ 159 static char * 160 mode_name[BOOT_MODE_EXIT + 1][2] = { 161 {"DEVICE", ""}, 162 {"THOR", "thor"}, 163 {"UMS", "ums"}, 164 {"DFU", "dfu"}, 165 {"GPT", "gpt"}, 166 {"ENV", "env"}, 167 {"EXIT", ""}, 168 }; 169 170 static char * 171 mode_info[BOOT_MODE_EXIT + 1] = { 172 "info", 173 "downloader", 174 "mass storage", 175 "firmware update", 176 "restore", 177 "default", 178 "and run normal boot" 179 }; 180 181 static char * 182 mode_cmd[BOOT_MODE_EXIT + 1] = { 183 "", 184 "thor 0 mmc 0", 185 "ums 0 mmc 0", 186 "dfu 0 mmc 0", 187 "gpt write mmc 0 $partitions", 188 "env default -a; saveenv", 189 "", 190 }; 191 192 static void display_board_info(void) 193 { 194 #ifdef CONFIG_GENERIC_MMC 195 struct mmc *mmc = find_mmc_device(0); 196 #endif 197 vidinfo_t *vid = &panel_info; 198 199 lcd_position_cursor(4, 4); 200 201 lcd_printf("%s\n\t", U_BOOT_VERSION); 202 lcd_puts("\n\t\tBoard Info:\n"); 203 #ifdef CONFIG_SYS_BOARD 204 lcd_printf("\tBoard name: %s\n", CONFIG_SYS_BOARD); 205 #endif 206 #ifdef CONFIG_REVISION_TAG 207 lcd_printf("\tBoard rev: %u\n", get_board_rev()); 208 #endif 209 lcd_printf("\tDRAM banks: %u\n", CONFIG_NR_DRAM_BANKS); 210 lcd_printf("\tDRAM size: %u MB\n", gd->ram_size / SZ_1M); 211 212 #ifdef CONFIG_GENERIC_MMC 213 if (mmc) { 214 if (!mmc->capacity) 215 mmc_init(mmc); 216 217 lcd_printf("\teMMC size: %llu MB\n", mmc->capacity / SZ_1M); 218 } 219 #endif 220 if (vid) 221 lcd_printf("\tDisplay resolution: %u x % u\n", 222 vid->vl_col, vid->vl_row); 223 224 lcd_printf("\tDisplay BPP: %u\n", 1 << vid->vl_bpix); 225 } 226 227 static int mode_leave_menu(int mode) 228 { 229 char *exit_option; 230 char *exit_reset = "reset"; 231 char *exit_back = "back"; 232 cmd_tbl_t *cmd; 233 int cmd_result; 234 int leave; 235 236 lcd_clear(); 237 238 switch (mode) { 239 case BOOT_MODE_EXIT: 240 return 1; 241 case BOOT_MODE_INFO: 242 display_board_info(); 243 exit_option = exit_back; 244 leave = 0; 245 break; 246 default: 247 cmd = find_cmd(mode_name[mode][1]); 248 if (cmd) { 249 printf("Enter: %s %s\n", mode_name[mode][0], 250 mode_info[mode]); 251 lcd_printf("\n\n\t%s %s\n", mode_name[mode][0], 252 mode_info[mode]); 253 lcd_puts("\n\tDo not turn off device before finish!\n"); 254 255 cmd_result = run_command(mode_cmd[mode], 0); 256 257 if (cmd_result == CMD_RET_SUCCESS) { 258 printf("Command finished\n"); 259 lcd_clear(); 260 lcd_printf("\n\n\t%s finished\n", 261 mode_name[mode][0]); 262 263 exit_option = exit_reset; 264 leave = 1; 265 } else { 266 printf("Command error\n"); 267 lcd_clear(); 268 lcd_printf("\n\n\t%s command error\n", 269 mode_name[mode][0]); 270 271 exit_option = exit_back; 272 leave = 0; 273 } 274 } else { 275 lcd_puts("\n\n\tThis mode is not supported.\n"); 276 exit_option = exit_back; 277 leave = 0; 278 } 279 } 280 281 lcd_printf("\n\n\tPress POWER KEY to %s\n", exit_option); 282 283 /* Clear PWR button Rising edge interrupt status flag */ 284 power_key_pressed(KEY_PWR_INTERRUPT_REG); 285 286 /* Wait for PWR key */ 287 while (!key_pressed(KEY_POWER)) 288 mdelay(1); 289 290 lcd_clear(); 291 return leave; 292 } 293 294 static void display_download_menu(int mode) 295 { 296 char *selection[BOOT_MODE_EXIT + 1]; 297 int i; 298 299 for (i = 0; i <= BOOT_MODE_EXIT; i++) 300 selection[i] = "[ ]"; 301 302 selection[mode] = "[=>]"; 303 304 lcd_clear(); 305 lcd_printf("\n\n\t\tDownload Mode Menu\n\n"); 306 307 for (i = 0; i <= BOOT_MODE_EXIT; i++) 308 lcd_printf("\t%s %s - %s\n\n", selection[i], 309 mode_name[i][0], 310 mode_info[i]); 311 } 312 313 static void download_menu(void) 314 { 315 int mode = 0; 316 int last_mode = 0; 317 int run; 318 int key = 0; 319 int timeout = 15; /* sec */ 320 int i; 321 322 display_download_menu(mode); 323 324 lcd_puts("\n"); 325 326 /* Start count if no key is pressed */ 327 while (check_keys()) 328 continue; 329 330 while (timeout--) { 331 lcd_printf("\r\tNormal boot will start in: %2.d seconds.", 332 timeout); 333 334 /* about 1000 ms in for loop */ 335 for (i = 0; i < 10; i++) { 336 mdelay(100); 337 key = check_keys(); 338 if (key) 339 break; 340 } 341 if (key) 342 break; 343 } 344 345 if (!key) { 346 lcd_clear(); 347 return; 348 } 349 350 while (1) { 351 run = 0; 352 353 if (mode != last_mode) 354 display_download_menu(mode); 355 356 last_mode = mode; 357 mdelay(200); 358 359 key = check_keys(); 360 switch (key) { 361 case KEY_POWER: 362 run = 1; 363 break; 364 case KEY_VOLUMEUP: 365 if (mode > 0) 366 mode--; 367 break; 368 case KEY_VOLUMEDOWN: 369 if (mode < BOOT_MODE_EXIT) 370 mode++; 371 break; 372 default: 373 break; 374 } 375 376 if (run) { 377 if (mode_leave_menu(mode)) 378 run_command("reset", 0); 379 380 display_download_menu(mode); 381 } 382 } 383 384 lcd_clear(); 385 } 386 387 void check_boot_mode(void) 388 { 389 int pwr_key; 390 391 pwr_key = power_key_pressed(KEY_PWR_STATUS_REG); 392 if (!pwr_key) 393 return; 394 395 /* Clear PWR button Rising edge interrupt status flag */ 396 power_key_pressed(KEY_PWR_INTERRUPT_REG); 397 398 if (key_pressed(KEY_VOLUMEUP)) 399 download_menu(); 400 else if (key_pressed(KEY_VOLUMEDOWN)) 401 mode_leave_menu(BOOT_MODE_THOR); 402 } 403 404 void keys_init(void) 405 { 406 /* Set direction to input */ 407 gpio_direction_input(KEY_VOL_UP_GPIO); 408 gpio_direction_input(KEY_VOL_DOWN_GPIO); 409 } 410 #endif /* CONFIG_LCD_MENU */ 411 412 #ifdef CONFIG_CMD_BMP 413 void draw_logo(void) 414 { 415 int x, y; 416 ulong addr; 417 418 addr = panel_info.logo_addr; 419 if (!addr) { 420 error("There is no logo data."); 421 return; 422 } 423 424 if (panel_info.vl_width >= panel_info.logo_width) { 425 x = ((panel_info.vl_width - panel_info.logo_width) >> 1); 426 x += panel_info.logo_x_offset; /* For X center align */ 427 } else { 428 x = 0; 429 printf("Warning: image width is bigger than display width\n"); 430 } 431 432 if (panel_info.vl_height >= panel_info.logo_height) { 433 y = ((panel_info.vl_height - panel_info.logo_height) >> 1); 434 y += panel_info.logo_y_offset; /* For Y center align */ 435 } else { 436 y = 0; 437 printf("Warning: image height is bigger than display height\n"); 438 } 439 440 bmp_display(addr, x, y); 441 } 442 #endif /* CONFIG_CMD_BMP */ 443