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