diff options
44 files changed, 3814 insertions, 61 deletions
diff --git a/arch/arm/cpu/armv7/omap-common/boot-common.c b/arch/arm/cpu/armv7/omap-common/boot-common.c index 155266dd33..b308859104 100644 --- a/arch/arm/cpu/armv7/omap-common/boot-common.c +++ b/arch/arm/cpu/armv7/omap-common/boot-common.c @@ -203,6 +203,10 @@ void spl_board_init(void) #ifdef CONFIG_AM33XX am33xx_spl_board_init(); #endif + +#if defined(CONFIG_SPL_ANDROID_BOOT_SUPPORT) + board_init(); +#endif } void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) diff --git a/arch/arm/cpu/armv7/omap-common/hwinit-common.c b/arch/arm/cpu/armv7/omap-common/hwinit-common.c index 207e7866f8..ad34d88e8c 100644 --- a/arch/arm/cpu/armv7/omap-common/hwinit-common.c +++ b/arch/arm/cpu/armv7/omap-common/hwinit-common.c @@ -283,6 +283,23 @@ u32 get_device_type(void) (DEVICE_TYPE_MASK)) >> DEVICE_TYPE_SHIFT; } +/* + * get_sysboot_value(void) - return SYS_BOOT[5:0] + */ +u32 get_sysboot_value(void) +{ + u32 sys_boot = 0; + + if (is_dra7xx()) + sys_boot = readl((*ctrl)->control_core_bootstrap) & + (SYSBOOT_MASK); + else + sys_boot = readl((*ctrl)->control_status) & + (SYSBOOT_MASK); + + return sys_boot; +} + #if defined(CONFIG_DISPLAY_CPUINFO) /* * Print CPU information diff --git a/arch/arm/cpu/armv7/omap-common/utils.c b/arch/arm/cpu/armv7/omap-common/utils.c index 52ea7342df..15d6bf8c39 100644 --- a/arch/arm/cpu/armv7/omap-common/utils.c +++ b/arch/arm/cpu/armv7/omap-common/utils.c @@ -6,6 +6,7 @@ */ #include <common.h> #include <asm/arch/sys_proto.h> + static void do_cancel_out(u32 *num, u32 *den, u32 factor) { while (1) { @@ -111,3 +112,128 @@ void omap_die_id_display(void) printf("OMAP die ID: %08x%08x%08x%08x\n", die_id[0], die_id[1], die_id[2], die_id[3]); } + +static const char *get_cpu_type(void) +{ + switch (get_device_type()) { + case EMU_DEVICE: + return "EMU"; + case HS_DEVICE: + return "HS"; + case GP_DEVICE: + return "GP"; + default: + return NULL; + } +} + +static void omap_set_fastboot_cpu(void) +{ + char *cpu; + + switch (omap_revision()) { + case DRA752_ES1_0: + case DRA752_ES1_1: + case DRA752_ES2_0: + cpu = "J6"; + break; + case DRA722_ES1_0: + case DRA722_ES2_0: + cpu = "J6ECO"; + break; + default: + cpu = "unknown"; + printf("Warning: fastboot.cpu: unknown cpu type\n"); + } + + setenv("fastboot.cpu", cpu); +} + +static void omap_set_fastboot_secure(void) +{ + const char *secure; + + secure = get_cpu_type(); + if (secure == NULL) { + secure = "unknown"; + printf("Warning: fastboot.secure: unknown CPU type\n"); + } + + setenv("fastboot.secure", secure); +} + +static void omap_set_fastboot_board_rev(void) +{ + const char *board_rev; + + board_rev = getenv("board_rev"); + if (board_rev == NULL) { + board_rev = "unknown"; + printf("Warning: fastboot.board_rev: unknown board revision\n"); + } + + setenv("fastboot.board_rev", board_rev); + +} + +#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV +u64 mmc_get_part_size(const char *part) +{ + int res; + struct blk_desc *dev_desc; + disk_partition_t info; + u64 sz = 0; + + dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV); + if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) { + error("invalid mmc device\n"); + return sz; + } + + res = part_get_info_efi_by_name(dev_desc, part, &info); + if (res) { + error("cannot find partition: '%s'\n", part); + return sz; + } + + /* Calculate size in bytes */ + sz = (info.size * (u64)info.blksz); + /* to KiB */ + sz >>= 10; + + return sz; +} + +static void omap_set_fastboot_userdata_size(void) +{ + char buf[64 + 1]; + u64 sz_kb; + + sz_kb = mmc_get_part_size("userdata"); + if (sz_kb == 0) { + strcpy(buf, "unknown"); + printf("Warning: fastboot.userdata_size: unable to calc\n"); + } else if (sz_kb >= 0xffffffff) { + u32 sz_mb; + + sz_mb = (u32)(sz_kb >> 10); + sprintf(buf, "0x%d MB", sz_mb); + } else { + sprintf(buf, "%d KB", (u32)sz_kb); + } + + setenv("fastboot.userdata_size", buf); +} +#else +static inline void omap_set_fastboot_userdata_size(void) +{ +} +#endif + +void omap_set_fastboot_vars(void) +{ + omap_set_fastboot_cpu(); + omap_set_fastboot_secure(); + omap_set_fastboot_board_rev(); + omap_set_fastboot_userdata_size(); +} diff --git a/arch/arm/cpu/armv7/omap5/prcm-regs.c b/arch/arm/cpu/armv7/omap5/prcm-regs.c index b5f1d700fd..27c6727c4a 100644 --- a/arch/arm/cpu/armv7/omap5/prcm-regs.c +++ b/arch/arm/cpu/armv7/omap5/prcm-regs.c @@ -396,6 +396,7 @@ struct omap_sys_ctrl_regs const dra7xx_ctrl = { .control_core_mmr_lock5 = 0x4A002550, .control_core_control_io1 = 0x4A002554, .control_core_control_io2 = 0x4A002558, + .control_core_bootstrap = 0x4A0026C4, .control_paconf_global = 0x4A002DA0, .control_paconf_mode = 0x4A002DA4, .control_smart1io_padconf_0 = 0x4A002DA8, diff --git a/arch/arm/include/asm/arch-omap4/cpu.h b/arch/arm/include/asm/arch-omap4/cpu.h index 34609b9f3e..f7f6fa040a 100644 --- a/arch/arm/include/asm/arch-omap4/cpu.h +++ b/arch/arm/include/asm/arch-omap4/cpu.h @@ -37,6 +37,8 @@ struct gptimer { #endif /* __ASSEMBLY__ */ #endif /* __KERNEL_STRICT_NAMES */ +#define SYSBOOT_MASK 0xFF + /* enable sys_clk NO-prescale /1 */ #define GPT_EN ((0x0 << 2) | (0x1 << 1) | (0x1 << 0)) diff --git a/arch/arm/include/asm/arch-omap5/cpu.h b/arch/arm/include/asm/arch-omap5/cpu.h index 2634426d8e..89b1c0e0ea 100644 --- a/arch/arm/include/asm/arch-omap5/cpu.h +++ b/arch/arm/include/asm/arch-omap5/cpu.h @@ -41,6 +41,8 @@ struct gptimer { #endif /* __ASSEMBLY__ */ #endif /* __KERNEL_STRICT_NAMES */ +#define SYSBOOT_MASK 0x3F + /* enable sys_clk NO-prescale /1 */ #define GPT_EN ((0x0 << 2) | (0x1 << 1) | (0x1 << 0)) diff --git a/arch/arm/include/asm/arch-omap5/spl.h b/arch/arm/include/asm/arch-omap5/spl.h index 3582880424..841afce207 100644 --- a/arch/arm/include/asm/arch-omap5/spl.h +++ b/arch/arm/include/asm/arch-omap5/spl.h @@ -22,6 +22,18 @@ #define BOOT_DEVICE_UART 0x43 #define BOOT_DEVICE_DFU 0x45 +#ifdef CONFIG_DRA7XX +#define SYSBOOT_TYPE_MASK (0x30) +/* Peripheral Preferred Booting */ +#define SYSBOOT_TYPE_PER (0x00) +/* Development Booting */ +#define SYSBOOT_TYPE_DEV (0x10) +/* Memory Preferred Booting */ +#define SYSBOOT_TYPE_MEM (0x20) +/* Automotive Production Booting */ +#define SYSBOOT_TYPE_PROD (0x30) +#endif + #define MMC_BOOT_DEVICES_START BOOT_DEVICE_MMC1 #define MMC_BOOT_DEVICES_END BOOT_DEVICE_MMC2_2 #endif diff --git a/arch/arm/include/asm/arch-omap5/sys_proto.h b/arch/arm/include/asm/arch-omap5/sys_proto.h index 26137f680e..fb563ee542 100644 --- a/arch/arm/include/asm/arch-omap5/sys_proto.h +++ b/arch/arm/include/asm/arch-omap5/sys_proto.h @@ -77,6 +77,7 @@ void force_emif_self_refresh(void); void get_ioregs(const struct ctrl_ioregs **regs); void srcomp_enable(void); void setup_warmreset_time(void); +u32 get_sysboot_value(void); static inline u32 div_round_up(u32 num, u32 den) { diff --git a/arch/arm/include/asm/omap_common.h b/arch/arm/include/asm/omap_common.h index 0e6196fe52..3e178be954 100644 --- a/arch/arm/include/asm/omap_common.h +++ b/arch/arm/include/asm/omap_common.h @@ -381,6 +381,7 @@ struct omap_sys_ctrl_regs { u32 control_core_mmr_lock5; u32 control_core_control_io1; u32 control_core_control_io2; + u32 control_core_bootstrap; u32 control_id_code; u32 control_std_fuse_die_id_0; u32 control_std_fuse_die_id_1; @@ -643,6 +644,8 @@ void omap_die_id_get_board_serial(struct tag_serialnr *serialnr); void omap_die_id_usbethaddr(void); void omap_die_id_display(void); +void omap_set_fastboot_vars(void); + void recalibrate_iodelay(void); void omap_smc1(u32 service, u32 val); diff --git a/board/ti/am57xx/board.c b/board/ti/am57xx/board.c index 2732aaa983..72c4312837 100644 --- a/board/ti/am57xx/board.c +++ b/board/ti/am57xx/board.c @@ -621,6 +621,9 @@ int board_late_init(void) board_ti_set_ethaddr(2); #endif + omap_die_id_serial(); + omap_set_fastboot_vars(); + /* * Default FIT boot on HS devices. Non FIT images are not allowed * on HS devices. diff --git a/board/ti/dra7xx/Kconfig b/board/ti/dra7xx/Kconfig index b642113b83..4b6269c8dd 100644 --- a/board/ti/dra7xx/Kconfig +++ b/board/ti/dra7xx/Kconfig @@ -18,6 +18,46 @@ config CONS_INDEX Depending on your specific board you may want something other than UART1 here. +config TARGET_DRA7XX_EVM_VISION + bool "Vision daughter card support" + +menu "Early Boot/Late Attach" + +config LATE_ATTACH + bool "Enable late attach" + default n + help + Enable this flag if you want to boot remotecores(M4/DSP) from + SPL. The specific cores loaded is controlled by the array + cores_to_boot[] in spl.c. Currently only ELF format + binaries are supported for loading. + + +config LATE_ATTACH_GPT_PART + bool "Enable loading remotecore binaries from GPT partitions" + depends on LATE_ATTACH + default n + help + In case of Linux boot, the binaries are read from the FAT parition of + the eMMC or SD card based on the boot media. Android uses GPT partitions + on eMMC for storing the binaries. Enable this option to read remotecore + binaries from GPT partitions. + + +config LATE_ATTACH_DMA_POOL + bool "Enable using a DMA pool instead of a CMA pool" + depends on LATE_ATTACH + default n + help + It may be desireable to define the reserved memory as no-map rather + than as reusable in order to prevent access by other kernel modules to + the memory before the remoteproc driver has a chance to allocate from + the CMA pool and reclaim the memory. In this way the memory is reserved + explicitly for the remote core and kernel cannot allocate from it even + when not in use by remoteproc. + +endmenu + source "board/ti/common/Kconfig" endif diff --git a/board/ti/dra7xx/Makefile b/board/ti/dra7xx/Makefile index 434e8d128e..c6b9c52256 100644 --- a/board/ti/dra7xx/Makefile +++ b/board/ti/dra7xx/Makefile @@ -6,3 +6,5 @@ # obj-y := evm.o + +obj-$(CONFIG_LATE_ATTACH) += lateattach.o diff --git a/board/ti/dra7xx/evm.c b/board/ti/dra7xx/evm.c index 39808474cc..8378488cb7 100644 --- a/board/ti/dra7xx/evm.c +++ b/board/ti/dra7xx/evm.c @@ -30,6 +30,7 @@ #include <dwc3-omap-uboot.h> #include <ti-usb-phy-uboot.h> #include <miiphy.h> +#include <spl.h> #include "mux_data.h" #include "../common/board_detect.h" @@ -513,6 +514,19 @@ int get_voltrail_opp(int rail_offset) */ int board_init(void) { +#ifndef CONFIG_SPL_DFU_SUPPORT +#ifdef CONFIG_SPL_ENV_SUPPORT +#ifdef CONFIG_ENV_IS_IN_MMC + struct mmc *mmc; + spl_mmc_init(&mmc, UINT_MAX); +#endif + + env_init(); + env_relocate_spec(); + omap_die_id_serial(); +#endif +#endif + gpmc_init(); gd->bd->bi_boot_params = (0x80000000 + 0x100); /* boot param addr */ @@ -559,6 +573,7 @@ int board_late_init(void) setenv("boot_fit", "1"); omap_die_id_serial(); + omap_set_fastboot_vars(); #endif return 0; } @@ -901,14 +916,17 @@ int spl_start_uboot(void) if (serial_tstc() && serial_getc() == 'c') return 1; + if ((get_sysboot_value() & SYSBOOT_TYPE_MASK) == SYSBOOT_TYPE_PROD) + return 0; + #ifdef CONFIG_SPL_ENV_SUPPORT env_init(); env_relocate_spec(); - if (getenv_yesno("boot_os") != 1) - return 1; + if (getenv_yesno("boot_os") == 1) + return 0; #endif - return 0; + return 1; } #endif diff --git a/board/ti/dra7xx/lateattach.c b/board/ti/dra7xx/lateattach.c new file mode 100644 index 0000000000..0db28aef6b --- /dev/null +++ b/board/ti/dra7xx/lateattach.c @@ -0,0 +1,1275 @@ +/* + * (C) Copyright 2015 + * Texas Instruments Incorporated, <www.ti.com> + * + * Venkateswara Rao Mandela <venkat.mandela@ti.com> + * + * Based on previous work by: + * Robert Tivy <rtivy@ti.com> + * Amarinder Bindra <a-bindra@ti.com> + * Sundar Raman <sunds@ti.com> + * Angela Stegmaier <angelabaker@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <common.h> +#include <asm/bitops.h> +#include <asm/io.h> +#include <omap_remoteproc.h> +#include <elf.h> + +#define DPLL_TIMEOUT 5000 +#define L4_CFG_TARG 0x4A000000 +#define L4_WKUP_TARG 0x4AE00000 +#define IPU2_TARGET_TARG 0x55000000 +#define IPU1_TARGET_TARG 0x58800000 +#define CTRL_MODULE_CORE (L4_CFG_TARG + 0x2000) +#define CM_CORE_AON (L4_CFG_TARG + 0x5000) +#define CM_CORE (L4_CFG_TARG + 0x8000) +#define PRM (L4_WKUP_TARG + 0x6000) +#define MPU_CM_CORE_AON (CM_CORE_AON + 0x300) +#define IPU_CM_CORE_AON (CM_CORE_AON + 0x500) +#define RTC_CM_CORE_AON (CM_CORE_AON + 0x740) +#define VPE_CM_CORE_AON (CM_CORE_AON + 0x760) +#define COREAON_CM_CORE (CM_CORE + 0x600) +#define CORE_CM_CORE (CM_CORE + 0x700) +#define CAM_CM_CORE (CM_CORE + 0x1000) +#define DSS_CM_CORE (CM_CORE + 0x1100) +#define L3INIT_CM_CORE (CM_CORE + 0x1300) +#define L4PER_CM_CORE (CM_CORE + 0x1700) +#define CKGEN_PRM (PRM + 0x100) +#define IPU_PRM (PRM + 0x500) +#define CORE_PRM (PRM + 0x700) +#define WKUPAON_CM (PRM + 0x1800) + +#define CM_CLKMODE_DPLL_DSP (0x4A005234) +#define CM_DSP1_CLKSTCTRL (0x4A005400) +#define CM_DSP2_CLKSTCTRL (0x4A005600) +#define DSP1_PRM_BASE (0x4AE06400) +#define DSP2_PRM_BASE (0x4AE07B00) +#define DSP1_SYS_MMU_CONFIG (0x40D00018) +#define DSP2_SYS_MMU_CONFIG (0x41500018) + +/* CTRL_CORE_CONTROL_DSP1_RST_VECTOR in TRM */ +#define DSP1_BOOTADDR (0x4A00255C) +/* CTRL_CORE_CONTROL_DSP2_RST_VECTOR in TRM */ +#define DSP2_BOOTADDR (0x4A002560) +#define DRA7XX_CTRL_CORE_DSP_RST_VECT_MASK (0x3FFFFF << 0) + +#define CM_L3MAIN1_CLKSTCTRL (CORE_CM_CORE + 0x000) +#define CM_IPU2_CLKSTCTRL (CORE_CM_CORE + 0x200) +#define CM_DMA_CLKSTCTRL (CORE_CM_CORE + 0x300) +#define CM_EMIF_CLKSTCTRL (CORE_CM_CORE + 0x400) +#define CM_L4CFG_CLKSTCTRL (CORE_CM_CORE + 0x600) + +#define CM_DSS_CLKSTCTRL (DSS_CM_CORE + 0x00) +#define CM_CAM_CLKSTCTRL (CAM_CM_CORE + 0x00) +#define CM_COREAON_CLKSTCTRL (COREAON_CM_CORE + 0x00) +#define CM_L3INIT_CLKSTCTRL (L3INIT_CM_CORE + 0x00) +#define CM_GMAC_CLKSTCTRL (L3INIT_CM_CORE + 0xC0) +#define CM_L4PER_CLKSTCTRL (L4PER_CM_CORE + 0x000) +#define CM_L4PER_TIMER10_CLKCTRL (CM_L4PER_CLKSTCTRL + 0x28) +#define CM_L4PER_TIMER11_CLKCTRL (CM_L4PER_CLKSTCTRL + 0x30) +#define CM_L4PER_TIMER3_CLKCTRL (CM_L4PER_CLKSTCTRL + 0x40) +#define CM_L4PER_TIMER4_CLKCTRL (CM_L4PER_CLKSTCTRL + 0x48) +#define CM_L4PER_TIMER9_CLKCTRL (CM_L4PER_CLKSTCTRL + 0x50) +#define CM_L4PER2_CLKSTCTRL (L4PER_CM_CORE + 0x1FC) +#define CM_L4PER3_CLKSTCTRL (L4PER_CM_CORE + 0x210) +#define CM_MPU_CLKSTCTRL (MPU_CM_CORE_AON + 0x00) +#define CM_RTC_CLKSTCTRL (RTC_CM_CORE_AON + 0x00) +#define CM_VPE_CLKSTCTRL (VPE_CM_CORE_AON + 0x00) +#define CM_WKUPAON_CLKSTCTRL (WKUPAON_CM + 0x00) + +#define RM_IPU1_RSTCTRL (IPU_PRM + 0x10) +#define RM_IPU1_RSTST (IPU_PRM + 0x14) +#define CM_IPU1_CLKSTCTRL (IPU_CM_CORE_AON + 0x0) +#define CM_IPU1_IPU1_CLKCTRL (IPU_CM_CORE_AON + 0x20) +#define CM_IPU2_IPU2_CLKCTRL (CORE_CM_CORE + 0x220) +#define CM_IPU_CLKSTCTRL (IPU_CM_CORE_AON + 0x40) +#define CM_IPU_MCASP1_CLKCTRL (IPU_CM_CORE_AON + 0x50) +#define CM_IPU_TIMER5_CLKCTRL (IPU_CM_CORE_AON + 0x58) +#define CM_IPU_TIMER6_CLKCTRL (IPU_CM_CORE_AON + 0x60) +#define CM_IPU_TIMER7_CLKCTRL (IPU_CM_CORE_AON + 0x68) +#define CM_IPU_TIMER8_CLKCTRL (IPU_CM_CORE_AON + 0x70) +#define CM_L4PER2_L4_PER2_CLKCTRL (L4PER_CM_CORE + 0x0C) +#define CM_L4PER3_L4_PER3_CLKCTRL (L4PER_CM_CORE + 0x14) +#define CM_L4PER_I2C1_CLKCTRL (L4PER_CM_CORE + 0xA0) +#define CM_L4PER_I2C2_CLKCTRL (L4PER_CM_CORE + 0xA8) +#define CM_L4PER_I2C3_CLKCTRL (L4PER_CM_CORE + 0xB0) +#define CM_L4PER_I2C4_CLKCTRL (L4PER_CM_CORE + 0xB8) +#define CM_L4PER_L4_PER1_CLKCTRL (L4PER_CM_CORE + 0xC0) +#define CM_CAM_VIP1_CLKCTRL (CAM_CM_CORE + 0x20) +#define CM_CAM_VIP2_CLKCTRL (CAM_CM_CORE + 0x28) +#define CM_CAM_VIP3_CLKCTRL (CAM_CM_CORE + 0x30) +#define CM_DMA_DMA_SYSTEM_CLKCTRL (CORE_CM_CORE + 0x320) +#define CM_L3INSTR_L3_MAIN_2_CLKCTRL (CORE_CM_CORE + 0x728) +#define CM_DSS_DSS_CLKCTRL (DSS_CM_CORE + 0x20) +#define CM_VPE_VPE_CLKCTRL (VPE_CM_CORE_AON + 0x04) + +#define RM_IPU2_RSTCTRL (CORE_PRM + 0x210) +#define RM_IPU2_RSTST (CORE_PRM + 0x214) + +#define CTRL_CORE_CONTROL_IO_2 (CTRL_MODULE_CORE + 0x558) + +#define CTRL_CORE_CORTEX_M4_MMUADDRTRANSLTR 0x4A002358 +#define CTRL_CORE_CORTEX_M4_MMUADDRLOGICTR 0x4A00235C + +#define PAGESIZE_1M 0x0 +#define PAGESIZE_64K 0x1 +#define PAGESIZE_4K 0x2 +#define PAGESIZE_16M 0x3 +#define LE 0 +#define BE 1 +#define ELEMSIZE_8 0x0 +#define ELEMSIZE_16 0x1 +#define ELEMSIZE_32 0x2 +#define MIXED_TLB 0x0 +#define MIXED_CPU 0x1 + +#define PGT_SMALLPAGE_SIZE 0x00001000 +#define PGT_LARGEPAGE_SIZE 0x00010000 +#define PGT_SECTION_SIZE 0x00100000 +#define PGT_SUPERSECTION_SIZE 0x01000000 + +#define PGT_L1_DESC_PAGE 0x00001 +#define PGT_L1_DESC_SECTION 0x00002 +#define PGT_L1_DESC_SUPERSECTION 0x40002 + +#define PGT_L1_DESC_PAGE_MASK 0xfffffC00 +#define PGT_L1_DESC_SECTION_MASK 0xfff00000 +#define PGT_L1_DESC_SUPERSECTION_MASK 0xff000000 + +#define PGT_L1_DESC_SMALLPAGE_INDEX_SHIFT 12 +#define PGT_L1_DESC_LARGEPAGE_INDEX_SHIFT 16 +#define PGT_L1_DESC_SECTION_INDEX_SHIFT 20 +#define PGT_L1_DESC_SUPERSECTION_INDEX_SHIFT 24 + +#define PGT_L2_DESC_SMALLPAGE 0x02 +#define PGT_L2_DESC_LARGEPAGE 0x01 + +#define PGT_L2_DESC_SMALLPAGE_MASK 0xfffff000 +#define PGT_L2_DESC_LARGEPAGE_MASK 0xffff0000 + +#define DRA7_RPROC_CMA_BASE_IPU1 0x9d000000 +#define DRA7_RPROC_CMA_BASE_IPU2 0x95800000 +#define DRA7_RPROC_CMA_BASE_DSP1 0x99000000 +#define DRA7_RPROC_CMA_BASE_DSP2 0x9f000000 + +#define DRA7_RPROC_CMA_SIZE_IPU1 0x02000000 +#define DRA7_RPROC_CMA_SIZE_IPU2 0x03800000 +#define DRA7_RPROC_CMA_SIZE_DSP1 0x04000000 +#define DRA7_RPROC_CMA_SIZE_DSP2 0x00800000 + +#define DRA7_PGTBL_BASE_IPU1 0xbfc00000 +#define DRA7_PGTBL_BASE_IPU2 0xbfc08000 +#define DRA7_PGTBL_BASE_DSP1 0xbfc10000 +#define DRA7_PGTBL_BASE_DSP2 0xbfc18000 + +/* + * The page table (32 KB) is placed at the end of the CMA reserved area. + * It's possible that this location is needed by the firmware (in which + * case the firmware is using pretty much *all* of the reserved area), but + * there doesn't seem to be a better location to place it. + * + * We only need 16 KB memory for the page table if we are using all 1 + * MB sections. There might be cases where we need to allocate memory + * at a lower granularity. For these cases, we are allocating 16 KB + * additional memory. + */ +#define PAGE_TABLE_SIZE_L1 (0x00004000) +#define PAGE_TABLE_SIZE_L2 (0x400) +#define MAX_NUM_L2_PAGE_TABLES (16) +#define PAGE_TABLE_SIZE_L2_TOTAL (MAX_NUM_L2_PAGE_TABLES*PAGE_TABLE_SIZE_L2) +#define PAGE_TABLE_SIZE (PAGE_TABLE_SIZE_L1+(PAGE_TABLE_SIZE_L2_TOTAL)) + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) + +#define BITS_PER_BYTE 8 +#undef BITS_PER_LONG +#define BITS_PER_LONG (sizeof(long) * BITS_PER_BYTE) +#define BITS_TO_LONGS(nbits) (((nbits) + BITS_PER_LONG - 1) / BITS_PER_LONG) + +#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) +#define BITOP_WORD(nr) BIT_WORD(nr) + +#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG)) +#define BITMAP_LAST_WORD_MASK(nbits) \ +( \ + ((nbits) % BITS_PER_LONG) ? \ + (1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL \ +) + +/* + * Determine if a valid ELF image exists at the given memory location. + * First look at the ELF header magic field, then make sure that it is + * executable. + */ +static int valid_elf_image_local(unsigned long addr) +{ + Elf32_Ehdr *ehdr; /* Elf header structure pointer */ + + ehdr = (Elf32_Ehdr *)addr; + + if (!IS_ELF(*ehdr)) { + printf("## No elf image at address 0x%08lx\n", addr); + return 0; + } + + if (ehdr->e_type != ET_EXEC) { + printf("## Not a 32-bit elf image at address 0x%08lx\n", addr); + return 0; + } + + return 1; +} + +unsigned int *page_table_l1 = (unsigned int *)0x0; +unsigned int *page_table_l2 = (unsigned int *)0x0; + +/* Set maximum carveout size to 96 MB */ +#define DRA7_RPROC_MAX_CMA_SIZE (96*0x100000) + +/* These global variables are used for deriving the MMU page tables. + * They are initialized for each core with the appropriate values. + * + * The length of the array mem_bitmap is set as per a 96 MB carveout which + * the maximum set aside in the current memory map. + */ +unsigned long mem_base = 0; +unsigned long mem_size = 0; +unsigned long mem_bitmap[BITS_TO_LONGS(DRA7_RPROC_MAX_CMA_SIZE >> PAGE_SHIFT)]; +unsigned long mem_count = 0; + +unsigned int pgtable_l2_map[MAX_NUM_L2_PAGE_TABLES]; +unsigned int pgtable_l2_cnt = 0; + +void bitmap_set(unsigned long *map, int start, int nr) +{ + unsigned long *p = map + BIT_WORD(start); + const int size = start + nr; + int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG); + unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start); + + while (nr - bits_to_set >= 0) { + *p |= mask_to_set; + nr -= bits_to_set; + bits_to_set = BITS_PER_LONG; + mask_to_set = ~0UL; + p++; + } + if (nr) { + mask_to_set &= BITMAP_LAST_WORD_MASK(size); + *p |= mask_to_set; + } +} + +#define ffz(x) __ffs(~(x)) + +/* + * This has an "evm_" prefix since without the prefix it clashes with the + * non-existant-yet-declared "find_next_zero_bit" in + * arch/arm/include/asm/bitops.h. + */ +unsigned long evm_find_next_zero_bit(const unsigned long *addr, + unsigned long size, unsigned long offset) +{ + const unsigned long *p = addr + BITOP_WORD(offset); + unsigned long result = offset & ~(BITS_PER_LONG - 1); + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset %= BITS_PER_LONG; + if (offset) { + tmp = *(p++); + tmp |= ~0UL >> (BITS_PER_LONG - offset); + if (size < BITS_PER_LONG) + goto found_first; + if (~tmp) + goto found_middle; + size -= BITS_PER_LONG; + result += BITS_PER_LONG; + } + while (size & ~(BITS_PER_LONG - 1)) { + tmp = *(p++); + if (~(tmp)) + goto found_middle; + result += BITS_PER_LONG; + size -= BITS_PER_LONG; + } + if (!size) + return result; + tmp = *p; + +found_first: + tmp |= ~0UL << size; + if (tmp == ~0UL) /* Are any bits zero? */ + return result + size; /* Nope. */ +found_middle: + return result + ffz(tmp); +} + +unsigned long find_next_bit(const unsigned long *addr, unsigned long size, + unsigned long offset) +{ + const unsigned long *p = addr + BITOP_WORD(offset); + unsigned long result = offset & ~(BITS_PER_LONG - 1); + unsigned long tmp; + + if (offset >= size) + return size; + size -= result; + offset %= BITS_PER_LONG; + if (offset) { + tmp = *(p++); + tmp &= (~0UL << offset); + if (size < BITS_PER_LONG) + goto found_first; + if (tmp) + goto found_middle; + size -= BITS_PER_LONG; + result += BITS_PER_LONG; + } + while (size & ~(BITS_PER_LONG - 1)) { + tmp = *(p++); + if ((tmp)) + goto found_middle; + result += BITS_PER_LONG; + size -= BITS_PER_LONG; + } + if (!size) + return result; + tmp = *p; + +found_first: + tmp &= (~0UL >> (BITS_PER_LONG - size)); + if (tmp == 0UL) /* Are any bits set? */ + return result + size; /* Nope. */ +found_middle: + return result + __ffs(tmp); +} + +unsigned long bitmap_find_next_zero_area(unsigned long *map, + unsigned long size, + unsigned long start, + unsigned int nr, + unsigned long align_mask) +{ + unsigned long index, end, i; +again: + index = evm_find_next_zero_bit(map, size, start); + + /* Align allocation */ + index = (index + align_mask) & ~align_mask; + + end = index + nr; + if (end > size) + return end; + i = find_next_bit(map, end, index); + if (i < end) { + start = i + 1; + goto again; + } + return index; +} + +#ifdef CONFIG_LATE_ATTACH_DMA_POOL + +/* size is rounded up to the next "order" (log base 2) + * allocations are made to be aligned to the order also + */ +void *alloc_mem(unsigned long len, unsigned long align) +{ + unsigned long mask; + unsigned long pageno; + int count; + unsigned int order; + + if (len < PAGE_SIZE) + order = 0; + else + order = __ilog2((len) - 1) - PAGE_SHIFT + 1; + count = (1 << order); + mask = (1 << order) - 1; + pageno = bitmap_find_next_zero_area(mem_bitmap, mem_count, 0, count, + mask); + debug("alloc_mem: count %d mask %#lx pageno %#lx\n", count, mask, + pageno); + + if (pageno >= mem_count) + return NULL; + + bitmap_set(mem_bitmap, pageno, count); + return (void *)(mem_base + (pageno << PAGE_SHIFT)); +} + +#else + +void *alloc_mem(unsigned long len, unsigned long align) +{ + unsigned long mask; + unsigned long pageno; + int count; + + count = ((len + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1)) >> PAGE_SHIFT; + mask = (1 << align) - 1; + pageno = bitmap_find_next_zero_area(mem_bitmap, mem_count, 0, count, + mask); + debug("alloc_mem: count %d mask %#lx pageno %#lx\n", count, mask, + pageno); + + if (pageno >= mem_count) { + printf("%s: %s Error allocating memory; " + "Please check carveout size\n", + __FILE__, __func__); + return NULL; + } + + bitmap_set(mem_bitmap, pageno, count); + return (void *)(mem_base + (pageno << PAGE_SHIFT)); +} + +#endif + +int find_pagesz(unsigned int virt, unsigned int phys, unsigned int len) +{ + int pg_sz_ind = -1; + unsigned int min_align = __ffs(virt); + + if (min_align > __ffs(phys)) + min_align = __ffs(phys); + + if ((min_align >= PGT_L1_DESC_SUPERSECTION_INDEX_SHIFT) && + (len >= 0x1000000)) { + pg_sz_ind = PAGESIZE_16M; + goto ret_block; + } + if ((min_align >= PGT_L1_DESC_SECTION_INDEX_SHIFT) && + (len >= 0x100000)) { + pg_sz_ind = PAGESIZE_1M; + goto ret_block; + } + if ((min_align >= PGT_L1_DESC_LARGEPAGE_INDEX_SHIFT) && + (len >= 0x10000)) { + pg_sz_ind = PAGESIZE_64K; + goto ret_block; + } + if ((min_align >= PGT_L1_DESC_SMALLPAGE_INDEX_SHIFT) && + (len >= 0x1000)) { + pg_sz_ind = PAGESIZE_4K; + goto ret_block; + } + +ret_block: + return pg_sz_ind; +} + +int get_l2_pg_tbl_addr(unsigned int virt, unsigned int *pg_tbl_addr) +{ + int ret = -1; + int i = 0; + int match_found = 0; + unsigned int tag = (virt & PGT_L1_DESC_SECTION_MASK); + + *pg_tbl_addr = 0; + for (i = 0; (i < pgtable_l2_cnt) && (match_found == 0); i++) { + if (tag == pgtable_l2_map[i]) { + *pg_tbl_addr = + ((unsigned int)page_table_l2) + + (i * PAGE_TABLE_SIZE_L2); + match_found = 1; + ret = 0; + } + } + + if ((match_found == 0) && (i < MAX_NUM_L2_PAGE_TABLES)) { + pgtable_l2_map[i] = tag; + pgtable_l2_cnt++; + *pg_tbl_addr = + ((unsigned int)page_table_l2) + (i * PAGE_TABLE_SIZE_L2); + ret = 0; + } + + return ret; +} + +int config_l2_pagetable(unsigned int virt, unsigned int phys, + unsigned int pg_sz, unsigned int pg_tbl_addr) +{ + int ret = -1; + unsigned int desc = 0; + int32_t i = 0; + unsigned int *pg_tbl = (unsigned int *)pg_tbl_addr; + + /* Pick bit 19:12 of the virtual address as index */ + unsigned int index = (virt & (~PGT_L1_DESC_SECTION_MASK)) >> PAGE_SHIFT; + + switch (pg_sz) { + case PAGESIZE_64K: + desc = + (phys & PGT_L2_DESC_LARGEPAGE_MASK) | PGT_L2_DESC_LARGEPAGE; + for (i = 0; i < 16; i++) + pg_tbl[index + i] = desc; + ret = 0; + break; + case PAGESIZE_4K: + desc = + (phys & PGT_L2_DESC_SMALLPAGE_MASK) | PGT_L2_DESC_SMALLPAGE; + pg_tbl[index] = desc; + ret = 0; + break; + default: + break; + } + + return ret; +} + +unsigned int config_pagetable(unsigned int virt, unsigned int phys, + unsigned int len) +{ + unsigned int index; + unsigned int l = len; + unsigned int desc; + int pg_sz = 0; + int32_t i = 0; + int32_t err = 0; + unsigned int pg_tbl_l2_addr = 0; + unsigned int tmp_pgsz; + + if ((len & 0x0FFF) != 0) + return 0; + + while (l > 0) { + pg_sz = find_pagesz(virt, phys, l); + index = virt >> PGT_L1_DESC_SECTION_INDEX_SHIFT; + switch (pg_sz) { + /* 16 MB super section */ + case PAGESIZE_16M: + /* Program the next 16 descriptors */ + desc = + (phys & PGT_L1_DESC_SUPERSECTION_MASK) | + PGT_L1_DESC_SUPERSECTION; + for (i = 0; i < 16; i++) + page_table_l1[index + i] = desc; + l -= PGT_SUPERSECTION_SIZE; + phys += PGT_SUPERSECTION_SIZE; + virt += PGT_SUPERSECTION_SIZE; + break; + /* 1 MB section */ + case PAGESIZE_1M: + desc = + (phys & PGT_L1_DESC_SECTION_MASK) | + PGT_L1_DESC_SECTION; + page_table_l1[index] = desc; + l -= PGT_SECTION_SIZE; + phys += PGT_SECTION_SIZE; + virt += PGT_SECTION_SIZE; + break; + /* 64 KB large page */ + case PAGESIZE_64K: + case PAGESIZE_4K: + if (pg_sz == PAGESIZE_64K) + tmp_pgsz = 0x10000; + else + tmp_pgsz = 0x1000; + + err = get_l2_pg_tbl_addr(virt, &pg_tbl_l2_addr); + if (err != 0) { + printf("error: Unable to get level 2 page table addresss\n"); + hang(); + } + err = + config_l2_pagetable(virt, phys, pg_sz, + pg_tbl_l2_addr); + desc = + (pg_tbl_l2_addr & PGT_L1_DESC_PAGE_MASK) | + PGT_L1_DESC_PAGE; + page_table_l1[index] = desc; + l -= tmp_pgsz; + phys += tmp_pgsz; + virt += tmp_pgsz; + break; + case -1: + default: + return 0; + } + } + + return len; +} + +void enable_common_clocks(void) +{ + static u32 do_config = 1; + + if (do_config != 1) + return; + + /* TODO: Review if all of these are actually + * necessary. + */ + + /* enable CORE domain transitions */ + __raw_writel(0x2, CM_CAM_CLKSTCTRL); + __raw_writel(0x2, CM_L3INIT_CLKSTCTRL); + __raw_writel(0x2, CM_GMAC_CLKSTCTRL); + __raw_writel(0x2, CM_EMIF_CLKSTCTRL); + __raw_writel(0x2, CM_L4CFG_CLKSTCTRL); + __raw_writel(0x2, CM_DMA_CLKSTCTRL); + __raw_writel(0x2, CM_COREAON_CLKSTCTRL); + __raw_writel(0x2, CM_L4PER_CLKSTCTRL); + + /* Some of the timers are on the IPU clock domain */ + __raw_writel(0x2, CM_IPU_CLKSTCTRL); + do_config = 0; + + return; +} + +u32 ipu_start_clocks(u32 core_id, struct rproc *cfg) +{ + u32 reg; + u32 ipu_clkstctrl = 0; + u32 ipu_clkctrl = 0; + u32 tick_timerctrl = 0; + u32 wdt_ctrl[2] = { 0, 0 }; + u32 ipu_rstctrl = 0; + u32 ipu_rstst = 0; + u32 i = 0; + + if (!((core_id == IPU1) || (core_id == IPU2))) { + printf("Error: %s invoked with incorrect core id: %d\n", + __func__, core_id); + return 1; + } + + debug("Configuring IPU\n"); + + enable_common_clocks(); + + if (core_id == IPU1) { + ipu_clkstctrl = CM_IPU1_CLKSTCTRL; + ipu_clkctrl = CM_IPU1_IPU1_CLKCTRL; + ipu_rstctrl = RM_IPU1_RSTCTRL; + ipu_rstst = RM_IPU1_RSTST; + + tick_timerctrl = CM_L4PER_TIMER11_CLKCTRL; + wdt_ctrl[0] = CM_IPU_TIMER7_CLKCTRL; + wdt_ctrl[1] = CM_IPU_TIMER8_CLKCTRL; + } else { + ipu_clkstctrl = CM_IPU2_CLKSTCTRL; + ipu_clkctrl = CM_IPU2_IPU2_CLKCTRL; + ipu_rstctrl = RM_IPU2_RSTCTRL; + ipu_rstst = RM_IPU2_RSTST; + + tick_timerctrl = CM_L4PER_TIMER3_CLKCTRL; + wdt_ctrl[0] = CM_L4PER_TIMER4_CLKCTRL; + wdt_ctrl[1] = CM_L4PER_TIMER9_CLKCTRL; + } + + __raw_writel(0x2, ipu_clkstctrl); + + /* Using TIMER_SYS_CLK as the clock source */ + reg = __raw_readl(tick_timerctrl); + __raw_writel((reg & ~0x0F000003) | 0x00000002, tick_timerctrl); + + for (i = 0; i < 2; i++) { + if (wdt_ctrl[i] != 0) { + /* + * Using SYS_CLK1_32K_CLK as the clock source for the + * watch dog timers. IPU will eventually configure + * these timers with the right clock source. If we use + * a higher frequency clock as the clock source, the + * timer will overflow and trigger a watchdog interrupt + * even before the kernel has a chance to connect to + * IPU. + */ + reg = __raw_readl(wdt_ctrl[i]); + __raw_writel((reg & ~0x0F000003) | 0x01000002, + wdt_ctrl[i]); + } + } + + /* enable IPU clocks / hw_auto mode */ + reg = __raw_readl(ipu_clkctrl); + __raw_writel(((reg & ~0x00000003) | 0x01000000 | 0x1), ipu_clkctrl); + + /* checking if IPU module is enabled */ + while ((__raw_readl(ipu_clkctrl) & 0x00030000) == 0x00030000); + + /* checking if clocks are enabled */ + while (((__raw_readl(ipu_clkstctrl) & 0x100) >> 8) != 1); + + /*Assert the IPU - CPU0,CPU1 & MMU,cache */ + __raw_writel(0x7, ipu_rstctrl); + + /* Bring the IPU Unicache/MMU out of reset */ + __raw_writel(0x7, ipu_rstst); + __raw_writel(0x3, ipu_rstctrl); + + while ((__raw_readl(ipu_rstst) & 0x4) != 0x4); + + return 0; +} + +u32 ipu_config_mmu(u32 core_id, struct rproc *cfg) +{ + u32 i = 0; + u32 reg = 0; + + /* + * Clear the entire pagetable location before programming the + * address into the MMU + */ + memset((void *)cfg->page_table_addr, 0x00, PAGE_TABLE_SIZE); + debug("Cleared the page table for MMU\n"); + + for (i = 0; i < cfg->num_iommus; i++) { + u32 mmu_base = cfg->mmu_base_addr[i]; + + __raw_writel((int)cfg->page_table_addr, mmu_base + 0x4c); + reg = __raw_readl(mmu_base + 0x88); + + /* enable bus-error back */ + __raw_writel(reg | 0x1, mmu_base + 0x88); + + /* + * Enable the MMU IRQs during MMU programming for the + * late attachcase. This is to allow the MMU fault to be + * detected by the kernel. + * + * MULTIHITFAULT|EMMUMISS|TRANSLATIONFAULT|TABLEWALKFAULT + */ + __raw_writel(0x1E, mmu_base + 0x1c); + + /* emutlbupdate|TWLENABLE|MMUENABLE */ + __raw_writel(0x6, mmu_base + 0x44); + } + + return 0; +} + +u32 ipu_start_core(u32 core_id, struct rproc *cfg) +{ + u32 ret = 1; + u32 RST_CTRL = 0; /* Reset control */ + u32 RST_ST = 0; /* Reset State */ + + if (core_id == IPU2) { + RST_CTRL = RM_IPU2_RSTCTRL; + RST_ST = RM_IPU2_RSTST; + ret = 0; + } else if (core_id == IPU1) { + RST_CTRL = RM_IPU1_RSTCTRL; + RST_ST = RM_IPU1_RSTST; + ret = 0; + } + + if (ret == 0) { + /* bring the IPU2 out of reset */ + __raw_writel(0x0, RST_CTRL); + + /* check module is functional or not */ + while (((__raw_readl(RST_ST) & 0x7) != 0x7)); + + ret = 0; + } + + return ret; +} + +/****************************************************************************** + * dpll_lock_sequence() : DPLL lock sequence + *****************************************************************************/ +void dpll_lock_sequence(u32 base_address) +{ + int timer = DPLL_TIMEOUT; + u32 reg = 0; + + reg = __raw_readl(base_address); + + /* Enable the DPLL lock mode. The bit field is 3 bits long. + * So not clearing the bit field before setting it. + */ + reg = (reg | 0x7); + + /* Put DPLL into lock mode */ + __raw_writel(reg, base_address); + + /* Wait for DPLL to be locked */ + while (((__raw_readl(base_address + 0x4) & 0x1) != 0x1) && (timer--)); + + if (timer <= 0) + printf("\tERROR: timeout while locking DPLL\n"); +} + +/****************************************************************************** + * dpll_unlock_sequence() : DPLL unlock sequence + *****************************************************************************/ +void dpll_unlock_sequence(u32 base_address) +{ + u32 reg = 0; + + reg = __raw_readl(base_address); + + /* Take DPLL out of lock mode */ + __raw_writel((reg & (~0x1)), base_address); +} + +/* Configuring to 600 MHz DSP with 20 MHz sys_clk. + * Code based on the DRA7xx_prcm_config.gel + */ +u32 dsp_enable_dpll(void) +{ + static u32 dpll_do_init = 1; + u32 dpll_m = 150; + u32 dpll_n = 4; + u32 divm2 = 1; + u32 dpll_base_addr = CM_CLKMODE_DPLL_DSP; + + /* return if the DPLL is already configured */ + if (dpll_do_init == 0) { + debug("DSP DPLL configuration already configured\n"); + return 0; + } + + /* We are assuming that the DPLL is unlocked and + we do not need to unlock it. + */ + + debug("DSP DPLL configuration in progress\n"); + + if (__raw_readl(dpll_base_addr + 0x4) & 0x1) { + debug("DSP DPLL already locked, now unlocking....\n"); + dpll_unlock_sequence(dpll_base_addr); + } + + __raw_writel(((dpll_m << 8) | dpll_n), dpll_base_addr + 0x0C); + __raw_writel(divm2, dpll_base_addr + 0x10); + + /* CM_DIV_M3_DPLL - not used in default configuration */ + /* Output of M3 divider can be routed to EVE if required */ + __raw_writel(0x3, dpll_base_addr + 0x14); + + dpll_lock_sequence(dpll_base_addr); + + debug("DSP DPLL configuration is DONE!\n"); + dpll_do_init = 0; + + return 0; +} + +u32 dsp_start_clocks(u32 core_id, struct rproc *cfg) +{ + u32 reg = 0; + u32 timer_reg = 0; + u32 dsp_clkstctrl = 0; + u32 prm_base = 0; + u32 mmu_config = 0; + u32 wdt_ctrl = 0; + + if ((core_id != DSP1) && (core_id != DSP2)) + return 1; + + debug("DSP initialization in progress\n"); + enable_common_clocks(); + + /* Configure the DSP PLL */ + dsp_enable_dpll(); + + if (core_id == DSP1) { + /* Enable Timer 5 for DSP1 */ + timer_reg = CM_IPU_TIMER5_CLKCTRL; + prm_base = DSP1_PRM_BASE; + dsp_clkstctrl = CM_DSP1_CLKSTCTRL; + mmu_config = DSP1_SYS_MMU_CONFIG; + wdt_ctrl = CM_L4PER_TIMER10_CLKCTRL; + + } else { + /* Enable Timer 6 for DSP2 */ + timer_reg = CM_IPU_TIMER6_CLKCTRL; + prm_base = DSP2_PRM_BASE; + dsp_clkstctrl = CM_DSP2_CLKSTCTRL; + mmu_config = DSP2_SYS_MMU_CONFIG; + } + + /* Using TIMER_SYS_CLK as the clock source */ + reg = __raw_readl(timer_reg); + __raw_writel((reg & ~0x0F000003) | 0x00000002, timer_reg); + debug("Enabled SysBIOS Tick Timer\n"); + + /* Enable the watchdog timer */ + if (wdt_ctrl != 0) { + /* + * Using SYS_CLK1_32K_CLK as the clock source for the + * watch dog timers. DSP will eventually configure + * these timers with the right clock source. If we use + * a higher frequency clock as the clock source, the + * timer will overflow and trigger a watchdog interrupt + * even before the kernel has a chance to connect to + * DSP. + */ + reg = __raw_readl(wdt_ctrl); + __raw_writel((reg & ~0x0F000003) | 0x01000002, + wdt_ctrl); + } + + /* Enable the DSP Clock domain in SW Wkup */ + __raw_writel(0x2, dsp_clkstctrl); + + /* Enable DSP and check that the clock is gated in the clock domain + register */ + __raw_writel(0x1, dsp_clkstctrl + 0x20); + while ((__raw_readl(dsp_clkstctrl) & 0x100) != 0x100); + debug("DSP Clock enabled and gated in domain controller\n"); + + /* + * Clear the prm status bits before bringing the core out of reset. + * This will prevent the below status checks from passing prematurely + * if the DSP core was powered on and off earlier in U-Boot. + * The register is write '1' to clear a bit. */ + __raw_writel(0x3, prm_base + 0x14); + + /* + * Enable RESET for the DSP MMU, cache and slave interface and + * DSP local reset. This may not be necessary since the reset value + * is the same.*/ + __raw_writel(0x3, prm_base + 0x10); + + /* Bring the MMU, cache and reset interface out of reset */ + __raw_writel(0x1, prm_base + 0x10); + + /* + * Check that the reset state reflects correctly in the status + * register. + */ + while ((__raw_readl(prm_base + 0x14) & 0x2) != 0x2); + debug("DSP MMU out of reset\n"); + + /* Enable the DSP1 SDMA and MDMA accesses to pass through the MMU */ + if (cfg->has_rsc_table) + __raw_writel(0x11, mmu_config); + + /* At this point, the DSP MMU can be configured. */ + + debug("DSP ready for MMU configuration and code loading\n"); + + return 0; +} + +u32 dsp_start_core(u32 core_id, struct rproc *cfg) +{ + u32 prm_base = 0; + u32 boot_addr = 0; + u32 ret = 1; + + if (core_id == DSP1) { + prm_base = DSP1_PRM_BASE; + boot_addr = DSP1_BOOTADDR; + ret = 0; + } else if (core_id == DSP2) { + prm_base = DSP2_PRM_BASE; + boot_addr = DSP2_BOOTADDR; + ret = 0; + } + + if (ret == 0) { + u32 boot_reg = 0; + + /* Configure the DSP entry point */ + /* DSP boots from CTRL_CORE_CONTROL_DSP1_RST_VECTOR */ + /* Boot address is shifted by 10 bits before begin written */ + + boot_reg = __raw_readl(boot_addr); + boot_reg = (boot_reg & (~DRA7XX_CTRL_CORE_DSP_RST_VECT_MASK)); + boot_reg = + (boot_reg | + ((cfg-> + entry_point >> 10) & + DRA7XX_CTRL_CORE_DSP_RST_VECT_MASK)); + + __raw_writel(boot_reg, boot_addr); + + /* bring the DSP out of reset */ + __raw_writel(0x0, prm_base + 0x10); + + /* check module is functional or not */ + while (((__raw_readl(prm_base + 0x14) & 0x3) != 0x3)); + + ret = 0; + } + + return ret; +} + +/* + * If the remotecore binary expects any peripherals to be setup before it has + * booted, configure them here. + * + * These functions are left empty by default as their operation is usecase + * specific. + */ + +u32 ipu1_config_peripherals(u32 core_id, struct rproc *cfg) +{ + return 0; +} + +u32 ipu2_config_peripherals(u32 core_id, struct rproc *cfg) +{ + return 0; +} + +u32 dsp1_config_peripherals(u32 core_id, struct rproc *cfg) +{ + return 0; +} + +u32 dsp2_config_peripherals(u32 core_id, struct rproc *cfg) +{ + return 0; +} + +struct rproc_intmem_to_l3_mapping ipu1_intmem_to_l3_mapping = { + .num_entries = 1, + .mappings = { + /* L2 SRAM */ + { + .priv_addr = 0x55020000, + .l3_addr = 0x58820000, + .len = (64*1024) + }, + } +}; + +struct rproc_intmem_to_l3_mapping ipu2_intmem_to_l3_mapping = { + .num_entries = 1, + .mappings = { + /* L2 SRAM */ + { + .priv_addr = 0x55020000, + .l3_addr = 0x55020000, + .len = (64*1024) + }, + } +}; + +struct rproc_intmem_to_l3_mapping dsp1_intmem_to_l3_mapping = { + .num_entries = 3, + .mappings = { + /* L2 SRAM */ + { + .priv_addr = 0x00800000, + .l3_addr = 0x40800000, + .len = (288*1024) + }, + /* L1P SRAM */ + { + .priv_addr = 0x00E00000, + .l3_addr = 0x40E00000, + .len = (32*1024) + }, + /* L1D SRAM */ + { + .priv_addr = 0x00F00000, + .l3_addr = 0x40F00000, + .len = (32*1024) + }, + } +}; + +struct rproc_intmem_to_l3_mapping dsp2_intmem_to_l3_mapping = { + .num_entries = 3, + .mappings = { + /* L2 SRAM */ + { + .priv_addr = 0x00800000, + .l3_addr = 0x41000000, + .len = (288*1024) + }, + /* L1P SRAM */ + { + .priv_addr = 0x00E00000, + .l3_addr = 0x41600000, + .len = (32*1024) + }, + /* L1D SRAM */ + { + .priv_addr = 0x00F00000, + .l3_addr = 0x41700000, + .len = (32*1024) + }, + } +}; +struct rproc ipu1_config = { + .num_iommus = 1, + .cma_base = DRA7_RPROC_CMA_BASE_IPU1, + .cma_size = DRA7_RPROC_CMA_SIZE_IPU1, + .page_table_addr = DRA7_PGTBL_BASE_IPU1, + .mmu_base_addr = {0x58882000, 0}, + .load_addr = IPU1_LOAD_ADDR, + .core_name = "IPU1", + .firmware_name = "dra7-ipu1-fw.xem4", +#ifdef CONFIG_MMC_IPU1_PART_NAME + .ptn = CONFIG_MMC_IPU1_PART_NAME, +#else + .ptn = NULL, +#endif + .start_clocks = ipu_start_clocks, + .config_mmu = ipu_config_mmu, + .config_peripherals = ipu1_config_peripherals, + .start_core = ipu_start_core, + .intmem_to_l3_mapping = &ipu1_intmem_to_l3_mapping +}; + +struct rproc ipu2_config = { + .num_iommus = 1, + .cma_base = DRA7_RPROC_CMA_BASE_IPU2, + .cma_size = DRA7_RPROC_CMA_SIZE_IPU2, + .page_table_addr = DRA7_PGTBL_BASE_IPU2, + .mmu_base_addr = {0x55082000, 0}, + .load_addr = IPU2_LOAD_ADDR, + .core_name = "IPU2", + .firmware_name = "dra7-ipu2-fw.xem4", +#ifdef CONFIG_MMC_IPU2_PART_NAME + .ptn = CONFIG_MMC_IPU2_PART_NAME, +#else + .ptn = NULL, +#endif + .start_clocks = ipu_start_clocks, + .config_mmu = ipu_config_mmu, + .config_peripherals = ipu2_config_peripherals, + .start_core = ipu_start_core, + .intmem_to_l3_mapping = &ipu2_intmem_to_l3_mapping +}; + +struct rproc dsp1_config = { + .num_iommus = 2, + .cma_base = DRA7_RPROC_CMA_BASE_DSP1, + .cma_size = DRA7_RPROC_CMA_SIZE_DSP1, + .page_table_addr = DRA7_PGTBL_BASE_DSP1, + .mmu_base_addr = {0x40D01000, 0x40D02000}, + .load_addr = DSP1_LOAD_ADDR, + .core_name = "DSP1", + .firmware_name = "dra7-dsp1-fw.xe66", +#ifdef CONFIG_MMC_DSP1_PART_NAME + .ptn = CONFIG_MMC_DSP1_PART_NAME, +#else + .ptn = NULL, +#endif + .start_clocks = dsp_start_clocks, + .config_mmu = ipu_config_mmu, + .config_peripherals = dsp1_config_peripherals, + .start_core = dsp_start_core, + .intmem_to_l3_mapping = &dsp1_intmem_to_l3_mapping +}; + +struct rproc dsp2_config = { + .num_iommus = 2, + .cma_base = DRA7_RPROC_CMA_BASE_DSP2, + .cma_size = DRA7_RPROC_CMA_SIZE_DSP2, + .page_table_addr = DRA7_PGTBL_BASE_DSP2, + .mmu_base_addr = {0x41501000, 0x41502000}, + .load_addr = DSP2_LOAD_ADDR, + .core_name = "DSP2", + .firmware_name = "dra7-dsp2-fw.xe66", +#ifdef CONFIG_MMC_DSP2_PART_NAME + .ptn = CONFIG_MMC_DSP2_PART_NAME, +#else + .ptn = NULL, +#endif + .start_clocks = dsp_start_clocks, + .config_mmu = ipu_config_mmu, + .config_peripherals = dsp2_config_peripherals, + .start_core = dsp_start_core, + .intmem_to_l3_mapping = &dsp2_intmem_to_l3_mapping +}; + +struct rproc *rproc_cfg_arr[RPROC_END_ENUMS] = { + [IPU2] = &ipu2_config, + [IPU1] = &ipu1_config, + [DSP2] = &dsp2_config, + [DSP1] = &dsp1_config +}; + +u32 spl_boot_core(u32 core_id) +{ + struct rproc *cfg = NULL; + unsigned long load_elf_status = 0; + int tablesz; + + if ((core_id == 0) || (core_id >= RPROC_END_ENUMS)) { + debug("Invalid core id speicified: %d\n", core_id); + return 1; + } + + cfg = rproc_cfg_arr[core_id]; + + /* Check for valid elf image */ + if (!valid_elf_image_local(cfg->load_addr)) + return 1; + else + debug("Core %d ELF Image is valid\n", core_id); + + if (find_resource_table(cfg->load_addr, &tablesz)) + cfg->has_rsc_table = 1; + else + cfg->has_rsc_table = 0; + + /* Clock the remote core */ + if (cfg->start_clocks) + cfg->start_clocks(core_id, cfg); + + debug("Configuring IOMMU\n"); + + /* Configure the MMU */ + if (cfg->config_mmu && cfg->has_rsc_table) + cfg->config_mmu(core_id, cfg); + + debug("Configured the IOMMU\n"); + /* Load the remote core. + * + * Fill the page table of the first(possibly only) IOMMU during ELF + * loading. Copy the page table to the second IOMMU before running the + * remote core. + */ + + page_table_l1 = (unsigned int *)cfg->page_table_addr; + page_table_l2 = + (unsigned int *)(cfg->page_table_addr + PAGE_TABLE_SIZE_L1); + mem_base = cfg->cma_base; + mem_size = cfg->cma_size; + memset(mem_bitmap, 0x00, sizeof(mem_bitmap)); + mem_count = (cfg->cma_size >> PAGE_SHIFT); + + /* Clear variables used for level 2 page table allocation */ + memset(pgtable_l2_map, 0x00, sizeof(pgtable_l2_map)); + pgtable_l2_cnt = 0; + + debug("Loading ELF Image\n"); + load_elf_status = load_elf_image_phdr_rproc(cfg); + if (load_elf_status == 0) { + printf("load_elf_image_phdr returned error for core %s\n", + cfg->core_name); + return 1; + } else { + debug("Core entry point is 0x%08x\n", + (unsigned int)cfg->entry_point); + } + flush_cache(cfg->page_table_addr, PAGE_TABLE_SIZE); + + + if (cfg->config_peripherals) + cfg->config_peripherals(core_id, cfg); + + /* Start running the remote core */ + debug("Starting the remote core\n"); + if (cfg->start_core) + cfg->start_core(core_id, cfg); + + return 0; +} + diff --git a/board/ti/dra7xx/mux_data.h b/board/ti/dra7xx/mux_data.h index 54d5995628..e70f8e6b8c 100644 --- a/board/ti/dra7xx/mux_data.h +++ b/board/ti/dra7xx/mux_data.h @@ -159,6 +159,27 @@ const struct pad_conf_entry dra72x_core_padconf_array_common[] = { {I2C2_SCL, (M1 | PIN_INPUT_PULLUP)}, /* i2c2_scl.hdmi1_ddc_sda */ {WAKEUP0, (M15 | PULL_UP)}, /* Wakeup0.safe for dcan1_rx */ {WAKEUP3, (M1 | PULL_ENA | PULL_UP)}, /* Wakeup3.sys_nirq1 */ + +#ifdef CONFIG_DRA7XX_JAMR3 + {XREF_CLK1, (M5 | PIN_INPUT_PULLDOWN)}, /* xref_clk1.atl_clk1 */ + {XREF_CLK3, (M14 | PIN_INPUT)}, /* xref_clk3.gpio6_20 */ + {MCASP1_AXR8, (M1 | PIN_OUTPUT_PULLDOWN | SLEWCONTROL)}, /* mcasp1_axr8.mcasp6_axr0 */ + {MCASP1_AXR9, (M1 | PIN_INPUT_SLEW)}, /* mcasp1_axr9.mcasp6_axr1 */ + {MCASP1_AXR10, (M1 | PIN_INPUT_SLEW)}, /* mcasp1_axr10.mcasp6_aclkx */ + {MCASP1_AXR11, (M1 | PIN_INPUT_SLEW)}, /* mcasp1_axr11.mcasp6_fsx */ + {MCASP2_ACLKX, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE9)}, /* mcasp2_aclkx.mcasp2_aclkx */ + {MCASP2_FSX, (M0 | PIN_INPUT_SLEW | VIRTUAL_MODE9)}, /* mcasp2_fsx.mcasp2_fsx */ + {MCASP2_AXR0, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE12)}, /* mcasp2_axr0.mcasp2_axr0 */ + {MCASP2_AXR1, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE12)}, /* mcasp2_axr1.mcasp2_axr1 */ + {MCASP2_AXR2, (M0 | PIN_INPUT_SLEW | VIRTUAL_MODE9)}, /* mcasp2_axr2.mcasp2_axr2 */ + {MCASP2_AXR3, (M0 | PIN_INPUT_SLEW | VIRTUAL_MODE9)}, /* mcasp2_axr3.mcasp2_axr3 */ + {MCASP2_AXR4, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE12)}, /* mcasp2_axr4.mcasp2_axr4 */ + {MCASP2_AXR5, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE12)}, /* mcasp2_axr5.mcasp2_axr5 */ + {MCASP2_AXR6, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE12)}, /* mcasp2_axr6.mcasp2_axr6 */ + {MCASP2_AXR7, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE12)}, /* mcasp2_axr7.mcasp2_axr7 */ + {MCASP4_ACLKX, (M4 | PIN_INPUT_PULLUP)},/* mcasp4_aclkx.i2c4_sda */ + {MCASP4_FSX, (M4 | PIN_INPUT_PULLUP)}, /* mcasp4_fsx.i2c4_scl */ +#endif }; const struct pad_conf_entry dra72x_rgmii_padconf_array_revb[] = { @@ -192,6 +213,64 @@ const struct pad_conf_entry dra72x_rgmii_padconf_array_revb[] = { }; const struct pad_conf_entry dra72x_rgmii_padconf_array_revc[] = { +#ifdef CONFIG_TARGET_DRA7XX_EVM_VISION + /* vin1a */ + { GPMC_AD0, (M2 | PIN_INPUT | VIRTUAL_MODE12) }, /* gpmc_ad0.vin1a_d0 */ + { GPMC_AD1, (M2 | PIN_INPUT | VIRTUAL_MODE12) }, /* gpmc_ad1.vin1a_d1 */ + { GPMC_AD2, (M2 | PIN_INPUT | VIRTUAL_MODE12) }, /* gpmc_ad2.vin1a_d2 */ + { GPMC_AD3, (M2 | PIN_INPUT | VIRTUAL_MODE12) }, /* gpmc_ad3.vin1a_d3 */ + { GPMC_AD4, (M2 | PIN_INPUT | VIRTUAL_MODE12) }, /* gpmc_ad4.vin1a_d4 */ + { GPMC_AD5, (M2 | PIN_INPUT | VIRTUAL_MODE12) }, /* gpmc_ad5.vin1a_d5 */ + { GPMC_AD6, (M2 | PIN_INPUT | VIRTUAL_MODE12) }, /* gpmc_ad6.vin1a_d6 */ + { GPMC_AD7, (M2 | PIN_INPUT | VIRTUAL_MODE12) }, /* gpmc_ad7.vin1a_d7 */ + { GPMC_A8, (M2 | PIN_INPUT | VIRTUAL_MODE12) }, /* gpmc_a8.vin1a_hsync0 */ + { GPMC_A9, (M2 | PIN_INPUT | VIRTUAL_MODE12) }, /* gpmc_a9.vin1a_vsync0 */ + { GPMC_CS3, (M2 | PIN_INPUT | VIRTUAL_MODE11) }, /* gpmc_cs3.vin1a_clk0 */ + + /* vin1b */ + { MDIO_MCLK, (M5 | PIN_INPUT | SLEWCONTROL | VIRTUAL_MODE10) }, /* mdio_mclk.vin1b_clk1 */ + { MDIO_D, (M5 | PIN_INPUT | SLEWCONTROL | VIRTUAL_MODE10) }, /* mdio_d.vin1b_d0 */ + { UART3_RXD, (M5 | PIN_INPUT | SLEWCONTROL | VIRTUAL_MODE10) }, /* uart3_rxd.vin1b_d1 */ + { UART3_TXD, (M5 | PIN_INPUT | SLEWCONTROL | VIRTUAL_MODE10) }, /* uart3_txd.vin1b_d2 */ + { RGMII0_TXC, (M5 | PIN_INPUT | VIRTUAL_MODE10) }, /* rgmii0_txc.vin1b_d3 */ + { RGMII0_TXCTL, (M5 | PIN_INPUT | VIRTUAL_MODE10) }, /* rgmii0_txctl.vin1b_d4 */ + { RGMII0_TXD2, (M5 | PIN_INPUT | VIRTUAL_MODE10) }, /* rgmii0_txd2.vin1b_hsync1 */ + { RGMII0_TXD1, (M5 | PIN_INPUT | VIRTUAL_MODE10) }, /* rgmii0_txd1.vin1b_vsync1 */ + { RGMII0_RXC, (M5 | PIN_INPUT | VIRTUAL_MODE10) }, /* rgmii0_rxc.vin1b_d5 */ + { RGMII0_RXCTL, (M5 | PIN_INPUT | VIRTUAL_MODE10) }, /* rgmii0_rxctl.vin1b_d6 */ + { RGMII0_RXD3, (M5 | PIN_INPUT | VIRTUAL_MODE10) }, /* rgmii0_rxd3.vin1b_d7 */ + + /* vin2a */ + { VIN2A_CLK0, (M0 | PIN_INPUT | VIRTUAL_MODE9) }, /* vin2a_clk0.vin2a_clk0 */ + { VIN2A_HSYNC0, (M0 | PIN_INPUT | VIRTUAL_MODE6) }, /* vin2a_hsync0.vin2a_hsync0 */ + { VIN2A_VSYNC0, (M0 | PIN_INPUT | VIRTUAL_MODE9) }, /* vin2a_vsync0.vin2a_vsync0 */ + { VIN2A_D0, (M0 | PIN_INPUT | VIRTUAL_MODE14) }, /* vin2a_d0.vin2a_d0 */ + { VIN2A_D1, (M0 | PIN_INPUT | VIRTUAL_MODE14) }, /* vin2a_d1.vin2a_d1 */ + { VIN2A_D2, (M0 | PIN_INPUT | VIRTUAL_MODE14) }, /* vin2a_d2.vin2a_d2 */ + { VIN2A_D3, (M0 | PIN_INPUT | VIRTUAL_MODE8) }, /* vin2a_d3.vin2a_d3 */ + { VIN2A_D4, (M0 | PIN_INPUT | VIRTUAL_MODE8) }, /* vin2a_d4.vin2a_d4 */ + { VIN2A_D5, (M0 | PIN_INPUT | VIRTUAL_MODE8) }, /* vin2a_d5.vin2a_d5 */ + { VIN2A_D6, (M0 | PIN_INPUT | VIRTUAL_MODE6) }, /* vin2a_d6.vin2a_d6 */ + { VIN2A_D7, (M0 | PIN_INPUT | VIRTUAL_MODE6) }, /* vin2a_d7.vin2a_d7 */ + + /* vin2b */ + { GPIO6_10, (M4 | PIN_INPUT | VIRTUAL_MODE8) }, /* gpio6_10.vin2b_hsync1 */ + { GPIO6_11, (M4 | PIN_INPUT | VIRTUAL_MODE8) }, /* gpio6_11.vin2b_vsync1 */ + { MMC3_CLK, (M4 | PIN_INPUT | VIRTUAL_MODE7) }, /* mmc3_clk.vin2b_d7 */ + { MMC3_CMD, (M4 | PIN_INPUT | VIRTUAL_MODE7) }, /* mmc3_cmd.vin2b_d6 */ + { MMC3_DAT0, (M4 | PIN_INPUT | VIRTUAL_MODE7) }, /* mmc3_dat0.vin2b_d5 */ + { MMC3_DAT1, (M4 | PIN_INPUT | VIRTUAL_MODE7) }, /* mmc3_dat1.vin2b_d4 */ + { MMC3_DAT2, (M4 | PIN_INPUT | VIRTUAL_MODE7) }, /* mmc3_dat2.vin2b_d3 */ + { MMC3_DAT3, (M4 | PIN_INPUT | VIRTUAL_MODE7) }, /* mmc3_dat3.vin2b_d2 */ + { MMC3_DAT4, (M4 | PIN_INPUT | VIRTUAL_MODE7) }, /* mmc3_dat4.vin2b_d1 */ + { MMC3_DAT5, (M4 | PIN_INPUT | VIRTUAL_MODE7) }, /* mmc3_dat5.vin2b_d0 */ + { MMC3_DAT7, (M4 | PIN_INPUT | VIRTUAL_MODE7) }, /* mmc3_dat7.vin2b_clk1 */ + + /* alternate mdio */ + { VIN2A_D10, (M3 | PIN_INPUT_PULLUP) }, /* vin2a_d10.mdio_mclk */ + { VIN2A_D11, (M3 | PIN_INPUT_PULLUP) }, /* vin2a_d11.mdio_d */ +#endif + {VIN2A_FLD0, (M14 | PIN_INPUT)}, /* vin2a_fld0.gpio3_30 */ {RGMII0_TXC, (M0 | PIN_OUTPUT | MANUAL_MODE)}, /* rgmii0_txc.rgmii0_txc */ {RGMII0_TXCTL, (M0 | PIN_OUTPUT | MANUAL_MODE)}, /* rgmii0_txctl.rgmii0_txctl */ @@ -369,6 +448,26 @@ const struct pad_conf_entry dra71x_core_padconf_array[] = { {I2C2_SCL, (M1 | PIN_INPUT_PULLUP)}, /* i2c2_scl.hdmi1_ddc_sda */ {WAKEUP0, (M15 | PULL_UP)}, /* Wakeup0.safe for dcan1_rx */ {WAKEUP3, (M1 | PULL_ENA | PULL_UP)}, /* Wakeup3.sys_nirq1 */ +#ifdef CONFIG_DRA7XX_JAMR3 + {XREF_CLK1, (M5 | PIN_INPUT_PULLDOWN)}, /* xref_clk1.atl_clk1 */ + {XREF_CLK3, (M14 | PIN_INPUT)}, /* xref_clk3.gpio6_20 */ + {MCASP1_AXR8, (M1 | PIN_OUTPUT_PULLDOWN | SLEWCONTROL)}, /* mcasp1_axr8.mcasp6_axr0 */ + {MCASP1_AXR9, (M1 | PIN_INPUT_SLEW)}, /* mcasp1_axr9.mcasp6_axr1 */ + {MCASP1_AXR10, (M1 | PIN_INPUT_SLEW)}, /* mcasp1_axr10.mcasp6_aclkx */ + {MCASP1_AXR11, (M1 | PIN_INPUT_SLEW)}, /* mcasp1_axr11.mcasp6_fsx */ + {MCASP2_ACLKX, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE9)}, /* mcasp2_aclkx.mcasp2_aclkx */ + {MCASP2_FSX, (M0 | PIN_INPUT_SLEW | VIRTUAL_MODE9)}, /* mcasp2_fsx.mcasp2_fsx */ + {MCASP2_AXR0, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE12)}, /* mcasp2_axr0.mcasp2_axr0 */ + {MCASP2_AXR1, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE12)}, /* mcasp2_axr1.mcasp2_axr1 */ + {MCASP2_AXR2, (M0 | PIN_INPUT_SLEW | VIRTUAL_MODE9)}, /* mcasp2_axr2.mcasp2_axr2 */ + {MCASP2_AXR3, (M0 | PIN_INPUT_SLEW | VIRTUAL_MODE9)}, /* mcasp2_axr3.mcasp2_axr3 */ + {MCASP2_AXR4, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE12)}, /* mcasp2_axr4.mcasp2_axr4 */ + {MCASP2_AXR5, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE12)}, /* mcasp2_axr5.mcasp2_axr5 */ + {MCASP2_AXR6, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE12)}, /* mcasp2_axr6.mcasp2_axr6 */ + {MCASP2_AXR7, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE12)}, /* mcasp2_axr7.mcasp2_axr7 */ + {MCASP4_ACLKX, (M4 | PIN_INPUT_PULLUP)},/* mcasp4_aclkx.i2c4_sda */ + {MCASP4_FSX, (M4 | PIN_INPUT_PULLUP)}, /* mcasp4_fsx.i2c4_scl */ +#endif }; const struct pad_conf_entry early_padconf[] = { @@ -696,6 +795,75 @@ const struct pad_conf_entry dra74x_core_padconf_array[] = { {I2C2_SCL, (M0 | PIN_INPUT_PULLUP)}, /* i2c2_scl.i2c2_scl */ {WAKEUP0, (M15 | PULL_UP)}, /* Wakeup0.safe for dcan1_rx */ {WAKEUP2, (M14)}, /* Wakeup2.gpio1_2 */ + +#ifdef CONFIG_DRA7XX_JAMR3 + {XREF_CLK1, (M5 | PIN_INPUT_PULLDOWN)}, /* xref_clk1.atl_clk1 */ + {XREF_CLK3, (M14 | PIN_INPUT)}, /* xref_clk3.gpio6_20 */ + {MCASP1_AXR8, (M1 | PIN_OUTPUT_PULLDOWN | SLEWCONTROL)}, /* mcasp1_axr8.mcasp6_axr0 */ + {MCASP1_AXR9, (M1 | PIN_INPUT_SLEW)}, /* mcasp1_axr9.mcasp6_axr1 */ + {MCASP1_AXR10, (M1 | PIN_INPUT_SLEW)}, /* mcasp1_axr10.mcasp6_aclkx */ + {MCASP1_AXR11, (M1 | PIN_INPUT_SLEW)}, /* mcasp1_axr11.mcasp6_fsx */ + {MCASP2_ACLKX, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE9)}, /* mcasp2_aclkx.mcasp2_aclkx */ + {MCASP2_FSX, (M0 | PIN_INPUT_SLEW | VIRTUAL_MODE9)}, /* mcasp2_fsx.mcasp2_fsx */ + {MCASP2_AXR0, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE12)}, /* mcasp2_axr0.mcasp2_axr0 */ + {MCASP2_AXR1, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE12)}, /* mcasp2_axr1.mcasp2_axr1 */ + {MCASP2_AXR2, (M0 | PIN_INPUT_SLEW | VIRTUAL_MODE9)}, /* mcasp2_axr2.mcasp2_axr2 */ + {MCASP2_AXR3, (M0 | PIN_INPUT_SLEW | VIRTUAL_MODE9)}, /* mcasp2_axr3.mcasp2_axr3 */ + {MCASP2_AXR4, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE12)}, /* mcasp2_axr4.mcasp2_axr4 */ + {MCASP2_AXR5, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE12)}, /* mcasp2_axr5.mcasp2_axr5 */ + {MCASP2_AXR6, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE12)}, /* mcasp2_axr6.mcasp2_axr6 */ + {MCASP2_AXR7, (M0 | PIN_INPUT_PULLDOWN | VIRTUAL_MODE12)}, /* mcasp2_axr7.mcasp2_axr7 */ + {MCASP4_ACLKX, (M4 | PIN_INPUT_PULLUP)},/* mcasp4_aclkx.i2c4_sda */ + {MCASP4_FSX, (M4 | PIN_INPUT_PULLUP)}, /* mcasp4_fsx.i2c4_scl */ +#endif + +#ifdef CONFIG_TARGET_DRA7XX_EVM_VISION + { VIN1B_CLK1, (M6 | PIN_INPUT | MANUAL_MODE) }, /* vin1b_clk1.vin3a_clk0 */ + { VIN1A_D16, (M6 | PIN_INPUT | MANUAL_MODE) }, /* vin1a_d16.vin3a_d0 */ + { VIN1A_D17, (M6 | PIN_INPUT | MANUAL_MODE) }, /* vin1a_d17.vin3a_d1 */ + { VIN1A_D18, (M6 | PIN_INPUT | MANUAL_MODE) }, /* vin1a_d18.vin3a_d2 */ + { VIN1A_D19, (M6 | PIN_INPUT | MANUAL_MODE) }, /* vin1a_d19.vin3a_d3 */ + { VIN1A_D20, (M6 | PIN_INPUT | MANUAL_MODE) }, /* vin1a_d20.vin3a_d4 */ + { VIN1A_D21, (M6 | PIN_INPUT | MANUAL_MODE) }, /* vin1a_d21.vin3a_d5 */ + { VIN1A_D22, (M6 | PIN_INPUT | MANUAL_MODE) }, /* vin1a_d22.vin3a_d6 */ + { VIN1A_D23, (M6 | PIN_INPUT | MANUAL_MODE) }, /* vin1a_d23.vin3a_d7 */ + { VIN2A_CLK0, (M0 | PIN_INPUT | MANUAL_MODE) }, /* vin2a_clk0.vin2a_clk0 */ + { VIN2A_HSYNC0, (M0 | PIN_INPUT | MANUAL_MODE) }, /* vin2a_hsync0.vin2a_hsync0 */ + { VIN2A_VSYNC0, (M0 | PIN_INPUT | MANUAL_MODE) }, /* vin2a_vsync0.vin2a_vsync0 */ + { VIN2A_D0, (M0 | PIN_INPUT | MANUAL_MODE) }, /* vin2a_d0.vin2a_d0 */ + { VIN2A_D1, (M0 | PIN_INPUT | MANUAL_MODE) }, /* vin2a_d1.vin2a_d1 */ + { VIN2A_D2, (M0 | PIN_INPUT | MANUAL_MODE) }, /* vin2a_d2.vin2a_d2 */ + { VIN2A_D3, (M0 | PIN_INPUT | MANUAL_MODE) }, /* vin2a_d3.vin2a_d3 */ + { VIN2A_D4, (M0 | PIN_INPUT | MANUAL_MODE) }, /* vin2a_d4.vin2a_d4 */ + { VIN2A_D5, (M0 | PIN_INPUT | MANUAL_MODE) }, /* vin2a_d5.vin2a_d5 */ + { VIN2A_D6, (M0 | PIN_INPUT | MANUAL_MODE) }, /* vin2a_d6.vin2a_d6 */ + { VIN2A_D7, (M0 | PIN_INPUT | MANUAL_MODE) }, /* vin2a_d7.vin2a_d7 */ + { VIN2A_D22, (M5 | PIN_INPUT | MANUAL_MODE) }, /* vin2a_d22.vin3a_hsync0 */ + { VIN2A_D23, (M5 | PIN_INPUT | MANUAL_MODE) }, /* vin2a_d23.vin3a_vsync0 */ + { XREF_CLK1, (M7 | PIN_INPUT | MANUAL_MODE) }, /* xref_clk1.vin6a_clk0 */ + { MCASP1_AXR0, (M7 | PIN_INPUT | MANUAL_MODE) }, /* mcasp1_axr0.vin6a_vsync0 */ + { MCASP1_AXR1, (M7 | PIN_INPUT | MANUAL_MODE) }, /* mcasp1_axr1.vin6a_hsync0 */ + { MCASP2_ACLKX, (M7 | PIN_INPUT | MANUAL_MODE) }, /* mcasp2_aclkx.vin6a_d7 */ + { MCASP2_FSX, (M7 | PIN_INPUT | MANUAL_MODE) }, /* mcasp2_fsx.vin6a_d6 */ + { MCASP2_AXR2, (M7 | PIN_INPUT | MANUAL_MODE) }, /* mcasp2_axr2.vin6a_d5 */ + { MCASP2_AXR3, (M7 | PIN_INPUT | MANUAL_MODE) }, /* mcasp2_axr3.vin6a_d4 */ + { MCASP3_ACLKX, (M7 | PIN_INPUT | MANUAL_MODE) }, /* mcasp3_aclkx.vin6a_d3 */ + { MCASP3_FSX, (M7 | PIN_INPUT | MANUAL_MODE) }, /* mcasp3_fsx.vin6a_d2 */ + { MCASP3_AXR0, (M7 | PIN_INPUT | MANUAL_MODE) }, /* mcasp3_axr0.vin6a_d1 */ + { MCASP3_AXR1, (M7 | PIN_INPUT | MANUAL_MODE) }, /* mcasp3_axr1.vin6a_d0 */ + { GPIO6_10, (M9 | PIN_INPUT | MANUAL_MODE) }, /* gpio6_10.vin5a_clk0 */ + { MMC3_CLK, (M9 | PIN_INPUT | MANUAL_MODE) }, /* mmc3_clk.vin5a_d7 */ + { MMC3_CMD, (M9 | PIN_INPUT | MANUAL_MODE) }, /* mmc3_cmd.vin5a_d6 */ + { MMC3_DAT0, (M9 | PIN_INPUT | MANUAL_MODE) }, /* mmc3_dat0.vin5a_d5 */ + { MMC3_DAT1, (M9 | PIN_INPUT | MANUAL_MODE) }, /* mmc3_dat1.vin5a_d4 */ + { MMC3_DAT2, (M9 | PIN_INPUT | MANUAL_MODE) }, /* mmc3_dat2.vin5a_d3 */ + { MMC3_DAT3, (M9 | PIN_INPUT | MANUAL_MODE) }, /* mmc3_dat3.vin5a_d2 */ + { MMC3_DAT4, (M9 | PIN_INPUT | MANUAL_MODE) }, /* mmc3_dat4.vin5a_d1 */ + { MMC3_DAT5, (M9 | PIN_INPUT | MANUAL_MODE) }, /* mmc3_dat5.vin5a_d0 */ + { MMC3_DAT6, (M9 | PIN_INPUT | MANUAL_MODE) }, /* mmc3_dat6.vin5a_hsync0 */ + { MMC3_DAT7, (M9 | PIN_INPUT | MANUAL_MODE) }, /* mmc3_dat7.vin5a_vsync0 */ +#endif + }; #ifdef CONFIG_IODELAY_RECALIBRATION @@ -761,6 +929,53 @@ const struct iodelay_cfg_entry dra742_es1_1_iodelay_cfg_array[] = { {0x0174, 1904, 1471}, /* CFG_GPMC_A17_IN */ {0x0188, 1690, 0}, /* CFG_GPMC_A18_OUT */ {0x0374, 0, 0}, /* CFG_GPMC_CS2_OUT */ +#ifdef CONFIG_TARGET_DRA7XX_EVM_VISION + { 0x0A2C, 0, 0 }, /* CFG_VIN1B_CLK1_IN : VIN3A_CLK0 - VIP2_MANUAL2 */ + { 0x0930, 2805, 459 }, /* CFG_VIN1A_D16_IN : VIN3A_D0 - VIP2_MANUAL2 */ + { 0x093C, 2904, 360 }, /* CFG_VIN1A_D17_IN : VIN3A_D1 - VIP2_MANUAL2 */ + { 0x0948, 2857, 527 }, /* CFG_VIN1A_D18_IN : VIN3A_D2 - VIP2_MANUAL2 */ + { 0x0954, 2861, 517 }, /* CFG_VIN1A_D19_IN : VIN3A_D3 - VIP2_MANUAL2 */ + { 0x096C, 2855, 344 }, /* CFG_VIN1A_D20_IN : VIN3A_D4 - VIP2_MANUAL2 */ + { 0x0978, 2908, 248 }, /* CFG_VIN1A_D21_IN : VIN3A_D5 - VIP2_MANUAL2 */ + { 0x0984, 2843, 191 }, /* CFG_VIN1A_D22_IN : VIN3A_D6 - VIP2_MANUAL2 */ + { 0x0990, 2683, 0 }, /* CFG_VIN1A_D23_IN : VIN3A_D7 - VIP2_MANUAL2 */ + { 0x0A38, 0, 0 }, /* CFG_VIN2A_CLK0_IN : VIN2A_CLK0 - VIP1_MANUAL2 */ + { 0x0B7C, 2174, 0 }, /* CFG_VIN2A_HSYNC0_IN : VIN2A_HSYNC0 - VIP1_MANUAL2 */ + { 0x0B88, 1924, 0 }, /* CFG_VIN2A_VSYNC0_IN : VIN2A_VSYNC0 - VIP1_MANUAL2 */ + { 0x0A44, 2090, 0 }, /* CFG_VIN2A_D0_IN : VIN2A_D0 - VIP1_MANUAL2 */ + { 0x0AC8, 2481, 0 }, /* CFG_VIN2A_D1_IN : VIN2A_D1 - VIP1_MANUAL2 */ + { 0x0B04, 1970, 0 }, /* CFG_VIN2A_D2_IN : VIN2A_D2 - VIP1_MANUAL2 */ + { 0x0B10, 2525, 0 }, /* CFG_VIN2A_D3_IN : VIN2A_D3 - VIP1_MANUAL2 */ + { 0x0B1C, 1981, 0 }, /* CFG_VIN2A_D4_IN : VIN2A_D4 - VIP1_MANUAL2 */ + { 0x0B28, 2510, 0 }, /* CFG_VIN2A_D5_IN : VIN2A_D5 - VIP1_MANUAL2 */ + { 0x0B34, 1769, 0 }, /* CFG_VIN2A_D6_IN : VIN2A_D6 - VIP1_MANUAL2 */ + { 0x0B40, 2080, 0 }, /* CFG_VIN2A_D7_IN : VIN2A_D7 - VIP1_MANUAL2 */ + { 0x0AEC, 1606, 0 }, /* CFG_VIN2A_D22_IN : VIN3A_HSYNC0 - VIP2_MANUAL2 */ + { 0x0AF8, 1673, 0 }, /* CFG_VIN2A_D23_IN : VIN3A_VSYNC0 - VIP2_MANUAL2 */ + { 0x0CFC, 0, 0 }, /* CFG_XREF_CLK1_IN : VIN6A_CLK0 - VIP3_MANUAL2 */ + { 0x03C0, 3386, 618 }, /* CFG_MCASP1_AXR0_IN : VIN6A_VSYNC0 - VIP3_MANUAL2 */ + { 0x0414, 3215, 0 }, /* CFG_MCASP1_AXR1_IN : VIN6A_HSYNC0 - VIP3_MANUAL2 */ + { 0x04A4, 2171, 0 }, /* CFG_MCASP2_ACLKX_IN : VIN6A_D7 - VIP3_MANUAL2 */ + { 0x051C, 2508, 0 }, /* CFG_MCASP2_FSX_IN : VIN6A_D6 - VIP3_MANUAL2 */ + { 0x04C8, 2393, 0 }, /* CFG_MCASP2_AXR2_IN : VIN6A_D5 - VIP3_MANUAL2 */ + { 0x04D4, 3010, 0 }, /* CFG_MCASP2_AXR3_IN : VIN6A_D4 - VIP3_MANUAL2 */ + { 0x0528, 1029, 0 }, /* CFG_MCASP3_ACLKX_IN : VIN6A_D3 - VIP3_MANUAL2 */ + { 0x054C, 2752, 0 }, /* CFG_MCASP3_FSX_IN : VIN6A_D2 - VIP3_MANUAL2 */ + { 0x0534, 2603, 0 }, /* CFG_MCASP3_AXR0_IN : VIN6A_D1 - VIP3_MANUAL2 */ + { 0x0540, 1821, 268 }, /* CFG_MCASP3_AXR1_IN : VIN6A_D0 - VIP3_MANUAL2 */ + { 0x00D8, 1872, 2451 }, /* CFG_GPIO6_10_IN : VIN5A_CLK0 - VIP3_MANUAL2 */ + { 0x0678, 5071, 1118 }, /* CFG_MMC3_CLK_IN : VIN5A_D7 - VIP3_MANUAL2 */ + { 0x0684, 4978, 1147 }, /* CFG_MMC3_CMD_IN : VIN5A_D6 - VIP3_MANUAL2 */ + { 0x0690, 4869, 1199 }, /* CFG_MMC3_DAT0_IN : VIN5A_D5 - VIP3_MANUAL2 */ + { 0x069C, 4858, 1047 }, /* CFG_MMC3_DAT1_IN : VIN5A_D4 - VIP3_MANUAL2 */ + { 0x06A8, 4986, 677 }, /* CFG_MMC3_DAT2_IN : VIN5A_D3 - VIP3_MANUAL2 */ + { 0x06B4, 5018, 1313 }, /* CFG_MMC3_DAT3_IN : VIN5A_D2 - VIP3_MANUAL2 */ + { 0x06C0, 5000, 888 }, /* CFG_MMC3_DAT4_IN : VIN5A_D1 - VIP3_MANUAL2 */ + { 0x06CC, 4966, 874 }, /* CFG_MMC3_DAT5_IN : VIN5A_D0 - VIP3_MANUAL2 */ + { 0x06D8, 4876, 941 }, /* CFG_MMC3_DAT6_IN : VIN5A_HSYNC0 - VIP3_MANUAL2 */ + { 0x06E4, 5025, 540 }, /* CFG_MMC3_DAT7_IN : VIN5A_VSYNC0 - VIP3_MANUAL2 */ +#endif + }; const struct iodelay_cfg_entry dra742_es2_0_iodelay_cfg_array[] = { @@ -825,6 +1040,42 @@ const struct iodelay_cfg_entry dra742_es2_0_iodelay_cfg_array[] = { {0x0174, 2533, 980}, /* CFG_GPMC_A17_IN */ {0x0188, 590, 0}, /* CFG_GPMC_A18_OUT */ {0x0374, 0, 0}, /* CFG_GPMC_CS2_OUT */ +#ifdef CONFIG_TARGET_DRA7XX_EVM_VISION + { 0x00D8, 765, 2551 }, /* CFG_GPIO6_10_IN : VIN5A_CLK0 - VIP3_MANUAL2 */ + { 0x03C0, 2459, 381 }, /* CFG_MCASP1_AXR0_IN : VIN6A_VSYNC0 - VIP3_MANUAL2 */ + { 0x0414, 2098, 0 }, /* CFG_MCASP1_AXR1_IN : VIN6A_HSYNC0 - VIP3_MANUAL2 */ + { 0x04A4, 1206, 0 }, /* CFG_MCASP2_ACLKX_IN : VIN6A_D7 - VIP3_MANUAL2 */ + { 0x04C8, 1277, 0 }, /* CFG_MCASP2_AXR2_IN : VIN6A_D5 - VIP3_MANUAL2 */ + { 0x04D4, 1888, 90 }, /* CFG_MCASP2_AXR3_IN : VIN6A_D4 - VIP3_MANUAL2 */ + { 0x051C, 1424, 0 }, /* CFG_MCASP2_FSX_IN : VIN6A_D6 - VIP3_MANUAL2 */ + { 0x0528, 0, 0 }, /* CFG_MCASP3_ACLKX_IN : VIN6A_D3 - VIP3_MANUAL2 */ + { 0x0534, 1428, 88 }, /* CFG_MCASP3_AXR0_IN : VIN6A_D1 - VIP3_MANUAL2 */ + { 0x0540, 1331, 254 }, /* CFG_MCASP3_AXR1_IN : VIN6A_D0 - VIP3_MANUAL2 */ + { 0x054C, 1633, 54 }, /* CFG_MCASP3_FSX_IN : VIN6A_D2 - VIP3_MANUAL2 */ + { 0x0678, 2915, 2475 }, /* CFG_MMC3_CLK_IN : VIN5A_D7 - VIP3_MANUAL2 */ + { 0x0684, 2832, 2485 }, /* CFG_MMC3_CMD_IN : VIN5A_D6 - VIP3_MANUAL2 */ + { 0x0690, 2743, 2526 }, /* CFG_MMC3_DAT0_IN : VIN5A_D5 - VIP3_MANUAL2 */ + { 0x069C, 2749, 2346 }, /* CFG_MMC3_DAT1_IN : VIN5A_D4 - VIP3_MANUAL2 */ + { 0x06A8, 1811, 3012 }, /* CFG_MMC3_DAT2_IN : VIN5A_D3 - VIP3_MANUAL2 */ + { 0x06B4, 2872, 2683 }, /* CFG_MMC3_DAT3_IN : VIN5A_D2 - VIP3_MANUAL2 */ + { 0x06C0, 2836, 2271 }, /* CFG_MMC3_DAT4_IN : VIN5A_D1 - VIP3_MANUAL2 */ + { 0x06CC, 1771, 3271 }, /* CFG_MMC3_DAT5_IN : VIN5A_D0 - VIP3_MANUAL2 */ + { 0x06D8, 2752, 2255 }, /* CFG_MMC3_DAT6_IN : VIN5A_HSYNC0 - VIP3_MANUAL2 */ + { 0x06E4, 1881, 2844 }, /* CFG_MMC3_DAT7_IN : VIN5A_VSYNC0 - VIP3_MANUAL2 */ + { 0x0930, 2244, 1202 }, /* CFG_VIN1A_D16_IN : VIN3A_D0 - VIP2_MANUAL2 */ + { 0x093C, 2321, 1116 }, /* CFG_VIN1A_D17_IN : VIN3A_D1 - VIP2_MANUAL2 */ + { 0x0948, 2280, 1288 }, /* CFG_VIN1A_D18_IN : VIN3A_D2 - VIP2_MANUAL2 */ + { 0x0954, 2282, 1281 }, /* CFG_VIN1A_D19_IN : VIN3A_D3 - VIP2_MANUAL2 */ + { 0x096C, 2284, 1090 }, /* CFG_VIN1A_D20_IN : VIN3A_D4 - VIP2_MANUAL2 */ + { 0x0978, 2324, 1000 }, /* CFG_VIN1A_D21_IN : VIN3A_D5 - VIP2_MANUAL2 */ + { 0x0984, 2278, 915 }, /* CFG_VIN1A_D22_IN : VIN3A_D6 - VIP2_MANUAL2 */ + { 0x0990, 2423, 398 }, /* CFG_VIN1A_D23_IN : VIN3A_D7 - VIP2_MANUAL2 */ + { 0x0A2C, 0, 0 }, /* CFG_VIN1B_CLK1_IN : VIN3A_CLK0 - VIP2_MANUAL2 */ + { 0x0AEC, 1641, 0 }, /* CFG_VIN2A_D22_IN : VIN3A_HSYNC0 - VIP2_MANUAL2 */ + { 0x0AF8, 1748, 0 }, /* CFG_VIN2A_D23_IN : VIN3A_VSYNC0 - VIP2_MANUAL2 */ + { 0x0CFC, 0, 0 }, /* CFG_XREF_CLK1_IN : VIN6A_CLK0 - VIP3_MANUAL2 */ +#endif + }; #endif diff --git a/common/Makefile b/common/Makefile index 02615c2023..462cd1b717 100644 --- a/common/Makefile +++ b/common/Makefile @@ -11,9 +11,7 @@ obj-y += init/ obj-y += main.o obj-y += exports.o obj-y += hash.o -ifdef CONFIG_SYS_HUSH_PARSER -obj-y += cli_hush.o -endif +obj-$(CONFIG_HUSH_PARSER) += cli_hush.o # This option is not just y/n - it can have a numeric value ifdef CONFIG_BOOTDELAY @@ -115,6 +113,10 @@ obj-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o obj-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o obj-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o endif +obj-$(CONFIG_SPL_ANDROID_BOOT_SUPPORT) += env_flags.o +obj-$(CONFIG_SPL_ANDROID_BOOT_SUPPORT) += env_attr.o +obj-$(CONFIG_SPL_ANDROID_BOOT_SUPPORT) += env_callback.o +obj-$(CONFIG_SPL_ANDROID_BOOT_SUPPORT) += fdt_support.o endif #environment obj-y += env_common.o @@ -164,3 +166,5 @@ obj-y += s_record.o obj-y += xyzModem.o CFLAGS_env_embedded.o := -Wa,--no-warn -DENV_CRC=$(shell tools/envcrc 2>/dev/null) + +obj-$(CONFIG_LATE_ATTACH) += elf_remoteproc.o diff --git a/common/command.c b/common/command.c index e5d9b9cf95..d1c049ca09 100644 --- a/common/command.c +++ b/common/command.c @@ -520,7 +520,7 @@ enum command_ret_t cmd_process(int flag, int argc, char * const argv[], if (argc > cmdtp->maxargs) rc = CMD_RET_USAGE; -#if defined(CONFIG_CMD_BOOTD) +#if defined(CONFIG_CMD_BOOTD) && !defined(CONFIG_SPL_BUILD) /* avoid "bootd" recursion */ else if (cmdtp->cmd == do_bootd) { if (flag & CMD_FLAG_BOOTD) { diff --git a/common/elf_remoteproc.c b/common/elf_remoteproc.c new file mode 100644 index 0000000000..093fc3ab1d --- /dev/null +++ b/common/elf_remoteproc.c @@ -0,0 +1,555 @@ +/* + * ELF loader with support for the "remoteproc" kernel module functionality. + * + * Copyright (c) 2015 Venkateswara Rao Mandela, Texas Instruments Inc + * <venkat.mandela@ti.com> + * + * Modified from cmd_elf.c which carries the below copyright notice. + */ + + /* Copyright (c) 2001 William L. Pitts + * All rights reserved. + * + * Redistribution and use in source and binary forms are freely + * permitted provided that the above copyright notice and this + * paragraph and the following disclaimer are duplicated in all + * such forms. + * + * This software is provided "AS IS" and without any express or + * implied warranties, including, without limitation, the implied + * warranties of merchantability and fitness for a particular + * purpose. + */ + +#include <common.h> +#include <errno.h> +#include <linux/compat.h> +#include <linux/kernel.h> +#include <malloc.h> +#include <elf.h> +#include "omap_remoteproc.h" + +static struct resource_table *rsc_table; +static struct list_head mappings; + +typedef int (*handle_resource_t) (void *, int offset, int avail); + +int va_to_pa(int va) +{ + struct rproc_mem_entry *maps = NULL; + + list_for_each_entry(maps, &mappings, node) { + if (va >= maps->da && va < (maps->da + maps->len)) + return maps->dma + (va - maps->da); + } + + return 0; +} + +/* Virtio ring descriptors: 16 bytes. These can chain together via "next". */ +struct vring_desc { + /* Address (guest-physical). */ + __u64 addr; + /* Length. */ + __u32 len; + /* The flags as indicated above. */ + __u16 flags; + /* We chain unused descriptors via this, too */ + __u16 next; +}; + +/* u32 is used here for ids for padding reasons. */ +struct vring_used_elem { + /* Index of start of used descriptor chain. */ + __u32 id; + /* Total length of the descriptor chain which was used (written to) */ + __u32 len; +}; + +static unsigned vring_size(unsigned int num, unsigned long align) +{ + return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (3 + num) + + align - 1) & ~(align - 1)) + + sizeof(__u16) * 3 + sizeof(struct vring_used_elem) * num; +} + +static int handle_trace(struct fw_rsc_trace *rsc, int offset, int avail) +{ + if (sizeof(*rsc) > avail) { + printf("trace rsc is truncated\n"); + return -EINVAL; + } + + /* make sure reserved bytes are zeroes */ + if (rsc->reserved) { + printf("trace rsc has non zero reserved bytes\n"); + return -EINVAL; + } + + debug("trace rsc: da 0x%x, len 0x%x\n", rsc->da, rsc->len); + + return 0; +} + +static int handle_devmem(struct fw_rsc_devmem *rsc, int offset, int avail) +{ + struct rproc_mem_entry *mapping; + + if (sizeof(*rsc) > avail) { + printf("devmem rsc is truncated\n"); + return -EINVAL; + } + + /* make sure reserved bytes are zeroes */ + if (rsc->reserved) { + printf("devmem rsc has non zero reserved bytes\n"); + return -EINVAL; + } + + debug("devmem rsc: pa 0x%x, da 0x%x, len 0x%x\n", + rsc->pa, rsc->da, rsc->len); + + config_pagetable(rsc->da, rsc->pa, rsc->len); + + mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); + if (!mapping) { + printf("kzalloc mapping failed\n"); + return -ENOMEM; + } + + /* + * We'll need this info later when we'll want to unmap everything + * (e.g. on shutdown). + * + * We can't trust the remote processor not to change the resource + * table, so we must maintain this info independently. + */ + mapping->dma = rsc->pa; + mapping->da = rsc->da; + mapping->len = rsc->len; + list_add_tail(&mapping->node, &mappings); + + debug("mapped devmem pa 0x%x, da 0x%x, len 0x%x\n", + rsc->pa, rsc->da, rsc->len); + + return 0; +} + +static int handle_carveout(struct fw_rsc_carveout *rsc, int offset, int avail) +{ + struct rproc_mem_entry *mapping; + + if (sizeof(*rsc) > avail) { + printf("carveout rsc is truncated\n"); + return -EINVAL; + } + + /* make sure reserved bytes are zeroes */ + if (rsc->reserved) { + printf("carveout rsc has non zero reserved bytes\n"); + return -EINVAL; + } + + debug("carveout rsc: da %x, pa %x, len %x, flags %x\n", + rsc->da, rsc->pa, rsc->len, rsc->flags); + + rsc->pa = (int)alloc_mem(rsc->len, 8); + if (!rsc->pa) { + printf("failed to allocate carveout rsc: da %x, pa %x, len %x, flags %x\n", + rsc->da, rsc->pa, rsc->len, rsc->flags); + return -ENOMEM; + } + config_pagetable(rsc->da, rsc->pa, rsc->len); + + /* + * Ok, this is non-standard. + * + * Sometimes we can't rely on the generic iommu-based DMA API + * to dynamically allocate the device address and then set the IOMMU + * tables accordingly, because some remote processors might + * _require_ us to use hard coded device addresses that their + * firmware was compiled with. + * + * In this case, we must use the IOMMU API directly and map + * the memory to the device address as expected by the remote + * processor. + * + * Obviously such remote processor devices should not be configured + * to use the iommu-based DMA API: we expect 'dma' to contain the + * physical address in this case. + */ + mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); + if (!mapping) { + printf("kzalloc mapping failed\n"); + return -ENOMEM; + } + + /* + * We'll need this info later when we'll want to unmap + * everything (e.g. on shutdown). + * + * We can't trust the remote processor not to change the + * resource table, so we must maintain this info independently. + */ + mapping->dma = rsc->pa; + mapping->da = rsc->da; + mapping->len = rsc->len; + list_add_tail(&mapping->node, &mappings); + + debug("carveout mapped 0x%x to 0x%x\n", rsc->da, rsc->pa); + + return 0; +} + +#define RPROC_PAGE_SHIFT 12 +#define RPROC_PAGE_SIZE (1 << RPROC_PAGE_SHIFT) +#define RPROC_PAGE_ALIGN(x) (((x) + (RPROC_PAGE_SIZE - 1)) & ~(RPROC_PAGE_SIZE - 1)) + +static int alloc_vring(struct fw_rsc_vdev *rsc, int i) +{ + struct fw_rsc_vdev_vring *vring = &rsc->vring[i]; + int size; + int order; + void *pa; + + debug("vdev rsc: vring%d: da %x, qsz %d, align %d\n", + i, vring->da, vring->num, vring->align); + + /* make sure reserved bytes are zeroes */ + if (vring->reserved) { + printf("vring rsc has non zero reserved bytes\n"); + return -EINVAL; + } + + /* verify queue size and vring alignment are sane */ + if (!vring->num || !vring->align) { + printf("invalid qsz (%d) or alignment (%d)\n", + vring->num, vring->align); + return -EINVAL; + } + + /* actual size of vring (in bytes) */ + size = RPROC_PAGE_ALIGN(vring_size(vring->num, vring->align)); + order = vring->align >> RPROC_PAGE_SHIFT; + + pa = alloc_mem(size, order); + if (!pa) { + printf("failed to allocate vring rsc\n"); + return -ENOMEM; + } + debug("alloc_mem(%#x, %d): %p\n", size, order, pa); + vring->da = (u32) pa; + + return pa == NULL; +} + +#define RPMSG_NUM_BUFS (512) +#define RPMSG_BUF_SIZE (512) +#define RPMSG_TOTAL_BUF_SPACE (RPMSG_NUM_BUFS * RPMSG_BUF_SIZE) + +static int handle_vdev(struct fw_rsc_vdev *rsc, int offset, int avail) +{ + int i, ret; + void *pa; + + /* make sure resource isn't truncated */ + if (sizeof(*rsc) + rsc->num_of_vrings * sizeof(struct fw_rsc_vdev_vring) + + rsc->config_len > avail) { + printf("vdev rsc is truncated\n"); + return -EINVAL; + } + + /* make sure reserved bytes are zeroes */ + if (rsc->reserved[0] || rsc->reserved[1]) { + printf("vdev rsc has non zero reserved bytes\n"); + return -EINVAL; + } + + debug("vdev rsc: id %d, dfeatures %x, cfg len %d, %d vrings\n", + rsc->id, rsc->dfeatures, rsc->config_len, rsc->num_of_vrings); + + /* we currently support only two vrings per rvdev */ + if (rsc->num_of_vrings > 2) { + printf("too many vrings: %d\n", rsc->num_of_vrings); + return -EINVAL; + } + + /* allocate the vrings */ + for (i = 0; i < rsc->num_of_vrings; i++) { + ret = alloc_vring(rsc, i); + if (ret) + goto alloc_error; + } + + pa = alloc_mem(RPMSG_TOTAL_BUF_SPACE, 6); + if (!pa) { + printf("failed to allocate vdev rsc\n"); + return -ENOMEM; + } + debug("vring buffer alloc_mem(%#x, 6): %p\n", + RPMSG_TOTAL_BUF_SPACE, pa); + + return 0; + +alloc_error: + return ret; +} + +/* + * A lookup table for resource handlers. The indices are defined in + * enum fw_resource_type. + */ +static handle_resource_t loading_handlers[RSC_LAST] = { + [RSC_CARVEOUT] = (handle_resource_t) handle_carveout, + [RSC_DEVMEM] = (handle_resource_t) handle_devmem, + [RSC_TRACE] = (handle_resource_t) handle_trace, + [RSC_VDEV] = (handle_resource_t) handle_vdev, +}; + +/* handle firmware resource entries before booting the remote processor */ +static int handle_resources(int len, handle_resource_t handlers[RSC_LAST]) +{ + handle_resource_t handler; + int ret = 0, i; + + for (i = 0; i < rsc_table->num; i++) { + int offset = rsc_table->offset[i]; + struct fw_rsc_hdr *hdr = (void *)rsc_table + offset; + int avail = len - offset - sizeof(*hdr); + void *rsc = (void *)hdr + sizeof(*hdr); + + /* make sure table isn't truncated */ + if (avail < 0) { + printf("rsc table is truncated\n"); + return -EINVAL; + } + + debug("rsc: type %d\n", hdr->type); + + if (hdr->type >= RSC_LAST) { + printf("unsupported resource %d\n", hdr->type); + continue; + } + + handler = handlers[hdr->type]; + if (!handler) + continue; + + ret = handler(rsc, offset + sizeof(*hdr), avail); + if (ret) + break; + } + + return ret; +} + +static int handle_intmem_to_l3_mapping(struct rproc_intmem_to_l3_mapping *l3_mapping) +{ + u32 i = 0; + + for (i = 0; i < l3_mapping->num_entries; i++) { + struct l3_map *curr_map = &l3_mapping->mappings[i]; + struct rproc_mem_entry *mapping; + + mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); + if (!mapping) { + printf("kzalloc mapping failed\n"); + return -ENOMEM; + } + + mapping->dma = curr_map->l3_addr; + mapping->da = curr_map->priv_addr; + mapping->len = curr_map->len; + list_add_tail(&mapping->node, &mappings); + } + + return 0; +} + +static Elf32_Shdr *find_table(unsigned int addr) +{ + Elf32_Ehdr *ehdr; /* Elf header structure pointer */ + Elf32_Shdr *shdr; /* Section header structure pointer */ + Elf32_Shdr sectionheader; + int i; + u8 *elf_data; + char *name_table; + struct resource_table *ptable; + + ehdr = (Elf32_Ehdr *)addr; + elf_data = (u8 *)ehdr; + shdr = (Elf32_Shdr *)(elf_data + ehdr->e_shoff); + memcpy(§ionheader, &shdr[ehdr->e_shstrndx], sizeof(sectionheader)); + name_table = (char *)(elf_data + sectionheader.sh_offset); + + for (i = 0; i < ehdr->e_shnum; i++, shdr++) { + memcpy(§ionheader, shdr, sizeof(sectionheader)); + u32 size = sectionheader.sh_size; + u32 offset = sectionheader.sh_offset; + + if (strcmp(name_table + sectionheader.sh_name, + ".resource_table")) + continue; + + ptable = (struct resource_table *)(elf_data + offset); + + /* make sure table has at least the header */ + if (sizeof(struct resource_table) > size) { + printf("header-less resource table\n"); + return NULL; + } + + /* we don't support any version beyond the first */ + if (ptable->ver != 1) { + printf("unsupported fw ver: %d\n", ptable->ver); + return NULL; + } + + /* make sure reserved bytes are zeroes */ + if (ptable->reserved[0] || ptable->reserved[1]) { + printf("non zero reserved bytes\n"); + return NULL; + } + + /* make sure the offsets array isn't truncated */ + if (ptable->num * sizeof(ptable->offset[0]) + + sizeof(struct resource_table) > size) { + printf("resource table incomplete\n"); + return NULL; + } + + return shdr; + } + + return NULL; +} + +struct resource_table *find_resource_table(unsigned int addr, + int *tablesz) +{ + Elf32_Shdr *shdr; + Elf32_Shdr sectionheader; + struct resource_table *ptable; + u8 *elf_data = (u8 *)addr; + + shdr = find_table(addr); + if (!shdr) { + printf("find_resource_table: " + "failed to get resource section header\n"); + return NULL; + } + + memcpy(§ionheader, shdr, sizeof(sectionheader)); + ptable = (struct resource_table *)(elf_data + sectionheader.sh_offset); + if (tablesz) + *tablesz = sectionheader.sh_size; + + return ptable; +} + +/* ====================================================================== + * A very simple elf loader, assumes the image is valid, returns the + * entry point address. + * ====================================================================== */ +unsigned long load_elf_image_phdr_rproc(struct rproc *cfg) +{ + Elf32_Ehdr *ehdr; /* Elf header structure pointer */ + Elf32_Phdr *phdr; /* Program header structure pointer */ + Elf32_Phdr proghdr; + struct resource_table *ptable = NULL; + int tablesz; + int va; + int pa; + int ret; + int i; + unsigned long addr; + + if (cfg == 0) + return 0; + + addr = cfg->load_addr; + + ehdr = (Elf32_Ehdr *)addr; + phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff); + + ptable = find_resource_table(addr, &tablesz); + if (!ptable) { + printf("%s : failed to find resource table\n", __func__); + return 0; + } else { + debug("%s : found resource table\n", __func__); + + rsc_table = kzalloc(tablesz, GFP_KERNEL); + if (!rsc_table) { + printf("resource table alloc failed!\n"); + return 0; + } + + /* Copy the resource table into a local buffer + * before handling the resource table. + */ + memcpy(rsc_table, ptable, tablesz); + + INIT_LIST_HEAD(&mappings); + if (cfg->intmem_to_l3_mapping) + handle_intmem_to_l3_mapping(cfg->intmem_to_l3_mapping); + + ret = handle_resources(tablesz, loading_handlers); + if (ret) { + printf("handle_resources failed: %d\n", ret); + return 0; + } + + /* Instead of trying to mimic the kernel flow of copying the + * processed resource table into its post ELF load location in + * DDR , I am copying it into its original location. + */ + memcpy(ptable, rsc_table, tablesz); + + free(rsc_table); + rsc_table = NULL; + } + + /* Load each program header */ + for (i = 0; i < ehdr->e_phnum; ++i) { + memcpy(&proghdr, phdr, sizeof(Elf32_Phdr)); + + if (proghdr.p_type != PT_LOAD) { + ++phdr; + continue; + } + + va = proghdr.p_paddr; + pa = va_to_pa(va); + if (pa) + proghdr.p_paddr = pa; + + void *dst = (void *)(uintptr_t) proghdr.p_paddr; + void *src = (void *)addr + proghdr.p_offset; + + debug("Loading phdr %i to 0x%p (%i bytes)\n", + i, dst, proghdr.p_filesz); + if (proghdr.p_filesz) + memcpy(dst, src, proghdr.p_filesz); + /* TODO: This line needs to be removed after test */ + if (!ptable) { + if ((proghdr.p_filesz != proghdr.p_memsz) && + ((proghdr.p_paddr - 0x58820000)) > 0x4000 && + proghdr.p_memsz > 9) + memset(dst + proghdr.p_filesz, 0x00, + proghdr.p_memsz - proghdr.p_filesz); + } else { + if (proghdr.p_filesz != proghdr.p_memsz) + memset(dst + proghdr.p_filesz, 0x00, + proghdr.p_memsz - proghdr.p_filesz); + } + + flush_cache((unsigned long)dst, proghdr.p_memsz); + + ++phdr; + } + + cfg->entry_point = ehdr->e_entry; + + return 1; +} diff --git a/common/fb_mmc.c b/common/fb_mmc.c index e3abcc85be..8e2b92ce96 100644 --- a/common/fb_mmc.c +++ b/common/fb_mmc.c @@ -141,6 +141,7 @@ void fb_mmc_flash_write(const char *cmd, unsigned int session_id, if (is_sparse_image(download_buffer)) { struct fb_mmc_sparse sparse_priv; sparse_storage_t sparse; + int ret; sparse_priv.dev_desc = dev_desc; @@ -153,8 +154,15 @@ void fb_mmc_flash_write(const char *cmd, unsigned int session_id, printf("Flashing sparse image at offset " LBAFU "\n", info.start); - store_sparse_image(&sparse, &sparse_priv, session_id, + ret = store_sparse_image(&sparse, &sparse_priv, session_id, download_buffer); + if (ret) { + printf("%s: writing sparse image failed: %d\n", + __func__, ret); + fastboot_fail(response_str, + "writing sparse image failed"); + return; + } } else { write_raw_image(dev_desc, &info, cmd, download_buffer, download_bytes); diff --git a/common/image-android.c b/common/image-android.c index b6a94b3a30..acf5342d5c 100644 --- a/common/image-android.c +++ b/common/image-android.c @@ -145,3 +145,8 @@ int android_image_get_ramdisk(const struct andr_img_hdr *hdr, *rd_len = hdr->ramdisk_size; return 0; } + +ulong android_image_get_rload(const struct andr_img_hdr *hdr) +{ + return hdr->ramdisk_addr; +} diff --git a/common/spl/spl.c b/common/spl/spl.c index defe4247b2..3fc0ff533d 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -18,6 +18,7 @@ #include <malloc.h> #include <dm/root.h> #include <linux/compiler.h> +#include <omap_remoteproc.h> #include <fdt_support.h> DECLARE_GLOBAL_DATA_PTR; @@ -136,6 +137,21 @@ void spl_parse_image_header(const struct image_header *header) debug("spl: payload image: %.*s load addr: 0x%x size: %d\n", (int)sizeof(spl_image.name), spl_image.name, spl_image.load_addr, spl_image.size); +#ifdef CONFIG_SPL_ANDROID_BOOT_SUPPORT + } else if (genimg_get_format(header) == IMAGE_FORMAT_ANDROID) { + ulong kern_start; + android_image_get_kernel((const struct andr_img_hdr *)header, + true, &kern_start, + (ulong *)&spl_image.size); + spl_image.entry_point = android_image_get_kload((const struct andr_img_hdr *)header); + spl_image.load_addr = spl_image.entry_point - (kern_start - (ulong)header); + spl_image.size += (kern_start - (ulong)header); + spl_image.os = IH_OS_LINUX; + spl_image.name = "Android Image"; + debug("spl: android image: %.*s load addr: 0x%x size: %d\n", + sizeof(spl_image.name), spl_image.name, + spl_image.load_addr, spl_image.size); +#endif } else { #ifdef CONFIG_SPL_PANIC_ON_RAW_IMAGE /* @@ -214,6 +230,38 @@ static int spl_ram_load_image(void) } #endif +#ifdef CONFIG_LATE_ATTACH + +/* + * Loads the remotecores specified in the cores array. + * + * In case of failure, the core id array is OR'ed with an error code + * to indicate that the load has failed. + * + * This information can be used to indicate status of the remotecore + * load to the kernel. + */ +void spl_load_cores(u32 boot_device, u32 *cores, u32 numcores) +{ + u32 i = 0; + + for (i = 0; i < numcores ; i++) { + u32 core = cores[i]; + if (spl_mmc_load_core(core, boot_device) || + spl_boot_core(core)) { + cores[i] = (cores[i] | SPL_CORE_LOAD_ERR_ID); + printf("Error loading remotecore %s!," + "Continuing with boot ...\n", + rproc_cfg_arr[core]->core_name); + } else { + debug("loading remote core %s successful\n", + rproc_cfg_arr[core]->core_name); + } + } + return; +} +#endif + int spl_init(void) { int ret; @@ -340,6 +388,15 @@ static void announce_boot_device(u32 boot_device) static inline void announce_boot_device(u32 boot_device) { } #endif +#ifdef CONFIG_LATE_ATTACH +/* List the id of the remotecores that need to be earlybooted + * in this array. This array is global as the success/failure + * of the early load operation is specified by updating this + * array. + */ +u32 cores_to_boot[] = { IPU2, DSP1, DSP2, IPU1 }; +#endif + static int spl_load_image(u32 boot_device) { switch (boot_device) { @@ -351,6 +408,10 @@ static int spl_load_image(u32 boot_device) case BOOT_DEVICE_MMC1: case BOOT_DEVICE_MMC2: case BOOT_DEVICE_MMC2_2: +#ifdef CONFIG_LATE_ATTACH + spl_load_cores(boot_device, cores_to_boot, + sizeof(cores_to_boot)/sizeof(u32)); +#endif return spl_mmc_load_image(boot_device); #endif #ifdef CONFIG_SPL_NAND_SUPPORT @@ -371,6 +432,10 @@ static int spl_load_image(u32 boot_device) #endif #ifdef CONFIG_SPL_SPI_SUPPORT case BOOT_DEVICE_SPI: +#ifdef CONFIG_LATE_ATTACH + spl_load_cores(boot_device, cores_to_boot, + sizeof(cores_to_boot)/sizeof(u32)); +#endif return spl_spi_load_image(); #endif #ifdef CONFIG_SPL_ETH_SUPPORT diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c index dde073e291..eaf03e4aa8 100644 --- a/common/spl/spl_fat.c +++ b/common/spl/spl_fat.c @@ -154,4 +154,27 @@ int spl_load_image_fat_os(struct blk_desc *block_dev, int partition) return -ENOSYS; } #endif + +int spl_load_file_fat(struct blk_desc *block_dev, + int partition, + const char *filename, + void *buf) { + int err; + + err = spl_register_fat_device(block_dev, partition); + if (err) + return err; + + err = file_fat_read(filename, buf, 0); + + if (err <= 0) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("%s: error reading file %s, err - %d\n", + __func__, filename, err); +#endif + return -1; + } + + return err; +} #endif diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 247df5735f..c6bd1b5893 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -15,15 +15,23 @@ #include <errno.h> #include <mmc.h> #include <image.h> +#ifdef CONFIG_SPL_ANDROID_BOOT_SUPPORT +#include <fdt_support.h> +#endif +#include <fat.h> +#include <omap_remoteproc.h> DECLARE_GLOBAL_DATA_PTR; static int mmc_load_legacy(struct mmc *mmc, ulong sector, - struct image_header *header) + struct image_header *header, bool *print_err) { u32 image_size_sectors; unsigned long count; + if (print_err) + *print_err = true; + spl_parse_image_header(header); /* convert size to sectors - round up */ image_size_sectors = (spl_image.size + mmc->read_bl_len - 1) / @@ -35,8 +43,100 @@ static int mmc_load_legacy(struct mmc *mmc, ulong sector, (void *)(ulong)spl_image.load_addr); debug("read %x sectors to %x\n", image_size_sectors, spl_image.load_addr); + +#ifndef CONFIG_SPL_ANDROID_BOOT_SUPPORT if (count != image_size_sectors) return -EIO; +#else + if (count == 0) + return -1; + + /* load the ramdisk if this is an Android image */ + if (genimg_get_format(header) == IMAGE_FORMAT_ANDROID) { + ulong ramdisk_start, ramdisk_len, ramdisk_load; + u32 sector_ramdisk; + int err; + const char *s; + + printf("Loading Android ramdisk\n"); + + android_image_get_ramdisk((const struct andr_img_hdr *)header, + &ramdisk_start, &ramdisk_len); + ramdisk_load = android_image_get_rload( + (const struct andr_img_hdr *)header); + sector_ramdisk = sector + + ((ramdisk_start - (ulong)header) / + mmc->block_dev.blksz); + image_size_sectors = (ramdisk_len + mmc->read_bl_len - 1) / + mmc->read_bl_len; + + count = mmc->block_dev.block_read(&mmc->block_dev, + sector_ramdisk, image_size_sectors, + (void *)ramdisk_load); + if (count == 0) + return -2; + + err = fdt_shrink_to_minimum((void *)CONFIG_SYS_SPL_ARGS_ADDR); + if (err == 0) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("spl: fdt_shrink_to_minimum err - %d\n", err); +#endif + if (print_err) + *print_err = false; + return -3; + } + err = fdt_chosen((void *)CONFIG_SYS_SPL_ARGS_ADDR); + if (err != 0) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("spl: fdt_chosen err - %d\n", err); +#endif + if (print_err) + *print_err = false; + return -4; + } + err = fdt_initrd((void *)CONFIG_SYS_SPL_ARGS_ADDR, ramdisk_load, + ramdisk_load + ramdisk_len); + if (err != 0) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("spl: fdt_initrd err - %d\n", err); +#endif + if (print_err) + *print_err = false; + return -5; + } + + s = getenv("serial#"); + if (s) { + static char data[512]; + int nodeoffset, len; + + printf("serial# is %s\n", s); + nodeoffset = fdt_path_offset((void *)CONFIG_SYS_SPL_ARGS_ADDR, "/chosen"); + if (nodeoffset < 0) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf ("spl: fdt_path_offset err - %d\n", err); +#endif + if (print_err) + *print_err = false; + return -6; + } + + sprintf(data, "androidboot.serialno=%s ", s); + len = strlen(data) + 1; + + err = fdt_setprop((void *)CONFIG_SYS_SPL_ARGS_ADDR, + nodeoffset, "bootargs", data, len); + if (err != 0) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf ("spl: fdt_setprop err - %d\n", err); +#endif + if (print_err) + *print_err = false; + return -7; + } + } + } +#endif return 0; } @@ -54,6 +154,7 @@ static int mmc_load_image_raw_sector(struct mmc *mmc, unsigned long sector) unsigned long count; struct image_header *header; int ret = 0; + bool print_err = true; header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - sizeof(struct image_header)); @@ -78,13 +179,19 @@ static int mmc_load_image_raw_sector(struct mmc *mmc, unsigned long sector) load.read = h_spl_load_read; ret = spl_load_simple_fit(&load, sector, header); } else { - ret = mmc_load_legacy(mmc, sector, header); +#ifdef CONFIG_SPL_ANDROID_BOOT_SUPPORT + if (genimg_get_format(header) == IMAGE_FORMAT_ANDROID) + printf("Loading Android image\n"); +#endif + ret = mmc_load_legacy(mmc, sector, header, &print_err); } end: if (ret) { #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT - puts("mmc_load_image_raw_sector: mmc block read error\n"); + if (print_err) + puts("mmc_load_image_raw_sector: mmc block read error" + "\n"); #endif return -1; } @@ -180,10 +287,33 @@ static int mmc_load_image_raw_os(struct mmc *mmc) { unsigned long count; int ret; + lbaint_t sector, num_sectors; + char *boot_ptn; - count = mmc->block_dev.block_read(&mmc->block_dev, - CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR, - CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS, +#if defined(CONFIG_SPL_MMC_DTB_NAME) || defined(CONFIG_SPL_MMC_KERNEL_NAME) + disk_partition_t info; +#endif + +#ifdef CONFIG_SPL_MMC_DTB_NAME + ret = part_get_info_efi_by_name(&mmc->block_dev, + CONFIG_SPL_MMC_DTB_NAME, + &info); + if (ret) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("cannot find partition: '%s'\n", + CONFIG_SPL_MMC_DTB_NAME); +#endif + return -1; + } + + sector = info.start; + num_sectors = info.size; +#else + sector = CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR; + num_sectors = CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR; +#endif + + count = mmc->block_dev.block_read(&mmc->block_dev, sector, num_sectors, (void *) CONFIG_SYS_SPL_ARGS_ADDR); if (count == 0) { #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT @@ -192,8 +322,35 @@ static int mmc_load_image_raw_os(struct mmc *mmc) return -1; } - ret = mmc_load_image_raw_sector(mmc, - CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR); +#ifdef CONFIG_SPL_MMC_KERNEL_NAME + boot_ptn = getenv("reboot_image"); + if (boot_ptn && !strcmp(boot_ptn, "recovery")) { + setenv("reboot_image", "boot"); +#ifdef CONFIG_SPL_SAVEENV + saveenv(); +#endif + boot_ptn = strdup("recovery"); + } else { + boot_ptn = strdup(CONFIG_SPL_MMC_KERNEL_NAME); + } + + printf("Booting from %s partition\n", boot_ptn); + ret = part_get_info_efi_by_name(&mmc->block_dev, + boot_ptn, + &info); + if (ret) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("cannot find partition: '%s'\n", + CONFIG_SPL_MMC_KERNEL_NAME); +#endif + return -1; + } + + sector = info.start; +#else + sector = CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR; +#endif + ret = mmc_load_image_raw_sector(mmc, sector); if (ret) return ret; @@ -264,18 +421,25 @@ int spl_mmc_do_fs_boot(struct mmc *mmc) } #endif -int spl_mmc_load_image(u32 boot_device) +/** + * @param boot_device Boot device index or UINT_MAX if unknown + */ +int spl_mmc_init(struct mmc **mmc, u32 boot_device) { - struct mmc *mmc = NULL; - u32 boot_mode; int err = 0; - __maybe_unused int part; - err = spl_mmc_find_device(&mmc, boot_device); + if (boot_device == UINT_MAX) + boot_device = spl_boot_device(); + + /* In case of QSPI boot we need to init eMMC */ + if (boot_device == BOOT_DEVICE_SPI) + boot_device = BOOT_DEVICE_MMC2_2; + + err = spl_mmc_find_device(mmc, boot_device); if (err) return err; - err = mmc_init(mmc); + err = mmc_init(*mmc); if (err) { #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT printf("spl: mmc init failed with error: %d\n", err); @@ -283,6 +447,32 @@ int spl_mmc_load_image(u32 boot_device) return err; } + return 0; +} + +#ifdef CONFIG_SPL_OS_BOOT +int spl_mmc_load_image_raw_os(void) +{ + struct mmc *mmc; + + spl_mmc_init(&mmc, UINT_MAX); + + return mmc_load_image_raw_os(mmc); +} +#endif + +int spl_mmc_load_image(u32 boot_device) +{ + int err = 0; + __maybe_unused int part; + struct mmc *mmc = NULL; + u32 boot_mode; + + (void)boot_device; /* unused */ + err = spl_mmc_init(&mmc, boot_device); + if (err) + return err; + boot_mode = spl_boot_mode(); err = -EINVAL; switch (boot_mode) { @@ -342,3 +532,57 @@ int spl_mmc_load_image(u32 boot_device) return err; } + +u32 spl_mmc_load_core(u32 core_id, u32 boot_device) +{ + struct rproc *cfg = NULL; + s32 err = 0; + struct mmc *mmc; + + if ((core_id == 0) || (core_id >= RPROC_END_ENUMS)) { + printf("Invalid core id speicified: %d\n", core_id); + return 1; + } + + cfg = rproc_cfg_arr[core_id]; + + debug("spl: loading remote core image %s\n", cfg->firmware_name); + + spl_mmc_init(&mmc, boot_device); + + /* load the remote core image from partition */ + if (cfg->ptn) { + disk_partition_t info; + + err = part_get_info_efi_by_name(&mmc->block_dev, + cfg->ptn, &info); + if (err) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("cannot find partition: '%s'\n", + cfg->ptn); +#endif + } else if (!mmc->block_dev.block_read(&mmc->block_dev, + info.start, + info.size, + (void *)cfg->load_addr)) { + printf("error reading from mmc\n"); + err = -1; + } else { + err = 1; + } + } else { + /* load the remotecore image */ + err = spl_load_file_fat(&mmc->block_dev, + CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, + cfg->firmware_name, + (u8 *)cfg->load_addr); + } + + if (err <= 0) { + printf("spl: error reading image %s, err - %d\n", + cfg->firmware_name, err); + return 1; + } + + return 0; +} diff --git a/configs/am57xx_evm_defconfig b/configs/am57xx_evm_defconfig index 7e7edda8ae..d50aa48630 100644 --- a/configs/am57xx_evm_defconfig +++ b/configs/am57xx_evm_defconfig @@ -29,6 +29,7 @@ CONFIG_CMD_EXT4=y CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y +CONFIG_CMD_USB_MASS_STORAGE=y CONFIG_OF_CONTROL=y CONFIG_DM=y CONFIG_DM_MMC=y @@ -62,6 +63,16 @@ CONFIG_PMIC_PALMAS=y CONFIG_DM_REGULATOR=y CONFIG_DM_REGULATOR_PALMAS=y CONFIG_CMD_TIME=y +CONFIG_USB=y +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_GADGET=y +CONFIG_USB_DWC3_OMAP=y +CONFIG_USB_DWC3_PHY_OMAP=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_G_DNL_MANUFACTURER="Texas Instruments" +CONFIG_G_DNL_VENDOR_NUM=0x0451 +CONFIG_G_DNL_PRODUCT_NUM=0xd022 CONFIG_DM_I2C=y CONFIG_DM_SPI=y CONFIG_DM_SPI_FLASH=y diff --git a/configs/am57xx_evm_nodt_defconfig b/configs/am57xx_evm_nodt_defconfig index da6876b999..0ad9849b0f 100644 --- a/configs/am57xx_evm_nodt_defconfig +++ b/configs/am57xx_evm_nodt_defconfig @@ -1,7 +1,10 @@ CONFIG_ARM=y CONFIG_OMAP54XX=y CONFIG_TARGET_AM57XX_EVM=y +CONFIG_DRA7_DSPEVE_OPP_HIGH=y +CONFIG_DRA7_IVA_OPP_HIGH=y CONFIG_SPL=y +CONFIG_OF_BOARD_SETUP=y CONFIG_HUSH_PARSER=y CONFIG_CMD_BOOTZ=y # CONFIG_CMD_IMLS is not set @@ -22,6 +25,16 @@ CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y CONFIG_SYS_NS16550=y +CONFIG_USB=y +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_GADGET=y +CONFIG_USB_DWC3_OMAP=y +CONFIG_USB_DWC3_PHY_OMAP=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_G_DNL_MANUFACTURER="Texas Instruments" +CONFIG_G_DNL_VENDOR_NUM=0x0451 +CONFIG_G_DNL_PRODUCT_NUM=0xd022 CONFIG_OF_LIBFDT=y CONFIG_OF_BOARD_SETUP=y CONFIG_DRA7_DSPEVE_OPP_HIGH=y diff --git a/configs/dra7xx_evm_defconfig b/configs/dra7xx_evm_defconfig index c30f7e500e..36a0acaa0b 100644 --- a/configs/dra7xx_evm_defconfig +++ b/configs/dra7xx_evm_defconfig @@ -33,6 +33,7 @@ CONFIG_CMD_EXT4=y CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y +CONFIG_CMD_USB_MASS_STORAGE=y CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_SPANSION=y @@ -48,12 +49,12 @@ CONFIG_USB_DWC3_PHY_OMAP=y CONFIG_USB_GADGET=y CONFIG_FIT=y CONFIG_SPL_OF_LIBFDT=y -CONFIG_SPL_LOAD_FIT=y CONFIG_OF_LIST="dra7-evm dra72-evm dra72-evm-revc dra71-evm" CONFIG_DM_ETH=y CONFIG_DM_PMIC=y CONFIG_PMIC_PALMAS=y CONFIG_PMIC_LP873X=y +CONFIG_SPL_LOAD_FIT=y CONFIG_DISK=y CONFIG_DWC_AHCI=y CONFIG_DM_MMC=y @@ -70,6 +71,8 @@ CONFIG_CMD_TIME=y CONFIG_DM_I2C=y CONFIG_DM_REGULATOR=y CONFIG_DM_REGULATOR_FIXED=y +CONFIG_LATE_ATTACH=n +CONFIG_LATE_ATTACH_GPT_PART=n CONFIG_DM_REGULATOR_GPIO=y CONFIG_DM_REGULATOR_PALMAS=y CONFIG_DM_REGULATOR_LP873X=y diff --git a/configs/dra7xx_evm_nodt_defconfig b/configs/dra7xx_evm_nodt_defconfig index 6dad282bc8..9c13366939 100644 --- a/configs/dra7xx_evm_nodt_defconfig +++ b/configs/dra7xx_evm_nodt_defconfig @@ -41,6 +41,7 @@ CONFIG_G_DNL_MANUFACTURER="Texas Instruments" CONFIG_G_DNL_VENDOR_NUM=0x0451 CONFIG_G_DNL_PRODUCT_NUM=0xd022 CONFIG_OF_LIBFDT=y +CONFIG_SPL_OF_LIBFDT=y CONFIG_OF_BOARD_SETUP=y CONFIG_DRA7_DSPEVE_OPP_HIGH=y CONFIG_DRA7_IVA_OPP_HIGH=y diff --git a/configs/dra7xx_evm_vision_defconfig b/configs/dra7xx_evm_vision_defconfig new file mode 100644 index 0000000000..8b97ec7b69 --- /dev/null +++ b/configs/dra7xx_evm_vision_defconfig @@ -0,0 +1,70 @@ +CONFIG_ARM=y +CONFIG_OMAP54XX=y +CONFIG_TARGET_DRA7XX_EVM=y +CONFIG_DM_SERIAL=y +CONFIG_DM_SPI=y +CONFIG_DM_SPI_FLASH=y +CONFIG_DM_GPIO=y +CONFIG_ARMV7_LPAE=y +CONFIG_SPL_STACK_R_ADDR=0x82000000 +CONFIG_DEFAULT_DEVICE_TREE="dra7-evm" +CONFIG_SPL=y +CONFIG_SPL_STACK_R=y +CONFIG_HUSH_PARSER=y +CONFIG_CMD_BOOTZ=y +# CONFIG_CMD_IMLS is not set +CONFIG_CMD_ASKENV=y +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_MMC=y +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +CONFIG_CMD_I2C=y +CONFIG_CMD_USB=y +CONFIG_CMD_DFU=y +CONFIG_CMD_GPIO=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_OF_CONTROL=y +CONFIG_DM=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_MII=y +CONFIG_CMD_PING=y +CONFIG_CMD_EXT2=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_BAR=y +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_SYS_NS16550=y +CONFIG_TI_QSPI=y +CONFIG_TIMER=y +CONFIG_OMAP_TIMER=y +CONFIG_USB=y +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_GADGET=y +CONFIG_USB_DWC3_OMAP=y +CONFIG_USB_DWC3_PHY_OMAP=y +CONFIG_USB_GADGET=y +CONFIG_FIT=y +CONFIG_SPL_OF_LIBFDT=y +CONFIG_SPL_LOAD_FIT=y +CONFIG_OF_LIST="dra7-evm dra72-evm dra72-evm-revc dra71-evm" +CONFIG_DM_ETH=y +CONFIG_DISK=y +CONFIG_DWC_AHCI=y +CONFIG_DM_MMC=y +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_G_DNL_MANUFACTURER="Texas Instruments" +CONFIG_G_DNL_VENDOR_NUM=0x0451 +CONFIG_G_DNL_PRODUCT_NUM=0xd022 +CONFIG_OF_LIBFDT=y +CONFIG_OF_BOARD_SETUP=y +CONFIG_DRA7_DSPEVE_OPP_HIGH=y +CONFIG_DRA7_IVA_OPP_HIGH=y +CONFIG_DRA7_GPU_OPP_HIGH=y +CONFIG_CMD_TIME=y +CONFIG_DM_I2C=y +CONFIG_DM_REGULATOR=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_TARGET_DRA7XX_EVM_VISION=y diff --git a/configs/dra7xx_hs_evm_defconfig b/configs/dra7xx_hs_evm_defconfig index 810ba1e3f5..c055711e43 100644 --- a/configs/dra7xx_hs_evm_defconfig +++ b/configs/dra7xx_hs_evm_defconfig @@ -2,7 +2,7 @@ CONFIG_ARM=y CONFIG_OMAP54XX=y CONFIG_TI_SECURE_DEVICE=y CONFIG_TARGET_DRA7XX_EVM=y -CONFIG_TI_SECURE_EMIF_REGION_START=0xbe000000 +CONFIG_TI_SECURE_EMIF_REGION_START=0xbdb00000 CONFIG_TI_SECURE_EMIF_TOTAL_REGION_SIZE=0x02000000 CONFIG_TI_SECURE_EMIF_PROTECTED_REGION_SIZE=0x01c00000 CONFIG_DM_SERIAL=y diff --git a/doc/README.earlyboot b/doc/README.earlyboot new file mode 100644 index 0000000000..93f7d89528 --- /dev/null +++ b/doc/README.earlyboot @@ -0,0 +1,136 @@ +/* + * (C) Copyright 2016 + * Texas Instruments Incorporated. + * Venkateswara Rao Mandela <venkat.mandela@ti.com> + * + * Documentation for Early Boot functionality + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + +Using Early Boot on TI DRA7xx platforms +======================================= + +"Early boot" as defined in the scope of this document is booting slave cores in +a heteregeneous multiprocessor system before the main core running Linux is +booted. In case of a DRA7xx SOC, this could be booting the M4 core or the DSP +core before the A15 core has booted Linux. This feature is typically used to +handle functionality that needs to be available immediately after boot. In the +automotive domain, these functionalities could be responding to CAN messages, +bringing up the rear view camera, playing out a chime as soon as the key is +inserted. The "Early Boot" functionality is typically used along side a "late +attach" feature in the Linux kernel. By doing a "late attach", the Linux kernel +starts communicating and controlling an already running remotecore(M4/DSP) +instead of a resetting, reloading and restarting the core. + +Current Support Status +====================== + +This version of U-Boot supports loading IPU1/IPU2/DSP1/DSP2 in the DRA7x SOC +from the bootloader. The selected remotecores are booted from a ELF images in +the FAT partition of the MMC/SD device or a specified eMMC partition. The MMU +of the remotecore is setup in a manner expected by the Linux kernel. + +Configuration Options +====================== + +The below options should be set through menuconfig or configs/dra7xx_evm_defconfig. + +CONFIG_LATE_ATTACH=y + + Setting this option enables the early boot functionality in U-Boot. + This option automatically enables the ELF loader support and includes + the common/elf_remoteproc.c required for remoteproc support in the + build. + +CONFIG_LATE_ATTACH_GPT_PART=y + + Enable this flag when booting Android. This flag enables MLO to look in + named EFI partitions for the remotecore binaries. + +Load addresses +============== +============== + +MAX_REMOTECORE_BIN_SIZE + + This macro is defined in ti_omap5_common.h and specifies the maximum size + of the ELF binary that can be loaded via early boot. This is currently + configured to 8 MB which should be a reasonable size of most of the symbol + stripped ELF binaries. + + +IPU1_LOAD_ADDR +IPU2_LOAD_ADDR +DSP1_LOAD_ADDR +DSP2_LOAD_ADDR + + The below four macros specify the addresses where MLO/SPL + loads the remotecore ELF binaries temporarily for + processing. These addresses should be chosen such that they do + not trample on each other or on the u-boot code or on the + final DDR addresses used by the remotecores. + + These macros are defined in ti_omap5_common.h. For convenience, + only IPU1_LOAD_ADDR needs to be defined. The other macros are + computed based on IPU1_LOAD_ADDR and MAX_REMOTECORE_BIN_SIZE. + +Binary storage locations (Linux) +================================ +================================ + +In case of Linux boot, the binaries are read from the FAT parition of +the eMMC or SD card based on the boot media. The binaries should be +stored with the same names as defined by the Linux Kernel. + +IPU1 - dra7-ipu1-fw.xem4 +IPU2 - dra7-ipu2-fw.xem4 +DSP1 - dra7-dsp1-fw.xe66 +DSP2 - dra7-dsp2-fw.xe66 + +Binary storage locations (Android) +================================== +================================== + +CONFIG_MMC_IPU1_PART_NAME +CONFIG_MMC_IPU2_PART_NAME +CONFIG_MMC_DSP1_PART_NAME +CONFIG_MMC_DSP2_PART_NAME + + Android uses a GPT partition on eMMC for boot. These macros + specify the name of the GPT parition from which the + corresponding ELF binary is read. The binary is expected to + stored as is without any header. The whole partition is read + into memory. So the partition size should be smaller than + MAX_REMOTECORE_BIN_SIZE. + +With these options enabled, the remotecores to be booted should be specified in +the array cores_to_boot[] in common/spl/spl.c. Only the cores +specified in this array are booted by the bootloader and in the same order as +specified in the array. + +#ifdef CONFIG_LATE_ATTACH +u32 cores_to_boot[] = { IPU2, DSP1, DSP2, IPU1 }; +#endif + +Test Status +=========== + +Early boot by U-Boot and Late attach by Linux Kernel has been verified using +IPC sample applications for MessageQ. + +Pending Development +=================== + +The pending features are listed in no specific priority. + +1. Currently we only support early booting the remotecores from SPL. Adding +support for early booting from U-Boot is desirable for debug purposes. + +2. Linux kernel requires the device tree nodes part of the remotecore being +early booted to be marked with specific attributes. Currently this done outside +the boot loader by compiling a new DTB file. Add a feature to U-Boot to set the +required attributes on the device tree nodes before booting the kernel. + +3. Add support for loading the remotecore binaries from QSPI. diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 585aaf3115..b2632af155 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o +obj-$(CONFIG_SPL_SAVEENV) += mmc_write.o else obj-$(CONFIG_GENERIC_MMC) += mmc_write.o endif diff --git a/drivers/mmc/mmc_private.h b/drivers/mmc/mmc_private.h index d3f6bfe123..95c44bb927 100644 --- a/drivers/mmc/mmc_private.h +++ b/drivers/mmc/mmc_private.h @@ -20,17 +20,16 @@ extern int mmc_set_blocklen(struct mmc *mmc, int len); void mmc_adapter_card_type_ident(void); #endif -#ifndef CONFIG_SPL_BUILD - +#if !(defined(CONFIG_SPL_BUILD) && !defined(CONFIG_SPL_SAVEENV)) unsigned long mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt); unsigned long mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, const void *src); -#else /* CONFIG_SPL_BUILD */ +#else /* CONFIG_SPL_BUILD and CONFIG_SPL_SAVEENV is not defined */ -/* SPL will never write or erase, declare dummies to reduce code size. */ +/* declare dummies to reduce code size. */ static inline unsigned long mmc_berase(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt) diff --git a/drivers/mtd/spi/spi_spl_load.c b/drivers/mtd/spi/spi_spl_load.c index 241b1a73ae..a216991264 100644 --- a/drivers/mtd/spi/spi_spl_load.c +++ b/drivers/mtd/spi/spi_spl_load.c @@ -15,7 +15,7 @@ #include <errno.h> #include <spl.h> -#ifdef CONFIG_SPL_OS_BOOT +#if defined(CONFIG_SPL_OS_BOOT) /* * Load the kernel, check for a valid header we can parse, and if found load * the kernel and then device tree. @@ -63,7 +63,7 @@ static ulong spl_spi_fit_read(struct spl_load_info *load, ulong sector, */ int spl_spi_load_image(void) { - int err = 0; + int err = 1; struct spi_flash *flash; struct image_header *header; @@ -83,10 +83,20 @@ int spl_spi_load_image(void) /* use CONFIG_SYS_TEXT_BASE as temporary storage area */ header = (struct image_header *)(CONFIG_SYS_TEXT_BASE); + #ifdef CONFIG_SPL_OS_BOOT - if (spl_start_uboot() || spi_load_image_os(flash, header)) + err = spl_start_uboot(); + if (!err) { + /* check for linux-os image */ + err = spi_load_image_os(flash, header); +#ifdef CONFIG_SPL_QSPI_OS_IN_MMC + if (err) + err = spl_mmc_load_image_raw_os(); #endif - { + } +#endif + + if (err) { /* Load u-boot, mkimage header is 64 bytes. */ err = spi_flash_read(flash, CONFIG_SYS_SPI_U_BOOT_OFFS, 0x40, (void *)header); diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 28b244a8d0..1c9ecb7ecd 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -27,6 +27,7 @@ #ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV #include <fb_nand.h> #endif +#include <android_image.h> #define FASTBOOT_VERSION "0.4" @@ -39,6 +40,7 @@ #define TX_ENDPOINT_MAXIMUM_PACKET_SIZE (0x0040) #define EP_BUFFER_SIZE 4096 +#define MAX_CMDS 4 /* * EP_BUFFER_SIZE must always be an integral multiple of maxpacket size * (64 or 512 or 1024), else we break on certain controllers like DWC3 @@ -62,6 +64,8 @@ static struct f_fastboot *fastboot_func; static unsigned int fastboot_flash_session_id; static unsigned int download_size; static unsigned int download_bytes; +static char f_cmdbuf[MAX_CMDS][32]; +static int flash_spi; static struct usb_endpoint_descriptor fs_ep_in = { .bLength = USB_DT_ENDPOINT_SIZE, @@ -397,6 +401,30 @@ static int strcmp_l1(const char *s1, const char *s2) return strncmp(s1, s2, strlen(s1)); } +static void reset_fastboot_cmd(void) +{ + int i; + for (i = 0; i < MAX_CMDS; ++i) + f_cmdbuf[i][0] = 0; +} + +static void run_fastboot_cmd(void) +{ + int i; + for (i = 0; f_cmdbuf[i][0] && i < MAX_CMDS; ++i) { + if (run_command(f_cmdbuf[i], 0)) + fastboot_tx_write_str("FAIL"); + else + fastboot_tx_write_str("OKAY"); + } +} + +static void add_fastboot_cmd(int index, char *str) +{ + if (index < MAX_CMDS) + strcpy(f_cmdbuf[index], str); +} + static void cb_getvar(struct usb_ep *ep, struct usb_request *req) { char *cmd = req->buf; @@ -586,6 +614,169 @@ static void cb_continue(struct usb_ep *ep, struct usb_request *req) } #ifdef CONFIG_FASTBOOT_FLASH +static int fastboot_update_zimage(void); + +static void fastboot_update_bootloader(char *cmd) +{ + char cmdbuf[32]; + reset_fastboot_cmd(); + + if (strncmp("xloader", cmd, 7) == 0) { + sprintf(cmdbuf, "sf write 0x%x 0 40000", + (unsigned int)CONFIG_FASTBOOT_BUF_ADDR); + add_fastboot_cmd(0, cmdbuf); + } else if (strncmp("bootloader", cmd, 10) == 0) { + sprintf(cmdbuf, "sf write 0x%x 40000 100000", + (unsigned int)CONFIG_FASTBOOT_BUF_ADDR); + add_fastboot_cmd(0, cmdbuf); + } + run_fastboot_cmd(); +} + +static u32 fastboot_get_boot_ptn(struct andr_img_hdr *hdr, char *response, + struct blk_desc *dev_desc) +{ + u32 hdr_sectors = 0; + u32 sector_size; + int status = 0; + strcpy(response, "OKAY"); + disk_partition_t info; + + status = part_get_info_efi_by_name(dev_desc, "boot", &info); + if (status) { + strcpy(response, "FAILCannot find boot partition"); + goto out; + } + + /* Read the boot image header */ + sector_size = info.blksz; + hdr_sectors = (sizeof(struct andr_img_hdr)/sector_size) + 1; + status = dev_desc->block_read(dev_desc, info.start, hdr_sectors, + (void *)hdr); + + if (status < 0) { + strcpy(response, "FAILCannot read hdr from boot partition"); + goto out; + } + if (android_image_check_header(hdr) != 0) { + printf("bad boot image magic\n"); + strcpy(response, "FAILBoot partition not initialized"); + goto out; + } + + return hdr_sectors; + +out: + strcpy(response, "INFO"); + fastboot_tx_write_str(response); + + return -1; +} + +#define CEIL(a, b) (((a) / (b)) + ((a % b) > 0 ? 1 : 0)) + +static int fastboot_update_zimage(void) +{ + struct andr_img_hdr *hdr = NULL; + u8 *ramdisk_buffer; + u32 ramdisk_sector_start, ramdisk_sectors; + u32 kernel_sector_start, kernel_sectors; + u32 hdr_sectors = 0; + u32 sectors_per_page = 0; + int ret = 0; + struct blk_desc *dev_desc; + disk_partition_t info; + char response[FASTBOOT_RESPONSE_LEN]; + u32 addr = CONFIG_FASTBOOT_BUF_ADDR; + + strcpy(response, "OKAY"); + printf("Flashing zImage...%d bytes\n", download_bytes); + + dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV); + if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) { + sprintf(response + strlen(response), + "FAILInvalid mmc device"); + ret = -1; + goto out; + } + + addr += CEIL(download_bytes, 0x1000) * 0x1000; + hdr = (struct andr_img_hdr *)addr; + + hdr_sectors = fastboot_get_boot_ptn(hdr, response, dev_desc); + if (hdr_sectors <= 0) { + sprintf(response + strlen(response), + "FAILInvalid number of boot sectors %d", hdr_sectors); + ret = -1; + goto out; + } + ret = part_get_info_efi_by_name(dev_desc, "boot", &info); + if (ret) { + strcpy(response, "FAILCannot find boot partition"); + ret = -1; + goto out; + } + + /* Extract ramdisk location and read it into local buffer */ + sectors_per_page = hdr->page_size / info.blksz; + ramdisk_sector_start = info.start + sectors_per_page; + ramdisk_sector_start += CEIL(hdr->kernel_size, hdr->page_size)* + sectors_per_page; + ramdisk_sectors = CEIL(hdr->ramdisk_size, hdr->page_size)* + sectors_per_page; + + ramdisk_buffer = (u8 *)hdr; + ramdisk_buffer += (hdr_sectors * info.blksz); + ret = dev_desc->block_read(dev_desc, ramdisk_sector_start, + ramdisk_sectors, ramdisk_buffer); + if (ret < 0) { + sprintf(response, "FAILCannot read ramdisk from 'boot'"); + ret = -1; + goto out; + } + + /* Change the boot img hdr */ + hdr->kernel_size = download_bytes; + ret = dev_desc->block_write(dev_desc, info.start, + hdr_sectors, (void *)hdr); + if (ret < 0) { + sprintf(response, "FAILCannot writeback boot img hdr"); + ret = -1; + goto out; + } + + /* Write the new downloaded kernel*/ + kernel_sector_start = info.start + sectors_per_page; + kernel_sectors = CEIL(hdr->kernel_size, hdr->page_size)* + sectors_per_page; + ret = dev_desc->block_write(dev_desc, kernel_sector_start, + kernel_sectors, + (const void *)CONFIG_FASTBOOT_BUF_ADDR); + if (ret < 0) { + sprintf(response, "FAILCannot write new kernel"); + ret = -1; + goto out; + } + + /* Write the saved Ramdisk back */ + ramdisk_sector_start = info.start + sectors_per_page; + ramdisk_sector_start += CEIL(hdr->kernel_size, hdr->page_size)* + sectors_per_page; + ret = dev_desc->block_write(dev_desc, ramdisk_sector_start, + ramdisk_sectors, ramdisk_buffer); + if (ret < 0) { + sprintf(response, "FAILCannot write back original ramdisk"); + ret = -1; + goto out; + } + fastboot_tx_write_str(response); + return 0; + +out: + fastboot_tx_write_str(response); + return ret; +} + static void cb_flash(struct usb_ep *ep, struct usb_request *req) { char *cmd = req->buf; @@ -599,6 +790,19 @@ static void cb_flash(struct usb_ep *ep, struct usb_request *req) } strcpy(response, "FAILno flash device defined"); + + if (!strcmp(cmd, "zImage") || !strcmp(cmd, "zimage")) { + fastboot_update_zimage(); + return; + } + + if (!strcmp(cmd, "xloader") || !strcmp(cmd, "bootloader")) { + if (flash_spi) { + fastboot_update_bootloader(cmd); + return; + } + } + #ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV fb_mmc_flash_write(cmd, fastboot_flash_session_id, (void *)CONFIG_FASTBOOT_BUF_ADDR, @@ -617,23 +821,34 @@ static void cb_flash(struct usb_ep *ep, struct usb_request *req) static void cb_oem(struct usb_ep *ep, struct usb_request *req) { char *cmd = req->buf; + char cmdbuf[32]; + + reset_fastboot_cmd(); + #ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV if (strncmp("format", cmd + 4, 6) == 0) { - char cmdbuf[32]; sprintf(cmdbuf, "gpt write mmc %x $partitions", CONFIG_FASTBOOT_FLASH_MMC_DEV); - if (run_command(cmdbuf, 0)) - fastboot_tx_write_str("FAIL"); - else - fastboot_tx_write_str("OKAY"); + add_fastboot_cmd(0, cmdbuf); } else #endif - if (strncmp("unlock", cmd + 4, 8) == 0) { + if (strncmp("mmc", cmd + 4, 3) == 0) { + flash_spi = 0; + fastboot_tx_write_str("OKAY"); + } else if (strncmp("spi", cmd + 4, 3) == 0) { + flash_spi = 1; + add_fastboot_cmd(0, "sf probe 0"); + add_fastboot_cmd(1, "sf erase 0 0x40000"); + add_fastboot_cmd(2, "sf erase 0x40000 0x100000"); + } else if (strncmp("unlock", cmd + 4, 8) == 0) { fastboot_tx_write_str("FAILnot implemented"); - } - else { + return ; + } else { fastboot_tx_write_str("FAILunknown oem command"); + return ; } + + run_fastboot_cmd(); } #ifdef CONFIG_FASTBOOT_FLASH diff --git a/include/configs/am57xx_evm.h b/include/configs/am57xx_evm.h index 7a68bba2d7..6c37cad494 100644 --- a/include/configs/am57xx_evm.h +++ b/include/configs/am57xx_evm.h @@ -12,6 +12,8 @@ #ifndef __CONFIG_AM57XX_EVM_H #define __CONFIG_AM57XX_EVM_H +#include <linux/sizes.h> + #define CONFIG_DRA7XX #define CONFIG_IODELAY_RECALIBRATION @@ -20,11 +22,14 @@ #define CONFIG_NR_DRAM_BANKS 2 -#define CONFIG_ENV_SIZE (64 << 10) -#define CONFIG_ENV_IS_IN_FAT -#define FAT_ENV_INTERFACE "mmc" -#define FAT_ENV_DEVICE_AND_PART "0:1" -#define FAT_ENV_FILE "uboot.env" +/* MMC ENV related defines */ +#define CONFIG_ENV_IS_IN_MMC +#define CONFIG_SYS_MMC_ENV_DEV 1 /* eMMC */ +#define CONFIG_SYS_MMC_ENV_PART 0 +#define CONFIG_ENV_SIZE SZ_128K +#define CONFIG_ENV_OFFSET 0x140000 /* "reserved" part. */ +#define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE) +#define CONFIG_SYS_REDUNDAND_ENVIRONMENT #define CONSOLEDEV "ttyO2" #define CONFIG_SYS_NS16550_COM1 UART1_BASE /* Base EVM has UART0 */ @@ -34,10 +39,44 @@ #define CONFIG_SYS_OMAP_ABE_SYSCK +#ifndef CONFIG_SPL_BUILD /* Define the default GPT table for eMMC */ #define PARTS_DEFAULT \ + /* Linux partitions */ \ + "uuid_disk=${uuid_gpt_disk};" \ + "name=rootfs,start=2MiB,size=-,uuid=${uuid_gpt_rootfs}\0" \ + /* Android partitions */ \ + "partitions_android=" \ "uuid_disk=${uuid_gpt_disk};" \ - "name=rootfs,start=2MiB,size=-,uuid=${uuid_gpt_rootfs}" + "name=xloader,start=128K,size=256K,uuid=${uuid_gpt_xloader};" \ + "name=bootloader,size=2048K,uuid=${uuid_gpt_bootloader};" \ + "name=environment,size=256K,uuid=${uuid_gpt_environment};" \ + "name=misc,size=128K,uuid=${uuid_gpt_misc};" \ + "name=reserved,size=384K,uuid=${uuid_gpt_reserved};" \ + "name=efs,size=16M,uuid=${uuid_gpt_efs};" \ + "name=crypto,size=16K,uuid=${uuid_gpt_crypto};" \ + "name=recovery,size=10M,uuid=${uuid_gpt_recovery};" \ + "name=boot,size=10M,uuid=${uuid_gpt_boot};" \ + "name=system,size=768M,uuid=${uuid_gpt_system};" \ + "name=cache,size=256M,uuid=${uuid_gpt_cache};" \ + "name=ipu1,size=1M,uuid=${uuid_gpt_ipu1};" \ + "name=ipu2,size=1M,uuid=${uuid_gpt_ipu2};" \ + "name=userdata,size=-,uuid=${uuid_gpt_userdata}" + +/* Fastboot */ +#define CONFIG_USB_FUNCTION_FASTBOOT +#define CONFIG_CMD_FASTBOOT +#define CONFIG_ANDROID_BOOT_IMAGE +#define CONFIG_FASTBOOT_BUF_ADDR CONFIG_SYS_LOAD_ADDR +#define CONFIG_FASTBOOT_BUF_SIZE 0x2F000000 +#define CONFIG_FASTBOOT_FLASH +#define CONFIG_FASTBOOT_FLASH_MMC_DEV 1 +#define CONFIG_FASTBOOT_USB_DEV 1 +#endif + +#define CONFIG_BOOTARGS_BOARD "console=ttyS2,115200 " \ + "androidboot.console=ttyS2 " \ + "androidboot.hardware=am57xevmboard" #define DFUARGS \ "dfu_bufsiz=0x10000\0" \ @@ -52,6 +91,8 @@ /* Enhance our eMMC support / experience. */ #define CONFIG_CMD_GPT #define CONFIG_EFI_PARTITION +#define CONFIG_RANDOM_UUID +#define CONFIG_HSMMC2_8BIT /* CPSW Ethernet */ #define CONFIG_BOOTP_DNS /* Configurable parts of CMD_DHCP */ @@ -79,6 +120,8 @@ #define CONFIG_OMAP_USB_PHY #define CONFIG_OMAP_USB3PHY1_HOST +#define CONFIG_USB_FUNCTION_MASS_STORAGE + /* USB Device Firmware Update support */ #define CONFIG_USB_FUNCTION_DFU #define CONFIG_DFU_RAM diff --git a/include/configs/dra7xx_evm.h b/include/configs/dra7xx_evm.h index 9fdc1e50d2..73536f1533 100644 --- a/include/configs/dra7xx_evm.h +++ b/include/configs/dra7xx_evm.h @@ -18,6 +18,7 @@ #define CONFIG_BOARD_EARLY_INIT_F #define CONFIG_IODELAY_RECALIBRATION +#define CONFIG_SPL_SAVEENV #define CONFIG_VERY_BIG_RAM #define CONFIG_PHYS_64BIT @@ -55,18 +56,21 @@ /* Android partitions */ \ "partitions_android=" \ "uuid_disk=${uuid_gpt_disk};" \ - "name=xloader,start=128K,size=128K,uuid=${uuid_gpt_xloader};" \ - "name=bootloader,size=384K,uuid=${uuid_gpt_bootloader};" \ - "name=environment,size=128K,uuid=${uuid_gpt_environment};" \ + "name=xloader,start=128K,size=256K,uuid=${uuid_gpt_xloader};" \ + "name=bootloader,size=2048K,uuid=${uuid_gpt_bootloader};" \ + "name=environment,size=256K,uuid=${uuid_gpt_environment};" \ "name=misc,size=128K,uuid=${uuid_gpt_misc};" \ - "name=efs,start=1280K,size=16M,uuid=${uuid_gpt_efs};" \ + "name=reserved,size=384K,uuid=${uuid_gpt_reserved};" \ + "name=efs,size=16M,uuid=${uuid_gpt_efs};" \ "name=crypto,size=16K,uuid=${uuid_gpt_crypto};" \ "name=recovery,size=10M,uuid=${uuid_gpt_recovery};" \ "name=boot,size=10M,uuid=${uuid_gpt_boot};" \ "name=system,size=768M,uuid=${uuid_gpt_system};" \ "name=cache,size=256M,uuid=${uuid_gpt_cache};" \ - "name=ipu1,size=1M,uuid=${uuid_gpt_ipu1};" \ - "name=ipu2,size=1M,uuid=${uuid_gpt_ipu2};" \ + "name=ipu1,size=8M,uuid=${uuid_gpt_ipu1};" \ + "name=ipu2,size=8M,uuid=${uuid_gpt_ipu2};" \ + "name=dsp1,size=8M,uuid=${uuid_gpt_dsp1};" \ + "name=dsp2,size=8M,uuid=${uuid_gpt_dsp2};" \ "name=userdata,size=-,uuid=${uuid_gpt_userdata}" #define DFUARGS \ @@ -79,13 +83,18 @@ /* Fastboot */ #define CONFIG_USB_FUNCTION_FASTBOOT #define CONFIG_CMD_FASTBOOT -#define CONFIG_ANDROID_BOOT_IMAGE #define CONFIG_FASTBOOT_BUF_ADDR CONFIG_SYS_LOAD_ADDR #define CONFIG_FASTBOOT_BUF_SIZE 0x2F000000 #define CONFIG_FASTBOOT_FLASH #define CONFIG_FASTBOOT_FLASH_MMC_DEV 1 #endif +#define CONFIG_ANDROID_BOOT_IMAGE + +#define CONFIG_BOOTARGS_BOARD "console=ttyS0,115200 " \ + "androidboot.console=ttyS0 " \ + "androidboot.hardware=jacinto6evmboard" + #ifdef CONFIG_SPL_BUILD #undef CONFIG_CMD_BOOTD #ifdef CONFIG_SPL_DFU_SUPPORT @@ -192,6 +201,8 @@ #define CONFIG_OMAP_USB_PHY #define CONFIG_OMAP_USB2PHY2_HOST +#define CONFIG_USB_FUNCTION_MASS_STORAGE + /* USB Device Firmware Update support */ #define CONFIG_USB_FUNCTION_DFU #define CONFIG_DFU_RAM @@ -308,5 +319,28 @@ #define CONFIG_PCF8575_GPIO #endif +/* JAMR3 board pin mux */ +#define CONFIG_DRA7XX_JAMR3 + +#undef CONFIG_SYS_SPL_ARGS_ADDR +#define CONFIG_SYS_SPL_ARGS_ADDR 0x82f80000 + +#ifndef CONFIG_SPL_DFU_SUPPORT +#ifndef CONFIG_PERIPHERAL_BOOT +#define CONFIG_SPL_QSPI_OS_IN_MMC +#define CONFIG_SPL_ANDROID_BOOT_SUPPORT +#define CONFIG_SPL_SPI_PROD_OS_BOOT +#define CONFIG_MACH_TYPE 4070 +#ifdef CONFIG_SPL_QSPI_OS_IN_MMC +#define CONFIG_SPL_MMC_DTB_NAME "environment" +#define CONFIG_SPL_MMC_KERNEL_NAME "boot" +#endif +#endif +#endif + +#ifdef CONFIG_SPL_BUILD +#define CONFIG_SPL_ENV_SUPPORT +#endif + #define CONFIG_DRA7XX_DWC1 #endif /* __CONFIG_DRA7XX_EVM_H */ diff --git a/include/configs/ti_armv7_common.h b/include/configs/ti_armv7_common.h index 13f8ccba94..0e5716459e 100644 --- a/include/configs/ti_armv7_common.h +++ b/include/configs/ti_armv7_common.h @@ -282,8 +282,8 @@ #endif /* RAW SD card / eMMC locations. */ -#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x300 /* address 0x60000 */ -#define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS 0x200 /* 256 KB */ +#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x300 /* address 0x60000 */ +#define CONFIG_SYS_U_BOOT_MAX_SIZE_SECTORS 0x1000 /* 2048 KB */ /* FAT sd card locations. */ #define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION 1 diff --git a/include/configs/ti_omap5_common.h b/include/configs/ti_omap5_common.h index 360860f3ca..171cc9aa36 100644 --- a/include/configs/ti_omap5_common.h +++ b/include/configs/ti_omap5_common.h @@ -70,6 +70,8 @@ DEFAULT_FIT_TI_ARGS \ "console=" CONSOLEDEV ",115200n8\0" \ "fdtfile=undefined\0" \ + "reboot_image=boot\0" \ + "boot_os=0\0" \ "bootpart=0:2\0" \ "bootdir=/boot\0" \ "bootfile=zImage\0" \ @@ -78,6 +80,43 @@ "partitions=" PARTS_DEFAULT "\0" \ "optargs=\0" \ "dofastboot=0\0" \ + "loadbootscript=fatload mmc ${mmcdev} ${loadaddr} boot.scr\0" \ + "bootscript=echo Running bootscript from mmc${mmcdev} ...; " \ + "source ${loadaddr}\0" \ + "loadimage=load mmc ${bootpart} ${loadaddr} ${bootdir}/${bootfile}\0" \ + "mmcboot=" \ + "if mmc dev ${mmcdev}; then " \ + "setenv devtype mmc; " \ + "if mmc rescan; then " \ + "echo SD/MMC found on device ${mmcdev};" \ + "if run loadimage; then " \ + "run loadfdt; " \ + "echo Booting from mmc${mmcdev} ...; " \ + "run args_mmc; " \ + "bootz ${loadaddr} - ${fdtaddr}; " \ + "fi; " \ + "fi; " \ + "fi;\0" \ + "emmc_android_boot=" \ + "setenv eval_bootargs setenv bootargs $bootargs; " \ + "run eval_bootargs; " \ + "setenv mmcdev 1; " \ + "setenv fdt_part 3; " \ + "setenv boot_part 9; " \ + "if test $reboot_image = recovery; then " \ + "setenv boot_part 8; " \ + "setenv reboot_image boot; saveenv; fi;" \ + "setenv machid fe6; " \ + "mmc dev $mmcdev; " \ + "mmc rescan; " \ + "part start mmc ${mmcdev} ${fdt_part} fdt_start; " \ + "part size mmc ${mmcdev} ${fdt_part} fdt_size; " \ + "part start mmc ${mmcdev} ${boot_part} boot_start; " \ + "part size mmc ${mmcdev} ${boot_part} boot_size; " \ + "mmc read ${fdtaddr} ${fdt_start} ${fdt_size}; " \ + "mmc read ${loadaddr} ${boot_start} ${boot_size}; " \ + "echo Booting from eMMC ...; " \ + "bootm $loadaddr $loadaddr $fdtaddr;\0" \ "findfdt="\ "if test $board_name = omap5_uevm; then " \ "setenv fdtfile omap5-uevm.dtb; fi; " \ @@ -114,11 +153,21 @@ DFUARGS \ NETARGS \ +#ifndef CONFIG_BOOTARGS_BOARD +#define CONFIG_BOOTARGS_BOARD +#endif +#define CONFIG_BOOTARGS "androidboot.serialno=${serial#} " \ + CONFIG_BOOTARGS_BOARD + +#ifndef CONFIG_FASTBOOT_USB_DEV +#define CONFIG_FASTBOOT_USB_DEV 0 +#endif #define CONFIG_BOOTCOMMAND \ "if test ${dofastboot} -eq 1; then " \ "echo Boot fastboot requested, resetting dofastboot ...;" \ "setenv dofastboot 0; saveenv;" \ - "echo Booting into fastboot ...; fastboot 0;" \ + "echo Booting into fastboot ...; " \ + "fastboot " __stringify(CONFIG_FASTBOOT_USB_DEV) "; " \ "fi;" \ "if test ${boot_fit} -eq 1; then " \ "run update_to_fit;" \ @@ -126,10 +175,7 @@ "run findfdt; " \ "run envboot; " \ "run mmcboot;" \ - "setenv mmcdev 1; " \ - "setenv bootpart 1:2; " \ - "setenv mmcroot /dev/mmcblk0p2 rw; " \ - "run mmcboot;" \ + "run emmc_android_boot; " \ "" /* @@ -184,4 +230,33 @@ #undef CONFIG_DM_ETH #endif +#define MAX_REMOTECORE_BIN_SIZE (8*0x100000) + +/* Define the address to which the IPU1 binary is + * loaded from persistent storage + */ +#define IPU1_LOAD_ADDR (0xa0fff000) + +/* + * Set load address for each core 8 MB after load + * address for the previous core + */ +#define IPU2_LOAD_ADDR (IPU1_LOAD_ADDR+MAX_REMOTECORE_BIN_SIZE) +#define DSP1_LOAD_ADDR (IPU2_LOAD_ADDR+MAX_REMOTECORE_BIN_SIZE) +#define DSP2_LOAD_ADDR (DSP1_LOAD_ADDR+MAX_REMOTECORE_BIN_SIZE) + +/* Define the GPT partition names only when they are used. + * This prevents warnings of invalid GPT table when loading + * binaries from FAT partition. + */ +#ifdef CONFIG_LATE_ATTACH_GPT_PART +#define CONFIG_MMC_IPU1_PART_NAME "ipu1" +#define CONFIG_MMC_IPU2_PART_NAME "ipu2" +#define CONFIG_MMC_DSP1_PART_NAME "dsp1" +#define CONFIG_MMC_DSP2_PART_NAME "dsp2" +#endif + +/* Error code to indicate that SPL failed to load a remotecore */ +#define SPL_CORE_LOAD_ERR_ID (0xFF00) + #endif /* __CONFIG_TI_OMAP5_COMMON_H */ diff --git a/include/image.h b/include/image.h index baa174c58c..6114bc6b66 100644 --- a/include/image.h +++ b/include/image.h @@ -1152,6 +1152,7 @@ int android_image_get_ramdisk(const struct andr_img_hdr *hdr, ulong *rd_data, ulong *rd_len); ulong android_image_get_end(const struct andr_img_hdr *hdr); ulong android_image_get_kload(const struct andr_img_hdr *hdr); +ulong android_image_get_rload(const struct andr_img_hdr *hdr); #endif /* CONFIG_ANDROID_BOOT_IMAGE */ diff --git a/include/omap_remoteproc.h b/include/omap_remoteproc.h new file mode 100644 index 0000000000..63bf9e282a --- /dev/null +++ b/include/omap_remoteproc.h @@ -0,0 +1,465 @@ +/* + * Remote Processor Framework + * + * Copyright(c) 2011 Texas Instruments, Inc. + * Copyright(c) 2011 Google, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Texas Instruments nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef REMOTEPROC_H +#define REMOTEPROC_H + +#include <linux/types.h> +#include <linux/list.h> + +/** + * struct resource_table - firmware resource table header + * @ver: version number + * @num: number of resource entries + * @reserved: reserved (must be zero) + * @offset: array of offsets pointing at the various resource entries + * + * A resource table is essentially a list of system resources required + * by the remote processor. It may also include configuration entries. + * If needed, the remote processor firmware should contain this table + * as a dedicated ".resource_table" ELF section. + * + * Some resources entries are mere announcements, where the host is informed + * of specific remoteproc configuration. Other entries require the host to + * do something (e.g. allocate a system resource). Sometimes a negotiation + * is expected, where the firmware requests a resource, and once allocated, + * the host should provide back its details (e.g. address of an allocated + * memory region). + * + * The header of the resource table, as expressed by this structure, + * contains a version number (should we need to change this format in the + * future), the number of available resource entries, and their offsets + * in the table. + * + * Immediately following this header are the resource entries themselves, + * each of which begins with a resource entry header (as described below). + */ +struct resource_table { + u32 ver; + u32 num; + u32 reserved[2]; + u32 offset[0]; +} __packed; + +/** + * struct fw_rsc_hdr - firmware resource entry header + * @type: resource type + * @data: resource data + * + * Every resource entry begins with a 'struct fw_rsc_hdr' header providing + * its @type. The content of the entry itself will immediately follow + * this header, and it should be parsed according to the resource type. + */ +struct fw_rsc_hdr { + u32 type; + u8 data[0]; +} __packed; + +/** + * enum fw_resource_type - types of resource entries + * + * @RSC_CARVEOUT: request for allocation of a physically contiguous + * memory region. + * @RSC_DEVMEM: request to iommu_map a memory-based peripheral. + * @RSC_TRACE: announces the availability of a trace buffer into which + * the remote processor will be writing logs. + * @RSC_VDEV: declare support for a virtio device, and serve as its + * virtio header. + * @RSC_INTMEM: request to map into kernel an internal memory region. + * @RSC_CUSTOM: a custom resource type that needs to be handled outside + * remoteproc core. + * @RSC_LAST: just keep this one at the end + * + * For more details regarding a specific resource type, please see its + * dedicated structure below. + * + * Please note that these values are used as indices to the rproc_handle_rsc + * lookup table, so please keep them sane. Moreover, @RSC_LAST is used to + * check the validity of an index before the lookup table is accessed, so + * please update it as needed. + */ +enum fw_resource_type { + RSC_CARVEOUT = 0, + RSC_DEVMEM = 1, + RSC_TRACE = 2, + RSC_VDEV = 3, + RSC_INTMEM = 4, + RSC_CUSTOM = 5, + RSC_LAST = 6, +}; + +#define FW_RSC_ADDR_ANY (0xFFFFFFFFFFFFFFFF) + +/** + * struct fw_rsc_carveout - physically contiguous memory request + * @da: device address + * @pa: physical address + * @len: length (in bytes) + * @flags: iommu protection flags + * @reserved: reserved (must be zero) + * @name: human-readable name of the requested memory region + * + * This resource entry requests the host to allocate a physically contiguous + * memory region. + * + * These request entries should precede other firmware resource entries, + * as other entries might request placing other data objects inside + * these memory regions (e.g. data/code segments, trace resource entries, ...). + * + * Allocating memory this way helps utilizing the reserved physical memory + * (e.g. CMA) more efficiently, and also minimizes the number of TLB entries + * needed to map it (in case @rproc is using an IOMMU). Reducing the TLB + * pressure is important; it may have a substantial impact on performance. + * + * If the firmware is compiled with static addresses, then @da should specify + * the expected device address of this memory region. If @da is set to + * FW_RSC_ADDR_ANY, then the host will dynamically allocate it, and then + * overwrite @da with the dynamically allocated address. + * + * We will always use @da to negotiate the device addresses, even if it + * isn't using an iommu. In that case, though, it will obviously contain + * physical addresses. + * + * Some remote processors needs to know the allocated physical address + * even if they do use an iommu. This is needed, e.g., if they control + * hardware accelerators which access the physical memory directly (this + * is the case with OMAP4 for instance). In that case, the host will + * overwrite @pa with the dynamically allocated physical address. + * Generally we don't want to expose physical addresses if we don't have to + * (remote processors are generally _not_ trusted), so we might want to + * change this to happen _only_ when explicitly required by the hardware. + * + * @flags is used to provide IOMMU protection flags, and @name should + * (optionally) contain a human readable name of this carveout region + * (mainly for debugging purposes). + */ +struct fw_rsc_carveout { + u32 da; + u32 pa; + u32 len; + u32 flags; + u32 reserved; + u8 name[32]; +} __packed; + +/** + * struct fw_rsc_devmem - iommu mapping request + * @da: device address + * @pa: physical address + * @len: length (in bytes) + * @flags: iommu protection flags + * @reserved: reserved (must be zero) + * @name: human-readable name of the requested region to be mapped + * + * This resource entry requests the host to iommu map a physically contiguous + * memory region. This is needed in case the remote processor requires + * access to certain memory-based peripherals; _never_ use it to access + * regular memory. + * + * This is obviously only needed if the remote processor is accessing memory + * via an iommu. + * + * @da should specify the required device address, @pa should specify + * the physical address we want to map, @len should specify the size of + * the mapping and @flags is the IOMMU protection flags. As always, @name may + * (optionally) contain a human readable name of this mapping (mainly for + * debugging purposes). + * + * Note: at this point we just "trust" those devmem entries to contain valid + * physical addresses, but this isn't safe and will be changed: eventually we + * want remoteproc implementations to provide us ranges of physical addresses + * the firmware is allowed to request, and not allow firmwares to request + * access to physical addresses that are outside those ranges. + */ +struct fw_rsc_devmem { + u32 da; + u32 pa; + u32 len; + u32 flags; + u32 reserved; + u8 name[32]; +} __packed; + +/** + * struct fw_rsc_trace - trace buffer declaration + * @da: device address + * @len: length (in bytes) + * @reserved: reserved (must be zero) + * @name: human-readable name of the trace buffer + * + * This resource entry provides the host information about a trace buffer + * into which the remote processor will write log messages. + * + * @da specifies the device address of the buffer, @len specifies + * its size, and @name may contain a human readable name of the trace buffer. + * + * After booting the remote processor, the trace buffers are exposed to the + * user via debugfs entries (called trace0, trace1, etc..). + */ +struct fw_rsc_trace { + u32 da; + u32 len; + u32 reserved; + u8 name[32]; +} __packed; + +/** + * struct fw_rsc_vdev_vring - vring descriptor entry + * @da: device address + * @align: the alignment between the consumer and producer parts of the vring + * @num: num of buffers supported by this vring (must be power of two) + * @notifyid is a unique rproc-wide notify index for this vring. This notify + * index is used when kicking a remote processor, to let it know that this + * vring is triggered. + * @reserved: reserved (must be zero) + * + * This descriptor is not a resource entry by itself; it is part of the + * vdev resource type (see below). + * + * Note that @da should either contain the device address where + * the remote processor is expecting the vring, or indicate that + * dynamically allocation of the vring's device address is supported. + */ +struct fw_rsc_vdev_vring { + u32 da; + u32 align; + u32 num; + u32 notifyid; + u32 reserved; +} __packed; + +/** + * struct fw_rsc_vdev - virtio device header + * @id: virtio device id (as in virtio_ids.h) + * @notifyid is a unique rproc-wide notify index for this vdev. This notify + * index is used when kicking a remote processor, to let it know that the + * status/features of this vdev have changes. + * @dfeatures specifies the virtio device features supported by the firmware + * @gfeatures is a place holder used by the host to write back the + * negotiated features that are supported by both sides. + * @config_len is the size of the virtio config space of this vdev. The config + * space lies in the resource table immediate after this vdev header. + * @status is a place holder where the host will indicate its virtio progress. + * @num_of_vrings indicates how many vrings are described in this vdev header + * @reserved: reserved (must be zero) + * @vring is an array of @num_of_vrings entries of 'struct fw_rsc_vdev_vring'. + * + * This resource is a virtio device header: it provides information about + * the vdev, and is then used by the host and its peer remote processors + * to negotiate and share certain virtio properties. + * + * By providing this resource entry, the firmware essentially asks remoteproc + * to statically allocate a vdev upon registration of the rproc (dynamic vdev + * allocation is not yet supported). + * + * Note: unlike virtualization systems, the term 'host' here means + * the Linux side which is running remoteproc to control the remote + * processors. We use the name 'gfeatures' to comply with virtio's terms, + * though there isn't really any virtualized guest OS here: it's the host + * which is responsible for negotiating the final features. + * Yeah, it's a bit confusing. + * + * Note: immediately following this structure is the virtio config space for + * this vdev (which is specific to the vdev; for more info, read the virtio + * spec). the size of the config space is specified by @config_len. + */ +struct fw_rsc_vdev { + u32 id; + u32 notifyid; + u32 dfeatures; + u32 gfeatures; + u32 config_len; + u8 status; + u8 num_of_vrings; + u8 reserved[2]; + struct fw_rsc_vdev_vring vring[0]; +} __packed; + +/** + * struct fw_rsc_intmem - internal memory publishing request + * @version: version for this resource type (must be one) + * @da: device address + * @pa: physical address + * @len: length (in bytes) + * @reserved: reserved (must be zero) + * @name: human-readable name of the region being published + * + * This resource entry allows a remote processor to publish an internal + * memory region to the host. This resource type allows a remote processor + * to publish the whole or just a portion of certain internal memories, + * while it owns and manages any unpublished portion (eg: a shared L1 + * memory that can be split configured as RAM and/or cache). This is + * primarily provided to allow a host to load code/data into internal + * memories, the memory for which is neither allocated nor required to + * be mapped into an iommu. + * + * @da should specify the required address as accessible by the device + * without going through an iommu, @pa should specify the physical address + * for the region as seen on the bus, @len should specify the size of the + * memory region. As always, @name may (optionally) contain a human readable + * name of this mapping (mainly for debugging purposes). The @version field + * is added for future scalability, and should be 1 for now. + * + * Note: at this point we just "trust" these intmem entries to contain valid + * physical bus addresses. these are not currently intended to be managed + * as host-controlled heaps, as it is much better to do that from the remote + * processor side. + */ +struct fw_rsc_intmem { + u32 version; + u32 da; + u32 pa; + u32 len; + u32 reserved; + u8 name[32]; +} __packed; + +/** + * struct fw_rsc_custom - custom resource definition + * @sub_type: implementation specific type + * @size: size of the custom resource + * @data: label for the start of the resource + */ +struct fw_rsc_custom { + u32 sub_type; + u32 size; + u8 data[0]; +} __packed; + +/** + * struct rproc_mem_entry - memory entry descriptor + * @va: virtual address + * @dma: dma address + * @len: length, in bytes + * @da: device address + * @priv: associated data + * @node: list node + */ +struct rproc_mem_entry { + void *va; + dma_addr_t dma; + int len; + u32 da; + void *priv; + struct list_head node; +}; + +/** Maximum number of IOMMU's for a remotecore */ +#define MAX_NUM_IOMMU (2) + +/* Enums to identify the remotecores. The identifier assigned is + * according the the convention followed by IPC3. + */ +enum rproc_core_id { + IPU2 = 1, + IPU1 = 2, + DSP2 = 3, + DSP1 = 4, + RPROC_END_ENUMS = 5 +}; + +struct rproc; + +typedef u32(*init_func_proto) (u32 core_id, struct rproc *cfg); + + +struct l3_map { + u32 priv_addr; + u32 l3_addr; + u32 len; +}; + +struct rproc_intmem_to_l3_mapping { + u32 num_entries; + struct l3_map mappings[16]; +}; +/** struct rproc - structure with all processor specific information for + * loading remotecore from boot loader. + * + * @num_iommus: Number of IOMMUs for this remote core. Zero indicates that the + * processor does not have an IOMMU. + * + * @cma_base: Base address of the carveout for this remotecore. + * + * @cma_size: Length of the carveout in bytes. + * + * @page_table_addr: array with the physical address of the page table. We are + * using the same page table for both IOMMU's. There is currently no strong + * usecase for maintaining different page tables for different MMU's servicing + * the same CPU. + * + * @mmu_base_addr: base address of the MMU + * + * @entry_point: address that is the entry point for the remote core. This + * address is in the memory view of the remotecore. + * + * @load_addr: Address to which the bootloader loads the firmware from + * persistent storage before invoking the ELF loader. Keeping this address + * configurable allows future optimizations such as loading the firmware from + * storage for remotecore2 via EDMA while the CPU is processing the ELF image + * of remotecore1. This address is in the memory view of the A15. + * + * @firmware_name: Name of the file that is expected to contain the ELF image. + * + * @has_rsc_table: Flag populated after parsing the ELF binary on target. + */ + +struct rproc { + u32 num_iommus; + unsigned long cma_base; + u32 cma_size; + unsigned long page_table_addr; + unsigned long mmu_base_addr[MAX_NUM_IOMMU]; + unsigned long load_addr; + unsigned long entry_point; + char *core_name; + char *firmware_name; + char *ptn; + init_func_proto start_clocks; + init_func_proto config_mmu; + init_func_proto config_peripherals; + init_func_proto start_core; + u32 has_rsc_table; + struct rproc_intmem_to_l3_mapping *intmem_to_l3_mapping; +}; + +extern struct rproc *rproc_cfg_arr[RPROC_END_ENUMS]; +struct resource_table *find_resource_table(unsigned int addr, + int *tablesz); +unsigned long load_elf_image_phdr_rproc(struct rproc *cfg); +unsigned int config_pagetable(unsigned int virt, unsigned int phys, + unsigned int len); +void *alloc_mem(unsigned long len, unsigned long align); + +#endif /* REMOTEPROC_H */ diff --git a/include/spl.h b/include/spl.h index 99ef15a66e..03e7bd5dc3 100644 --- a/include/spl.h +++ b/include/spl.h @@ -10,6 +10,7 @@ /* Platform-specific defines */ #include <linux/compiler.h> #include <asm/spl.h> +#include <mmc.h> /* Value in r0 indicates we booted from U-Boot */ #define UBOOT_NOT_LOADED_FROM_SPL 0x13578642 @@ -87,6 +88,11 @@ int spl_nor_load_image(void); /* MMC SPL functions */ int spl_mmc_load_image(u32 boot_device); +#ifdef CONFIG_SPL_OS_BOOT +/* MMC SPL functions */ +int spl_mmc_load_image_raw_os(void); +#endif + /* YMODEM SPL functions */ int spl_ymodem_load_image(void); @@ -106,6 +112,8 @@ int spl_sata_load_image(void); int spl_load_image_fat(struct blk_desc *block_dev, int partition, const char *filename); int spl_load_image_fat_os(struct blk_desc *block_dev, int partition); +int spl_load_file_fat(struct blk_desc *block_dev, int partition, + const char *filename, void *buf); void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image); @@ -126,6 +134,8 @@ int spl_load_image_ext_os(struct blk_desc *block_dev, int partition); */ int spl_init(void); +int spl_mmc_init(struct mmc **mmc, u32 boot_device); + #ifdef CONFIG_SPL_BOARD_INIT void spl_board_init(void); #endif @@ -148,4 +158,7 @@ bool spl_was_boot_source(void); * @return 0 on success, otherwise error code */ int spl_dfu_cmd(int usbctrl, char *dfu_alt_info, char *interface, char *devstr); + +u32 spl_mmc_load_core(u32 core_id, u32 boot_device); +u32 spl_boot_core(u32 core_id); #endif diff --git a/lib/Makefile b/lib/Makefile index 02dfa29507..d1a4be5e42 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_BITREVERSE) += bitrev.o obj-y += list_sort.o endif +obj-$(CONFIG_SPL_SAVEENV) += qsort.o obj-$(CONFIG_$(SPL_)OF_LIBFDT) += libfdt/ ifdef CONFIG_SPL_OF_CONTROL obj-$(CONFIG_OF_LIBFDT) += libfdt/ diff --git a/lib/hashtable.c b/lib/hashtable.c index 02b41050a4..a2f2aa5a42 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -477,11 +477,11 @@ int hdelete_r(const char *key, struct hsearch_data *htab, int flag) return 1; } +#if !(defined(CONFIG_SPL_BUILD) && !defined(CONFIG_SPL_SAVEENV)) /* * hexport() */ -#ifndef CONFIG_SPL_BUILD /* * Export the data stored in the hash table in linearized form. * diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl index 803c1de4bb..d47dd84585 100644 --- a/scripts/Makefile.spl +++ b/scripts/Makefile.spl @@ -63,6 +63,7 @@ libs-$(CONFIG_SPL_DFU_SUPPORT) += drivers/usb/dwc3/ libs-y += dts/ libs-y += fs/ libs-$(CONFIG_SPL_LIBGENERIC_SUPPORT) += lib/ +#libs-$(CONFIG_SPL_ANDROID_BOOT_SUPPORT) += lib/libfdt/ libs-$(CONFIG_SPL_POST_MEM_SUPPORT) += post/drivers/ libs-$(CONFIG_SPL_NET_SUPPORT) += net/ |