blob: b6d535a71a9d7f9ec19694677c9f00dff2613154 [file] [log] [blame]
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -07001/*
2 * SPI flash interface
3 *
4 * Copyright (C) 2008 Atmel Corporation
5 * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik
6 *
7 * Licensed under the GPL-2 or later.
8 */
9
Furquan Shaikhc28984d2016-11-20 21:04:00 -080010#include <arch/early_variables.h>
11#include <assert.h>
Aaron Durbin899d13d2015-05-15 23:39:23 -050012#include <boot_device.h>
Dan Ehrenberga5aac762015-01-08 10:29:19 -080013#include <cbfs.h>
Edward O'Callaghanc4561e22014-06-26 15:02:40 +100014#include <cpu/x86/smm.h>
15#include <delay.h>
Aaron Durbinc0a823c2016-08-11 14:51:38 -050016#include <rules.h>
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -070017#include <stdlib.h>
18#include <string.h>
Zheng Bao600784e2013-02-07 17:30:23 +080019#include <spi-generic.h>
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -070020#include <spi_flash.h>
Edward O'Callaghanc4561e22014-06-26 15:02:40 +100021
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -070022#include "spi_flash_internal.h"
Dave Frodinc50c0ab2014-06-11 12:53:47 -060023#include <timer.h>
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -070024
Dan Ehrenberga5aac762015-01-08 10:29:19 -080025static struct spi_flash *spi_flash_dev = NULL;
26
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -070027static void spi_flash_addr(u32 addr, u8 *cmd)
28{
29 /* cmd[0] is actual command */
30 cmd[1] = addr >> 16;
31 cmd[2] = addr >> 8;
32 cmd[3] = addr >> 0;
33}
34
David Hendricksf101bbe2014-03-21 19:13:34 -070035/*
36 * If atomic sequencing is used, the cycle type is known to the SPI
37 * controller so that it can perform consecutive transfers and arbitrate
38 * automatically. Otherwise the SPI controller transfers whatever the
39 * user requests immediately, without regard to sequence. Atomic
40 * sequencing is commonly used on x86 platforms.
41 *
42 * SPI flash commands are simple two-step sequences. The command byte is
43 * always written first and may be followed by an address. Then data is
44 * either read or written. For atomic sequencing we'll pass everything into
45 * spi_xfer() at once and let the controller handle the details. Otherwise
46 * we will write all output bytes first and then read if necessary.
47 *
48 * FIXME: This really should be abstracted better, but that will
49 * require overhauling the entire SPI infrastructure.
50 */
Furquan Shaikh0dba0252016-11-30 04:34:22 -080051static int do_spi_flash_cmd(const struct spi_slave *spi, const void *dout,
52 size_t bytes_out, void *din, size_t bytes_in)
David Hendricksf101bbe2014-03-21 19:13:34 -070053{
54 int ret = 1;
55
David Hendricks032c8432014-04-11 19:48:55 -070056 if (spi_claim_bus(spi))
57 return ret;
58
David Hendricksf101bbe2014-03-21 19:13:34 -070059#if CONFIG_SPI_ATOMIC_SEQUENCING == 1
60 if (spi_xfer(spi, dout, bytes_out, din, bytes_in) < 0)
61 goto done;
62#else
63 if (dout && bytes_out) {
64 if (spi_xfer(spi, dout, bytes_out, NULL, 0) < 0)
65 goto done;
66 }
67
68 if (din && bytes_in) {
69 if (spi_xfer(spi, NULL, 0, din, bytes_in) < 0)
70 goto done;
71 }
72#endif
73
74 ret = 0;
75done:
David Hendricks032c8432014-04-11 19:48:55 -070076 spi_release_bus(spi);
David Hendricksf101bbe2014-03-21 19:13:34 -070077 return ret;
78}
79
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -070080int spi_flash_cmd(struct spi_slave *spi, u8 cmd, void *response, size_t len)
81{
David Hendricksf101bbe2014-03-21 19:13:34 -070082 int ret = do_spi_flash_cmd(spi, &cmd, sizeof(cmd), response, len);
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -070083 if (ret)
84 printk(BIOS_WARNING, "SF: Failed to send command %02x: %d\n", cmd, ret);
85
86 return ret;
87}
88
Vadim Bendeburyf9ff3532014-11-29 15:06:26 -080089static int spi_flash_cmd_read(struct spi_slave *spi, const u8 *cmd,
90 size_t cmd_len, void *data, size_t data_len)
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -070091{
David Hendricksf101bbe2014-03-21 19:13:34 -070092 int ret = do_spi_flash_cmd(spi, cmd, cmd_len, data, data_len);
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -070093 if (ret) {
94 printk(BIOS_WARNING, "SF: Failed to send read command (%zu bytes): %d\n",
95 data_len, ret);
96 }
97
98 return ret;
99}
100
Julius Werner8d8799a2014-12-19 16:11:14 -0800101/* TODO: This code is quite possibly broken and overflowing stacks. Fix ASAP! */
102#pragma GCC diagnostic push
103#pragma GCC diagnostic ignored "-Wstack-usage="
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700104int spi_flash_cmd_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len,
105 const void *data, size_t data_len)
106{
107 int ret;
108 u8 buff[cmd_len + data_len];
109 memcpy(buff, cmd, cmd_len);
110 memcpy(buff + cmd_len, data, data_len);
111
David Hendricksf101bbe2014-03-21 19:13:34 -0700112 ret = do_spi_flash_cmd(spi, buff, cmd_len + data_len, NULL, 0);
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700113 if (ret) {
114 printk(BIOS_WARNING, "SF: Failed to send write command (%zu bytes): %d\n",
115 data_len, ret);
116 }
117
118 return ret;
119}
Julius Werner8d8799a2014-12-19 16:11:14 -0800120#pragma GCC diagnostic pop
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700121
Vadim Bendeburyf9ff3532014-11-29 15:06:26 -0800122static int spi_flash_cmd_read_array(struct spi_slave *spi, u8 *cmd,
123 size_t cmd_len, u32 offset,
124 size_t len, void *data)
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700125{
Furquan Shaikhdc34fb62016-11-17 16:17:37 -0800126 spi_flash_addr(offset, cmd);
127 return spi_flash_cmd_read(spi, cmd, cmd_len, data, len);
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700128}
129
Furquan Shaikhc28984d2016-11-20 21:04:00 -0800130int spi_flash_cmd_read_fast(const struct spi_flash *flash, u32 offset,
131 size_t len, void *data)
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700132{
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700133 u8 cmd[5];
134
135 cmd[0] = CMD_READ_ARRAY_FAST;
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700136 cmd[4] = 0x00;
137
Vadim Bendeburyf9ff3532014-11-29 15:06:26 -0800138 return spi_flash_cmd_read_array(flash->spi, cmd, sizeof(cmd),
139 offset, len, data);
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700140}
141
Furquan Shaikhc28984d2016-11-20 21:04:00 -0800142int spi_flash_cmd_read_slow(const struct spi_flash *flash, u32 offset,
143 size_t len, void *data)
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700144{
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700145 u8 cmd[4];
146
147 cmd[0] = CMD_READ_ARRAY_SLOW;
Vadim Bendeburyf9ff3532014-11-29 15:06:26 -0800148 return spi_flash_cmd_read_array(flash->spi, cmd, sizeof(cmd),
149 offset, len, data);
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700150}
151
Furquan Shaikhc28984d2016-11-20 21:04:00 -0800152int spi_flash_cmd_poll_bit(const struct spi_flash *flash, unsigned long timeout,
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700153 u8 cmd, u8 poll_bit)
154{
155 struct spi_slave *spi = flash->spi;
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700156 int ret;
157 u8 status;
Dave Frodinc50c0ab2014-06-11 12:53:47 -0600158 struct mono_time current, end;
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700159
Dave Frodinc50c0ab2014-06-11 12:53:47 -0600160 timer_monotonic_get(&current);
161 end = current;
162 mono_time_add_msecs(&end, timeout);
163
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700164 do {
165 ret = spi_flash_cmd_read(spi, &cmd, 1, &status, 1);
166 if (ret)
167 return -1;
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700168 if ((status & poll_bit) == 0)
Dave Frodinc50c0ab2014-06-11 12:53:47 -0600169 return 0;
170 timer_monotonic_get(&current);
171 } while (!mono_time_after(&current, &end));
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700172
Dave Frodinc50c0ab2014-06-11 12:53:47 -0600173 printk(BIOS_DEBUG, "SF: timeout at %ld msec\n",timeout);
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700174 return -1;
175}
176
Furquan Shaikhc28984d2016-11-20 21:04:00 -0800177int spi_flash_cmd_wait_ready(const struct spi_flash *flash,
178 unsigned long timeout)
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700179{
180 return spi_flash_cmd_poll_bit(flash, timeout,
181 CMD_READ_STATUS, STATUS_WIP);
182}
183
Furquan Shaikhc28984d2016-11-20 21:04:00 -0800184int spi_flash_cmd_erase(const struct spi_flash *flash, u32 offset, size_t len)
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700185{
186 u32 start, end, erase_size;
187 int ret;
188 u8 cmd[4];
189
190 erase_size = flash->sector_size;
191 if (offset % erase_size || len % erase_size) {
192 printk(BIOS_WARNING, "SF: Erase offset/length not multiple of erase size\n");
193 return -1;
194 }
195
Dan Ehrenberga5aac762015-01-08 10:29:19 -0800196 cmd[0] = flash->erase_cmd;
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700197 start = offset;
198 end = start + len;
199
200 while (offset < end) {
201 spi_flash_addr(offset, cmd);
202 offset += erase_size;
203
Marc Jones747127d2012-12-03 22:16:29 -0700204#if CONFIG_DEBUG_SPI_FLASH
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700205 printk(BIOS_SPEW, "SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
206 cmd[2], cmd[3], offset);
Marc Jones747127d2012-12-03 22:16:29 -0700207#endif
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700208 ret = spi_flash_cmd(flash->spi, CMD_WRITE_ENABLE, NULL, 0);
209 if (ret)
210 goto out;
211
212 ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), NULL, 0);
213 if (ret)
214 goto out;
215
216 ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
217 if (ret)
218 goto out;
219 }
220
221 printk(BIOS_DEBUG, "SF: Successfully erased %zu bytes @ %#x\n", len, start);
222
Patrick Georgi20959ba2012-05-12 23:30:36 +0200223out:
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700224 return ret;
225}
226
Furquan Shaikhc28984d2016-11-20 21:04:00 -0800227int spi_flash_cmd_status(const struct spi_flash *flash, u8 *reg)
Duncan Lauriefb032392015-01-15 15:28:46 -0800228{
229 return spi_flash_cmd(flash->spi, flash->status_cmd, reg, sizeof(*reg));
230}
231
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700232/*
233 * The following table holds all device probe functions
234 *
235 * shift: number of continuation bytes before the ID
236 * idcode: the expected IDCODE or 0xff for non JEDEC devices
237 * probe: the function to call
238 *
239 * Non JEDEC devices should be ordered in the table such that
240 * the probe functions with best detection algorithms come first.
241 *
242 * Several matching entries are permitted, they will be tried
243 * in sequence until a probe function returns non NULL.
244 *
245 * IDCODE_CONT_LEN may be redefined if a device needs to declare a
246 * larger "shift" value. IDCODE_PART_LEN generally shouldn't be
247 * changed. This is the max number of bytes probe functions may
248 * examine when looking up part-specific identification info.
249 *
250 * Probe functions will be given the idcode buffer starting at their
251 * manu id byte (the "idcode" in the table below). In other words,
252 * all of the continuation bytes will be skipped (the "shift" below).
253 */
254#define IDCODE_CONT_LEN 0
255#define IDCODE_PART_LEN 5
Duncan Laurie181bbdd2012-06-23 16:53:57 -0700256static struct {
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700257 const u8 shift;
258 const u8 idcode;
259 struct spi_flash *(*probe) (struct spi_slave *spi, u8 *idcode);
260} flashes[] = {
261 /* Keep it sorted by define name */
Idwer Vollering73a10182014-02-16 00:32:13 +0000262#if CONFIG_SPI_FLASH_AMIC
263 { 0, 0x37, spi_flash_probe_amic, },
264#endif
Kyösti Mälkki96d92762014-11-11 15:04:38 +0200265#if CONFIG_SPI_FLASH_ATMEL
266 { 0, 0x1f, spi_flash_probe_atmel, },
267#endif
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700268#if CONFIG_SPI_FLASH_EON
269 { 0, 0x1c, spi_flash_probe_eon, },
270#endif
Martin Rothbceaf7f2012-09-07 15:02:35 -0600271#if CONFIG_SPI_FLASH_GIGADEVICE
272 { 0, 0xc8, spi_flash_probe_gigadevice, },
273#endif
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700274#if CONFIG_SPI_FLASH_MACRONIX
275 { 0, 0xc2, spi_flash_probe_macronix, },
276#endif
277#if CONFIG_SPI_FLASH_SPANSION
278 { 0, 0x01, spi_flash_probe_spansion, },
279#endif
280#if CONFIG_SPI_FLASH_SST
281 { 0, 0xbf, spi_flash_probe_sst, },
282#endif
283#if CONFIG_SPI_FLASH_STMICRO
284 { 0, 0x20, spi_flash_probe_stmicro, },
285#endif
286#if CONFIG_SPI_FLASH_WINBOND
287 { 0, 0xef, spi_flash_probe_winbond, },
288#endif
289 /* Keep it sorted by best detection */
290#if CONFIG_SPI_FLASH_STMICRO
291 { 0, 0xff, spi_flash_probe_stmicro, },
292#endif
Chris Douglassb34739b2014-02-14 13:51:26 -0500293#if CONFIG_SPI_FLASH_ADESTO
294 { 0, 0x1f, spi_flash_probe_adesto, },
295#endif
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700296};
297#define IDCODE_LEN (IDCODE_CONT_LEN + IDCODE_PART_LEN)
298
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800299struct spi_flash *
300__attribute__((weak)) spi_flash_programmer_probe(struct spi_slave *spi,
301 int force)
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700302{
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800303 /* Default weak implementation. Do nothing. */
304 return NULL;
305}
306
307static struct spi_flash *__spi_flash_probe(struct spi_slave *spi)
308{
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700309 int ret, i, shift;
310 u8 idcode[IDCODE_LEN], *idp;
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800311 struct spi_flash *flash = NULL;
Vladimir Serbinenkoe23bd0e2014-01-18 17:45:32 +0100312
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700313 /* Read the ID codes */
314 ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
315 if (ret)
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800316 return NULL;
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700317
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800318 if (IS_ENABLED(CONFIG_DEBUG_SPI_FLASH)) {
319 printk(BIOS_SPEW, "SF: Got idcode: ");
320 for (i = 0; i < sizeof(idcode); i++)
321 printk(BIOS_SPEW, "%02x ", idcode[i]);
322 printk(BIOS_SPEW, "\n");
323 }
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700324
325 /* count the number of continuation bytes */
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800326 for (shift = 0, idp = idcode; shift < IDCODE_CONT_LEN && *idp == 0x7f;
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700327 ++shift, ++idp)
328 continue;
329
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800330 printk(BIOS_INFO, "Manufacturer: %02x\n", *idp);
331
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700332 /* search the table for matches in shift and id */
333 for (i = 0; i < ARRAY_SIZE(flashes); ++i)
334 if (flashes[i].shift == shift && flashes[i].idcode == *idp) {
335 /* we have a match, call probe */
336 flash = flashes[i].probe(spi, idp);
337 if (flash)
338 break;
339 }
340
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800341 return flash;
342}
343
344struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs)
345{
346 struct spi_slave *spi;
347 struct spi_flash *flash;
348
349 spi = spi_setup_slave(bus, cs);
350 if (!spi) {
351 printk(BIOS_WARNING, "SF: Failed to set up slave\n");
352 return NULL;
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700353 }
354
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800355 /* Try special programmer probe if any (without force). */
356 flash = spi_flash_programmer_probe(spi, 0);
357
358 /* If flash is not found, try generic spi flash probe. */
359 if (!flash)
360 flash = __spi_flash_probe(spi);
361
362 /* If flash is not yet found, force special programmer probe if any. */
363 if (!flash)
364 flash = spi_flash_programmer_probe(spi, 1);
365
366 /* Give up -- nothing more to try if flash is not found. */
367 if (!flash) {
368 printk(BIOS_WARNING, "SF: Unsupported manufacturer!\n");
369 return NULL;
370 }
371
David Imhoff8d4377b2015-05-03 13:47:49 +0200372 printk(BIOS_INFO, "SF: Detected %s with sector size 0x%x, total 0x%x\n",
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700373 flash->name, flash->sector_size, flash->size);
374
Aaron Durbinc0a823c2016-08-11 14:51:38 -0500375 /*
376 * Only set the global spi_flash_dev if this is the boot
377 * device's bus and it's previously unset while in ramstage.
378 */
379 if (ENV_RAMSTAGE && IS_ENABLED(CONFIG_BOOT_DEVICE_SPI_FLASH) &&
380 CONFIG_BOOT_DEVICE_SPI_FLASH_BUS == bus && !spi_flash_dev)
381 spi_flash_dev = flash;
Dan Ehrenberga5aac762015-01-08 10:29:19 -0800382
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700383 return flash;
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700384}
Dan Ehrenberga5aac762015-01-08 10:29:19 -0800385
Furquan Shaikhc28984d2016-11-20 21:04:00 -0800386int spi_flash_read(const struct spi_flash *flash, u32 offset, size_t len,
387 void *buf)
388{
389 return flash->internal_read(flash, offset, len, buf);
390}
391
392int spi_flash_write(const struct spi_flash *flash, u32 offset, size_t len,
393 const void *buf)
394{
395 int ret;
396
397 if (spi_flash_volatile_group_begin(flash))
398 return -1;
399
400 ret = flash->internal_write(flash, offset, len, buf);
401
402 if (spi_flash_volatile_group_end(flash))
403 return -1;
404
405 return ret;
406}
407
408int spi_flash_erase(const struct spi_flash *flash, u32 offset, size_t len)
409{
410 int ret;
411
412 if (spi_flash_volatile_group_begin(flash))
413 return -1;
414
415 ret = flash->internal_erase(flash, offset, len);
416
417 if (spi_flash_volatile_group_end(flash))
418 return -1;
419
420 return ret;
421}
422
423int spi_flash_status(const struct spi_flash *flash, u8 *reg)
424{
425 return flash->internal_status(flash, reg);
426}
427
428static uint32_t volatile_group_count CAR_GLOBAL;
429
430int spi_flash_volatile_group_begin(const struct spi_flash *flash)
431{
432 uint32_t count;
433 int ret = 0;
434
435 if (!IS_ENABLED(CONFIG_SPI_FLASH_HAS_VOLATILE_GROUP))
436 return ret;
437
438 count = car_get_var(volatile_group_count);
439 if (count == 0)
440 ret = chipset_volatile_group_begin(flash);
441
442 count++;
443 car_set_var(volatile_group_count, count);
444 return ret;
445}
446
447int spi_flash_volatile_group_end(const struct spi_flash *flash)
448{
449 uint32_t count;
450 int ret = 0;
451
452 if (!IS_ENABLED(CONFIG_SPI_FLASH_HAS_VOLATILE_GROUP))
453 return ret;
454
455 count = car_get_var(volatile_group_count);
456 assert(count == 0);
457 count--;
458 car_set_var(volatile_group_count, count);
459
460 if (count == 0)
461 ret = chipset_volatile_group_end(flash);
462
463 return ret;
464}
465
Dan Ehrenberga5aac762015-01-08 10:29:19 -0800466void lb_spi_flash(struct lb_header *header)
467{
468 struct lb_spi_flash *flash;
469
Aaron Durbinc0a823c2016-08-11 14:51:38 -0500470 if (!IS_ENABLED(CONFIG_BOOT_DEVICE_SPI_FLASH))
471 return;
472
Dan Ehrenberga5aac762015-01-08 10:29:19 -0800473 flash = (struct lb_spi_flash *)lb_new_record(header);
474
475 flash->tag = LB_TAG_SPI_FLASH;
476 flash->size = sizeof(*flash);
477
478 /* Try to get the flash device if not loaded yet */
Aaron Durbin899d13d2015-05-15 23:39:23 -0500479 if (!spi_flash_dev)
480 boot_device_init();
Dan Ehrenberga5aac762015-01-08 10:29:19 -0800481
482 if (spi_flash_dev) {
483 flash->flash_size = spi_flash_dev->size;
484 flash->sector_size = spi_flash_dev->sector_size;
485 flash->erase_cmd = spi_flash_dev->erase_cmd;
486 } else {
487 flash->flash_size = CONFIG_ROM_SIZE;
488 /* Default 64k erase command should work on most flash.
489 * Uniform 4k erase only works on certain devices. */
490 flash->sector_size = 64 * KiB;
491 flash->erase_cmd = CMD_BLOCK_ERASE;
492 }
493}