Blame view
common/spl/spl_spi.c
4.23 KB
83d290c56
|
1 |
// SPDX-License-Identifier: GPL-2.0+ |
32b112739
|
2 3 4 |
/* * Copyright (C) 2011 OMICRON electronics GmbH * |
a430fa06a
|
5 |
* based on drivers/mtd/nand/raw/nand_spl_load.c |
32b112739
|
6 7 8 |
* * Copyright (C) 2011 * Heiko Schocher, DENX Software Engineering, hs@denx.de. |
32b112739
|
9 10 11 |
*/ #include <common.h> |
ff0960f9a
|
12 |
#include <spi.h> |
32b112739
|
13 |
#include <spi_flash.h> |
36afd4513
|
14 |
#include <errno.h> |
a4cc1c487
|
15 |
#include <spl.h> |
32b112739
|
16 |
|
2bac55bc1
|
17 |
DECLARE_GLOBAL_DATA_PTR; |
fa1a73fa8
|
18 19 20 21 22 |
#ifdef 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. */ |
2a2ee2ac3
|
23 24 |
static int spi_load_image_os(struct spl_image_info *spl_image, struct spi_flash *flash, |
fa1a73fa8
|
25 26 |
struct image_header *header) { |
7e0f22674
|
27 |
int err; |
fa1a73fa8
|
28 |
/* Read for a header, parse or error out. */ |
51c12319b
|
29 |
spi_flash_read(flash, CONFIG_SYS_SPI_KERNEL_OFFS, sizeof(*header), |
fa1a73fa8
|
30 31 32 33 |
(void *)header); if (image_get_magic(header) != IH_MAGIC) return -1; |
2a2ee2ac3
|
34 |
err = spl_parse_image_header(spl_image, header); |
7e0f22674
|
35 36 |
if (err) return err; |
fa1a73fa8
|
37 38 |
spi_flash_read(flash, CONFIG_SYS_SPI_KERNEL_OFFS, |
2a2ee2ac3
|
39 |
spl_image->size, (void *)spl_image->load_addr); |
fa1a73fa8
|
40 41 42 43 44 45 46 47 48 |
/* Read device tree. */ spi_flash_read(flash, CONFIG_SYS_SPI_ARGS_OFFS, CONFIG_SYS_SPI_ARGS_SIZE, (void *)CONFIG_SYS_SPL_ARGS_ADDR); return 0; } #endif |
2512787d3
|
49 50 51 52 53 54 |
#ifdef CONFIG_SYS_SPI_U_BOOT_OFFS unsigned long __weak spl_spi_get_uboot_raw_sector(struct spi_flash *flash) { return CONFIG_SYS_SPI_U_BOOT_OFFS; } #endif |
68a7d9bef
|
55 56 57 58 59 60 61 62 |
#ifdef CONFIG_PARSE_CONTAINER int __weak spi_load_image_parse_container(struct spl_image_info *spl_image, struct spi_flash *flash, unsigned long offset) { return -EINVAL; } #endif |
00d559561
|
63 64 65 66 67 68 69 70 71 72 73 74 |
static ulong spl_spi_fit_read(struct spl_load_info *load, ulong sector, ulong count, void *buf) { struct spi_flash *flash = load->dev; ulong ret; ret = spi_flash_read(flash, sector, count, buf); if (!ret) return count; else return 0; } |
32b112739
|
75 76 77 78 79 |
/* * The main entry for SPI booting. It's necessary that SDRAM is already * configured and available since this code loads the main U-Boot image * from SPI into SDRAM and starts it from there. */ |
2a2ee2ac3
|
80 81 |
static int spl_spi_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) |
32b112739
|
82 |
{ |
36afd4513
|
83 |
int err = 0; |
2512787d3
|
84 |
unsigned payload_offs = 0; |
32b112739
|
85 |
struct spi_flash *flash; |
a4cc1c487
|
86 |
struct image_header *header; |
32b112739
|
87 88 89 90 |
/* * Load U-Boot image from SPI flash into RAM */ |
88e34e5ff
|
91 92 93 94 |
flash = spi_flash_probe(CONFIG_SF_DEFAULT_BUS, CONFIG_SF_DEFAULT_CS, CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE); |
32b112739
|
95 |
if (!flash) { |
a4cc1c487
|
96 97 |
puts("SPI probe failed. "); |
36afd4513
|
98 |
return -ENODEV; |
32b112739
|
99 |
} |
2512787d3
|
100 |
payload_offs = spl_spi_get_uboot_raw_sector(flash); |
51c12319b
|
101 |
header = spl_get_load_buffer(-sizeof(*header), sizeof(*header)); |
32b112739
|
102 |
|
2bac55bc1
|
103 104 105 106 107 |
#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) payload_offs = fdtdec_get_config_int(gd->fdt_blob, "u-boot,spl-payload-offset", payload_offs); #endif |
fa1a73fa8
|
108 |
#ifdef CONFIG_SPL_OS_BOOT |
2a2ee2ac3
|
109 |
if (spl_start_uboot() || spi_load_image_os(spl_image, flash, header)) |
fa1a73fa8
|
110 111 112 |
#endif { /* Load u-boot, mkimage header is 64 bytes. */ |
51c12319b
|
113 |
err = spi_flash_read(flash, payload_offs, sizeof(*header), |
36afd4513
|
114 |
(void *)header); |
a70449003
|
115 116 117 118 |
if (err) { debug("%s: Failed to read from SPI flash (err=%d) ", __func__, err); |
36afd4513
|
119 |
return err; |
a70449003
|
120 |
} |
36afd4513
|
121 |
|
26ad648ff
|
122 123 124 125 126 127 128 129 130 131 132 |
if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) && image_get_magic(header) == FDT_MAGIC) { err = spi_flash_read(flash, payload_offs, roundup(fdt_totalsize(header), 4), (void *)CONFIG_SYS_LOAD_ADDR); if (err) return err; err = spl_parse_image_header(spl_image, (struct image_header *)CONFIG_SYS_LOAD_ADDR); } else if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && image_get_magic(header) == FDT_MAGIC) { |
00d559561
|
133 134 135 136 137 138 139 140 141 |
struct spl_load_info load; debug("Found FIT "); load.dev = flash; load.priv = NULL; load.filename = NULL; load.bl_len = 1; load.read = spl_spi_fit_read; |
f4d7d8596
|
142 |
err = spl_load_simple_fit(spl_image, &load, |
2bac55bc1
|
143 |
payload_offs, |
00d559561
|
144 145 |
header); } else { |
68a7d9bef
|
146 147 148 149 150 |
#ifdef CONFIG_PARSE_CONTAINER err = spi_load_image_parse_container(spl_image, flash, payload_offs); #else |
2a2ee2ac3
|
151 |
err = spl_parse_image_header(spl_image, header); |
00d559561
|
152 153 |
if (err) return err; |
2bac55bc1
|
154 |
err = spi_flash_read(flash, payload_offs, |
2a2ee2ac3
|
155 156 |
spl_image->size, (void *)spl_image->load_addr); |
68a7d9bef
|
157 |
#endif |
00d559561
|
158 |
} |
fa1a73fa8
|
159 |
} |
36afd4513
|
160 161 |
return err; |
32b112739
|
162 |
} |
139db7af4
|
163 |
/* Use priorty 1 so that boards can override this */ |
ebc4ef61d
|
164 |
SPL_LOAD_IMAGE_METHOD("SPI", 1, BOOT_DEVICE_SPI, spl_spi_load_image); |