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