u-boot-brain/board/samsung/common/misc.c
Simon Glass 7f1961018c dm: exynos: Make sure that GPIOs are requested
With driver model GPIOs must be requested before use. Make sure this is
done correctly.

(Note that the soft SPI part of universal is omitted, since this driver
is about to be replaced with a driver-model-aware version)

Signed-off-by: Simon Glass <sjg@chromium.org>
2014-10-22 10:36:33 -06:00

452 lines
8.5 KiB
C

/*
* Copyright (C) 2013 Samsung Electronics
* Przemyslaw Marczak <p.marczak@samsung.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <lcd.h>
#include <libtizen.h>
#include <samsung/misc.h>
#include <errno.h>
#include <version.h>
#include <malloc.h>
#include <linux/sizes.h>
#include <asm/arch/cpu.h>
#include <asm/gpio.h>
#include <linux/input.h>
#include <power/pmic.h>
#include <mmc.h>
DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_SET_DFU_ALT_INFO
void set_dfu_alt_info(void)
{
size_t buf_size = CONFIG_SET_DFU_ALT_BUF_LEN;
ALLOC_CACHE_ALIGN_BUFFER(char, buf, buf_size);
char *alt_info = "Settings not found!";
char *status = "error!\n";
char *alt_setting;
char *alt_sep;
int offset = 0;
puts("DFU alt info setting: ");
alt_setting = get_dfu_alt_boot();
if (alt_setting) {
setenv("dfu_alt_boot", alt_setting);
offset = snprintf(buf, buf_size, "%s", alt_setting);
}
alt_setting = get_dfu_alt_system();
if (alt_setting) {
if (offset)
alt_sep = ";";
else
alt_sep = "";
offset += snprintf(buf + offset, buf_size - offset,
"%s%s", alt_sep, alt_setting);
}
if (offset) {
alt_info = buf;
status = "done\n";
}
setenv("dfu_alt_info", alt_info);
puts(status);
}
#endif
#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
void set_board_info(void)
{
char info[64];
snprintf(info, ARRAY_SIZE(info), "%u.%u", (s5p_cpu_rev & 0xf0) >> 4,
s5p_cpu_rev & 0xf);
setenv("soc_rev", info);
snprintf(info, ARRAY_SIZE(info), "%x", s5p_cpu_id);
setenv("soc_id", info);
#ifdef CONFIG_REVISION_TAG
snprintf(info, ARRAY_SIZE(info), "%x", get_board_rev());
setenv("board_rev", info);
#endif
#ifdef CONFIG_OF_LIBFDT
const char *bdtype = "";
const char *bdname = CONFIG_SYS_BOARD;
#ifdef CONFIG_BOARD_TYPES
bdtype = get_board_type();
sprintf(info, "%s%s", bdname, bdtype);
setenv("boardname", info);
#endif
snprintf(info, ARRAY_SIZE(info), "%s%x-%s%s.dtb",
CONFIG_SYS_SOC, s5p_cpu_id, bdname, bdtype);
setenv("fdtfile", info);
#endif
}
#endif /* CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG */
#ifdef CONFIG_LCD_MENU
static int power_key_pressed(u32 reg)
{
struct pmic *pmic;
u32 status;
u32 mask;
pmic = pmic_get(KEY_PWR_PMIC_NAME);
if (!pmic) {
printf("%s: Not found\n", KEY_PWR_PMIC_NAME);
return 0;
}
if (pmic_probe(pmic))
return 0;
if (reg == KEY_PWR_STATUS_REG)
mask = KEY_PWR_STATUS_MASK;
else
mask = KEY_PWR_INTERRUPT_MASK;
if (pmic_reg_read(pmic, reg, &status))
return 0;
return !!(status & mask);
}
static int key_pressed(int key)
{
int value;
switch (key) {
case KEY_POWER:
value = power_key_pressed(KEY_PWR_INTERRUPT_REG);
break;
case KEY_VOLUMEUP:
value = !gpio_get_value(KEY_VOL_UP_GPIO);
break;
case KEY_VOLUMEDOWN:
value = !gpio_get_value(KEY_VOL_DOWN_GPIO);
break;
default:
value = 0;
break;
}
return value;
}
static int check_keys(void)
{
int keys = 0;
if (key_pressed(KEY_POWER))
keys += KEY_POWER;
if (key_pressed(KEY_VOLUMEUP))
keys += KEY_VOLUMEUP;
if (key_pressed(KEY_VOLUMEDOWN))
keys += KEY_VOLUMEDOWN;
return keys;
}
/*
* 0 BOOT_MODE_INFO
* 1 BOOT_MODE_THOR
* 2 BOOT_MODE_UMS
* 3 BOOT_MODE_DFU
* 4 BOOT_MODE_EXIT
*/
static char *
mode_name[BOOT_MODE_EXIT + 1][2] = {
{"DEVICE", ""},
{"THOR", "thor"},
{"UMS", "ums"},
{"DFU", "dfu"},
{"GPT", "gpt"},
{"ENV", "env"},
{"EXIT", ""},
};
static char *
mode_info[BOOT_MODE_EXIT + 1] = {
"info",
"downloader",
"mass storage",
"firmware update",
"restore",
"default",
"and run normal boot"
};
static char *
mode_cmd[BOOT_MODE_EXIT + 1] = {
"",
"thor 0 mmc 0",
"ums 0 mmc 0",
"dfu 0 mmc 0",
"gpt write mmc 0 $partitions",
"env default -a; saveenv",
"",
};
static void display_board_info(void)
{
#ifdef CONFIG_GENERIC_MMC
struct mmc *mmc = find_mmc_device(0);
#endif
vidinfo_t *vid = &panel_info;
lcd_position_cursor(4, 4);
lcd_printf("%s\n\t", U_BOOT_VERSION);
lcd_puts("\n\t\tBoard Info:\n");
#ifdef CONFIG_SYS_BOARD
lcd_printf("\tBoard name: %s\n", CONFIG_SYS_BOARD);
#endif
#ifdef CONFIG_REVISION_TAG
lcd_printf("\tBoard rev: %u\n", get_board_rev());
#endif
lcd_printf("\tDRAM banks: %u\n", CONFIG_NR_DRAM_BANKS);
lcd_printf("\tDRAM size: %u MB\n", gd->ram_size / SZ_1M);
#ifdef CONFIG_GENERIC_MMC
if (mmc) {
if (!mmc->capacity)
mmc_init(mmc);
lcd_printf("\teMMC size: %llu MB\n", mmc->capacity / SZ_1M);
}
#endif
if (vid)
lcd_printf("\tDisplay resolution: %u x % u\n",
vid->vl_col, vid->vl_row);
lcd_printf("\tDisplay BPP: %u\n", 1 << vid->vl_bpix);
}
static int mode_leave_menu(int mode)
{
char *exit_option;
char *exit_reset = "reset";
char *exit_back = "back";
cmd_tbl_t *cmd;
int cmd_result;
int leave;
lcd_clear();
switch (mode) {
case BOOT_MODE_EXIT:
return 1;
case BOOT_MODE_INFO:
display_board_info();
exit_option = exit_back;
leave = 0;
break;
default:
cmd = find_cmd(mode_name[mode][1]);
if (cmd) {
printf("Enter: %s %s\n", mode_name[mode][0],
mode_info[mode]);
lcd_printf("\n\n\t%s %s\n", mode_name[mode][0],
mode_info[mode]);
lcd_puts("\n\tDo not turn off device before finish!\n");
cmd_result = run_command(mode_cmd[mode], 0);
if (cmd_result == CMD_RET_SUCCESS) {
printf("Command finished\n");
lcd_clear();
lcd_printf("\n\n\t%s finished\n",
mode_name[mode][0]);
exit_option = exit_reset;
leave = 1;
} else {
printf("Command error\n");
lcd_clear();
lcd_printf("\n\n\t%s command error\n",
mode_name[mode][0]);
exit_option = exit_back;
leave = 0;
}
} else {
lcd_puts("\n\n\tThis mode is not supported.\n");
exit_option = exit_back;
leave = 0;
}
}
lcd_printf("\n\n\tPress POWER KEY to %s\n", exit_option);
/* Clear PWR button Rising edge interrupt status flag */
power_key_pressed(KEY_PWR_INTERRUPT_REG);
/* Wait for PWR key */
while (!key_pressed(KEY_POWER))
mdelay(1);
lcd_clear();
return leave;
}
static void display_download_menu(int mode)
{
char *selection[BOOT_MODE_EXIT + 1];
int i;
for (i = 0; i <= BOOT_MODE_EXIT; i++)
selection[i] = "[ ]";
selection[mode] = "[=>]";
lcd_clear();
lcd_printf("\n\n\t\tDownload Mode Menu\n\n");
for (i = 0; i <= BOOT_MODE_EXIT; i++)
lcd_printf("\t%s %s - %s\n\n", selection[i],
mode_name[i][0],
mode_info[i]);
}
static void download_menu(void)
{
int mode = 0;
int last_mode = 0;
int run;
int key = 0;
int timeout = 15; /* sec */
int i;
display_download_menu(mode);
lcd_puts("\n");
/* Start count if no key is pressed */
while (check_keys())
continue;
while (timeout--) {
lcd_printf("\r\tNormal boot will start in: %2.d seconds.",
timeout);
/* about 1000 ms in for loop */
for (i = 0; i < 10; i++) {
mdelay(100);
key = check_keys();
if (key)
break;
}
if (key)
break;
}
if (!key) {
lcd_clear();
return;
}
while (1) {
run = 0;
if (mode != last_mode)
display_download_menu(mode);
last_mode = mode;
mdelay(200);
key = check_keys();
switch (key) {
case KEY_POWER:
run = 1;
break;
case KEY_VOLUMEUP:
if (mode > 0)
mode--;
break;
case KEY_VOLUMEDOWN:
if (mode < BOOT_MODE_EXIT)
mode++;
break;
default:
break;
}
if (run) {
if (mode_leave_menu(mode))
run_command("reset", 0);
display_download_menu(mode);
}
}
lcd_clear();
}
void check_boot_mode(void)
{
int pwr_key;
pwr_key = power_key_pressed(KEY_PWR_STATUS_REG);
if (!pwr_key)
return;
/* Clear PWR button Rising edge interrupt status flag */
power_key_pressed(KEY_PWR_INTERRUPT_REG);
if (key_pressed(KEY_VOLUMEUP))
download_menu();
else if (key_pressed(KEY_VOLUMEDOWN))
mode_leave_menu(BOOT_MODE_THOR);
}
void keys_init(void)
{
/* Set direction to input */
gpio_request(KEY_VOL_UP_GPIO, "volume-up");
gpio_request(KEY_VOL_DOWN_GPIO, "volume-down");
gpio_direction_input(KEY_VOL_UP_GPIO);
gpio_direction_input(KEY_VOL_DOWN_GPIO);
}
#endif /* CONFIG_LCD_MENU */
#ifdef CONFIG_CMD_BMP
void draw_logo(void)
{
int x, y;
ulong addr;
addr = panel_info.logo_addr;
if (!addr) {
error("There is no logo data.");
return;
}
if (panel_info.vl_width >= panel_info.logo_width) {
x = ((panel_info.vl_width - panel_info.logo_width) >> 1);
x += panel_info.logo_x_offset; /* For X center align */
} else {
x = 0;
printf("Warning: image width is bigger than display width\n");
}
if (panel_info.vl_height >= panel_info.logo_height) {
y = ((panel_info.vl_height - panel_info.logo_height) >> 1);
y += panel_info.logo_y_offset; /* For Y center align */
} else {
y = 0;
printf("Warning: image height is bigger than display height\n");
}
bmp_display(addr, x, y);
}
#endif /* CONFIG_CMD_BMP */