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