diff --git a/common/Makefile b/common/Makefile index 8daca5b378..862b3a319e 100644 --- a/common/Makefile +++ b/common/Makefile @@ -201,6 +201,10 @@ COBJS-$(CONFIG_SPL_NET_SUPPORT) += miiphyutil.o COBJS-$(CONFIG_SPL_ENV_SUPPORT) += env_attr.o COBJS-$(CONFIG_SPL_ENV_SUPPORT) += env_flags.o COBJS-$(CONFIG_SPL_ENV_SUPPORT) += env_callback.o +ifdef CONFIG_SPL_USB_HOST_SUPPORT +COBJS-$(CONFIG_SPL_USB_SUPPORT) += usb.o usb_hub.o +COBJS-$(CONFIG_USB_STORAGE) += usb_storage.o +endif ifneq ($(CONFIG_SPL_NET_SUPPORT),y) COBJS-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o COBJS-$(CONFIG_ENV_IS_IN_MMC) += env_mmc.o diff --git a/common/spl/Makefile b/common/spl/Makefile index e8144f7040..0342d22b9f 100644 --- a/common/spl/Makefile +++ b/common/spl/Makefile @@ -20,6 +20,7 @@ COBJS-$(CONFIG_SPL_NAND_SUPPORT) += spl_nand.o COBJS-$(CONFIG_SPL_ONENAND_SUPPORT) += spl_onenand.o COBJS-$(CONFIG_SPL_NET_SUPPORT) += spl_net.o COBJS-$(CONFIG_SPL_MMC_SUPPORT) += spl_mmc.o +COBJS-$(CONFIG_SPL_USB_SUPPORT) += spl_usb.o endif COBJS := $(sort $(COBJS-y)) diff --git a/common/spl/spl.c b/common/spl/spl.c index da31457d5f..0645cee789 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -204,6 +204,11 @@ void board_init_r(gd_t *dummy1, ulong dummy2) case BOOT_DEVICE_USBETH: spl_net_load_image("usb_ether"); break; +#endif +#ifdef CONFIG_SPL_USB_SUPPORT + case BOOT_DEVICE_USB: + spl_usb_load_image(); + break; #endif default: debug("SPL: Un-supported Boot Device\n"); diff --git a/common/spl/spl_usb.c b/common/spl/spl_usb.c new file mode 100644 index 0000000000..93e05f9b0e --- /dev/null +++ b/common/spl/spl_usb.c @@ -0,0 +1,176 @@ +/* + * (C) Copyright 2013 + * Texas Instruments, + * + * Dan Murphy + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Derived work from spl_mmc.c + */ + +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_USB_STORAGE +static int usb_stor_curr_dev = -1; /* current device */ +#endif + +static int usb_load_image_raw(block_dev_desc_t *stor_dev, unsigned long sector) +{ + unsigned long err; + u32 image_size_sectors; + struct image_header *header; + + header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - + sizeof(struct image_header)); + + /* read image header to find the image size & load address */ + err = stor_dev->block_read(usb_stor_curr_dev, sector, 1, (ulong *)header); + if (err == 0) + goto end; + + if (image_get_magic(header) != IH_MAGIC) + return -1; + + spl_parse_image_header(header); + + image_size_sectors = spl_image.size; + + /* Read the header too to avoid extra memcpy */ + err = stor_dev->block_read(usb_stor_curr_dev, sector, + image_size_sectors, (void *)spl_image.load_addr); + +end: +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + if (err == 0) + printf("spl: USB blk read err - %lu\n", err); +#endif + return (err == 0); + +} + +#ifdef CONFIG_SPL_OS_BOOT +static int usb_load_image_raw_os(struct usb_device *usb_dev) +{ + return -1; +} +#endif + +#ifdef CONFIG_SPL_FAT_SUPPORT +static int usb_load_image_fat(const char *filename) +{ + int err; + struct image_header *header; + + header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - + sizeof(struct image_header)); + + err = file_fat_read(filename, header, sizeof(struct image_header)); + if (err <= 0) + goto end; + + spl_parse_image_header(header); + + err = file_fat_read(filename, (u8 *)spl_image.load_addr, 0); + +end: +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + if (err <= 0) + printf("spl: error reading image %s, err - %d\n", + filename, err); +#endif + + return (err <= 0); +} + +#ifdef CONFIG_SPL_OS_BOOT +static int usb_load_image_fat_os(struct usb_device *usb_dev) +{ + int err; + + err = file_fat_read(CONFIG_SPL_FAT_LOAD_ARGS_NAME, + (void *)CONFIG_SYS_SPL_ARGS_ADDR, 0); + if (err <= 0) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("spl: error reading image %s, err - %d\n", + CONFIG_SPL_FAT_LOAD_ARGS_NAME, err); +#endif + return -1; + } + + return usb_load_image_fat(CONFIG_SPL_FAT_LOAD_KERNEL_NAME); +} +#endif + +#endif + +void spl_usb_load_image(void) +{ + struct usb_device *usb_dev; + int err; + u32 boot_mode; + block_dev_desc_t *stor_dev; + + usb_stop(); + err = usb_init(); + if (err) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("spl: usb init failed: err - %d\n", err); +#endif + hang(); + } else { +#ifdef CONFIG_USB_STORAGE + /* try to recognize storage devices immediately */ + usb_stor_curr_dev = usb_stor_scan(1); + stor_dev = usb_stor_get_dev(usb_stor_curr_dev); +#endif + } + + boot_mode = spl_boot_mode(); + if (boot_mode == USB_MODE_RAW) { + debug("boot mode - RAW\n"); +#ifdef CONFIG_SPL_OS_BOOT + if (spl_start_uboot() || usb_load_image_raw_os(usb_dev)) +#endif + err = usb_load_image_raw(stor_dev, + CONFIG_SYS_USB_MODE_U_BOOT_SECTOR); +#ifdef CONFIG_SPL_FAT_SUPPORT + } else if (boot_mode == USB_MODE_FAT) { + debug("boot mode - FAT\n"); + + err = fat_register_device(stor_dev, + CONFIG_SYS_USB_FAT_BOOT_PARTITION); + if (err) { + #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("spl: fat register err - %d\n", err); + #endif + hang(); + } + +#ifdef CONFIG_SPL_OS_BOOT + if (spl_start_uboot() || usb_load_image_fat_os(usb_dev)) +#endif + err = usb_load_image_fat(CONFIG_SPL_FAT_LOAD_PAYLOAD_NAME); + if (err) { + puts("Error loading USB device\n"); + hang(); + } +#endif + } else { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + puts("spl: wrong USB boot mode\n"); +#endif + hang(); + } + + if (err) + hang(); +} diff --git a/include/spl.h b/include/spl.h index 2bd6e16a0e..5730ec765e 100644 --- a/include/spl.h +++ b/include/spl.h @@ -16,6 +16,10 @@ #define MMCSD_MODE_RAW 1 #define MMCSD_MODE_FAT 2 +#define USB_MODE_UNDEFINED 0 +#define USB_MODE_RAW 1 +#define USB_MODE_FAT 2 + struct spl_image_info { const char *name; u8 os; @@ -60,6 +64,9 @@ void spl_spi_load_image(void); /* Ethernet SPL functions */ void spl_net_load_image(const char *device); +/* USB SPL functions */ +void spl_usb_load_image(void); + #ifdef CONFIG_SPL_BOARD_INIT void spl_board_init(void); #endif diff --git a/spl/Makefile b/spl/Makefile index e3b5d850ad..4db12f5629 100644 --- a/spl/Makefile +++ b/spl/Makefile @@ -101,6 +101,10 @@ LIBS-$(CONFIG_SPL_MUSB_NEW_SUPPORT) += drivers/usb/musb-new/libusb_musb-new.o LIBS-$(CONFIG_SPL_USBETH_SUPPORT) += drivers/usb/gadget/libusb_gadget.o LIBS-$(CONFIG_SPL_WATCHDOG_SUPPORT) += drivers/watchdog/libwatchdog.o +# SPL USB Support +LIBS-$(CONFIG_SPL_USB_HOST_SUPPORT) += drivers/usb/host/libusb_host.o +LIBS-$(CONFIG_OMAP_USB_PHY) += drivers/usb/phy/libusb_phy.o + ifneq ($(CONFIG_OMAP_COMMON),) LIBS-y += $(CPUDIR)/omap-common/libomap-common.o endif