10a9b73a1SSimon Glass /* 20a9b73a1SSimon Glass * Copyright (C) 2011 OMICRON electronics GmbH 30a9b73a1SSimon Glass * 40a9b73a1SSimon Glass * based on drivers/mtd/nand/nand_spl_load.c 50a9b73a1SSimon Glass * 60a9b73a1SSimon Glass * Copyright (C) 2011 70a9b73a1SSimon Glass * Heiko Schocher, DENX Software Engineering, hs@denx.de. 80a9b73a1SSimon Glass * 90a9b73a1SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 100a9b73a1SSimon Glass */ 110a9b73a1SSimon Glass 120a9b73a1SSimon Glass #include <common.h> 130a9b73a1SSimon Glass #include <spi.h> 140a9b73a1SSimon Glass #include <spi_flash.h> 150a9b73a1SSimon Glass #include <errno.h> 160a9b73a1SSimon Glass #include <spl.h> 170a9b73a1SSimon Glass 18*2bac55bcSPhilipp Tomsich DECLARE_GLOBAL_DATA_PTR; 19*2bac55bcSPhilipp Tomsich 200a9b73a1SSimon Glass #ifdef CONFIG_SPL_OS_BOOT 210a9b73a1SSimon Glass /* 220a9b73a1SSimon Glass * Load the kernel, check for a valid header we can parse, and if found load 230a9b73a1SSimon Glass * the kernel and then device tree. 240a9b73a1SSimon Glass */ 252a2ee2acSSimon Glass static int spi_load_image_os(struct spl_image_info *spl_image, 262a2ee2acSSimon Glass struct spi_flash *flash, 270a9b73a1SSimon Glass struct image_header *header) 280a9b73a1SSimon Glass { 290a9b73a1SSimon Glass int err; 300a9b73a1SSimon Glass 310a9b73a1SSimon Glass /* Read for a header, parse or error out. */ 320a9b73a1SSimon Glass spi_flash_read(flash, CONFIG_SYS_SPI_KERNEL_OFFS, 0x40, 330a9b73a1SSimon Glass (void *)header); 340a9b73a1SSimon Glass 350a9b73a1SSimon Glass if (image_get_magic(header) != IH_MAGIC) 360a9b73a1SSimon Glass return -1; 370a9b73a1SSimon Glass 382a2ee2acSSimon Glass err = spl_parse_image_header(spl_image, header); 390a9b73a1SSimon Glass if (err) 400a9b73a1SSimon Glass return err; 410a9b73a1SSimon Glass 420a9b73a1SSimon Glass spi_flash_read(flash, CONFIG_SYS_SPI_KERNEL_OFFS, 432a2ee2acSSimon Glass spl_image->size, (void *)spl_image->load_addr); 440a9b73a1SSimon Glass 450a9b73a1SSimon Glass /* Read device tree. */ 460a9b73a1SSimon Glass spi_flash_read(flash, CONFIG_SYS_SPI_ARGS_OFFS, 470a9b73a1SSimon Glass CONFIG_SYS_SPI_ARGS_SIZE, 480a9b73a1SSimon Glass (void *)CONFIG_SYS_SPL_ARGS_ADDR); 490a9b73a1SSimon Glass 500a9b73a1SSimon Glass return 0; 510a9b73a1SSimon Glass } 520a9b73a1SSimon Glass #endif 530a9b73a1SSimon Glass 540a9b73a1SSimon Glass static ulong spl_spi_fit_read(struct spl_load_info *load, ulong sector, 550a9b73a1SSimon Glass ulong count, void *buf) 560a9b73a1SSimon Glass { 570a9b73a1SSimon Glass struct spi_flash *flash = load->dev; 580a9b73a1SSimon Glass ulong ret; 590a9b73a1SSimon Glass 600a9b73a1SSimon Glass ret = spi_flash_read(flash, sector, count, buf); 610a9b73a1SSimon Glass if (!ret) 620a9b73a1SSimon Glass return count; 630a9b73a1SSimon Glass else 640a9b73a1SSimon Glass return 0; 650a9b73a1SSimon Glass } 660a9b73a1SSimon Glass /* 670a9b73a1SSimon Glass * The main entry for SPI booting. It's necessary that SDRAM is already 680a9b73a1SSimon Glass * configured and available since this code loads the main U-Boot image 690a9b73a1SSimon Glass * from SPI into SDRAM and starts it from there. 700a9b73a1SSimon Glass */ 712a2ee2acSSimon Glass static int spl_spi_load_image(struct spl_image_info *spl_image, 722a2ee2acSSimon Glass struct spl_boot_device *bootdev) 730a9b73a1SSimon Glass { 740a9b73a1SSimon Glass int err = 0; 75*2bac55bcSPhilipp Tomsich unsigned payload_offs = CONFIG_SYS_SPI_U_BOOT_OFFS; 760a9b73a1SSimon Glass struct spi_flash *flash; 770a9b73a1SSimon Glass struct image_header *header; 780a9b73a1SSimon Glass 790a9b73a1SSimon Glass /* 800a9b73a1SSimon Glass * Load U-Boot image from SPI flash into RAM 810a9b73a1SSimon Glass */ 820a9b73a1SSimon Glass 830a9b73a1SSimon Glass flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS, 840a9b73a1SSimon Glass CONFIG_SF_DEFAULT_CS, 850a9b73a1SSimon Glass CONFIG_SF_DEFAULT_SPEED, 860a9b73a1SSimon Glass CONFIG_SF_DEFAULT_MODE); 870a9b73a1SSimon Glass if (!flash) { 880a9b73a1SSimon Glass puts("SPI probe failed.\n"); 890a9b73a1SSimon Glass return -ENODEV; 900a9b73a1SSimon Glass } 910a9b73a1SSimon Glass 920a9b73a1SSimon Glass /* use CONFIG_SYS_TEXT_BASE as temporary storage area */ 930a9b73a1SSimon Glass header = (struct image_header *)(CONFIG_SYS_TEXT_BASE); 940a9b73a1SSimon Glass 95*2bac55bcSPhilipp Tomsich #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) 96*2bac55bcSPhilipp Tomsich payload_offs = fdtdec_get_config_int(gd->fdt_blob, 97*2bac55bcSPhilipp Tomsich "u-boot,spl-payload-offset", 98*2bac55bcSPhilipp Tomsich payload_offs); 99*2bac55bcSPhilipp Tomsich #endif 100*2bac55bcSPhilipp Tomsich 1010a9b73a1SSimon Glass #ifdef CONFIG_SPL_OS_BOOT 1022a2ee2acSSimon Glass if (spl_start_uboot() || spi_load_image_os(spl_image, flash, header)) 1030a9b73a1SSimon Glass #endif 1040a9b73a1SSimon Glass { 1050a9b73a1SSimon Glass /* Load u-boot, mkimage header is 64 bytes. */ 106*2bac55bcSPhilipp Tomsich err = spi_flash_read(flash, payload_offs, 0x40, 1070a9b73a1SSimon Glass (void *)header); 108a7044900SSimon Glass if (err) { 109a7044900SSimon Glass debug("%s: Failed to read from SPI flash (err=%d)\n", 110a7044900SSimon Glass __func__, err); 1110a9b73a1SSimon Glass return err; 112a7044900SSimon Glass } 1130a9b73a1SSimon Glass 114f72250e7Stomas.melin@vaisala.com if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && 115f72250e7Stomas.melin@vaisala.com image_get_magic(header) == FDT_MAGIC) { 1160a9b73a1SSimon Glass struct spl_load_info load; 1170a9b73a1SSimon Glass 1180a9b73a1SSimon Glass debug("Found FIT\n"); 1190a9b73a1SSimon Glass load.dev = flash; 1200a9b73a1SSimon Glass load.priv = NULL; 1210a9b73a1SSimon Glass load.filename = NULL; 1220a9b73a1SSimon Glass load.bl_len = 1; 1230a9b73a1SSimon Glass load.read = spl_spi_fit_read; 124f4d7d859SSimon Glass err = spl_load_simple_fit(spl_image, &load, 125*2bac55bcSPhilipp Tomsich payload_offs, 1260a9b73a1SSimon Glass header); 1270a9b73a1SSimon Glass } else { 1282a2ee2acSSimon Glass err = spl_parse_image_header(spl_image, header); 1290a9b73a1SSimon Glass if (err) 1300a9b73a1SSimon Glass return err; 131*2bac55bcSPhilipp Tomsich err = spi_flash_read(flash, payload_offs, 1322a2ee2acSSimon Glass spl_image->size, 1332a2ee2acSSimon Glass (void *)spl_image->load_addr); 1340a9b73a1SSimon Glass } 1350a9b73a1SSimon Glass } 1360a9b73a1SSimon Glass 1370a9b73a1SSimon Glass return err; 1380a9b73a1SSimon Glass } 139139db7afSSimon Glass /* Use priorty 1 so that boards can override this */ 140ebc4ef61SSimon Glass SPL_LOAD_IMAGE_METHOD("SPI", 1, BOOT_DEVICE_SPI, spl_spi_load_image); 141