GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
# SPDX-License-Identifier: GPL-2.0+
|
||||
#
|
||||
# Copyright (C) 2012 Samsung Electronics
|
||||
# Lukasz Majewski <l.majewski@samsung.com>
|
||||
|
||||
obj-$(CONFIG_USB_GADGET_DOWNLOAD) += gadget.o
|
||||
obj-$(CONFIG_MISC_COMMON) += misc.o
|
||||
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
obj-$(CONFIG_BOARD_COMMON) += board.o
|
||||
ifdef CONFIG_EXYNOS5_DT
|
||||
obj-y += exynos5-dt.o
|
||||
obj-$(CONFIG_BOARD_TYPES) += exynos5-dt-types.o
|
||||
endif
|
||||
endif
|
||||
@@ -0,0 +1,361 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2013 SAMSUNG Electronics
|
||||
* Rajeshwari Shinde <rajeshwari.s@samsung.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <cros_ec.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
#include <init.h>
|
||||
#include <spi.h>
|
||||
#include <tmu.h>
|
||||
#include <netdev.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/arch/board.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/dwmmc.h>
|
||||
#include <asm/arch/mmc.h>
|
||||
#include <asm/arch/pinmux.h>
|
||||
#include <asm/arch/power.h>
|
||||
#include <asm/arch/system.h>
|
||||
#include <asm/arch/sromc.h>
|
||||
#include <lcd.h>
|
||||
#include <i2c.h>
|
||||
#include <usb.h>
|
||||
#include <dwc3-uboot.h>
|
||||
#include <samsung/misc.h>
|
||||
#include <dm/pinctrl.h>
|
||||
#include <dm.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
__weak int exynos_early_init_f(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
__weak int exynos_power_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined CONFIG_EXYNOS_TMU
|
||||
/* Boot Time Thermal Analysis for SoC temperature threshold breach */
|
||||
static void boot_temp_check(void)
|
||||
{
|
||||
int temp;
|
||||
|
||||
switch (tmu_monitor(&temp)) {
|
||||
case TMU_STATUS_NORMAL:
|
||||
break;
|
||||
case TMU_STATUS_TRIPPED:
|
||||
/*
|
||||
* Status TRIPPED ans WARNING means corresponding threshold
|
||||
* breach
|
||||
*/
|
||||
puts("EXYNOS_TMU: TRIPPING! Device power going down ...\n");
|
||||
set_ps_hold_ctrl();
|
||||
hang();
|
||||
break;
|
||||
case TMU_STATUS_WARNING:
|
||||
puts("EXYNOS_TMU: WARNING! Temperature very high\n");
|
||||
break;
|
||||
case TMU_STATUS_INIT:
|
||||
/*
|
||||
* TMU_STATUS_INIT means something is wrong with temperature
|
||||
* sensing and TMU status was changed back from NORMAL to INIT.
|
||||
*/
|
||||
puts("EXYNOS_TMU: WARNING! Temperature sensing not done\n");
|
||||
break;
|
||||
default:
|
||||
debug("EXYNOS_TMU: Unknown TMU state\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int board_init(void)
|
||||
{
|
||||
gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL);
|
||||
#if defined CONFIG_EXYNOS_TMU
|
||||
if (tmu_init(gd->fdt_blob) != TMU_STATUS_NORMAL) {
|
||||
debug("%s: Failed to init TMU\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
boot_temp_check();
|
||||
#endif
|
||||
#ifdef CONFIG_TZSW_RESERVED_DRAM_SIZE
|
||||
/* The last few MB of memory can be reserved for secure firmware */
|
||||
ulong size = CONFIG_TZSW_RESERVED_DRAM_SIZE;
|
||||
|
||||
gd->ram_size -= size;
|
||||
gd->bd->bi_dram[CONFIG_NR_DRAM_BANKS - 1].size -= size;
|
||||
#endif
|
||||
return exynos_init();
|
||||
}
|
||||
|
||||
int dram_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned long addr;
|
||||
|
||||
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
|
||||
addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE);
|
||||
gd->ram_size += get_ram_size((long *)addr, SDRAM_BANK_SIZE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dram_init_banksize(void)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned long addr, size;
|
||||
|
||||
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
|
||||
addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE);
|
||||
size = get_ram_size((long *)addr, SDRAM_BANK_SIZE);
|
||||
|
||||
gd->bd->bi_dram[i].start = addr;
|
||||
gd->bd->bi_dram[i].size = size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int board_uart_init(void)
|
||||
{
|
||||
#ifndef CONFIG_PINCTRL_EXYNOS
|
||||
int err, uart_id, ret = 0;
|
||||
|
||||
for (uart_id = PERIPH_ID_UART0; uart_id <= PERIPH_ID_UART3; uart_id++) {
|
||||
err = exynos_pinmux_config(uart_id, PINMUX_FLAG_NONE);
|
||||
if (err) {
|
||||
debug("UART%d not configured\n",
|
||||
(uart_id - PERIPH_ID_UART0));
|
||||
ret |= err;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BOARD_EARLY_INIT_F
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
int err;
|
||||
#ifdef CONFIG_BOARD_TYPES
|
||||
set_board_type();
|
||||
#endif
|
||||
err = board_uart_init();
|
||||
if (err) {
|
||||
debug("UART init failed\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_I2C_INIT_BOARD
|
||||
board_i2c_init(gd->fdt_blob);
|
||||
#endif
|
||||
|
||||
return exynos_early_init_f();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_POWER) || defined(CONFIG_DM_PMIC)
|
||||
int power_init_board(void)
|
||||
{
|
||||
set_ps_hold_ctrl();
|
||||
|
||||
return exynos_power_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMC911X
|
||||
static int decode_sromc(const void *blob, struct fdt_sromc *config)
|
||||
{
|
||||
int err;
|
||||
int node;
|
||||
|
||||
node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_SROMC);
|
||||
if (node < 0) {
|
||||
debug("Could not find SROMC node\n");
|
||||
return node;
|
||||
}
|
||||
|
||||
config->bank = fdtdec_get_int(blob, node, "bank", 0);
|
||||
config->width = fdtdec_get_int(blob, node, "width", 2);
|
||||
|
||||
err = fdtdec_get_int_array(blob, node, "srom-timing", config->timing,
|
||||
FDT_SROM_TIMING_COUNT);
|
||||
if (err < 0) {
|
||||
debug("Could not decode SROMC configuration Error: %s\n",
|
||||
fdt_strerror(err));
|
||||
return -FDT_ERR_NOTFOUND;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int board_eth_init(bd_t *bis)
|
||||
{
|
||||
#ifdef CONFIG_SMC911X
|
||||
u32 smc_bw_conf, smc_bc_conf;
|
||||
struct fdt_sromc config;
|
||||
fdt_addr_t base_addr;
|
||||
int node;
|
||||
|
||||
node = decode_sromc(gd->fdt_blob, &config);
|
||||
if (node < 0) {
|
||||
debug("%s: Could not find sromc configuration\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
node = fdtdec_next_compatible(gd->fdt_blob, node, COMPAT_SMSC_LAN9215);
|
||||
if (node < 0) {
|
||||
debug("%s: Could not find lan9215 configuration\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We now have a node, so any problems from now on are errors */
|
||||
base_addr = fdtdec_get_addr(gd->fdt_blob, node, "reg");
|
||||
if (base_addr == FDT_ADDR_T_NONE) {
|
||||
debug("%s: Could not find lan9215 address\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Ethernet needs data bus width of 16 bits */
|
||||
if (config.width != 2) {
|
||||
debug("%s: Unsupported bus width %d\n", __func__,
|
||||
config.width);
|
||||
return -1;
|
||||
}
|
||||
smc_bw_conf = SROMC_DATA16_WIDTH(config.bank)
|
||||
| SROMC_BYTE_ENABLE(config.bank);
|
||||
|
||||
smc_bc_conf = SROMC_BC_TACS(config.timing[FDT_SROM_TACS]) |
|
||||
SROMC_BC_TCOS(config.timing[FDT_SROM_TCOS]) |
|
||||
SROMC_BC_TACC(config.timing[FDT_SROM_TACC]) |
|
||||
SROMC_BC_TCOH(config.timing[FDT_SROM_TCOH]) |
|
||||
SROMC_BC_TAH(config.timing[FDT_SROM_TAH]) |
|
||||
SROMC_BC_TACP(config.timing[FDT_SROM_TACP]) |
|
||||
SROMC_BC_PMC(config.timing[FDT_SROM_PMC]);
|
||||
|
||||
/* Select and configure the SROMC bank */
|
||||
exynos_pinmux_config(PERIPH_ID_SROMC, config.bank);
|
||||
s5p_config_sromc(config.bank, smc_bw_conf, smc_bc_conf);
|
||||
return smc911x_initialize(0, base_addr);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DISPLAY_BOARDINFO) || defined(CONFIG_DISPLAY_BOARDINFO_LATE)
|
||||
int checkboard(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_BOARD_TYPES)) {
|
||||
const char *board_info;
|
||||
|
||||
if (IS_ENABLED(CONFIG_DISPLAY_BOARDINFO_LATE)) {
|
||||
/*
|
||||
* Printing type requires having revision, although
|
||||
* this will succeed only if done late.
|
||||
* Otherwise revision will be set in misc_init_r().
|
||||
*/
|
||||
set_board_revision();
|
||||
}
|
||||
|
||||
board_info = get_board_type();
|
||||
|
||||
if (board_info)
|
||||
printf("Type: %s\n", board_info);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BOARD_LATE_INIT
|
||||
int board_late_init(void)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
stdio_print_current_devices();
|
||||
ret = uclass_first_device_err(UCLASS_CROS_EC, &dev);
|
||||
if (ret && ret != -ENODEV) {
|
||||
/* Force console on */
|
||||
gd->flags &= ~GD_FLG_SILENT;
|
||||
|
||||
printf("cros-ec communications failure %d\n", ret);
|
||||
puts("\nPlease reset with Power+Refresh\n\n");
|
||||
panic("Cannot init cros-ec device");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MISC_INIT_R
|
||||
int misc_init_r(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_BOARD_TYPES) &&
|
||||
!IS_ENABLED(CONFIG_DISPLAY_BOARDINFO_LATE)) {
|
||||
/*
|
||||
* If revision was not set by late display boardinfo,
|
||||
* set it here. At this point regulators should be already
|
||||
* available.
|
||||
*/
|
||||
set_board_revision();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
|
||||
set_board_info();
|
||||
#endif
|
||||
#ifdef CONFIG_LCD_MENU
|
||||
keys_init();
|
||||
check_boot_mode();
|
||||
#endif
|
||||
#ifdef CONFIG_CMD_BMP
|
||||
if (panel_info.logo_on)
|
||||
draw_logo();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void reset_misc(void)
|
||||
{
|
||||
struct gpio_desc gpio = {};
|
||||
int node;
|
||||
|
||||
node = fdt_node_offset_by_compatible(gd->fdt_blob, 0,
|
||||
"samsung,emmc-reset");
|
||||
if (node < 0)
|
||||
return;
|
||||
|
||||
gpio_request_by_name_nodev(offset_to_ofnode(node), "reset-gpio", 0,
|
||||
&gpio, GPIOD_IS_OUT);
|
||||
|
||||
if (dm_gpio_is_valid(&gpio)) {
|
||||
/*
|
||||
* Reset eMMC
|
||||
*
|
||||
* FIXME: Need to optimize delay time. Minimum 1usec pulse is
|
||||
* required by 'JEDEC Standard No.84-A441' (eMMC)
|
||||
* document but real delay time is expected to greater
|
||||
* than 1usec.
|
||||
*/
|
||||
dm_gpio_set_value(&gpio, 0);
|
||||
mdelay(10);
|
||||
dm_gpio_set_value(&gpio, 1);
|
||||
}
|
||||
}
|
||||
|
||||
int board_usb_cleanup(int index, enum usb_init_type init)
|
||||
{
|
||||
#ifdef CONFIG_USB_DWC3
|
||||
dwc3_uboot_exit(index);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
# This is an example file to generate boot.scr - a boot script for U-Boot
|
||||
# Generate boot.scr:
|
||||
# ./tools/mkimage -c none -A arm -T script -d autoboot.cmd boot.scr
|
||||
#
|
||||
# It requires a list of environment variables to be defined before load:
|
||||
# platform dependent: board_name, fdtfile, console
|
||||
# system dependent: mmcbootdev, mmcbootpart, mmcrootdev, mmcrootpart, rootfstype
|
||||
#
|
||||
setenv fdtaddr "40800000"
|
||||
setenv initrdname "uInitrd"
|
||||
setenv initrdaddr "42000000"
|
||||
setenv loaddtb "load mmc ${mmcbootdev}:${mmcbootpart} ${fdtaddr} ${fdtfile}"
|
||||
setenv loadinitrd "load mmc ${mmcbootdev}:${mmcbootpart} ${initrdaddr} ${initrdname}"
|
||||
setenv loadkernel "load mmc ${mmcbootdev}:${mmcbootpart} '${kerneladdr}' '${kernelname}'"
|
||||
setenv kernel_args "setenv bootargs ${console} root=/dev/mmcblk${mmcrootdev}p${mmcrootpart} rootfstype=${rootfstype} rootwait ${opts}"
|
||||
|
||||
#### Routine: check_dtb - check that target.dtb exists on boot partition
|
||||
setenv check_dtb "
|
||||
if test -e mmc '${mmcbootdev}':'${mmcbootpart}' '${fdtfile}'; then
|
||||
run loaddtb;
|
||||
setenv fdt_addr ${fdtaddr};
|
||||
else
|
||||
echo Warning! Booting without DTB: '${fdtfile}'!;
|
||||
setenv fdt_addr;
|
||||
fi;"
|
||||
|
||||
#### Routine: check_ramdisk - check that uInitrd exists on boot partition
|
||||
setenv check_ramdisk "
|
||||
if test -e mmc '${mmcbootdev}':'${mmcbootpart}' '${initrdname}'; then
|
||||
echo "Found ramdisk image.";
|
||||
run loadinitrd;
|
||||
setenv initrd_addr ${initrdaddr};
|
||||
else
|
||||
echo Warning! Booting without RAMDISK: '${initrdname}'!;
|
||||
setenv initrd_addr -;
|
||||
fi;"
|
||||
|
||||
#### Routine: boot_fit - check that env $board_name is set and boot proper config of ITB image
|
||||
setenv setboot_fit "
|
||||
if test -e '${board_name}'; then
|
||||
setenv fdt_addr ;
|
||||
setenv initrd_addr ;
|
||||
setenv kerneladdr 0x42000000;
|
||||
setenv kernelname Image.itb;
|
||||
setenv itbcfg "\"#${board_name}\"";
|
||||
setenv imgbootcmd bootm;
|
||||
else
|
||||
echo Warning! Variable: \$board_name is undefined!;
|
||||
fi"
|
||||
|
||||
#### Routine: setboot_uimg - prepare env to boot uImage
|
||||
setenv setboot_uimg "
|
||||
setenv kerneladdr 0x40007FC0;
|
||||
setenv kernelname uImage;
|
||||
setenv itbcfg ;
|
||||
setenv imgbootcmd bootm;
|
||||
run check_dtb;
|
||||
run check_ramdisk;"
|
||||
|
||||
#### Routine: setboot_zimg - prepare env to boot zImage
|
||||
setenv setboot_zimg "
|
||||
setenv kerneladdr 0x40007FC0;
|
||||
setenv kernelname zImage;
|
||||
setenv itbcfg ;
|
||||
setenv imgbootcmd bootz;
|
||||
run check_dtb;
|
||||
run check_ramdisk;"
|
||||
|
||||
#### Routine: boot_img - boot the kernel after env setup
|
||||
setenv boot_img "
|
||||
run loadkernel;
|
||||
run kernel_args;
|
||||
'${imgbootcmd}' '${kerneladdr}${itbcfg}' '${initrd_addr}' '${fdt_addr}';"
|
||||
|
||||
#### Routine: autoboot - choose proper boot path
|
||||
setenv autoboot "
|
||||
if test -e mmc ${mmcbootdev}:${mmcbootpart} Image.itb; then
|
||||
echo Found kernel image: Image.itb;
|
||||
run setboot_fit;
|
||||
run boot_img;
|
||||
elif test -e mmc ${mmcbootdev}:${mmcbootpart} zImage; then
|
||||
echo Found kernel image: zImage;
|
||||
run setboot_zimg;
|
||||
run boot_img;
|
||||
elif test -e mmc ${mmcbootdev}:${mmcbootpart} uImage; then
|
||||
echo Found kernel image: uImage;
|
||||
run setboot_uimg;
|
||||
run boot_img;
|
||||
fi;"
|
||||
|
||||
#### Execute the defined autoboot macro
|
||||
run autoboot
|
||||
@@ -0,0 +1,10 @@
|
||||
setenv kernelname zImage;
|
||||
setenv boot_kernel "setenv bootargs \"${console} root=/dev/mmcblk${mmcrootdev}p${mmcrootpart} rootfstype=${rootfstype} rootwait ${opts}\";
|
||||
load mmc ${mmcbootdev}:${mmcbootpart} 0x40007FC0 '${kernelname}';
|
||||
if load mmc ${mmcbootdev}:${mmcbootpart} 40800000 ${fdtfile}; then
|
||||
bootz 0x40007FC0 - 40800000;
|
||||
else
|
||||
echo Warning! Booting without DTB: '${fdtfile}'!;
|
||||
bootz 0x40007FC0 -;
|
||||
fi;"
|
||||
run boot_kernel;
|
||||
@@ -0,0 +1,9 @@
|
||||
mmcboot=setenv bootargs root=/dev/mmcblk${mmcdev}p${mmcrootpart} ${rootfstype} rootwait ${console}; run loaduimage; bootm 0x40007FC0
|
||||
rootfstype=ext4
|
||||
loaduimage=ext4load mmc ${mmcdev}:${mmcbootpart} 0x40007FC0 uImage
|
||||
mmcdev=0
|
||||
mmcbootpart=2
|
||||
mmcrootpart=5
|
||||
console=console=ttySAC2,115200n8
|
||||
bootcmd=run mmcboot
|
||||
dfu_alt_info=u-boot mmc 80 800;params.bin mmc 0x38 0x8;uImage ext4 0 2
|
||||
@@ -0,0 +1,58 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
/*
|
||||
* (C) Copyright 2002
|
||||
* Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
|
||||
*
|
||||
* Copyright (C) 2012 Samsung Electronics
|
||||
*
|
||||
* Based on arch/arm/cpu/armv7/omap-common/u-boot-spl.lds
|
||||
*/
|
||||
|
||||
MEMORY { .sram : ORIGIN = IMAGE_TEXT_BASE, \
|
||||
LENGTH = CONFIG_SPL_MAX_FOOTPRINT }
|
||||
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
__start = .;
|
||||
*(.vectors)
|
||||
arch/arm/cpu/armv7/start.o (.text*)
|
||||
*(.text*)
|
||||
} >.sram
|
||||
. = ALIGN(4);
|
||||
|
||||
.rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
|
||||
. = ALIGN(4);
|
||||
|
||||
.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
|
||||
. = ALIGN(4);
|
||||
|
||||
.u_boot_list : {
|
||||
KEEP(*(SORT(.u_boot_list*)));
|
||||
} >.sram
|
||||
. = ALIGN(4);
|
||||
|
||||
.machine_param : { *(.machine_param) } >.sram
|
||||
. = ALIGN(4);
|
||||
|
||||
__image_copy_end = .;
|
||||
|
||||
.end :
|
||||
{
|
||||
*(.__end)
|
||||
} >.sram
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start = .;
|
||||
*(.bss*)
|
||||
. = ALIGN(4);
|
||||
__bss_end = .;
|
||||
} >.sram
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2015 Samsung Electronics
|
||||
* Przemyslaw Marczak <p.marczak@samsung.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <adc.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <fdtdec.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/regulator.h>
|
||||
#include <power/s2mps11.h>
|
||||
#include <samsung/exynos5-dt-types.h>
|
||||
#include <samsung/misc.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static const struct udevice_id board_ids[] = {
|
||||
{ .compatible = "samsung,odroidxu3", .data = EXYNOS5_BOARD_ODROID_XU3 },
|
||||
{ .compatible = "samsung,exynos5", .data = EXYNOS5_BOARD_GENERIC },
|
||||
{ },
|
||||
};
|
||||
|
||||
/**
|
||||
* Odroix XU3/XU4/HC1/HC2 board revisions (from HC1+_HC2_MAIN_REV0.1_20171017.pdf):
|
||||
* Rev ADCmax Board
|
||||
* 0.1 0 XU3 0.1
|
||||
* 0.2 372 XU3 0.2 | XU3L - no DISPLAYPORT (probe I2C0:0x40 / INA231)
|
||||
* 0.3 1280 XU4 0.1
|
||||
* 0.4 739 XU4 0.2
|
||||
* 0.5 1016 XU4+Air0.1 (Passive cooling)
|
||||
* 0.6 1309 XU4-HC1 0.1
|
||||
* 0.7 1470 XU4-HC1+ 0.1 (HC2)
|
||||
* Use +1% for ADC value tolerance in the array below, the code loops until
|
||||
* the measured ADC value is lower than then ADCmax from the array.
|
||||
*/
|
||||
struct odroid_rev_info odroid_info[] = {
|
||||
{ EXYNOS5_BOARD_ODROID_XU3_REV01, 1, 10, "xu3" },
|
||||
{ EXYNOS5_BOARD_ODROID_XU3_REV02, 2, 375, "xu3" },
|
||||
{ EXYNOS5_BOARD_ODROID_XU4_REV01, 1, 1293, "xu4" },
|
||||
{ EXYNOS5_BOARD_ODROID_HC1_REV01, 1, 1322, "hc1" },
|
||||
{ EXYNOS5_BOARD_ODROID_HC2_REV01, 1, 1484, "hc1" },
|
||||
{ EXYNOS5_BOARD_ODROID_UNKNOWN, 0, 4095, "unknown" },
|
||||
};
|
||||
|
||||
static unsigned int odroid_get_rev(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(odroid_info); i++) {
|
||||
if (odroid_info[i].board_type == gd->board_type)
|
||||
return odroid_info[i].board_rev;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read ADC at least twice and check the resuls. If regulator providing voltage
|
||||
* on to measured point was just turned on, first reads might require time
|
||||
* to stabilize.
|
||||
*/
|
||||
static int odroid_get_adc_val(unsigned int *adcval)
|
||||
{
|
||||
unsigned int adcval_prev = 0;
|
||||
int ret, retries = 20;
|
||||
|
||||
ret = adc_channel_single_shot("adc", CONFIG_ODROID_REV_AIN,
|
||||
&adcval_prev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
while (retries--) {
|
||||
mdelay(5);
|
||||
|
||||
ret = adc_channel_single_shot("adc", CONFIG_ODROID_REV_AIN,
|
||||
adcval);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* If difference between ADC reads is less than 3%,
|
||||
* accept the result
|
||||
*/
|
||||
if ((100 * abs(*adcval - adcval_prev) / adcval_prev) < 3)
|
||||
return ret;
|
||||
|
||||
adcval_prev = *adcval;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int odroid_get_board_type(void)
|
||||
{
|
||||
unsigned int adcval;
|
||||
int ret, i;
|
||||
|
||||
ret = odroid_get_adc_val(&adcval);
|
||||
if (ret)
|
||||
goto rev_default;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(odroid_info); i++) {
|
||||
/* ADC tolerance: +1% */
|
||||
if (adcval < odroid_info[i].adc_val)
|
||||
return odroid_info[i].board_type;
|
||||
}
|
||||
|
||||
rev_default:
|
||||
return EXYNOS5_BOARD_ODROID_XU3;
|
||||
}
|
||||
|
||||
/**
|
||||
* odroid_get_type_str - returns pointer to one of the board type string.
|
||||
* Board types: "xu3", "xu3-lite", "xu4". However the "xu3lite" can be
|
||||
* detected only when the i2c controller is ready to use. Fortunately,
|
||||
* XU3 and XU3L are compatible, and the information about board lite
|
||||
* revision is needed before booting the linux, to set proper environment
|
||||
* variable: $fdtfile.
|
||||
*/
|
||||
static const char *odroid_get_type_str(void)
|
||||
{
|
||||
const char *type_xu3l = "xu3-lite";
|
||||
struct udevice *dev, *chip;
|
||||
int i, ret;
|
||||
|
||||
if (gd->board_type != EXYNOS5_BOARD_ODROID_XU3_REV02)
|
||||
goto exit;
|
||||
|
||||
ret = pmic_get("s2mps11", &dev);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
/* Enable LDO26: 3.0V */
|
||||
ret = pmic_reg_write(dev, S2MPS11_REG_L26CTRL,
|
||||
S2MPS11_LDO26_ENABLE);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
/* Check XU3Lite by probe INA231 I2C0:0x40 */
|
||||
ret = uclass_get_device(UCLASS_I2C, 0, &dev);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
ret = dm_i2c_probe(dev, 0x40, 0x0, &chip);
|
||||
if (ret)
|
||||
return type_xu3l;
|
||||
|
||||
exit:
|
||||
for (i = 0; i < ARRAY_SIZE(odroid_info); i++) {
|
||||
if (odroid_info[i].board_type == gd->board_type)
|
||||
return odroid_info[i].name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool board_is_odroidxu3(void)
|
||||
{
|
||||
if (gd->board_type >= EXYNOS5_BOARD_ODROID_XU3 &&
|
||||
gd->board_type <= EXYNOS5_BOARD_ODROID_XU3_REV02)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool board_is_odroidxu4(void)
|
||||
{
|
||||
if (gd->board_type == EXYNOS5_BOARD_ODROID_XU4_REV01)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool board_is_odroidhc1(void)
|
||||
{
|
||||
if (gd->board_type == EXYNOS5_BOARD_ODROID_HC1_REV01)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool board_is_odroidhc2(void)
|
||||
{
|
||||
if (gd->board_type == EXYNOS5_BOARD_ODROID_HC2_REV01)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool board_is_generic(void)
|
||||
{
|
||||
if (gd->board_type == EXYNOS5_BOARD_GENERIC)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_board_rev() - return detected board revision.
|
||||
*
|
||||
* @return: return board revision number for XU3 or 0 for generic
|
||||
*/
|
||||
u32 get_board_rev(void)
|
||||
{
|
||||
if (board_is_generic())
|
||||
return 0;
|
||||
|
||||
return odroid_get_rev();
|
||||
}
|
||||
|
||||
/**
|
||||
* get_board_type() - returns board type string.
|
||||
*
|
||||
* @return: return board type string for XU3 or empty string for generic
|
||||
*/
|
||||
const char *get_board_type(void)
|
||||
{
|
||||
const char *generic = "";
|
||||
|
||||
if (board_is_generic())
|
||||
return generic;
|
||||
|
||||
return odroid_get_type_str();
|
||||
}
|
||||
|
||||
/**
|
||||
* set_board_type() - set board type in gd->board_type.
|
||||
* As default type set EXYNOS5_BOARD_GENERIC. If Odroid is detected,
|
||||
* set its proper type based on device tree.
|
||||
*
|
||||
* This might be called early when some more specific ways to detect revision
|
||||
* are not yet available.
|
||||
*/
|
||||
void set_board_type(void)
|
||||
{
|
||||
const struct udevice_id *of_match = board_ids;
|
||||
int ret;
|
||||
|
||||
gd->board_type = EXYNOS5_BOARD_GENERIC;
|
||||
|
||||
while (of_match->compatible) {
|
||||
ret = fdt_node_check_compatible(gd->fdt_blob, 0,
|
||||
of_match->compatible);
|
||||
if (ret)
|
||||
of_match++;
|
||||
|
||||
gd->board_type = of_match->data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set_board_revision() - set detailed board type in gd->board_type.
|
||||
* Should be called when resources (e.g. regulators) are available
|
||||
* so ADC can be used to detect the specific revision of a board.
|
||||
*/
|
||||
void set_board_revision(void)
|
||||
{
|
||||
if (board_is_odroidxu3())
|
||||
gd->board_type = odroid_get_board_type();
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2012 Samsung Electronics
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <dwc3-uboot.h>
|
||||
#include <env.h>
|
||||
#include <fdtdec.h>
|
||||
#include <asm/io.h>
|
||||
#include <errno.h>
|
||||
#include <i2c.h>
|
||||
#include <mmc.h>
|
||||
#include <netdev.h>
|
||||
#include <samsung-usb-phy-uboot.h>
|
||||
#include <spi.h>
|
||||
#include <usb.h>
|
||||
#include <video_bridge.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/arch/dwmmc.h>
|
||||
#include <asm/arch/mmc.h>
|
||||
#include <asm/arch/pinmux.h>
|
||||
#include <asm/arch/power.h>
|
||||
#include <asm/arch/sromc.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/max77686_pmic.h>
|
||||
#include <power/regulator.h>
|
||||
#include <power/s2mps11.h>
|
||||
#include <power/s5m8767.h>
|
||||
#include <samsung/exynos5-dt-types.h>
|
||||
#include <samsung/misc.h>
|
||||
#include <tmu.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
int exynos_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_set_regulator(const char *name, uint uv)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
ret = regulator_get_by_platname(name, &dev);
|
||||
if (ret) {
|
||||
debug("%s: Cannot find regulator %s\n", __func__, name);
|
||||
return ret;
|
||||
}
|
||||
ret = regulator_set_value(dev, uv);
|
||||
if (ret) {
|
||||
debug("%s: Cannot set regulator %s\n", __func__, name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int exynos_power_init(void)
|
||||
{
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_PMIC_S2MPS11
|
||||
ret = pmic_get("s2mps11_pmic", &dev);
|
||||
#else
|
||||
ret = pmic_get("max77686", &dev);
|
||||
if (!ret) {
|
||||
/* TODO(sjg@chromium.org): Move into the clock/pmic API */
|
||||
ret = pmic_clrsetbits(dev, MAX77686_REG_PMIC_32KHZ, 0,
|
||||
MAX77686_32KHCP_EN);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = pmic_clrsetbits(dev, MAX77686_REG_PMIC_BBAT, 0,
|
||||
MAX77686_BBCHOSTEN | MAX77686_BBCVS_3_5V);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
ret = pmic_get("s5m8767-pmic", &dev);
|
||||
/* TODO(sjg@chromium.org): Use driver model to access clock */
|
||||
#ifdef CONFIG_PMIC_S5M8767
|
||||
if (!ret)
|
||||
s5m8767_enable_32khz_cp(dev);
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_PMIC_S2MPS11 */
|
||||
if (ret == -ENODEV)
|
||||
return 0;
|
||||
|
||||
ret = regulators_enable_boot_on(false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = exynos_set_regulator("vdd_mif", 1100000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = exynos_set_regulator("vdd_arm", 1300000);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = exynos_set_regulator("vdd_int", 1012500);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = exynos_set_regulator("vdd_g3d", 1200000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_get_revision(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_DWC3
|
||||
static struct dwc3_device dwc3_device_data = {
|
||||
.maximum_speed = USB_SPEED_SUPER,
|
||||
.base = 0x12400000,
|
||||
.dr_mode = USB_DR_MODE_PERIPHERAL,
|
||||
.index = 0,
|
||||
};
|
||||
|
||||
int usb_gadget_handle_interrupts(void)
|
||||
{
|
||||
dwc3_uboot_handle_interrupt(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int board_usb_init(int index, enum usb_init_type init)
|
||||
{
|
||||
struct exynos_usb3_phy *phy = (struct exynos_usb3_phy *)
|
||||
samsung_get_base_usb3_phy();
|
||||
|
||||
if (!phy) {
|
||||
pr_err("usb3 phy not supported\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
set_usbdrd_phy_ctrl(POWER_USB_DRD_PHY_CTRL_EN);
|
||||
exynos5_usb3_phy_init(phy);
|
||||
|
||||
return dwc3_uboot_init(&dwc3_device_data);
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_SET_DFU_ALT_INFO
|
||||
char *get_dfu_alt_system(char *interface, char *devstr)
|
||||
{
|
||||
char *info = "Not supported!";
|
||||
|
||||
if (board_is_odroidxu4() || board_is_odroidhc1() || board_is_odroidhc2())
|
||||
return info;
|
||||
|
||||
return env_get("dfu_alt_system");
|
||||
}
|
||||
|
||||
char *get_dfu_alt_boot(char *interface, char *devstr)
|
||||
{
|
||||
char *info = "Not supported!";
|
||||
struct mmc *mmc;
|
||||
char *alt_boot;
|
||||
int dev_num;
|
||||
|
||||
if (board_is_odroidxu4() || board_is_odroidhc1() || board_is_odroidhc2())
|
||||
return info;
|
||||
|
||||
dev_num = simple_strtoul(devstr, NULL, 10);
|
||||
|
||||
mmc = find_mmc_device(dev_num);
|
||||
if (!mmc)
|
||||
return NULL;
|
||||
|
||||
if (mmc_init(mmc))
|
||||
return NULL;
|
||||
|
||||
if (IS_SD(mmc))
|
||||
alt_boot = CONFIG_DFU_ALT_BOOT_SD;
|
||||
else
|
||||
alt_boot = CONFIG_DFU_ALT_BOOT_EMMC;
|
||||
|
||||
return alt_boot;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2013 Samsung Electronics
|
||||
* Lukasz Majewski <l.majewski@samsung.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
|
||||
int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
|
||||
{
|
||||
if (!strcmp(name, "usb_dnl_thor")) {
|
||||
put_unaligned(CONFIG_G_DNL_THOR_VENDOR_NUM, &dev->idVendor);
|
||||
put_unaligned(CONFIG_G_DNL_THOR_PRODUCT_NUM, &dev->idProduct);
|
||||
} else if (!strcmp(name, "usb_dnl_ums")) {
|
||||
put_unaligned(CONFIG_G_DNL_UMS_VENDOR_NUM, &dev->idVendor);
|
||||
put_unaligned(CONFIG_G_DNL_UMS_PRODUCT_NUM, &dev->idProduct);
|
||||
} else {
|
||||
put_unaligned(CONFIG_USB_GADGET_VENDOR_NUM, &dev->idVendor);
|
||||
put_unaligned(CONFIG_USB_GADGET_PRODUCT_NUM, &dev->idProduct);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,483 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2013 Samsung Electronics
|
||||
* Przemyslaw Marczak <p.marczak@samsung.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <env.h>
|
||||
#include <lcd.h>
|
||||
#include <libtizen.h>
|
||||
#include <samsung/misc.h>
|
||||
#include <errno.h>
|
||||
#include <version.h>
|
||||
#include <malloc.h>
|
||||
#include <memalign.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <asm/arch/cpu.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <linux/input.h>
|
||||
#include <dm.h>
|
||||
/*
|
||||
* Use #ifdef to work around conflicting headers while we wait for this to be
|
||||
* converted to driver model.
|
||||
*/
|
||||
#ifdef CONFIG_DM_PMIC_MAX77686
|
||||
#include <power/max77686_pmic.h>
|
||||
#endif
|
||||
#ifdef CONFIG_DM_PMIC_MAX8998
|
||||
#include <power/max8998_pmic.h>
|
||||
#endif
|
||||
#ifdef CONFIG_PMIC_MAX8997
|
||||
#include <power/max8997_pmic.h>
|
||||
#endif
|
||||
#include <power/pmic.h>
|
||||
#include <mmc.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifdef CONFIG_SET_DFU_ALT_INFO
|
||||
void set_dfu_alt_info(char *interface, char *devstr)
|
||||
{
|
||||
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(interface, devstr);
|
||||
if (alt_setting) {
|
||||
env_set("dfu_alt_boot", alt_setting);
|
||||
offset = snprintf(buf, buf_size, "%s", alt_setting);
|
||||
}
|
||||
|
||||
alt_setting = get_dfu_alt_system(interface, devstr);
|
||||
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";
|
||||
}
|
||||
|
||||
env_set("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);
|
||||
env_set("soc_rev", info);
|
||||
|
||||
snprintf(info, ARRAY_SIZE(info), "%x", s5p_cpu_id);
|
||||
env_set("soc_id", info);
|
||||
|
||||
#ifdef CONFIG_REVISION_TAG
|
||||
snprintf(info, ARRAY_SIZE(info), "%x", get_board_rev());
|
||||
env_set("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();
|
||||
if (!bdtype)
|
||||
bdtype = "";
|
||||
|
||||
sprintf(info, "%s%s", bdname, bdtype);
|
||||
env_set("board_name", info);
|
||||
#endif
|
||||
snprintf(info, ARRAY_SIZE(info), "%s%x-%s%s.dtb",
|
||||
CONFIG_SYS_SOC, s5p_cpu_id, bdname, bdtype);
|
||||
env_set("fdtfile", info);
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG */
|
||||
|
||||
#ifdef CONFIG_LCD_MENU
|
||||
static int power_key_pressed(u32 reg)
|
||||
{
|
||||
#ifndef CONFIG_DM_I2C /* TODO(maintainer): Convert to driver model */
|
||||
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);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LCD
|
||||
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_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_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);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int mode_leave_menu(int mode)
|
||||
{
|
||||
#ifdef CONFIG_LCD
|
||||
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;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LCD
|
||||
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]);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void download_menu(void)
|
||||
{
|
||||
#ifdef CONFIG_LCD
|
||||
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();
|
||||
#endif
|
||||
}
|
||||
|
||||
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) {
|
||||
pr_err("There is no logo data.\n");
|
||||
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 */
|
||||
Reference in New Issue
Block a user