blob: 95362f261826783749a27fc679d44218b80b42d2 [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
Furquan Shaikh0dba0252016-11-30 04:34:22 -080035static int do_spi_flash_cmd(const struct spi_slave *spi, const void *dout,
36 size_t bytes_out, void *din, size_t bytes_in)
David Hendricksf101bbe2014-03-21 19:13:34 -070037{
38 int ret = 1;
Furquan Shaikhc2973d12016-11-29 22:07:42 -080039 /*
40 * SPI flash requires command-response kind of behavior. Thus, two
41 * separate SPI vectors are required -- first to transmit dout and other
42 * to receive in din. If some specialized SPI flash controllers
43 * (e.g. x86) can perform both command and response together, it should
44 * be handled at SPI flash controller driver level.
45 */
46 struct spi_op vectors[] = {
47 [0] = { .dout = dout, .bytesout = bytes_out,
48 .din = NULL, .bytesin = 0, },
49 [1] = { .dout = NULL, .bytesout = 0,
50 .din = din, .bytesin = bytes_in },
51 };
Kyösti Mälkki85b2b272017-01-10 06:25:57 +020052 size_t count = ARRAY_SIZE(vectors);
53 if (!bytes_in)
54 count = 1;
David Hendricksf101bbe2014-03-21 19:13:34 -070055
David Hendricks032c8432014-04-11 19:48:55 -070056 if (spi_claim_bus(spi))
57 return ret;
58
Kyösti Mälkki85b2b272017-01-10 06:25:57 +020059 if (spi_xfer_vector(spi, vectors, count) == 0)
Furquan Shaikhc2973d12016-11-29 22:07:42 -080060 ret = 0;
David Hendricksf101bbe2014-03-21 19:13:34 -070061
David Hendricks032c8432014-04-11 19:48:55 -070062 spi_release_bus(spi);
David Hendricksf101bbe2014-03-21 19:13:34 -070063 return ret;
64}
65
Furquan Shaikh810e2cd2016-12-05 20:32:24 -080066int spi_flash_cmd(const struct spi_slave *spi, u8 cmd, void *response, size_t len)
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -070067{
David Hendricksf101bbe2014-03-21 19:13:34 -070068 int ret = do_spi_flash_cmd(spi, &cmd, sizeof(cmd), response, len);
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -070069 if (ret)
70 printk(BIOS_WARNING, "SF: Failed to send command %02x: %d\n", cmd, ret);
71
72 return ret;
73}
74
Furquan Shaikh810e2cd2016-12-05 20:32:24 -080075static int spi_flash_cmd_read(const struct spi_slave *spi, const u8 *cmd,
Vadim Bendeburyf9ff3532014-11-29 15:06:26 -080076 size_t cmd_len, void *data, size_t data_len)
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -070077{
David Hendricksf101bbe2014-03-21 19:13:34 -070078 int ret = do_spi_flash_cmd(spi, cmd, cmd_len, data, data_len);
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -070079 if (ret) {
80 printk(BIOS_WARNING, "SF: Failed to send read command (%zu bytes): %d\n",
81 data_len, ret);
82 }
83
84 return ret;
85}
86
Julius Werner8d8799a2014-12-19 16:11:14 -080087/* TODO: This code is quite possibly broken and overflowing stacks. Fix ASAP! */
88#pragma GCC diagnostic push
89#pragma GCC diagnostic ignored "-Wstack-usage="
Furquan Shaikh810e2cd2016-12-05 20:32:24 -080090int spi_flash_cmd_write(const struct spi_slave *spi, const u8 *cmd,
91 size_t cmd_len, const void *data, size_t data_len)
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -070092{
93 int ret;
94 u8 buff[cmd_len + data_len];
95 memcpy(buff, cmd, cmd_len);
96 memcpy(buff + cmd_len, data, data_len);
97
David Hendricksf101bbe2014-03-21 19:13:34 -070098 ret = do_spi_flash_cmd(spi, buff, cmd_len + data_len, NULL, 0);
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -070099 if (ret) {
100 printk(BIOS_WARNING, "SF: Failed to send write command (%zu bytes): %d\n",
101 data_len, ret);
102 }
103
104 return ret;
105}
Julius Werner8d8799a2014-12-19 16:11:14 -0800106#pragma GCC diagnostic pop
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700107
Furquan Shaikh810e2cd2016-12-05 20:32:24 -0800108static int spi_flash_cmd_read_array(const struct spi_slave *spi, u8 *cmd,
Vadim Bendeburyf9ff3532014-11-29 15:06:26 -0800109 size_t cmd_len, u32 offset,
110 size_t len, void *data)
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700111{
Furquan Shaikhdc34fb62016-11-17 16:17:37 -0800112 spi_flash_addr(offset, cmd);
113 return spi_flash_cmd_read(spi, cmd, cmd_len, data, len);
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700114}
115
Furquan Shaikhc28984d2016-11-20 21:04:00 -0800116int spi_flash_cmd_read_fast(const struct spi_flash *flash, u32 offset,
117 size_t len, void *data)
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700118{
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700119 u8 cmd[5];
120
121 cmd[0] = CMD_READ_ARRAY_FAST;
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700122 cmd[4] = 0x00;
123
Furquan Shaikh810e2cd2016-12-05 20:32:24 -0800124 return spi_flash_cmd_read_array(&flash->spi, cmd, sizeof(cmd),
Vadim Bendeburyf9ff3532014-11-29 15:06:26 -0800125 offset, len, data);
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700126}
127
Furquan Shaikhc28984d2016-11-20 21:04:00 -0800128int spi_flash_cmd_read_slow(const struct spi_flash *flash, u32 offset,
129 size_t len, void *data)
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700130{
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700131 u8 cmd[4];
132
133 cmd[0] = CMD_READ_ARRAY_SLOW;
Furquan Shaikh810e2cd2016-12-05 20:32:24 -0800134 return spi_flash_cmd_read_array(&flash->spi, cmd, sizeof(cmd),
Vadim Bendeburyf9ff3532014-11-29 15:06:26 -0800135 offset, len, data);
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700136}
137
Furquan Shaikhc28984d2016-11-20 21:04:00 -0800138int spi_flash_cmd_poll_bit(const struct spi_flash *flash, unsigned long timeout,
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700139 u8 cmd, u8 poll_bit)
140{
Furquan Shaikh810e2cd2016-12-05 20:32:24 -0800141 const struct spi_slave *spi = &flash->spi;
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700142 int ret;
143 u8 status;
Dave Frodinc50c0ab2014-06-11 12:53:47 -0600144 struct mono_time current, end;
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700145
Dave Frodinc50c0ab2014-06-11 12:53:47 -0600146 timer_monotonic_get(&current);
147 end = current;
148 mono_time_add_msecs(&end, timeout);
149
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700150 do {
151 ret = spi_flash_cmd_read(spi, &cmd, 1, &status, 1);
152 if (ret)
153 return -1;
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700154 if ((status & poll_bit) == 0)
Dave Frodinc50c0ab2014-06-11 12:53:47 -0600155 return 0;
156 timer_monotonic_get(&current);
157 } while (!mono_time_after(&current, &end));
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700158
Dave Frodinc50c0ab2014-06-11 12:53:47 -0600159 printk(BIOS_DEBUG, "SF: timeout at %ld msec\n",timeout);
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700160 return -1;
161}
162
Furquan Shaikhc28984d2016-11-20 21:04:00 -0800163int spi_flash_cmd_wait_ready(const struct spi_flash *flash,
164 unsigned long timeout)
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700165{
166 return spi_flash_cmd_poll_bit(flash, timeout,
167 CMD_READ_STATUS, STATUS_WIP);
168}
169
Furquan Shaikhc28984d2016-11-20 21:04:00 -0800170int spi_flash_cmd_erase(const struct spi_flash *flash, u32 offset, size_t len)
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700171{
172 u32 start, end, erase_size;
173 int ret;
174 u8 cmd[4];
175
176 erase_size = flash->sector_size;
177 if (offset % erase_size || len % erase_size) {
178 printk(BIOS_WARNING, "SF: Erase offset/length not multiple of erase size\n");
179 return -1;
180 }
181
Dan Ehrenberga5aac762015-01-08 10:29:19 -0800182 cmd[0] = flash->erase_cmd;
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700183 start = offset;
184 end = start + len;
185
186 while (offset < end) {
187 spi_flash_addr(offset, cmd);
188 offset += erase_size;
189
Marc Jones747127d2012-12-03 22:16:29 -0700190#if CONFIG_DEBUG_SPI_FLASH
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700191 printk(BIOS_SPEW, "SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
192 cmd[2], cmd[3], offset);
Marc Jones747127d2012-12-03 22:16:29 -0700193#endif
Furquan Shaikh810e2cd2016-12-05 20:32:24 -0800194 ret = spi_flash_cmd(&flash->spi, CMD_WRITE_ENABLE, NULL, 0);
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700195 if (ret)
196 goto out;
197
Furquan Shaikh810e2cd2016-12-05 20:32:24 -0800198 ret = spi_flash_cmd_write(&flash->spi, cmd, sizeof(cmd), NULL, 0);
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700199 if (ret)
200 goto out;
201
202 ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
203 if (ret)
204 goto out;
205 }
206
207 printk(BIOS_DEBUG, "SF: Successfully erased %zu bytes @ %#x\n", len, start);
208
Patrick Georgi20959ba2012-05-12 23:30:36 +0200209out:
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700210 return ret;
211}
212
Furquan Shaikhc28984d2016-11-20 21:04:00 -0800213int spi_flash_cmd_status(const struct spi_flash *flash, u8 *reg)
Duncan Lauriefb032392015-01-15 15:28:46 -0800214{
Furquan Shaikh810e2cd2016-12-05 20:32:24 -0800215 return spi_flash_cmd(&flash->spi, flash->status_cmd, reg, sizeof(*reg));
Duncan Lauriefb032392015-01-15 15:28:46 -0800216}
217
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700218/*
219 * The following table holds all device probe functions
220 *
221 * shift: number of continuation bytes before the ID
222 * idcode: the expected IDCODE or 0xff for non JEDEC devices
223 * probe: the function to call
224 *
225 * Non JEDEC devices should be ordered in the table such that
226 * the probe functions with best detection algorithms come first.
227 *
228 * Several matching entries are permitted, they will be tried
229 * in sequence until a probe function returns non NULL.
230 *
231 * IDCODE_CONT_LEN may be redefined if a device needs to declare a
232 * larger "shift" value. IDCODE_PART_LEN generally shouldn't be
233 * changed. This is the max number of bytes probe functions may
234 * examine when looking up part-specific identification info.
235 *
236 * Probe functions will be given the idcode buffer starting at their
237 * manu id byte (the "idcode" in the table below). In other words,
238 * all of the continuation bytes will be skipped (the "shift" below).
239 */
240#define IDCODE_CONT_LEN 0
241#define IDCODE_PART_LEN 5
Duncan Laurie181bbdd2012-06-23 16:53:57 -0700242static struct {
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700243 const u8 shift;
244 const u8 idcode;
245 struct spi_flash *(*probe) (struct spi_slave *spi, u8 *idcode);
246} flashes[] = {
247 /* Keep it sorted by define name */
Idwer Vollering73a10182014-02-16 00:32:13 +0000248#if CONFIG_SPI_FLASH_AMIC
249 { 0, 0x37, spi_flash_probe_amic, },
250#endif
Kyösti Mälkki96d92762014-11-11 15:04:38 +0200251#if CONFIG_SPI_FLASH_ATMEL
252 { 0, 0x1f, spi_flash_probe_atmel, },
253#endif
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700254#if CONFIG_SPI_FLASH_EON
255 { 0, 0x1c, spi_flash_probe_eon, },
256#endif
Martin Rothbceaf7f2012-09-07 15:02:35 -0600257#if CONFIG_SPI_FLASH_GIGADEVICE
258 { 0, 0xc8, spi_flash_probe_gigadevice, },
259#endif
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700260#if CONFIG_SPI_FLASH_MACRONIX
261 { 0, 0xc2, spi_flash_probe_macronix, },
262#endif
263#if CONFIG_SPI_FLASH_SPANSION
264 { 0, 0x01, spi_flash_probe_spansion, },
265#endif
266#if CONFIG_SPI_FLASH_SST
267 { 0, 0xbf, spi_flash_probe_sst, },
268#endif
269#if CONFIG_SPI_FLASH_STMICRO
270 { 0, 0x20, spi_flash_probe_stmicro, },
271#endif
272#if CONFIG_SPI_FLASH_WINBOND
273 { 0, 0xef, spi_flash_probe_winbond, },
274#endif
275 /* Keep it sorted by best detection */
276#if CONFIG_SPI_FLASH_STMICRO
277 { 0, 0xff, spi_flash_probe_stmicro, },
278#endif
Chris Douglassb34739b2014-02-14 13:51:26 -0500279#if CONFIG_SPI_FLASH_ADESTO
280 { 0, 0x1f, spi_flash_probe_adesto, },
281#endif
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700282};
283#define IDCODE_LEN (IDCODE_CONT_LEN + IDCODE_PART_LEN)
284
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800285struct spi_flash *
286__attribute__((weak)) spi_flash_programmer_probe(struct spi_slave *spi,
287 int force)
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700288{
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800289 /* Default weak implementation. Do nothing. */
290 return NULL;
291}
292
293static struct spi_flash *__spi_flash_probe(struct spi_slave *spi)
294{
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700295 int ret, i, shift;
296 u8 idcode[IDCODE_LEN], *idp;
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800297 struct spi_flash *flash = NULL;
Vladimir Serbinenkoe23bd0e2014-01-18 17:45:32 +0100298
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700299 /* Read the ID codes */
300 ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
301 if (ret)
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800302 return NULL;
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700303
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800304 if (IS_ENABLED(CONFIG_DEBUG_SPI_FLASH)) {
305 printk(BIOS_SPEW, "SF: Got idcode: ");
306 for (i = 0; i < sizeof(idcode); i++)
307 printk(BIOS_SPEW, "%02x ", idcode[i]);
308 printk(BIOS_SPEW, "\n");
309 }
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700310
311 /* count the number of continuation bytes */
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800312 for (shift = 0, idp = idcode; shift < IDCODE_CONT_LEN && *idp == 0x7f;
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700313 ++shift, ++idp)
314 continue;
315
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800316 printk(BIOS_INFO, "Manufacturer: %02x\n", *idp);
317
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700318 /* search the table for matches in shift and id */
319 for (i = 0; i < ARRAY_SIZE(flashes); ++i)
320 if (flashes[i].shift == shift && flashes[i].idcode == *idp) {
321 /* we have a match, call probe */
322 flash = flashes[i].probe(spi, idp);
323 if (flash)
324 break;
325 }
326
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800327 return flash;
328}
329
330struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs)
331{
Furquan Shaikh36b81af2016-12-01 01:02:44 -0800332 struct spi_slave spi;
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800333 struct spi_flash *flash;
334
Furquan Shaikh36b81af2016-12-01 01:02:44 -0800335 if (spi_setup_slave(bus, cs, &spi)) {
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800336 printk(BIOS_WARNING, "SF: Failed to set up slave\n");
337 return NULL;
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700338 }
339
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800340 /* Try special programmer probe if any (without force). */
Furquan Shaikh36b81af2016-12-01 01:02:44 -0800341 flash = spi_flash_programmer_probe(&spi, 0);
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800342
343 /* If flash is not found, try generic spi flash probe. */
344 if (!flash)
Furquan Shaikh36b81af2016-12-01 01:02:44 -0800345 flash = __spi_flash_probe(&spi);
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800346
347 /* If flash is not yet found, force special programmer probe if any. */
348 if (!flash)
Furquan Shaikh36b81af2016-12-01 01:02:44 -0800349 flash = spi_flash_programmer_probe(&spi, 1);
Furquan Shaikhd2fb6ae2016-11-17 20:38:07 -0800350
351 /* Give up -- nothing more to try if flash is not found. */
352 if (!flash) {
353 printk(BIOS_WARNING, "SF: Unsupported manufacturer!\n");
354 return NULL;
355 }
356
David Imhoff8d4377b2015-05-03 13:47:49 +0200357 printk(BIOS_INFO, "SF: Detected %s with sector size 0x%x, total 0x%x\n",
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700358 flash->name, flash->sector_size, flash->size);
359
Aaron Durbinc0a823c2016-08-11 14:51:38 -0500360 /*
361 * Only set the global spi_flash_dev if this is the boot
362 * device's bus and it's previously unset while in ramstage.
363 */
364 if (ENV_RAMSTAGE && IS_ENABLED(CONFIG_BOOT_DEVICE_SPI_FLASH) &&
365 CONFIG_BOOT_DEVICE_SPI_FLASH_BUS == bus && !spi_flash_dev)
366 spi_flash_dev = flash;
Dan Ehrenberga5aac762015-01-08 10:29:19 -0800367
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700368 return flash;
Stefan Reinauer1c56d9b2012-05-10 11:27:32 -0700369}
Dan Ehrenberga5aac762015-01-08 10:29:19 -0800370
Furquan Shaikhc28984d2016-11-20 21:04:00 -0800371int spi_flash_read(const struct spi_flash *flash, u32 offset, size_t len,
372 void *buf)
373{
374 return flash->internal_read(flash, offset, len, buf);
375}
376
377int spi_flash_write(const struct spi_flash *flash, u32 offset, size_t len,
378 const void *buf)
379{
380 int ret;
381
382 if (spi_flash_volatile_group_begin(flash))
383 return -1;
384
385 ret = flash->internal_write(flash, offset, len, buf);
386
387 if (spi_flash_volatile_group_end(flash))
388 return -1;
389
390 return ret;
391}
392
393int spi_flash_erase(const struct spi_flash *flash, u32 offset, size_t len)
394{
395 int ret;
396
397 if (spi_flash_volatile_group_begin(flash))
398 return -1;
399
400 ret = flash->internal_erase(flash, offset, len);
401
402 if (spi_flash_volatile_group_end(flash))
403 return -1;
404
405 return ret;
406}
407
408int spi_flash_status(const struct spi_flash *flash, u8 *reg)
409{
410 return flash->internal_status(flash, reg);
411}
412
413static uint32_t volatile_group_count CAR_GLOBAL;
414
415int spi_flash_volatile_group_begin(const struct spi_flash *flash)
416{
417 uint32_t count;
418 int ret = 0;
419
420 if (!IS_ENABLED(CONFIG_SPI_FLASH_HAS_VOLATILE_GROUP))
421 return ret;
422
423 count = car_get_var(volatile_group_count);
424 if (count == 0)
425 ret = chipset_volatile_group_begin(flash);
426
427 count++;
428 car_set_var(volatile_group_count, count);
429 return ret;
430}
431
432int spi_flash_volatile_group_end(const struct spi_flash *flash)
433{
434 uint32_t count;
435 int ret = 0;
436
437 if (!IS_ENABLED(CONFIG_SPI_FLASH_HAS_VOLATILE_GROUP))
438 return ret;
439
440 count = car_get_var(volatile_group_count);
441 assert(count == 0);
442 count--;
443 car_set_var(volatile_group_count, count);
444
445 if (count == 0)
446 ret = chipset_volatile_group_end(flash);
447
448 return ret;
449}
450
Dan Ehrenberga5aac762015-01-08 10:29:19 -0800451void lb_spi_flash(struct lb_header *header)
452{
453 struct lb_spi_flash *flash;
454
Aaron Durbinc0a823c2016-08-11 14:51:38 -0500455 if (!IS_ENABLED(CONFIG_BOOT_DEVICE_SPI_FLASH))
456 return;
457
Dan Ehrenberga5aac762015-01-08 10:29:19 -0800458 flash = (struct lb_spi_flash *)lb_new_record(header);
459
460 flash->tag = LB_TAG_SPI_FLASH;
461 flash->size = sizeof(*flash);
462
463 /* Try to get the flash device if not loaded yet */
Aaron Durbin899d13d2015-05-15 23:39:23 -0500464 if (!spi_flash_dev)
465 boot_device_init();
Dan Ehrenberga5aac762015-01-08 10:29:19 -0800466
467 if (spi_flash_dev) {
468 flash->flash_size = spi_flash_dev->size;
469 flash->sector_size = spi_flash_dev->sector_size;
470 flash->erase_cmd = spi_flash_dev->erase_cmd;
471 } else {
472 flash->flash_size = CONFIG_ROM_SIZE;
473 /* Default 64k erase command should work on most flash.
474 * Uniform 4k erase only works on certain devices. */
475 flash->sector_size = 64 * KiB;
476 flash->erase_cmd = CMD_BLOCK_ERASE;
477 }
478}