summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/boards/beagle/Makefile1
-rw-r--r--arch/arm/boards/beagle/board.c13
-rw-r--r--arch/arm/boards/beagle/defaultenv-beagle/boot/mmc (renamed from arch/arm/boards/beagle/env/boot/mmc)0
-rw-r--r--arch/arm/boards/beagle/defaultenv-beagle/boot/nand-ubi (renamed from arch/arm/boards/beagle/env/boot/nand-ubi)0
-rw-r--r--arch/arm/boards/beagle/defaultenv-beagle/boot/nand-ubi-dt (renamed from arch/arm/boards/beagle/env/boot/nand-ubi-dt)0
-rw-r--r--arch/arm/boards/beagle/defaultenv-beagle/init/mtdparts-nand (renamed from arch/arm/boards/beagle/env/init/mtdparts-nand)0
-rw-r--r--arch/arm/boards/beagle/defaultenv-beagle/network/eth0-discover (renamed from arch/arm/boards/beagle/env/network/eth0-discover)0
-rw-r--r--arch/arm/boards/beagle/lowlevel.c39
-rw-r--r--arch/arm/configs/omap3530_beagle_defconfig81
-rw-r--r--arch/arm/configs/omap3530_beagle_xload_defconfig17
-rw-r--r--arch/arm/configs/phytec-phycard-omap3_defconfig1
-rw-r--r--arch/arm/cpu/start.c43
-rw-r--r--arch/arm/include/asm/barebox-arm.h27
-rw-r--r--arch/arm/mach-omap/Kconfig37
-rw-r--r--arch/arm/mach-omap/Makefile6
-rw-r--r--arch/arm/mach-omap/include/mach/omap3-clock.h2
-rw-r--r--arch/arm/mach-omap/include/mach/omap3-generic.h2
-rw-r--r--arch/arm/mach-omap/omap3_generic.c5
-rw-r--r--arch/arm/mach-omap/omap3_xload_usb.c185
-rw-r--r--arch/arm/mach-omap/xload.c8
-rw-r--r--drivers/bus/omap-gpmc.c144
-rw-r--r--drivers/of/platform.c2
-rw-r--r--images/Makefile1
-rw-r--r--images/Makefile.omap319
-rw-r--r--include/of.h2
-rw-r--r--scripts/Makefile3
-rw-r--r--scripts/omap3-usb-loader.c921
27 files changed, 1468 insertions, 91 deletions
diff --git a/arch/arm/boards/beagle/Makefile b/arch/arm/boards/beagle/Makefile
index 01c7a259e9..3bee9a22ab 100644
--- a/arch/arm/boards/beagle/Makefile
+++ b/arch/arm/boards/beagle/Makefile
@@ -1,2 +1,3 @@
obj-y += board.o
lwl-y += lowlevel.o
+bbenv-y += defaultenv-beagle
diff --git a/arch/arm/boards/beagle/board.c b/arch/arm/boards/beagle/board.c
index c56205e05c..4ac9517dbe 100644
--- a/arch/arm/boards/beagle/board.c
+++ b/arch/arm/boards/beagle/board.c
@@ -24,6 +24,7 @@
#include <bbu.h>
#include <filetype.h>
#include <ns16550.h>
+#include <envfs.h>
#include <asm/armlinux.h>
#include <generated/mach-types.h>
#include <mach/gpmc.h>
@@ -33,6 +34,7 @@
#include <i2c/i2c.h>
#include <linux/err.h>
#include <usb/ehci.h>
+#include <asm/barebox-arm.h>
#ifdef CONFIG_DRIVER_SERIAL_NS16550
@@ -44,6 +46,9 @@
*/
static int beagle_console_init(void)
{
+ if (barebox_arm_machine() != MACH_TYPE_OMAP3_BEAGLE)
+ return 0;
+
barebox_set_model("Texas Instruments beagle");
barebox_set_hostname("beagle");
@@ -84,6 +89,9 @@ static struct gpmc_nand_platform_data nand_plat = {
static int beagle_mem_init(void)
{
+ if (barebox_arm_machine() != MACH_TYPE_OMAP3_BEAGLE)
+ return 0;
+
omap_add_ram0(SZ_128M);
return 0;
@@ -92,6 +100,9 @@ mem_initcall(beagle_mem_init);
static int beagle_devices_init(void)
{
+ if (barebox_arm_machine() != MACH_TYPE_OMAP3_BEAGLE)
+ return 0;
+
i2c_register_board_info(0, i2c_devices, ARRAY_SIZE(i2c_devices));
omap3_add_i2c1(NULL);
@@ -114,6 +125,8 @@ static int beagle_devices_init(void)
bbu_register_std_file_update("nand", 0,
"/dev/nand0.barebox.bb", filetype_arm_barebox);
+ defaultenv_append_directory(defaultenv_beagle);
+
return 0;
}
device_initcall(beagle_devices_init);
diff --git a/arch/arm/boards/beagle/env/boot/mmc b/arch/arm/boards/beagle/defaultenv-beagle/boot/mmc
index db638f8cf8..db638f8cf8 100644
--- a/arch/arm/boards/beagle/env/boot/mmc
+++ b/arch/arm/boards/beagle/defaultenv-beagle/boot/mmc
diff --git a/arch/arm/boards/beagle/env/boot/nand-ubi b/arch/arm/boards/beagle/defaultenv-beagle/boot/nand-ubi
index e0ef904432..e0ef904432 100644
--- a/arch/arm/boards/beagle/env/boot/nand-ubi
+++ b/arch/arm/boards/beagle/defaultenv-beagle/boot/nand-ubi
diff --git a/arch/arm/boards/beagle/env/boot/nand-ubi-dt b/arch/arm/boards/beagle/defaultenv-beagle/boot/nand-ubi-dt
index 5fc0a6c53a..5fc0a6c53a 100644
--- a/arch/arm/boards/beagle/env/boot/nand-ubi-dt
+++ b/arch/arm/boards/beagle/defaultenv-beagle/boot/nand-ubi-dt
diff --git a/arch/arm/boards/beagle/env/init/mtdparts-nand b/arch/arm/boards/beagle/defaultenv-beagle/init/mtdparts-nand
index 9335bb17a3..9335bb17a3 100644
--- a/arch/arm/boards/beagle/env/init/mtdparts-nand
+++ b/arch/arm/boards/beagle/defaultenv-beagle/init/mtdparts-nand
diff --git a/arch/arm/boards/beagle/env/network/eth0-discover b/arch/arm/boards/beagle/defaultenv-beagle/network/eth0-discover
index 86d13f5c43..86d13f5c43 100644
--- a/arch/arm/boards/beagle/env/network/eth0-discover
+++ b/arch/arm/boards/beagle/defaultenv-beagle/network/eth0-discover
diff --git a/arch/arm/boards/beagle/lowlevel.c b/arch/arm/boards/beagle/lowlevel.c
index d6e6b9f91c..30cc1f2c54 100644
--- a/arch/arm/boards/beagle/lowlevel.c
+++ b/arch/arm/boards/beagle/lowlevel.c
@@ -1,4 +1,5 @@
#include <init.h>
+#include <debug_ll.h>
#include <io.h>
#include <linux/sizes.h>
#include <asm/barebox-arm-head.h>
@@ -11,6 +12,7 @@
#include <mach/sdrc.h>
#include <mach/syslib.h>
#include <mach/sys_info.h>
+#include <generated/mach-types.h>
/**
* @brief Do the pin muxing required for Board operation.
@@ -157,6 +159,22 @@ static void sdrc_init(void)
return;
}
+static noinline int beagle_board_init_sdram(void)
+{
+ struct barebox_arm_boarddata *bd = (void *)OMAP3_SRAM_SCRATCH_SPACE + 0x10;
+
+ boarddata_create(bd, MACH_TYPE_OMAP3_BEAGLE);
+
+ barebox_arm_entry(0x80000000, SZ_128M, bd);
+}
+
+ENTRY_FUNCTION(start_omap3_beagleboard_sdram, bootinfo, r1, r2)
+{
+ omap3_save_bootinfo((void *)bootinfo);
+
+ beagle_board_init_sdram();
+}
+
/**
* @brief The basic entry point for board initialization.
*
@@ -166,28 +184,37 @@ static void sdrc_init(void)
*
* @return void
*/
-static int beagle_board_init(void)
+static noinline int beagle_board_init(void)
{
int in_sdram = omap3_running_in_sdram();
+ struct barebox_arm_boarddata bd;
if (!in_sdram)
omap3_core_init();
mux_config();
+
+ omap_uart_lowlevel_init((void *)OMAP3_UART3_BASE);
+
/* Dont reconfigure SDRAM while running in SDRAM! */
if (!in_sdram)
sdrc_init();
- return 0;
+ boarddata_create(&bd, MACH_TYPE_OMAP3_BEAGLE);
+
+ barebox_arm_entry(0x80000000, SZ_128M, &bd);
}
-void __naked __bare_init barebox_arm_reset_vector(uint32_t *data)
+ENTRY_FUNCTION(start_omap3_beagleboard_sram, bootinfo, r1, r2)
{
- omap3_save_bootinfo(data);
+ omap3_save_bootinfo((void *)bootinfo);
arm_cpu_lowlevel_init();
- beagle_board_init();
+ omap3_gp_romcode_call(OMAP3_GP_ROMCODE_API_L2_INVAL, 0);
+
+ relocate_to_current_adr();
+ setup_c();
- barebox_arm_entry(0x80000000, SZ_128M, NULL);
+ beagle_board_init();
}
diff --git a/arch/arm/configs/omap3530_beagle_defconfig b/arch/arm/configs/omap3530_beagle_defconfig
index 3068fbb94b..070f1566ee 100644
--- a/arch/arm/configs/omap3530_beagle_defconfig
+++ b/arch/arm/configs/omap3530_beagle_defconfig
@@ -1,67 +1,79 @@
CONFIG_ARCH_OMAP=y
+CONFIG_OMAP_MULTI_BOARDS=y
CONFIG_MACH_BEAGLE=y
CONFIG_THUMB2_BAREBOX=y
-CONFIG_CMD_ARM_MMUINFO=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
CONFIG_ARM_UNWIND=y
-CONFIG_PBL_IMAGE=y
CONFIG_MMU=y
-CONFIG_TEXT_BASE=0x87e00000
-CONFIG_MALLOC_SIZE=0x2000000
+CONFIG_TEXT_BASE=0x0
+CONFIG_MALLOC_SIZE=0x0
CONFIG_MALLOC_TLSF=y
CONFIG_KALLSYMS=y
+CONFIG_RELOCATABLE=y
CONFIG_PROMPT="barebox> "
-CONFIG_LONGHELP=y
CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_MENU=y
+CONFIG_BLSPEC=y
+CONFIG_IMD_TARGET=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
-CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/beagle/env"
-CONFIG_CMD_EDIT=y
-CONFIG_CMD_SLEEP=y
-CONFIG_CMD_MSLEEP=y
-CONFIG_CMD_SAVEENV=y
-CONFIG_CMD_EXPORT=y
-CONFIG_CMD_PRINTENV=y
-CONFIG_CMD_READLINE=y
-CONFIG_CMD_MENU=y
-CONFIG_CMD_MENU_MANAGEMENT=y
-CONFIG_CMD_TIME=y
-CONFIG_CMD_DIRNAME=y
-CONFIG_CMD_LN=y
-CONFIG_CMD_READLINK=y
-CONFIG_CMD_TFTP=y
-CONFIG_CMD_ECHO_E=y
-CONFIG_CMD_LOADB=y
-CONFIG_CMD_MEMINFO=y
+CONFIG_RESET_SOURCE=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_OMAP_UART_PORT=3
+CONFIG_DEBUG_INITCALLS=y
+CONFIG_CMD_DMESG=y
+CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
-CONFIG_CMD_CRC=y
-CONFIG_CMD_CRC_CMP=y
-CONFIG_CMD_MD5SUM=y
-CONFIG_CMD_FLASH=y
+CONFIG_CMD_IMD=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_ARM_MMUINFO=y
CONFIG_CMD_BOOTM_SHOW_TYPE=y
CONFIG_CMD_BOOTM_VERBOSE=y
CONFIG_CMD_BOOTM_INITRD=y
CONFIG_CMD_BOOTM_OFTREE=y
CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
# CONFIG_CMD_BOOTU is not set
-CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
-CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_RESET=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_DEFAULTENV=y
+CONFIG_CMD_PRINTENV=y
CONFIG_CMD_MAGICVAR=y
CONFIG_CMD_MAGICVAR_HELP=y
-CONFIG_CMD_GPIO=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_FILETYPE=y
+CONFIG_CMD_LN=y
+CONFIG_CMD_MD5SUM=y
CONFIG_CMD_UNCOMPRESS=y
-CONFIG_CMD_I2C=y
+CONFIG_CMD_MSLEEP=y
+CONFIG_CMD_READF=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_HOST=y
CONFIG_CMD_MIITOOL=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TFTP=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_MENU=y
+CONFIG_CMD_MENU_MANAGEMENT=y
+CONFIG_CMD_MENUTREE=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_CRC=y
+CONFIG_CMD_CRC_CMP=y
+CONFIG_CMD_DETECT=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_BAREBOX_UPDATE=y
+CONFIG_CMD_TIME=y
CONFIG_NET=y
-CONFIG_CMD_DHCP=y
CONFIG_NET_NFS=y
-CONFIG_CMD_PING=y
CONFIG_NET_NETCONSOLE=y
-CONFIG_NET_RESOLV=y
CONFIG_DRIVER_SERIAL_NS16550=y
CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS=y
CONFIG_NET_USB=y
@@ -81,6 +93,7 @@ CONFIG_MCI=y
CONFIG_MCI_STARTUP=y
CONFIG_MCI_OMAP_HSMMC=y
CONFIG_MFD_TWL4030=y
+CONFIG_FS_EXT4=y
CONFIG_FS_TFTP=y
CONFIG_FS_NFS=y
CONFIG_FS_FAT=y
diff --git a/arch/arm/configs/omap3530_beagle_xload_defconfig b/arch/arm/configs/omap3530_beagle_xload_defconfig
index 585ee0f1d1..074cc2116b 100644
--- a/arch/arm/configs/omap3530_beagle_xload_defconfig
+++ b/arch/arm/configs/omap3530_beagle_xload_defconfig
@@ -1,21 +1,25 @@
CONFIG_ARCH_OMAP=y
CONFIG_OMAP_BUILD_IFT=y
+CONFIG_OMAP3_USBBOOT=y
+CONFIG_OMAP3_USB_LOADER=y
+CONFIG_OMAP_MULTI_BOARDS=y
CONFIG_MACH_BEAGLE=y
CONFIG_THUMB2_BAREBOX=y
-# CONFIG_CMD_ARM_CPUINFO is not set
-# CONFIG_ARM_EXCEPTIONS is not set
-CONFIG_TEXT_BASE=0x40200000
-CONFIG_MEMORY_LAYOUT_FIXED=y
-CONFIG_STACK_BASE=0x4020F000
+CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_ARM_UNWIND=y
+CONFIG_MMU=y
+CONFIG_TEXT_BASE=0x0
CONFIG_STACK_SIZE=0xc00
-CONFIG_MALLOC_BASE=0x87BFFF10
+CONFIG_MALLOC_SIZE=0x0
CONFIG_MALLOC_DUMMY=y
+CONFIG_RELOCATABLE=y
CONFIG_PROMPT="X-load Beagle>"
CONFIG_SHELL_NONE=y
# CONFIG_ERRNO_MESSAGES is not set
# CONFIG_TIMESTAMP is not set
CONFIG_CONSOLE_SIMPLE=y
# CONFIG_DEFAULT_ENVIRONMENT is not set
+CONFIG_OFDEVICE=y
CONFIG_DRIVER_SERIAL_NS16550=y
CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS=y
# CONFIG_SPI is not set
@@ -33,6 +37,7 @@ CONFIG_MCI=y
CONFIG_MCI_STARTUP=y
# CONFIG_MCI_WRITE is not set
CONFIG_MCI_OMAP_HSMMC=y
+# CONFIG_PINCTRL is not set
# CONFIG_FS_RAMFS is not set
# CONFIG_FS_DEVFS is not set
CONFIG_FS_FAT=y
diff --git a/arch/arm/configs/phytec-phycard-omap3_defconfig b/arch/arm/configs/phytec-phycard-omap3_defconfig
index a2564d4459..5865ebd8b9 100644
--- a/arch/arm/configs/phytec-phycard-omap3_defconfig
+++ b/arch/arm/configs/phytec-phycard-omap3_defconfig
@@ -7,7 +7,6 @@ CONFIG_CPU_V7=y
CONFIG_CPU_32v7=y
CONFIG_ARCH_OMAP3=y
CONFIG_OMAP_CLOCK_SOURCE_S32K=y
-CONFIG_OMAP3_CLOCK_CONFIG=y
CONFIG_OMAP3_COPY_CLOCK_SRAM=n
CONFIG_OMAP_GPMC=y
CONFIG_MACH_PCAAL1=y
diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
index 91fd9b987b..8e5097b560 100644
--- a/arch/arm/cpu/start.c
+++ b/arch/arm/cpu/start.c
@@ -28,17 +28,22 @@
#include <asm/cache.h>
#include <memory.h>
+#include <debug_ll.h>
#include "mmu-early.h"
unsigned long arm_stack_top;
static void *barebox_boarddata;
-/*
- * return the boarddata variable passed to barebox_arm_entry
- */
-void *barebox_arm_boarddata(void)
+u32 barebox_arm_machine(void)
{
- return barebox_boarddata;
+ struct barebox_arm_boarddata *bd;
+
+ if (!barebox_boarddata)
+ return 0;
+
+ bd = barebox_boarddata;
+
+ return bd->machine;
}
static void *barebox_boot_dtb;
@@ -83,17 +88,23 @@ static noinline __noreturn void __start(unsigned long membase,
}
}
- /*
- * If boarddata is a pointer inside valid memory and contains a
- * FDT magic then use it as later to probe devices
- */
- if (boarddata && get_unaligned_be32(boarddata) == FDT_MAGIC) {
- uint32_t totalsize = get_unaligned_be32(boarddata + 4);
- endmem -= ALIGN(totalsize, 64);
- barebox_boot_dtb = (void *)endmem;
- pr_debug("found DTB in boarddata, copying to 0x%p\n",
- barebox_boot_dtb);
- memcpy(barebox_boot_dtb, boarddata, totalsize);
+ if (boarddata) {
+ if (get_unaligned_be32(boarddata) == FDT_MAGIC) {
+ uint32_t totalsize = get_unaligned_be32(boarddata + 4);
+ endmem -= ALIGN(totalsize, 64);
+ barebox_boot_dtb = (void *)endmem;
+ pr_debug("found DTB in boarddata, copying to 0x%p\n",
+ barebox_boot_dtb);
+ memcpy(barebox_boot_dtb, boarddata, totalsize);
+ } else if (((struct barebox_arm_boarddata *)boarddata)->magic ==
+ BAREBOX_ARM_BOARDDATA_MAGIC) {
+ endmem -= ALIGN(sizeof(struct barebox_arm_boarddata), 64);
+ barebox_boarddata = (void *)endmem;
+ pr_debug("found machine type in boarddata, copying to 0x%p\n",
+ barebox_boarddata);
+ memcpy(barebox_boarddata, boarddata,
+ sizeof(struct barebox_arm_boarddata));
+ }
}
if ((unsigned long)_text > membase + memsize ||
diff --git a/arch/arm/include/asm/barebox-arm.h b/arch/arm/include/asm/barebox-arm.h
index dbc8aaaba7..0b8acb8b8e 100644
--- a/arch/arm/include/asm/barebox-arm.h
+++ b/arch/arm/include/asm/barebox-arm.h
@@ -48,7 +48,32 @@ void setup_c(void);
void relocate_to_current_adr(void);
void relocate_to_adr(unsigned long target);
void __noreturn barebox_arm_entry(unsigned long membase, unsigned long memsize, void *boarddata);
-void *barebox_arm_boarddata(void);
+
+struct barebox_arm_boarddata {
+#define BAREBOX_ARM_BOARDDATA_MAGIC 0xabe742c3
+ u32 magic;
+ u32 machine; /* machine number to pass to barebox. This may or may
+ * not be a ARM machine number registered on arm.linux.org.uk.
+ * It must only be unique across barebox. Please use a number
+ * that do not potientially clashes with registered machines,
+ * i.e. use a number > 0x10000.
+ */
+};
+
+/*
+ * Create a boarddata struct at given address. Suitable to be passed
+ * as boarddata to barebox_arm_entry(). The machine can be retrieved
+ * later with barebox_arm_machine().
+ */
+static inline void boarddata_create(void *adr, u32 machine)
+{
+ struct barebox_arm_boarddata *bd = adr;
+
+ bd->magic = BAREBOX_ARM_BOARDDATA_MAGIC;
+ bd->machine = machine;
+}
+
+u32 barebox_arm_machine(void);
#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_ARM_EXCEPTIONS)
void arm_fixup_vectors(void);
diff --git a/arch/arm/mach-omap/Kconfig b/arch/arm/mach-omap/Kconfig
index bc00d5bf7f..af359756ba 100644
--- a/arch/arm/mach-omap/Kconfig
+++ b/arch/arm/mach-omap/Kconfig
@@ -54,14 +54,6 @@ config OMAP_CLOCK_SOURCE_S32K
config OMAP_CLOCK_SOURCE_DMTIMER0
bool
-config OMAP3_CLOCK_CONFIG
- prompt "Clock Configuration"
- bool
- depends on ARCH_OMAP3
- default y
- help
- Say Y here if you like to have OMAP3 Clock configuration done.
-
config OMAP_GPMC
prompt "Support for GPMC configuration"
bool
@@ -128,6 +120,21 @@ config OMAP4_USBBOOT
You need the utility program omap4_usbboot to boot from USB.
Please read omap4_usb_booting.txt for more information.
+config OMAP3_USBBOOT
+ bool "enable booting from USB"
+ depends on ARCH_OMAP3
+ help
+ Say Y here if you want to be able to boot the 2nd stage via USB. This
+ works by transferring the 2nd stage image using the MUSB controller
+ which is already initialized by the ROM code. Use the omap3-usb-loader
+ tool selectable below to upload images.
+
+config OMAP3_USB_LOADER
+ bool "enable omap3 USB loader host tool"
+ depends on ARCH_OMAP3
+ help
+ Say Y here to build the omap3 usb loader tool.
+
config OMAP_SERIALBOOT
bool "enable booting from serial"
select XYMODEM
@@ -150,6 +157,13 @@ config MACH_AFI_GF
help
Say Y here if you are using afis GF
+config MACH_BEAGLE
+ bool "Texas Instrument's Beagle Board"
+ select HAVE_DEFAULT_ENVIRONMENT_NEW
+ select ARCH_OMAP3
+ help
+ Say Y here if you are using Beagle Board
+
config MACH_BEAGLEBONE
bool "Texas Instrument's Beagle Bone"
select ARCH_AM33XX
@@ -173,13 +187,6 @@ config MACH_OMAP343xSDP
help
Say Y here if you are using SDP343x platform
-config MACH_BEAGLE
- bool "Texas Instrument's Beagle Board"
- select HAVE_DEFAULT_ENVIRONMENT_NEW
- select ARCH_OMAP3
- help
- Say Y here if you are using Beagle Board
-
config MACH_OMAP3EVM
bool "Texas Instrument's OMAP3 EVM"
select ARCH_OMAP3
diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile
index bef1d0500f..65072b91e4 100644
--- a/arch/arm/mach-omap/Makefile
+++ b/arch/arm/mach-omap/Makefile
@@ -25,12 +25,14 @@ obj-$(CONFIG_ARCH_OMAP4) += omap4_generic.o omap4_clock.o
pbl-$(CONFIG_ARCH_OMAP4) += omap4_generic.o omap4_clock.o
obj-pbl-$(CONFIG_ARCH_AM33XX) += am33xx_generic.o am33xx_clock.o am33xx_mux.o
obj-$(CONFIG_ARCH_AM33XX) += am33xx_scrm.o
-obj-$(CONFIG_OMAP3_CLOCK_CONFIG) += omap3_clock.o
-pbl-$(CONFIG_OMAP3_CLOCK_CONFIG) += omap3_clock.o
+obj-$(CONFIG_ARCH_OMAP3) += omap3_clock.o
+pbl-$(CONFIG_ARCH_OMAP3) += omap3_clock.o
obj-$(CONFIG_OMAP_GPMC) += gpmc.o devices-gpmc-nand.o
obj-$(CONFIG_SHELL_NONE) += xload.o
obj-$(CONFIG_MFD_TWL6030) += omap4_twl6030_mmc.o
obj-$(CONFIG_OMAP4_USBBOOT) += omap4_rom_usb.o
+obj-$(CONFIG_OMAP3_USBBOOT) += omap3_xload_usb.o
+pbl-$(CONFIG_OMAP3_USBBOOT) += omap3_xload_usb.o
obj-$(CONFIG_CMD_BOOT_ORDER) += boot_order.o
obj-$(CONFIG_BAREBOX_UPDATE_AM33XX_SPI_NOR_MLO) += am33xx_bbu_spi_mlo.o
obj-$(CONFIG_BAREBOX_UPDATE_AM33XX_NAND) += am33xx_bbu_nand.o
diff --git a/arch/arm/mach-omap/include/mach/omap3-clock.h b/arch/arm/mach-omap/include/mach/omap3-clock.h
index 1ef46aa3e5..7c52da754f 100644
--- a/arch/arm/mach-omap/include/mach/omap3-clock.h
+++ b/arch/arm/mach-omap/include/mach/omap3-clock.h
@@ -107,7 +107,7 @@
/* PER DPLL */
#define PER_M6X2 3 /* 288MHz: CM_CLKSEL1_EMU */
#define PER_M5X2 4 /* 216MHz: CM_CLKSEL_CAM */
-#define PER_M4X2 9 /* 96MHz : CM_CLKSEL_DSS-dss1 */
+#define PER_M4X2 2 /* 432MHz: CM_CLKSEL_DSS-dss1 */
#define PER_M3X2 16 /* 54MHz : CM_CLKSEL_DSS-tv */
#define CLSEL1_EMU_VAL ((CORE_M3X2 << 16) | (PER_M6X2 << 24) | (0x0a50))
diff --git a/arch/arm/mach-omap/include/mach/omap3-generic.h b/arch/arm/mach-omap/include/mach/omap3-generic.h
index 7db0838a5f..ab53b98971 100644
--- a/arch/arm/mach-omap/include/mach/omap3-generic.h
+++ b/arch/arm/mach-omap/include/mach/omap3-generic.h
@@ -29,4 +29,6 @@ void __noreturn omap3_reset_cpu(unsigned long addr);
int omap3_init(void);
int omap3_devices_init(void);
+void *omap3_xload_boot_usb(void);
+
#endif /* __MACH_OMAP3_GENERIC_H */
diff --git a/arch/arm/mach-omap/omap3_generic.c b/arch/arm/mach-omap/omap3_generic.c
index dbb0b5f86c..0f2e9ce6b7 100644
--- a/arch/arm/mach-omap/omap3_generic.c
+++ b/arch/arm/mach-omap/omap3_generic.c
@@ -435,9 +435,6 @@ static void try_unlock_memory(void)
* Does early system init of disabling the watchdog, enable
* memory and configuring the clocks.
*
- * prcm_init is called only if CONFIG_OMAP3_CLOCK_CONFIG is defined.
- * We depend on link time clean up to remove a_init if no caller exists.
- *
* @warning Called path is with SRAM stack
*
* @return void
@@ -459,9 +456,7 @@ void omap3_core_init(void)
sdelay(100);
-#ifdef CONFIG_OMAP3_CLOCK_CONFIG
prcm_init();
-#endif
}
#define OMAP3_TRACING_VECTOR1 0x4020ffb4
diff --git a/arch/arm/mach-omap/omap3_xload_usb.c b/arch/arm/mach-omap/omap3_xload_usb.c
new file mode 100644
index 0000000000..e7dc21e4a7
--- /dev/null
+++ b/arch/arm/mach-omap/omap3_xload_usb.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2015 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * Based on a patch by:
+ *
+ * Copyright (C) 2011 Rick Bronson
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <io.h>
+#include <malloc.h>
+#include <mach/omap3-silicon.h>
+#include <mach/omap3-generic.h>
+
+static void __iomem *omap3_usb_base = (void __iomem *)OMAP3_MUSB0_BASE;
+
+#define OMAP34XX_USB_EP(n) (omap3_usb_base + 0x100 + 0x10 * (n))
+
+#define MUSB_RXCSR 0x06
+#define MUSB_RXCOUNT 0x08
+#define MUSB_TXCSR 0x02
+#define MUSB_FIFOSIZE 0x0F
+#define OMAP34XX_USB_RXCSR(n) (OMAP34XX_USB_EP(n) + MUSB_RXCSR)
+#define OMAP34XX_USB_RXCOUNT(n) (OMAP34XX_USB_EP(n) + MUSB_RXCOUNT)
+#define OMAP34XX_USB_TXCSR(n) (OMAP34XX_USB_EP(n) + MUSB_TXCSR)
+#define OMAP34XX_USB_FIFOSIZE(n) (OMAP34XX_USB_EP(n) + MUSB_FIFOSIZE)
+#define OMAP34XX_USB_FIFO(n) (omap3_usb_base + 0x20 + ((n) * 4))
+
+/* memory mapped registers */
+#define BULK_ENDPOINT 1
+#define MUSB_RXCSR_RXPKTRDY 0x0001
+#define MUSB_TXCSR_TXPKTRDY 0x0001
+
+#define PACK4(a,b,c,d) (((d) << 24) | ((c) << 16) | ((b) << 8) | (a))
+#define USBLOAD_CMD_FILE PACK4('U', 'S', 'B', 's') /* send file size */
+#define USBLOAD_CMD_JUMP PACK4('U', 'S', 'B', 'j') /* go where I tell you */
+#define USBLOAD_CMD_FILE_REQ PACK4('U', 'S', 'B', 'f') /* file request */
+#define USBLOAD_CMD_ECHO_SZ PACK4('U', 'S', 'B', 'n') /* echo file size */
+#define USBLOAD_CMD_REPORT_SZ PACK4('U', 'S', 'B', 'o') /* report file size */
+#define USBLOAD_CMD_MESSAGE PACK4('U', 'S', 'B', 'm') /* message for debug */
+
+static int usb_send(unsigned char *buffer, unsigned int buffer_size)
+{
+ unsigned int cntr;
+ u16 txcsr;
+ void __iomem *reg = (void *)OMAP34XX_USB_TXCSR(BULK_ENDPOINT);
+ void __iomem *bulk_fifo = (void *)OMAP34XX_USB_FIFO(BULK_ENDPOINT);
+
+ txcsr = readw(reg);
+
+ if (txcsr & MUSB_TXCSR_TXPKTRDY)
+ return 0;
+
+ for (cntr = 0; cntr < buffer_size; cntr++)
+ writeb(buffer[cntr], bulk_fifo);
+
+ txcsr = readw(reg);
+ txcsr |= MUSB_TXCSR_TXPKTRDY;
+ writew(txcsr, reg);
+
+ return buffer_size;
+}
+
+static int usb_recv(u8 *buffer)
+{
+ int cntr;
+ u16 count = 0;
+ u16 rxcsr;
+ void __iomem *reg = (void *)OMAP34XX_USB_RXCSR(BULK_ENDPOINT);
+ void __iomem *bulk_fifo = (void *)OMAP34XX_USB_FIFO(BULK_ENDPOINT);
+
+ rxcsr = readw(reg);
+
+ if (!(rxcsr & MUSB_RXCSR_RXPKTRDY))
+ return 0;
+
+ count = readw((void *)OMAP34XX_USB_RXCOUNT(BULK_ENDPOINT));
+ for (cntr = 0; cntr < count; cntr++)
+ *buffer++ = readb(bulk_fifo);
+
+ /* Clear the RXPKTRDY bit */
+ rxcsr = readw(reg);
+ rxcsr &= ~MUSB_RXCSR_RXPKTRDY;
+ writew(rxcsr, reg);
+
+ return count;
+}
+
+static unsigned char usb_outbuffer[64];
+
+static void usb_msg(unsigned int cmd, const char *msg)
+{
+ unsigned char *p_char = usb_outbuffer;
+
+ *(int *)p_char = cmd;
+
+ p_char += sizeof(cmd);
+
+ if (msg) {
+ while (*msg)
+ *p_char++= *msg++;
+ *p_char++= 0;
+ }
+
+ usb_send(usb_outbuffer, p_char - usb_outbuffer);
+}
+
+static void usb_code(unsigned int cmd, u32 code)
+{
+ unsigned int *p_int = (unsigned int *)usb_outbuffer;
+
+ *p_int++ = cmd;
+ *p_int++ = code;
+ usb_send (usb_outbuffer, ((unsigned char *) p_int) - usb_outbuffer);
+}
+
+void *omap3_xload_boot_usb(void)
+{
+ int res;
+ void *buf;
+ u32 *buf32;
+ u32 total;
+ void *addr;
+ u32 bytes;
+ int size;
+ int cntr;
+ void *fn;
+ u8 __buf[512];
+
+ buf32 = buf = __buf;
+
+ usb_msg (USBLOAD_CMD_FILE_REQ, "file req");
+ for (cntr = 0; cntr < 10000000; cntr++) {
+ size = usb_recv(buf);
+ if (!size)
+ continue;
+
+ switch (buf32[0]) {
+ case USBLOAD_CMD_FILE:
+ pr_debug ("USBLOAD_CMD_FILE total = %d size = 0x%x addr = 0x%x\n",
+ res, buf32[1], buf32[2]);
+ total = buf32[1]; /* get size and address */
+ addr = (void *)buf32[2];
+ usb_code(USBLOAD_CMD_ECHO_SZ, total);
+
+ bytes = 0;
+
+ while (bytes < total) {
+ size = usb_recv(buf);
+ memcpy(addr, buf, size);
+ addr += size;
+ bytes += size;
+ }
+
+ usb_code(USBLOAD_CMD_REPORT_SZ, total); /* tell him we got this many bytes */
+ usb_msg (USBLOAD_CMD_FILE_REQ, "file req"); /* see if they have another file for us */
+ break;
+ case USBLOAD_CMD_JUMP:
+ pr_debug("USBLOAD_CMD_JUMP total = %d addr = 0x%x val = 0x%x\n",
+ res, buf32[0], buf32[1]);
+ fn = (void *)buf32[1];
+ goto out;
+ default:
+ break;
+ }
+ }
+
+ fn = NULL;
+out:
+
+ return fn;
+}
diff --git a/arch/arm/mach-omap/xload.c b/arch/arm/mach-omap/xload.c
index 85c9120ccf..4a0714ed93 100644
--- a/arch/arm/mach-omap/xload.c
+++ b/arch/arm/mach-omap/xload.c
@@ -14,6 +14,7 @@
#include <xymodem.h>
#include <mach/generic.h>
#include <mach/am33xx-generic.h>
+#include <mach/omap3-generic.h>
#include <net.h>
#include <environment.h>
#include <dhcp.h>
@@ -284,13 +285,16 @@ static __noreturn int omap_xload(void)
func = omap_xload_boot_mmc();
break;
case BOOTSOURCE_USB:
- if (IS_ENABLED(CONFIG_FS_OMAP4_USBBOOT)) {
+ if (IS_ENABLED(CONFIG_OMAP3_USBBOOT) && cpu_is_omap3()) {
+ printf("booting from USB\n");
+ func = omap3_xload_boot_usb();
+ } else if (IS_ENABLED(CONFIG_FS_OMAP4_USBBOOT)) {
printf("booting from USB\n");
func = omap4_xload_boot_usb();
- break;
} else {
printf("booting from USB not enabled\n");
}
+ break;
case BOOTSOURCE_NAND:
printf("booting from NAND\n");
func = omap_xload_boot_nand(barebox_part->nand_offset,
diff --git a/drivers/bus/omap-gpmc.c b/drivers/bus/omap-gpmc.c
index 6752c42a35..8ae909a1b6 100644
--- a/drivers/bus/omap-gpmc.c
+++ b/drivers/bus/omap-gpmc.c
@@ -24,6 +24,14 @@
#define GPMC_CS_NUM 8
#define GPMC_NR_WAITPINS 4
+#define GPMC_BURST_4 4 /* 4 word burst */
+#define GPMC_BURST_8 8 /* 8 word burst */
+#define GPMC_BURST_16 16 /* 16 word burst */
+#define GPMC_DEVWIDTH_8BIT 1 /* 8-bit device width */
+#define GPMC_DEVWIDTH_16BIT 2 /* 16-bit device width */
+#define GPMC_MUX_AAD 1 /* Addr-Addr-Data multiplex */
+#define GPMC_MUX_AD 2 /* Addr-Data multiplex */
+
#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
#define GPMC_CONFIG1_READTYPE_ASYNC (0 << 29)
@@ -55,6 +63,9 @@
#define GPMC_CONFIG6_CYCLE2CYCLESAMECSEN (1 << 7)
#define GPMC_CONFIG7_CSVALID (1 << 6)
+#define GPMC_DEVICETYPE_NOR 0
+#define GPMC_DEVICETYPE_NAND 2
+
static unsigned int gpmc_cs_num = GPMC_CS_NUM;
static unsigned int gpmc_nr_waitpins;
static unsigned long gpmc_l3_clk = 100000000; /* This should be a proper clock */
@@ -149,7 +160,7 @@ static void gpmc_cs_bool_timings(struct gpmc_config *gpmc_config, const struct g
if (p->oe_extra_delay)
gpmc_config->cfg[3] |= GPMC_CONFIG4_OEEXTRADELAY;
if (p->we_extra_delay)
- gpmc_config->cfg[3] |= GPMC_CONFIG4_OEEXTRADELAY;
+ gpmc_config->cfg[3] |= GPMC_CONFIG4_WEEXTRADELAY;
if (p->cycle2cyclesamecsen)
gpmc_config->cfg[5] |= GPMC_CONFIG6_CYCLE2CYCLESAMECSEN;
if (p->cycle2cyclediffcsen)
@@ -220,6 +231,8 @@ static int gpmc_timings_to_config(struct gpmc_config *gpmc_config, const struct
if (div < 0)
return div;
+ gpmc_config->cfg[0] |= div - 1;
+
ret |= set_cfg(gpmc_config, 0, 18, 19, t->wait_monitoring);
ret |= set_cfg(gpmc_config, 0, 25, 26, t->clk_activation);
@@ -255,6 +268,60 @@ static int gpmc_timings_to_config(struct gpmc_config *gpmc_config, const struct
return 0;
}
+static int gpmc_settings_to_config(struct gpmc_config *gpmc_config,
+ struct gpmc_settings *p)
+{
+ u32 config1 = gpmc_config->cfg[0];
+
+ /* Page/burst mode supports lengths of 4, 8 and 16 bytes */
+ if (p->burst_read || p->burst_write) {
+ switch (p->burst_len) {
+ case GPMC_BURST_4:
+ case GPMC_BURST_8:
+ case GPMC_BURST_16:
+ break;
+ default:
+ pr_err("%s: invalid page/burst-length (%d)\n",
+ __func__, p->burst_len);
+ return -EINVAL;
+ }
+ }
+
+ if (p->wait_pin > gpmc_nr_waitpins) {
+ pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin);
+ return -EINVAL;
+ }
+
+ config1 |= GPMC_CONFIG1_DEVICESIZE((p->device_width - 1));
+
+ if (p->sync_read)
+ config1 |= GPMC_CONFIG1_READTYPE_SYNC;
+ if (p->sync_write)
+ config1 |= GPMC_CONFIG1_WRITETYPE_SYNC;
+ if (p->wait_on_read)
+ config1 |= GPMC_CONFIG1_WAIT_READ_MON;
+ if (p->wait_on_write)
+ config1 |= GPMC_CONFIG1_WAIT_WRITE_MON;
+ if (p->wait_on_read || p->wait_on_write)
+ config1 |= GPMC_CONFIG1_WAIT_PIN_SEL(p->wait_pin);
+ if (p->device_nand)
+ config1 |= GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NAND);
+ if (p->mux_add_data)
+ config1 |= GPMC_CONFIG1_MUXTYPE(p->mux_add_data);
+ if (p->burst_read)
+ config1 |= GPMC_CONFIG1_READMULTIPLE_SUPP;
+ if (p->burst_write)
+ config1 |= GPMC_CONFIG1_WRITEMULTIPLE_SUPP;
+ if (p->burst_read || p->burst_write) {
+ config1 |= GPMC_CONFIG1_PAGE_LEN(p->burst_len >> 3);
+ config1 |= p->burst_wrap ? GPMC_CONFIG1_WRAPBURST_SUPP : 0;
+ }
+
+ gpmc_config->cfg[0] = config1;
+
+ return 0;
+}
+
/**
* gpmc_read_settings_dt - read gpmc settings from device-tree
* @np: pointer to device-tree node for a gpmc child device
@@ -464,6 +531,77 @@ static int gpmc_probe_nand_child(struct device_d *dev,
return 0;
}
+/**
+ * gpmc_probe_generic_child - configures the gpmc for a child device
+ * @pdev: pointer to gpmc platform device
+ * @child: pointer to device-tree node for child device
+ *
+ * Allocates and configures a GPMC chip-select for a child device.
+ * Returns 0 on success and appropriate negative error code on failure.
+ */
+static int gpmc_probe_generic_child(struct device_d *dev,
+ struct device_node *child)
+{
+ struct gpmc_settings gpmc_s = {};
+ struct gpmc_timings gpmc_t = {};
+ struct resource res;
+ int ret, cs;
+ struct gpmc_config cfg = {};
+ resource_size_t size;
+
+ if (of_property_read_u32(child, "reg", &cs) < 0) {
+ dev_err(dev, "%s has no 'reg' property\n",
+ child->full_name);
+ return -ENODEV;
+ }
+
+ if (of_address_to_resource(child, 0, &res) < 0) {
+ dev_err(dev, "%s has malformed 'reg' property\n",
+ child->full_name);
+ return -ENODEV;
+ }
+
+ gpmc_read_settings_dt(child, &gpmc_s);
+ gpmc_read_timings_dt(child, &gpmc_t);
+
+ ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width);
+ if (ret < 0)
+ goto err;
+
+ gpmc_timings_to_config(&cfg, &gpmc_t);
+
+ cfg.base = res.start;
+
+ size = resource_size(&res);
+ if (size > SZ_64M)
+ cfg.size = GPMC_SIZE_128M;
+ else if (size > SZ_32M)
+ cfg.size = GPMC_SIZE_64M;
+ else if (size > SZ_16M)
+ cfg.size = GPMC_SIZE_32M;
+ else
+ cfg.size = GPMC_SIZE_16M;
+
+ gpmc_settings_to_config(&cfg, &gpmc_s);
+
+ gpmc_cs_config(cs, &cfg);
+
+ /* create platform device, NULL on error or when disabled */
+ if (of_get_property(child, "compatible", NULL) && !of_platform_device_create(child, dev))
+ goto err_child_fail;
+
+ return 0;
+
+err_child_fail:
+
+ dev_err(dev, "failed to create gpmc child %s\n", child->name);
+ ret = -ENODEV;
+
+err:
+
+ return ret;
+}
+
static int gpmc_probe(struct device_d *dev)
{
struct device_node *child, *node = dev->device_node;
@@ -488,6 +626,10 @@ static int gpmc_probe(struct device_d *dev)
if (!strncmp(child->name, "nand", 4))
ret = gpmc_probe_nand_child(dev, child);
+ else if (strncmp(child->name, "ethernet", 8) == 0 ||
+ strncmp(child->name, "nor", 3) == 0 ||
+ strncmp(child->name, "uart", 4) == 0)
+ ret = gpmc_probe_generic_child(dev, child);
else
dev_warn(dev, "unhandled child %s\n", child->name);
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index ab3ccab3b6..2c075dbae3 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -118,7 +118,7 @@ static void of_device_make_bus_id(struct device_d *dev)
* Returns pointer to created platform device, or NULL if a device was not
* registered. Unavailable devices will not get registered.
*/
-static struct device_d *of_platform_device_create(struct device_node *np,
+struct device_d *of_platform_device_create(struct device_node *np,
struct device_d *parent)
{
struct device_d *dev;
diff --git a/images/Makefile b/images/Makefile
index 6ee1dccac0..a5f589b303 100644
--- a/images/Makefile
+++ b/images/Makefile
@@ -107,6 +107,7 @@ include $(srctree)/images/Makefile.imx
include $(srctree)/images/Makefile.imxhabv4
include $(srctree)/images/Makefile.mvebu
include $(srctree)/images/Makefile.mxs
+include $(srctree)/images/Makefile.omap3
include $(srctree)/images/Makefile.rockchip
include $(srctree)/images/Makefile.socfpga
include $(srctree)/images/Makefile.tegra
diff --git a/images/Makefile.omap3 b/images/Makefile.omap3
new file mode 100644
index 0000000000..694ec30836
--- /dev/null
+++ b/images/Makefile.omap3
@@ -0,0 +1,19 @@
+# %.mlo - convert into mlo image
+# ----------------------------------------------------------------
+quiet_cmd_omap3_mlo_image = MLO $@
+ cmd_omap3_mlo_image = scripts/omap_signGP -o $@ -l 0x40200000 -c $<
+
+$(obj)/%.omap3_mlo: $(obj)/% FORCE
+ $(call if_changed,omap3_mlo_image)
+
+pblx-$(CONFIG_MACH_BEAGLE) += start_omap3_beagleboard_sdram start_omap3_beagleboard_sram
+FILE_barebox-beagleboard.img = start_omap3_beagleboard_sdram.pblx
+omap3-barebox-$(CONFIG_MACH_BEAGLE) += barebox-beagleboard.img
+FILE_barebox-beagleboard-mlo.img = start_omap3_beagleboard_sram.pblx.omap3_mlo
+omap3-mlo-$(CONFIG_MACH_BEAGLE) += barebox-beagleboard-mlo.img
+
+ifdef CONFIG_OMAP_BUILD_IFT
+image-y += $(omap3-mlo-y)
+else
+image-y += $(omap3-barebox-y)
+endif
diff --git a/include/of.h b/include/of.h
index c02f5f49ab..1db210b38a 100644
--- a/include/of.h
+++ b/include/of.h
@@ -224,6 +224,8 @@ extern int of_modalias_node(struct device_node *node, char *modalias, int len);
extern struct device_node *of_get_root_node(void);
extern int of_set_root_node(struct device_node *node);
+extern struct device_d *of_platform_device_create(struct device_node *np,
+ struct device_d *parent);
extern int of_platform_populate(struct device_node *root,
const struct of_device_id *matches,
struct device_d *parent);
diff --git a/scripts/Makefile b/scripts/Makefile
index 74c22136db..a3f6222d08 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -24,6 +24,9 @@ HOSTLOADLIBES_mxsimage = `pkg-config --libs openssl`
HOSTCFLAGS_mxs-usb-loader.o = `pkg-config --cflags libusb-1.0`
HOSTLOADLIBES_mxs-usb-loader = `pkg-config --libs libusb-1.0`
hostprogs-$(CONFIG_ARCH_MXS_USBLOADER) += mxs-usb-loader
+HOSTCFLAGS_omap3-usb-loader.o = `pkg-config --cflags libusb-1.0`
+HOSTLOADLIBES_omap3-usb-loader = `pkg-config --libs libusb-1.0`
+hostprogs-$(CONFIG_OMAP3_USB_LOADER) += omap3-usb-loader
subdir-y += mod
subdir-$(CONFIG_OMAP4_USBBOOT) += omap4_usbboot
diff --git a/scripts/omap3-usb-loader.c b/scripts/omap3-usb-loader.c
new file mode 100644
index 0000000000..edf6043edf
--- /dev/null
+++ b/scripts/omap3-usb-loader.c
@@ -0,0 +1,921 @@
+/*
+ * OMAP Loader, a USB uploader application targeted at OMAP3 processors
+ * Copyright (C) 2008 Martin Mueller <martinmm@pfump.org>
+ * Copyright (C) 2014 Grant Hernandez <grant.h.hernandez@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdbool.h>
+
+/*
+ * Reasons for the name change: this is a complete rewrite of
+ * the unversioned omap3_usbload so to lower ambiguity the name was changed.
+ * The GPLv2 license specifies rewrites as derived work.
+ */
+#define PROG_NAME "OMAP Loader"
+#define VERSION "1.0.0"
+
+#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define OMAP_IS_BIG_ENDIAN
+#endif
+
+#ifdef OMAP_IS_BIG_ENDIAN
+#include <arpa/inet.h>
+#endif
+
+#include <unistd.h> /* for usleep and friends */
+#include <getopt.h>
+#include <errno.h>
+#include <libgen.h> /* for basename */
+
+#include <libusb-1.0/libusb.h> /* the main event */
+
+/* Device specific defines (OMAP)
+ * Primary source: http://www.ti.com/lit/pdf/sprugn4
+ * Section 26.4.5 "Peripheral Booting"
+ */
+#define OMAP_BASE_ADDRESS 0x40200000
+#define OMAP_PERIPH_BOOT 0xF0030002
+#define OMAP_VENDOR_ID 0x0451
+#define OMAP_PRODUCT_ID 0xD00E
+/* TODO: dynamically discover these endpoints */
+#define OMAP_USB_BULK_IN 0x81
+#define OMAP_USB_BULK_OUT 0x01
+#define OMAP_ASIC_ID_LEN 69
+
+#ifdef OMAP_IS_BIG_ENDIAN
+#define cpu_to_le32(v) (((v & 0xff) << 24) | ((v & 0xff00) << 8) | \
+ ((v & 0xff0000) >> 8) | ((v & 0xff000000) >> 24))
+#define le32_to_cpu(v) cpu_to_le32(v)
+#else
+#define cpu_to_le32(v) (v)
+#define le32_to_cpu(v) (v)
+#endif
+
+/*
+ * taken from x-loader/drivers/usb/usb.c
+ * All credit to Martin Mueller
+ */
+#define PACK4(a,b,c,d) (((d)<<24) | ((c)<<16) | ((b)<<8) | (a))
+#define USBLOAD_CMD_FILE PACK4('U','S','B','s') /* file size request */
+#define USBLOAD_CMD_FILE_REQ PACK4('U','S','B','f') /* file size resp */
+#define USBLOAD_CMD_JUMP PACK4('U','S','B','j') /* execute code here */
+#define USBLOAD_CMD_ECHO_SZ PACK4('U','S','B','n') /* file size confirm to */
+#define USBLOAD_CMD_REPORT_SZ PACK4('U','S','B','o') /* confirm full file */
+#define USBLOAD_CMD_MESSAGE PACK4('U','S','B','m') /* debug message */
+
+/* USB transfer characteristics */
+#define USB_MAX_WAIT 5000
+#define USB_TIMEOUT 1000
+#define USB_MAX_TIMEOUTS (USB_MAX_WAIT/USB_TIMEOUT)
+
+/* stores the data and attributes of a file to upload in to memory */
+struct file_upload {
+ size_t size;
+ void *data;
+ uint32_t addr;
+ char *path;
+ char *basename;
+};
+
+/* stores all of the arguments read in by getopt in main() */
+struct arg_state {
+ struct file_upload **files;
+ int numfiles;
+ uint32_t jumptarget;
+ uint16_t vendor, product;
+};
+
+static int g_verbose = 0;
+
+static void log_error(char *fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ fprintf(stdout, "[-] ");
+ vfprintf(stdout, fmt, va);
+ va_end(va);
+}
+
+static void log_info(char *fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ fprintf(stdout, "[+] ");
+ vfprintf(stdout, fmt, va);
+ va_end(va);
+}
+
+static bool omap_usb_read(libusb_device_handle *handle, unsigned char *data,
+ int length, int *actuallength)
+{
+ int ret = 0;
+ int iter = 0;
+ int sizeleft = length;
+
+ if (!actuallength)
+ return false;
+
+ while (sizeleft > 0) {
+ int actualread = 0;
+ int readamt = sizeleft;
+
+ ret = libusb_bulk_transfer(handle, OMAP_USB_BULK_IN, data + iter,
+ readamt, &actualread, USB_TIMEOUT);
+
+ if (ret == LIBUSB_ERROR_TIMEOUT) {
+ sizeleft -= actualread;
+ iter += actualread;
+
+ /* we got some data, lets cut our losses and stop here */
+ if (iter > 0)
+ break;
+
+ log_error("device timed out while transfering in %d bytes (got %d)\n",
+ length, iter);
+
+ return false;
+ } else if (ret == LIBUSB_SUCCESS) {
+ /* we cant trust actualRead on anything but a timeout or success */
+ sizeleft -= actualread;
+ iter += actualread;
+
+ /* stop at the first sign of data */
+ if (iter > 0)
+ break;
+ } else {
+ log_error("fatal transfer error (BULK_IN) for %d bytes (got %d): %s\n",
+ length, iter, libusb_error_name(ret));
+ return false;
+ }
+ }
+
+ *actuallength = iter;
+
+ return true;
+}
+
+static bool omap_usb_write(libusb_device_handle *handle, void *data, int length)
+{
+ int ret = 0;
+ int numtimeouts = 0;
+ int iter = 0;
+ int sizeleft = length;
+
+ while (sizeleft > 0) {
+ int actualwrite = 0;
+ int writeamt = sizeleft > 512 ? 512 : sizeleft;
+
+ ret = libusb_bulk_transfer(handle, OMAP_USB_BULK_OUT, data + iter,
+ writeamt, &actualwrite, USB_TIMEOUT);
+
+ if (ret == LIBUSB_ERROR_TIMEOUT) {
+ numtimeouts++;
+ sizeleft -= actualwrite;
+ iter += actualwrite;
+
+ /* build in some reliablity */
+ if (numtimeouts > USB_MAX_TIMEOUTS) {
+ log_error("device timed out while transfering out %d bytes (%d made it)\n",
+ length, iter);
+ return false;
+ }
+ } else if (ret == LIBUSB_SUCCESS) {
+ /* we cant trust actualWrite on anything but a timeout or success */
+ sizeleft -= actualwrite;
+ iter += actualwrite;
+ } else {
+ log_error("fatal transfer error (BULK_OUT) for %d bytes (%d made it): %s\n",
+ length, iter, libusb_error_name(ret));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static unsigned char *omap_usb_get_string(libusb_device_handle *handle, uint8_t idx)
+{
+ unsigned char *data = NULL;
+ int len = 0;
+ int ret = 0;
+
+ if (!handle)
+ return NULL;
+
+ while (true) {
+ if (!len || ret < 0) {
+ len += 256;
+ data = realloc(data, len);
+
+ if (!data)
+ return NULL;
+ }
+
+ ret = libusb_get_string_descriptor_ascii(handle, idx, data, len);
+
+ /* we can still recover... */
+ if (ret < 0) {
+ if (ret == LIBUSB_ERROR_INVALID_PARAM)
+ continue; /* try again with an increased size */
+
+ log_error("failed to lookup string index %hhu: %s\n",
+ idx, libusb_error_name(ret));
+
+ /* unrecoverable */
+ free(data);
+ return NULL;
+ } else {
+ /* we got something! */
+ break;
+ }
+ }
+
+ return data;
+}
+
+uint16_t omap_products[] = {
+ 0xd009,
+ 0xd00f,
+};
+
+static libusb_device_handle *omap_usb_open(libusb_context *ctx, uint16_t vendor, uint16_t product)
+{
+ libusb_device **devlist;
+ libusb_device_handle *handle;
+ struct libusb_device_descriptor desc;
+ ssize_t count, i;
+ int ret;
+
+ log_info("scanning for USB device matching %04hx:%04hx...\n",
+ vendor, product);
+
+ while (1) {
+ if ((count = libusb_get_device_list(ctx, &devlist)) < 0) {
+ log_error("failed to gather USB device list: %s\n",
+ libusb_error_name(count));
+ return NULL;
+ }
+
+ for (i = 0; i < count; i++) {
+ ret = libusb_get_device_descriptor(devlist[i], &desc);
+ if (ret < 0) {
+ log_error("failed to get USB device descriptor: %s\n",
+ libusb_error_name(ret));
+ libusb_free_device_list(devlist, 1);
+ return NULL;
+ }
+
+ if (desc.idVendor != vendor)
+ continue;
+
+ if (product) {
+ if (desc.idProduct != product)
+ continue;
+ goto found;
+ }
+
+ for (i = 0; i < sizeof(omap_products) / sizeof(uint16_t); i++)
+ if (desc.idProduct == omap_products[i]) {
+ product = desc.idProduct;
+ goto found;
+ }
+ }
+
+ libusb_free_device_list(devlist, 1);
+
+ /* nothing found yet. have a 10ms nap */
+ usleep(10000);
+ }
+found:
+ ret = libusb_open(devlist[i], &handle);
+ if (ret < 0) {
+ log_error("failed to open USB device %04hx:%04hx: %s\n",
+ vendor, product, libusb_error_name(ret));
+ libusb_free_device_list(devlist, 1);
+ return NULL;
+ }
+
+ ret = libusb_claim_interface(handle, 0);
+ if (ret) {
+ printf("Claim failed\n");
+ return NULL;
+ }
+
+ /* grab the manufacturer and product strings for printing */
+ unsigned char *mfgstr = omap_usb_get_string(handle, desc.iManufacturer);
+ unsigned char *prodstr = omap_usb_get_string(handle, desc.iProduct);
+
+ log_info("successfully opened %04hx:%04hx (", vendor, product);
+
+ if (mfgstr) {
+ fprintf(stdout, prodstr ? "%s " : "%s", mfgstr);
+ free(mfgstr);
+ }
+
+ if (prodstr) {
+ fprintf(stdout, "%s", prodstr);
+ free(prodstr);
+ }
+
+ fprintf(stdout, ")\n");
+
+ return handle;
+}
+
+static unsigned char *read_file(char *path, size_t *readamt)
+{
+ FILE *fp = fopen(path, "rb");
+
+ if (!fp) {
+ log_error("failed to open file \'%s\': %s\n", path,
+ strerror(errno));
+ return NULL;
+ }
+
+ unsigned char *data = NULL;
+ size_t allocsize = 0;
+ size_t iter = 0;
+
+ while (1) {
+ if (iter >= iter) {
+ allocsize += 1024;
+ data = realloc(data, allocsize);
+ if (!data)
+ return NULL;
+ }
+
+ size_t readsize = allocsize - iter;
+ size_t ret = fread(data + iter, sizeof (unsigned char), readsize, fp);
+
+ iter += ret;
+
+ if (ret != readsize) {
+ if (feof(fp)) {
+ break;
+ } else if (ferror(fp)) {
+ log_error("error file reading file \'%s\': %s\n",
+ path, strerror(errno));
+ free(data);
+ return NULL;
+ }
+ }
+ }
+
+ /* trim the allocation down to size */
+ data = realloc(data, iter);
+ *readamt = iter;
+
+ return data;
+}
+
+static int transfer_first_stage(libusb_device_handle * handle, struct arg_state *args)
+{
+ unsigned char *buffer = NULL;
+ uint32_t cmd = 0;
+ uint32_t filelen = 0;
+ int bufsize = 0x200;
+ int transLen = 0;
+ int i;
+ void *data;
+ uint32_t *dbuf;
+
+ struct file_upload *file = args->files[0];
+
+ /* TODO determine buffer size based on endpoint */
+ buffer = calloc(bufsize, sizeof (unsigned char));
+ filelen = cpu_to_le32(file->size);
+
+ data = file->data;
+ dbuf = data;
+
+ if (le32toh(dbuf[5]) == 0x45534843) {
+ int chsettingssize = 512 + 2 * sizeof(uint32_t);
+
+ log_info("CHSETTINGS image detected. Skipping header\n");
+
+ data += chsettingssize;
+ filelen -= chsettingssize;
+ }
+
+ /* read the ASIC ID */
+ if (!omap_usb_read(handle, buffer, bufsize, &transLen)) {
+ log_error("failed to read ASIC ID from USB connection. "
+ "Check your USB device!\n");
+ goto fail;
+ }
+
+ if (transLen != OMAP_ASIC_ID_LEN) {
+ log_error("got some ASIC ID, but it's not the right length, %d "
+ "(expected %d)\n", transLen, OMAP_ASIC_ID_LEN);
+ goto fail;
+ }
+
+ /* optionally, print some ASIC ID info */
+ if (g_verbose) {
+ char *fields[] =
+ { "Num Subblocks", "Device ID Info", "Reserved",
+ "Ident Data", "Reserved", "CRC (4 bytes)"
+ };
+ int fieldLen[] = { 1, 7, 4, 23, 23, 11 };
+ int field = 0;
+ int nextSep = 0;
+
+ log_info("got ASIC ID - ");
+
+ for (i = 0; i < transLen; i++) {
+ if (i == nextSep) {
+ fprintf(stdout, "%s%s ",
+ (field > 0) ? ", " : "", fields[field]);
+ nextSep += fieldLen[field];
+ field++;
+
+ fprintf(stdout, "[");
+ }
+
+ fprintf(stdout, "%02x", buffer[i]);
+
+ if (i + 1 == nextSep)
+ fprintf(stdout, "]");
+ }
+
+ fprintf(stdout, "\n");
+ }
+
+ /* send the peripheral boot command */
+ cmd = cpu_to_le32(OMAP_PERIPH_BOOT);
+
+ if (!omap_usb_write(handle, (unsigned char *) &cmd, sizeof (cmd))) {
+ log_error("failed to send the peripheral boot command 0x%08x\n",
+ OMAP_PERIPH_BOOT);
+ goto fail;
+ }
+
+ /* send the length of the first file (little endian) */
+ if (!omap_usb_write
+ (handle, (unsigned char *) &filelen, sizeof (filelen))) {
+ log_error("failed to length specifier of %u to OMAP BootROM\n",
+ filelen);
+ goto fail;
+ }
+
+ /* send the file! */
+ if (!omap_usb_write(handle, data, filelen)) {
+ log_error("failed to send file \'%s\' (size %u)\n",
+ file->basename, filelen);
+ goto fail;
+ }
+
+ free(buffer);
+ return 1;
+
+ fail:
+ free(buffer);
+ return 0;
+}
+
+static int transfer_other_files(libusb_device_handle *handle, struct arg_state *args)
+{
+ uint32_t *buffer = NULL;
+ int bufsize = 128 * sizeof (*buffer);
+ int numfailures = 0; /* build in some reliablity */
+ int maxfailures = 3;
+ int transLen = 0;
+ int curfile = 1; /* skip the first file */
+ size_t len;
+
+ buffer = calloc(bufsize, sizeof(unsigned char));
+
+ /* handle the state machine for the X-Loader */
+ while (curfile < args->numfiles) {
+ uint32_t opcode = 0;
+ uint8_t *extra = NULL;
+ struct file_upload *f = args->files[curfile];
+
+ /* read the opcode from xloader ID */
+ if (!omap_usb_read
+ (handle, (unsigned char *) buffer, bufsize, &transLen)) {
+ numfailures++;
+
+ if (numfailures >= maxfailures) {
+ log_error("failed to read command from X-Loader\n");
+ goto fail;
+ }
+
+ /* sleep a bit */
+ usleep(2000 * 1000); /* 2s */
+ continue; /* try the opcode read again */
+ }
+
+ if (transLen < 8) {
+ log_error("failed to recieve enough data for the opcode\n");
+ goto fail;
+ }
+
+ /* extract the opcode and extra data pointer */
+ opcode = le32_to_cpu(buffer[0]);
+ extra = (uint8_t *)buffer;
+
+ switch (opcode) {
+ case USBLOAD_CMD_FILE_REQ:
+ /* X-loader is requesting a file to be sent */
+ /* send the opcode, size, and addr */
+ buffer[0] = cpu_to_le32(USBLOAD_CMD_FILE);
+ buffer[1] = cpu_to_le32(f->size);
+ buffer[2] = cpu_to_le32(f->addr);
+
+ if (!omap_usb_write(handle, (unsigned char *)buffer, sizeof(*buffer) * 3)) {
+ log_error("failed to send load file command to the X-loader\n");
+ goto fail;
+ }
+
+ if (g_verbose) {
+ log_info("uploading \'%s\' (size %zu) to 0x%08x\n",
+ f->basename, f->size, f->addr);
+ }
+
+ break;
+ case USBLOAD_CMD_ECHO_SZ:
+ /* X-loader confirms the size to recieve */
+ if (buffer[1] != f->size) {
+ log_error
+ ("X-loader failed to recieve the right file size for "
+ "file \'%s\' (got %u, expected %zu)\n",
+ f->basename, buffer[1], f->size);
+ goto fail;
+ }
+
+ /* upload the raw file data */
+ if (!omap_usb_write(handle, f->data, f->size)) {
+ log_error
+ ("failed to send file \'%s\' to the X-loader\n",
+ f->basename);
+ goto fail;
+ }
+
+ break;
+ case USBLOAD_CMD_REPORT_SZ:
+ /* X-loader confirms the amount of data it recieved */
+ if (buffer[1] != f->size) {
+ log_error
+ ("X-loader failed to recieve the right amount of data for "
+ "file \'%s\' (got %u, expected %zu)\n",
+ f->basename, buffer[1], f->size);
+ goto fail;
+ }
+
+ curfile++; /* move on to the next file */
+ break;
+ case USBLOAD_CMD_MESSAGE:
+ /* X-loader debug message */
+ len = strlen((char *)extra);
+
+ if (len > (bufsize - sizeof (opcode) - 1))
+ log_error("X-loader debug message not NUL terminated (size %zu)\n",
+ len);
+ else
+ fprintf(stdout, "X-loader Debug: %s\n", extra);
+ break;
+ default:
+ log_error("unknown X-Loader opcode 0x%08X (%c%c%c%c)\n",
+ opcode, extra[0], extra[1], extra[2],
+ extra[3]);
+ goto fail;
+ }
+ }
+
+ /* we're done uploading files to X-loader send the jump command */
+ buffer[0] = cpu_to_le32(USBLOAD_CMD_JUMP);
+ buffer[1] = cpu_to_le32(args->jumptarget);
+
+ if (!omap_usb_write
+ (handle, (unsigned char *) buffer, sizeof (*buffer) * 2)) {
+ log_error
+ ("failed to send the final jump command to the X-loader. "
+ "Target was 0x%08x\n", args->jumptarget);
+ goto fail;
+ }
+
+ if (g_verbose)
+ log_info("jumping to address 0x%08x\n", args->jumptarget);
+
+ free(buffer);
+ return 1;
+
+ fail:
+ free(buffer);
+ return 0;
+}
+
+static int process_args(struct arg_state *args)
+{
+ int i;
+
+ /* For each file, load it in to memory
+ * TODO: defer this until transfer time (save memory and pipeline IO)
+ */
+
+ for (i = 0; i < args->numfiles; i++) {
+ struct file_upload *f = args->files[i];
+
+ f->data = read_file(f->path, &f->size);
+
+ if (!f->data) {
+ return 1;
+ }
+ }
+
+ if (g_verbose > 0) {
+ for (i = 0; i < args->numfiles; i++) {
+ struct file_upload *f = args->files[i];
+
+ printf("File \'%s\' at 0x%08x, size %zu\n",
+ f->basename, f->addr, f->size);
+ }
+ }
+
+ libusb_context *ctx;
+ libusb_device_handle *dev;
+ int ret;
+
+ if ((ret = libusb_init(&ctx)) < 0) {
+ log_error("failed to initialize libusb context: %s\n",
+ libusb_error_name(ret));
+ return ret;
+ }
+
+ dev = omap_usb_open(ctx, args->vendor, args->product);
+
+ if (!dev) {
+ libusb_exit(ctx);
+ return 1;
+ }
+
+ /* Communicate with the TI BootROM directly
+ * - retrieve ASIC ID
+ * - start peripheral boot
+ * - upload first file
+ * - execute first file
+ */
+ if (!transfer_first_stage(dev, args)) {
+ log_error("failed to transfer the first stage file \'%s\'\n",
+ args->files[0]->basename);
+ goto fail;
+ }
+
+ /* Note: this is a race between the target's processor getting X-loader
+ * running and our processor. If we fail to communicate with the X-loader,
+ * it's possible that it hasn't been fully initialized. I'm not going to put
+ * some stupid, arbitrary sleep value here. The transfer_other_files function
+ * should be robust enough to handle some errors.
+ */
+
+ /* If we are passed one file, assume that the user just wants to
+ * upload some initial code with no X-loader chaining
+ */
+ if (args->numfiles > 1) {
+ if (!transfer_other_files(dev, args)) {
+ log_error
+ ("failed to transfer the additional files in to memory\n");
+ goto fail;
+ }
+ }
+
+ log_info("successfully transfered %d %s\n", args->numfiles,
+ (args->numfiles > 1) ? "files" : "file");
+
+ /* safely close our USB handle and context */
+ libusb_close(dev);
+ libusb_exit(ctx);
+ return 0;
+
+fail:
+ libusb_close(dev);
+ libusb_exit(ctx);
+
+ return 1;
+}
+
+/* getopt configuration */
+static int do_version = 0;
+static const char *const short_opt = "f:a:j:i:p:vh";
+static const struct option long_opt[] = {
+ {"file", 1, NULL, 'f'},
+ {"addr", 1, NULL, 'a'},
+ {"jump", 1, NULL, 'j'},
+ {"vendor", 1, NULL, 'i'},
+ {"product", 1, NULL, 'p'},
+ {"verbose", 0, NULL, 'v'},
+ {"help", 0, NULL, 'h'},
+ {"version", 0, &do_version, 1},
+ {NULL, 0, NULL, 0}
+};
+
+static void usage(char *exe)
+{
+ printf(
+"Usage: %s [options] -f first-stage [-f file -a addr]...\n"
+"Options:\n"
+" -f, --file Provide the filename of a binary file to be\n"
+" uploaded. The first file specified is uploaded to\n"
+" the fixed address 0x%08x as defined by the manual.\n"
+" Additional files must be followed by an address\n"
+" argument (-a).\n"
+" -a, --addr The address to load the prior file at.\n"
+" -j, --jump Specify the address to jump to after loading all\n"
+" of the files in to memory.\n"
+" -i, --vendor Override the default vendor ID to poll for\n"
+" (default 0x%04x).\n"
+" -p, --product Poll for specific product id. Default: All known OMAP chips\n"
+" -h, --help Display this message.\n"
+" -v, --verbose Enable verbose output.\n"
+"\n"
+"Description:\n"
+" %s's basic usage is to upload an arbitrary file in to the memory\n"
+" of a TI OMAP3 compatible processor. This program directly\n"
+" communicates with the TI BootROM in order to upload a first stage\n"
+" payload, in most cases, TI's X-Loader. Using a compatible X-Loader\n"
+" will enable the upload of any file to any part in device memory.\n"
+"\n"
+"Examples:\n"
+" Uploading a compatible X-Loader, U-Boot, Kernel, and RAMDisk, then jumping\n"
+" to the U-Boot image for further bootloading:\n"
+" %s -f x-load.bin -f u-boot.bin -a 0x80200000 -f uImage -a 0x80800000 \\\n"
+" -f uRamdisk -a 0x81000000 -j 0x80200000\n"
+" Uploading arbitrary code to be executed (doesn't have to be X-loader):\n"
+" %s -f exec_me.bin\n"
+" Trying to debug an upload issue using verbose output:\n"
+" %s -v -f exec_me.bin -f file1.bin -a 0xdeadbeef -j 0xabad1dea\n"
+"\n"
+"Authors:\n"
+" Grant Hernandez <grant.h.hernandez@gmail.com> - rewrite of omap3_usbload to\n"
+" use the newer libusb 1.0\n"
+" Martin Mueller <martinmm@pfump.org> - initial code (omap3_usbload)\n"
+" and X-Loader patch\n",
+ exe, OMAP_BASE_ADDRESS, OMAP_VENDOR_ID, PROG_NAME, exe, exe, exe
+ );
+}
+
+static void license(void)
+{
+ printf(
+"Copyright (C) 2008 Martin Mueller <martinmm@pfump.org>\n"
+"Copyright (C) 2014 Grant Hernandez <grant.h.hernandez@gmail.com>\n"
+"License GPLv2: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.\n"
+"This is free software: you are free to change and redistribute it.\n"
+"There is NO WARRANTY, to the extent permitted by law.\n"
+ );
+}
+
+int main(int argc, char *argv[])
+{
+ int opt;
+ bool gotfile = false;
+ bool gotjump = false;
+ int filecount = 0;
+ char *exe = NULL;
+
+ /* temporary local file object */
+ struct file_upload file;
+ /* total arg state */
+ struct arg_state *args = calloc(1, sizeof (*args));
+
+ if (argc < 1) {
+ log_error("invalid arguments (no argv[0])\n");
+ return 1;
+ }
+
+ exe = argv[0];
+
+ fprintf(stdout, "%s %s\n", PROG_NAME, VERSION);
+
+ /* set the default vendor and product */
+ args->vendor = OMAP_VENDOR_ID;
+ args->product = 0;
+
+ while ((opt = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1) {
+ switch (opt) {
+ case 0:
+ if (do_version) {
+ license();
+ return 0;
+ }
+ break;
+ case 'f':
+ if (gotfile) {
+ log_error("missing address argument (-a) for file \'%s\'\n",
+ file.path);
+ usage(exe);
+ return 1;
+ }
+
+ file.path = strdup(optarg);
+
+ /* necessary to be sure that we own all the memory
+ and that the path input can be modified */
+ char *tmpPath = strdup(file.path);
+ file.basename = strdup(basename(tmpPath));
+ free(tmpPath);
+
+ filecount++;
+
+ /* the first file gets uploaded to a fixed address
+ as specified by the technical reference manual */
+ if (filecount == 1) {
+ file.addr = OMAP_BASE_ADDRESS;
+
+ /* commit the file object with the processor specified base address */
+ args->files = realloc(args->files, filecount);
+ args->numfiles = filecount;
+ args->files[filecount - 1] = malloc(sizeof (file));
+ memcpy(args->files[filecount - 1], &file, sizeof (file));
+ } else {
+ /* commit only after an address is specified */
+ gotfile = true;
+ }
+ break;
+ case 'a':
+ if (!gotfile) {
+ log_error
+ ("missing file argument (-f) before address \'%s\'\n",
+ optarg);
+ usage(exe);
+ return 1;
+ }
+
+ /* passing 0 to strtoul enables detection of the 0x prefix with
+ base-10 fallback if missing */
+ file.addr = strtoul(optarg, NULL, 0);
+
+ /* commit the file object */
+ args->files = realloc(args->files, filecount);
+ args->numfiles = filecount;
+ args->files[filecount - 1] = malloc(sizeof(file));
+ memcpy(args->files[filecount - 1], &file, sizeof(file));
+
+ gotfile = false;
+ break;
+ case 'j':
+ args->jumptarget = strtoul(optarg, NULL, 0);
+ gotjump = true;
+ break;
+ case 'i':
+ args->vendor = (uint16_t)strtoul(optarg, NULL, 0);
+ break;
+ case 'p':
+ args->product = (uint16_t)strtoul(optarg, NULL, 0);
+ break;
+ case 'v':
+ g_verbose++;
+ break;
+ case 'h':
+ usage(exe);
+ return 0;
+ default:
+ usage(exe);
+ return 1;
+ }
+ }
+
+ if (gotfile) {
+ log_error("got file \'%s\', but no address!\n", file.path);
+ usage(exe);
+ return 1;
+ }
+
+ if (args->numfiles <= 0) {
+ log_error("at least one file needs to be specified\n");
+ usage(exe);
+ return 1;
+ }
+
+ if (args->numfiles == 1 && gotjump) {
+ log_info
+ ("WARNING: jump target 0x%08x specified, but will never be taken "
+ "(more than one file required)\n", args->jumptarget);
+ } else if (args->numfiles > 1 && !gotjump) {
+ log_info
+ ("WARNING: no jump target specified. Defaulting to the first "
+ "file's (\'%s\') address 0x%08x\n",
+ args->files[1]->basename, args->files[1]->addr);
+ args->jumptarget = args->files[1]->addr;
+ }
+
+ return process_args(args);
+}