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