aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/cpu/armv7/omap-common/boot-common.c4
-rw-r--r--arch/arm/cpu/armv7/omap-common/hwinit-common.c17
-rw-r--r--arch/arm/cpu/armv7/omap-common/utils.c126
-rw-r--r--arch/arm/cpu/armv7/omap5/prcm-regs.c1
-rw-r--r--arch/arm/include/asm/arch-omap4/cpu.h2
-rw-r--r--arch/arm/include/asm/arch-omap5/cpu.h2
-rw-r--r--arch/arm/include/asm/arch-omap5/spl.h12
-rw-r--r--arch/arm/include/asm/arch-omap5/sys_proto.h1
-rw-r--r--arch/arm/include/asm/omap_common.h3
-rw-r--r--board/ti/am57xx/board.c3
-rw-r--r--board/ti/dra7xx/Kconfig40
-rw-r--r--board/ti/dra7xx/Makefile2
-rw-r--r--board/ti/dra7xx/evm.c24
-rw-r--r--board/ti/dra7xx/lateattach.c1275
-rw-r--r--board/ti/dra7xx/mux_data.h251
-rw-r--r--common/Makefile10
-rw-r--r--common/command.c2
-rw-r--r--common/elf_remoteproc.c555
-rw-r--r--common/fb_mmc.c10
-rw-r--r--common/image-android.c5
-rw-r--r--common/spl/spl.c65
-rw-r--r--common/spl/spl_fat.c23
-rw-r--r--common/spl/spl_mmc.c272
-rw-r--r--configs/am57xx_evm_defconfig11
-rw-r--r--configs/am57xx_evm_nodt_defconfig13
-rw-r--r--configs/dra7xx_evm_defconfig5
-rw-r--r--configs/dra7xx_evm_nodt_defconfig1
-rw-r--r--configs/dra7xx_evm_vision_defconfig70
-rw-r--r--configs/dra7xx_hs_evm_defconfig2
-rw-r--r--doc/README.earlyboot136
-rw-r--r--drivers/mmc/Makefile1
-rw-r--r--drivers/mmc/mmc_private.h7
-rw-r--r--drivers/mtd/spi/spi_spl_load.c18
-rw-r--r--drivers/usb/gadget/f_fastboot.c231
-rw-r--r--include/configs/am57xx_evm.h55
-rw-r--r--include/configs/dra7xx_evm.h48
-rw-r--r--include/configs/ti_armv7_common.h4
-rw-r--r--include/configs/ti_omap5_common.h85
-rw-r--r--include/image.h1
-rw-r--r--include/omap_remoteproc.h465
-rw-r--r--include/spl.h13
-rw-r--r--lib/Makefile1
-rw-r--r--lib/hashtable.c2
-rw-r--r--scripts/Makefile.spl1
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(&sectionheader, &shdr[ehdr->e_shstrndx], sizeof(sectionheader));
+ name_table = (char *)(elf_data + sectionheader.sh_offset);
+
+ for (i = 0; i < ehdr->e_shnum; i++, shdr++) {
+ memcpy(&sectionheader, 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(&sectionheader, 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/