diff options
Diffstat (limited to 'roms/u-boot/board/samsung/common')
-rw-r--r-- | roms/u-boot/board/samsung/common/Makefile | 15 | ||||
-rw-r--r-- | roms/u-boot/board/samsung/common/board.c | 394 | ||||
-rw-r--r-- | roms/u-boot/board/samsung/common/bootscripts/autoboot.cmd | 92 | ||||
-rw-r--r-- | roms/u-boot/board/samsung/common/bootscripts/bootzimg.cmd | 10 | ||||
-rw-r--r-- | roms/u-boot/board/samsung/common/dfu_sample_env.txt | 9 | ||||
-rw-r--r-- | roms/u-boot/board/samsung/common/exynos-uboot-spl.lds | 58 | ||||
-rw-r--r-- | roms/u-boot/board/samsung/common/exynos5-dt-types.c | 266 | ||||
-rw-r--r-- | roms/u-boot/board/samsung/common/exynos5-dt.c | 188 | ||||
-rw-r--r-- | roms/u-boot/board/samsung/common/gadget.c | 23 | ||||
-rw-r--r-- | roms/u-boot/board/samsung/common/misc.c | 486 |
10 files changed, 1541 insertions, 0 deletions
diff --git a/roms/u-boot/board/samsung/common/Makefile b/roms/u-boot/board/samsung/common/Makefile new file mode 100644 index 000000000..3593c77cb --- /dev/null +++ b/roms/u-boot/board/samsung/common/Makefile @@ -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 diff --git a/roms/u-boot/board/samsung/common/board.c b/roms/u-boot/board/samsung/common/board.c new file mode 100644 index 000000000..104d2a657 --- /dev/null +++ b/roms/u-boot/board/samsung/common/board.c @@ -0,0 +1,394 @@ +// 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 <env.h> +#include <errno.h> +#include <fdtdec.h> +#include <hang.h> +#include <init.h> +#include <log.h> +#include <net.h> +#include <spi.h> +#include <tmu.h> +#include <netdev.h> +#include <asm/global_data.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 <mmc.h> +#include <stdio_dev.h> +#include <usb.h> +#include <dwc3-uboot.h> +#include <linux/delay.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; +} + +/** + * get_boot_mmc_dev() - read boot MMC device id from XOM[7:5] pins. + */ +static int get_boot_mmc_dev(void) +{ + u32 mode = readl(EXYNOS4_OP_MODE) & 0x1C; + + if (mode == 0x04) + return 2; /* MMC2: SD */ + + /* MMC0: eMMC or unknown */ + 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(struct bd_info *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; + int mmcbootdev = get_boot_mmc_dev(); + char mmcbootdev_str[16]; + + 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; + } + + printf("Boot device: MMC(%u)\n", mmcbootdev); + sprintf(mmcbootdev_str, "%u", mmcbootdev); + env_set("mmcbootdev", mmcbootdev_str); + + 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; +} + +int mmc_get_env_dev(void) +{ + return get_boot_mmc_dev(); +} diff --git a/roms/u-boot/board/samsung/common/bootscripts/autoboot.cmd b/roms/u-boot/board/samsung/common/bootscripts/autoboot.cmd new file mode 100644 index 000000000..d66bcccf5 --- /dev/null +++ b/roms/u-boot/board/samsung/common/bootscripts/autoboot.cmd @@ -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 diff --git a/roms/u-boot/board/samsung/common/bootscripts/bootzimg.cmd b/roms/u-boot/board/samsung/common/bootscripts/bootzimg.cmd new file mode 100644 index 000000000..2fb4c163a --- /dev/null +++ b/roms/u-boot/board/samsung/common/bootscripts/bootzimg.cmd @@ -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;
\ No newline at end of file diff --git a/roms/u-boot/board/samsung/common/dfu_sample_env.txt b/roms/u-boot/board/samsung/common/dfu_sample_env.txt new file mode 100644 index 000000000..d6ee8a228 --- /dev/null +++ b/roms/u-boot/board/samsung/common/dfu_sample_env.txt @@ -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 diff --git a/roms/u-boot/board/samsung/common/exynos-uboot-spl.lds b/roms/u-boot/board/samsung/common/exynos-uboot-spl.lds new file mode 100644 index 000000000..5b32f7feb --- /dev/null +++ b/roms/u-boot/board/samsung/common/exynos-uboot-spl.lds @@ -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 +} diff --git a/roms/u-boot/board/samsung/common/exynos5-dt-types.c b/roms/u-boot/board/samsung/common/exynos5-dt-types.c new file mode 100644 index 000000000..e2d5a7c9b --- /dev/null +++ b/roms/u-boot/board/samsung/common/exynos5-dt-types.c @@ -0,0 +1,266 @@ +// 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 <asm/global_data.h> +#include <linux/delay.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@12D10000", CONFIG_ODROID_REV_AIN, + &adcval_prev); + if (ret) + return ret; + + while (retries--) { + mdelay(5); + + ret = adc_channel_single_shot("adc@12D10000", + 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_pmic@66", &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(); +} diff --git a/roms/u-boot/board/samsung/common/exynos5-dt.c b/roms/u-boot/board/samsung/common/exynos5-dt.c new file mode 100644 index 000000000..1318ea716 --- /dev/null +++ b/roms/u-boot/board/samsung/common/exynos5-dt.c @@ -0,0 +1,188 @@ +// 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 <log.h> +#include <asm/global_data.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@66", &dev); +#else + ret = pmic_get("max77686_pmic@09", &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@66", &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(int index) +{ + 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 diff --git a/roms/u-boot/board/samsung/common/gadget.c b/roms/u-boot/board/samsung/common/gadget.c new file mode 100644 index 000000000..6d783e61e --- /dev/null +++ b/roms/u-boot/board/samsung/common/gadget.c @@ -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; +} diff --git a/roms/u-boot/board/samsung/common/misc.c b/roms/u-boot/board/samsung/common/misc.c new file mode 100644 index 000000000..b3b1bbcc8 --- /dev/null +++ b/roms/u-boot/board/samsung/common/misc.c @@ -0,0 +1,486 @@ +// 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 <asm/global_data.h> +#include <linux/delay.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) +{ + struct udevice *dev; + int ret; + u32 status; + u32 mask; + + if (IS_ENABLED(CONFIG_TARGET_TRATS)) + ret = pmic_get("max8997-pmic", &dev); + else if (IS_ENABLED(CONFIG_TARGET_TRATS2)) + ret = pmic_get("max77686-pmic", &dev); + else if (IS_ENABLED(CONFIG_TARGET_S5PC210_UNIVERSAL)) + ret = pmic_get("max8998-pmic", &dev); + else + return 0; + + if (ret) + return ret; + + if (reg == KEY_PWR_STATUS_REG) + mask = KEY_PWR_STATUS_MASK; + else + mask = KEY_PWR_INTERRUPT_MASK; + + status = pmic_reg_read(dev, reg); + if (status < 0) + return status; + + 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; +} + +#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"; + struct cmd_tbl *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 */ |