soc/intel/alderlake: Add ADL-P 4+4 with 28W TDP
[coreboot.git] / src / drivers / spi / spi_flash.c
blobea1b7162d286a17c037c16580192975220808dfc
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <assert.h>
4 #include <boot/coreboot_tables.h>
5 #include <commonlib/region.h>
6 #include <console/console.h>
7 #include <string.h>
8 #include <spi-generic.h>
9 #include <spi_flash.h>
10 #include <timer.h>
11 #include <types.h>
13 #include "spi_flash_internal.h"
15 #if CONFIG(SPI_FLASH_FORCE_4_BYTE_ADDR_MODE)
16 #define ADDR_MOD 1
17 #else
18 #define ADDR_MOD 0
19 #endif
21 static void spi_flash_addr(u32 addr, u8 *cmd)
23 /* cmd[0] is actual command */
24 if (CONFIG(SPI_FLASH_FORCE_4_BYTE_ADDR_MODE)) {
25 cmd[1] = addr >> 24;
26 cmd[2] = addr >> 16;
27 cmd[3] = addr >> 8;
28 cmd[4] = addr >> 0;
29 } else {
30 cmd[1] = addr >> 16;
31 cmd[2] = addr >> 8;
32 cmd[3] = addr >> 0;
36 static int do_spi_flash_cmd(const struct spi_slave *spi, const u8 *dout,
37 size_t bytes_out, void *din, size_t bytes_in)
39 int ret;
41 * SPI flash requires command-response kind of behavior. Thus, two
42 * separate SPI vectors are required -- first to transmit dout and other
43 * to receive in din. If some specialized SPI flash controllers
44 * (e.g. x86) can perform both command and response together, it should
45 * be handled at SPI flash controller driver level.
47 struct spi_op vectors[] = {
48 [0] = { .dout = dout, .bytesout = bytes_out,
49 .din = NULL, .bytesin = 0, },
50 [1] = { .dout = NULL, .bytesout = 0,
51 .din = din, .bytesin = bytes_in },
53 size_t count = ARRAY_SIZE(vectors);
54 if (!bytes_in)
55 count = 1;
57 ret = spi_claim_bus(spi);
58 if (ret)
59 return ret;
61 ret = spi_xfer_vector(spi, vectors, count);
63 spi_release_bus(spi);
64 return ret;
67 static int do_dual_output_cmd(const struct spi_slave *spi, const u8 *dout,
68 size_t bytes_out, void *din, size_t bytes_in)
70 int ret;
73 * spi_xfer_vector() will automatically fall back to .xfer() if
74 * .xfer_vector() is unimplemented. So using vector API here is more
75 * flexible, even though a controller that implements .xfer_vector()
76 * and (the non-vector based) .xfer_dual() but not .xfer() would be
77 * pretty odd.
79 struct spi_op vector = { .dout = dout, .bytesout = bytes_out,
80 .din = NULL, .bytesin = 0 };
82 ret = spi_claim_bus(spi);
83 if (ret)
84 return ret;
86 ret = spi_xfer_vector(spi, &vector, 1);
88 if (!ret)
89 ret = spi->ctrlr->xfer_dual(spi, NULL, 0, din, bytes_in);
91 spi_release_bus(spi);
92 return ret;
95 static int do_dual_io_cmd(const struct spi_slave *spi, const u8 *dout,
96 size_t bytes_out, void *din, size_t bytes_in)
98 int ret;
100 /* Only the very first byte (opcode) is transferred in "single" mode. */
101 struct spi_op vector = { .dout = dout, .bytesout = 1,
102 .din = NULL, .bytesin = 0 };
104 ret = spi_claim_bus(spi);
105 if (ret)
106 return ret;
108 ret = spi_xfer_vector(spi, &vector, 1);
110 if (!ret)
111 ret = spi->ctrlr->xfer_dual(spi, &dout[1], bytes_out - 1, NULL, 0);
113 if (!ret)
114 ret = spi->ctrlr->xfer_dual(spi, NULL, 0, din, bytes_in);
116 spi_release_bus(spi);
117 return ret;
120 int spi_flash_cmd(const struct spi_slave *spi, u8 cmd, void *response, size_t len)
122 int ret = do_spi_flash_cmd(spi, &cmd, sizeof(cmd), response, len);
123 if (ret)
124 printk(BIOS_WARNING, "SF: Failed to send command %02x: %d\n", cmd, ret);
126 return ret;
129 /* TODO: This code is quite possibly broken and overflowing stacks. Fix ASAP! */
130 #pragma GCC diagnostic push
131 #if defined(__GNUC__) && !defined(__clang__)
132 #pragma GCC diagnostic ignored "-Wstack-usage="
133 #endif
134 #pragma GCC diagnostic ignored "-Wvla"
135 int spi_flash_cmd_write(const struct spi_slave *spi, const u8 *cmd,
136 size_t cmd_len, const void *data, size_t data_len)
138 int ret;
139 u8 buff[cmd_len + data_len];
140 memcpy(buff, cmd, cmd_len);
141 memcpy(buff + cmd_len, data, data_len);
143 ret = do_spi_flash_cmd(spi, buff, cmd_len + data_len, NULL, 0);
144 if (ret) {
145 printk(BIOS_WARNING, "SF: Failed to send write command (%zu bytes): %d\n",
146 data_len, ret);
149 return ret;
151 #pragma GCC diagnostic pop
153 /* Perform the read operation honoring spi controller fifo size, reissuing
154 * the read command until the full request completed. */
155 int spi_flash_cmd_read(const struct spi_flash *flash, u32 offset,
156 size_t len, void *buf)
158 u8 cmd[5 + ADDR_MOD];
159 int ret, cmd_len;
160 int (*do_cmd)(const struct spi_slave *spi, const u8 *din,
161 size_t in_bytes, void *out, size_t out_bytes);
163 if (CONFIG(SPI_FLASH_NO_FAST_READ)) {
164 cmd_len = 4 + ADDR_MOD;
165 cmd[0] = CMD_READ_ARRAY_SLOW;
166 do_cmd = do_spi_flash_cmd;
167 } else if (flash->flags.dual_io && flash->spi.ctrlr->xfer_dual) {
168 cmd_len = 5 + ADDR_MOD;
169 cmd[0] = CMD_READ_FAST_DUAL_IO;
170 cmd[4 + ADDR_MOD] = 0;
171 do_cmd = do_dual_io_cmd;
172 } else if (flash->flags.dual_output && flash->spi.ctrlr->xfer_dual) {
173 cmd_len = 5 + ADDR_MOD;
174 cmd[0] = CMD_READ_FAST_DUAL_OUTPUT;
175 cmd[4 + ADDR_MOD] = 0;
176 do_cmd = do_dual_output_cmd;
177 } else {
178 cmd_len = 5 + ADDR_MOD;
179 cmd[0] = CMD_READ_ARRAY_FAST;
180 cmd[4 + ADDR_MOD] = 0;
181 do_cmd = do_spi_flash_cmd;
184 uint8_t *data = buf;
185 while (len) {
186 size_t xfer_len = spi_crop_chunk(&flash->spi, cmd_len, len);
187 spi_flash_addr(offset, cmd);
188 ret = do_cmd(&flash->spi, cmd, cmd_len, data, xfer_len);
189 if (ret) {
190 printk(BIOS_WARNING,
191 "SF: Failed to send read command %#.2x(%#x, %#zx): %d\n",
192 cmd[0], offset, xfer_len, ret);
193 return ret;
195 offset += xfer_len;
196 data += xfer_len;
197 len -= xfer_len;
200 return 0;
203 int spi_flash_cmd_poll_bit(const struct spi_flash *flash, unsigned long timeout,
204 u8 cmd, u8 poll_bit)
206 const struct spi_slave *spi = &flash->spi;
207 int ret;
208 int attempt = 0;
209 u8 status;
210 struct stopwatch sw;
212 stopwatch_init_msecs_expire(&sw, timeout);
213 do {
214 attempt++;
216 ret = do_spi_flash_cmd(spi, &cmd, 1, &status, 1);
217 if (ret) {
218 printk(BIOS_WARNING,
219 "SF: SPI command failed on attempt %d with rc %d\n", attempt,
220 ret);
221 return -1;
224 if ((status & poll_bit) == 0)
225 return 0;
226 } while (!stopwatch_expired(&sw));
228 printk(BIOS_WARNING, "SF: timeout at %lld msec after %d attempts\n",
229 stopwatch_duration_msecs(&sw), attempt);
231 return -1;
234 int spi_flash_cmd_wait_ready(const struct spi_flash *flash,
235 unsigned long timeout)
237 return spi_flash_cmd_poll_bit(flash, timeout,
238 CMD_READ_STATUS, STATUS_WIP);
241 int spi_flash_cmd_erase(const struct spi_flash *flash, u32 offset, size_t len)
243 u32 start, end, erase_size;
244 int ret = -1;
245 u8 cmd[4 + ADDR_MOD];
247 erase_size = flash->sector_size;
248 if (offset % erase_size || len % erase_size) {
249 printk(BIOS_WARNING, "SF: Erase offset/length not multiple of erase size\n");
250 return -1;
252 if (len == 0) {
253 printk(BIOS_WARNING, "SF: Erase length cannot be 0\n");
254 return -1;
257 cmd[0] = flash->erase_cmd;
258 start = offset;
259 end = start + len;
261 while (offset < end) {
262 spi_flash_addr(offset, cmd);
263 offset += erase_size;
265 if (CONFIG(DEBUG_SPI_FLASH)) {
266 if (ADDR_MOD)
267 printk(BIOS_SPEW, "SF: erase %2x %2x %2x %2x %2x (%x)\n",
268 cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], offset);
269 else
270 printk(BIOS_SPEW, "SF: erase %2x %2x %2x %2x (%x)\n",
271 cmd[0], cmd[1], cmd[2], cmd[3], offset);
274 ret = spi_flash_cmd(&flash->spi, CMD_WRITE_ENABLE, NULL, 0);
275 if (ret)
276 goto out;
278 ret = spi_flash_cmd_write(&flash->spi, cmd, sizeof(cmd), NULL, 0);
279 if (ret)
280 goto out;
282 ret = spi_flash_cmd_wait_ready(flash,
283 SPI_FLASH_PAGE_ERASE_TIMEOUT_MS);
284 if (ret)
285 goto out;
288 printk(BIOS_DEBUG, "SF: Successfully erased %zu bytes @ %#x\n", len, start);
290 out:
291 return ret;
294 int spi_flash_cmd_status(const struct spi_flash *flash, u8 *reg)
296 return spi_flash_cmd(&flash->spi, flash->status_cmd, reg, sizeof(*reg));
299 int spi_flash_cmd_write_page_program(const struct spi_flash *flash, u32 offset,
300 size_t len, const void *buf)
302 unsigned long byte_addr;
303 unsigned long page_size;
304 size_t chunk_len;
305 size_t actual;
306 int ret = 0;
307 u8 cmd[4 + ADDR_MOD];
309 page_size = flash->page_size;
310 cmd[0] = flash->pp_cmd;
312 for (actual = 0; actual < len; actual += chunk_len) {
313 byte_addr = offset % page_size;
314 chunk_len = MIN(len - actual, page_size - byte_addr);
315 chunk_len = spi_crop_chunk(&flash->spi, sizeof(cmd), chunk_len);
317 spi_flash_addr(offset, cmd);
318 if (CONFIG(DEBUG_SPI_FLASH)) {
319 if (ADDR_MOD)
320 printk(BIOS_SPEW,
321 "PP: %p => cmd = { 0x%02x 0x%02x%02x%02x%02x } chunk_len = %zu\n",
322 buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4],
323 chunk_len);
324 else
325 printk(BIOS_SPEW,
326 "PP: %p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
327 buf + actual, cmd[0], cmd[1], cmd[2], cmd[3],
328 chunk_len);
331 ret = spi_flash_cmd(&flash->spi, flash->wren_cmd, NULL, 0);
332 if (ret < 0) {
333 printk(BIOS_WARNING, "SF: Enabling Write failed\n");
334 goto out;
337 ret = spi_flash_cmd_write(&flash->spi, cmd, sizeof(cmd),
338 buf + actual, chunk_len);
339 if (ret < 0) {
340 printk(BIOS_WARNING, "SF: Page Program failed\n");
341 goto out;
344 ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT_MS);
345 if (ret)
346 goto out;
348 offset += chunk_len;
351 if (CONFIG(DEBUG_SPI_FLASH))
352 printk(BIOS_SPEW, "SF: : Successfully programmed %zu bytes @ 0x%lx\n",
353 len, (unsigned long)(offset - len));
354 ret = 0;
356 out:
357 return ret;
360 static const struct spi_flash_vendor_info *spi_flash_vendors[] = {
361 #if CONFIG(SPI_FLASH_ADESTO)
362 &spi_flash_adesto_vi,
363 #endif
364 #if CONFIG(SPI_FLASH_AMIC)
365 &spi_flash_amic_vi,
366 #endif
367 #if CONFIG(SPI_FLASH_ATMEL)
368 &spi_flash_atmel_vi,
369 #endif
370 #if CONFIG(SPI_FLASH_EON)
371 &spi_flash_eon_vi,
372 #endif
373 #if CONFIG(SPI_FLASH_GIGADEVICE)
374 &spi_flash_gigadevice_vi,
375 #endif
376 #if CONFIG(SPI_FLASH_MACRONIX)
377 &spi_flash_macronix_vi,
378 #endif
379 #if CONFIG(SPI_FLASH_SPANSION)
380 &spi_flash_spansion_ext1_vi,
381 &spi_flash_spansion_ext2_vi,
382 &spi_flash_spansion_vi,
383 #endif
384 #if CONFIG(SPI_FLASH_SST)
385 &spi_flash_sst_ai_vi,
386 &spi_flash_sst_vi,
387 #endif
388 #if CONFIG(SPI_FLASH_STMICRO)
389 &spi_flash_stmicro1_vi,
390 &spi_flash_stmicro2_vi,
391 &spi_flash_stmicro3_vi,
392 &spi_flash_stmicro4_vi,
393 #endif
394 #if CONFIG(SPI_FLASH_WINBOND)
395 &spi_flash_winbond_vi,
396 #endif
398 #define IDCODE_LEN 5
400 static int fill_spi_flash(const struct spi_slave *spi, struct spi_flash *flash,
401 const struct spi_flash_vendor_info *vi,
402 const struct spi_flash_part_id *part)
404 memcpy(&flash->spi, spi, sizeof(*spi));
405 flash->vendor = vi->id;
406 flash->model = part->id[0];
408 flash->page_size = 1U << vi->page_size_shift;
409 flash->sector_size = (1U << vi->sector_size_kib_shift) * KiB;
410 flash->size = flash->sector_size * (1U << part->nr_sectors_shift);
411 flash->erase_cmd = vi->desc->erase_cmd;
412 flash->status_cmd = vi->desc->status_cmd;
413 flash->pp_cmd = vi->desc->pp_cmd;
414 flash->wren_cmd = vi->desc->wren_cmd;
416 flash->flags.dual_output = part->fast_read_dual_output_support;
417 flash->flags.dual_io = part->fast_read_dual_io_support;
419 flash->ops = &vi->desc->ops;
420 flash->prot_ops = vi->prot_ops;
421 flash->part = part;
423 if (vi->after_probe)
424 return vi->after_probe(flash);
426 return 0;
429 static const struct spi_flash_part_id *find_part(const struct spi_flash_vendor_info *vi,
430 uint16_t id[2])
432 size_t i;
433 const uint16_t lid[2] = {
434 [0] = id[0] & vi->match_id_mask[0],
435 [1] = id[1] & vi->match_id_mask[1],
438 for (i = 0; i < vi->nr_part_ids; i++) {
439 const struct spi_flash_part_id *part = &vi->ids[i];
441 if (part->id[0] == lid[0] && part->id[1] == lid[1])
442 return part;
445 return NULL;
448 static int find_match(const struct spi_slave *spi, struct spi_flash *flash,
449 uint8_t manuf_id, uint16_t id[2])
451 int i;
453 for (i = 0; i < (int)ARRAY_SIZE(spi_flash_vendors); i++) {
454 const struct spi_flash_vendor_info *vi;
455 const struct spi_flash_part_id *part;
457 vi = spi_flash_vendors[i];
459 if (manuf_id != vi->id)
460 continue;
462 part = find_part(vi, id);
464 if (part == NULL)
465 continue;
467 return fill_spi_flash(spi, flash, vi, part);
470 return -1;
473 int spi_flash_generic_probe(const struct spi_slave *spi,
474 struct spi_flash *flash)
476 int ret, i;
477 u8 idcode[IDCODE_LEN];
478 u8 manuf_id;
479 u16 id[2];
481 /* Read the ID codes */
482 ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode));
483 if (ret)
484 return -1;
486 if (CONFIG(DEBUG_SPI_FLASH)) {
487 printk(BIOS_SPEW, "SF: Got idcode: ");
488 for (i = 0; i < sizeof(idcode); i++)
489 printk(BIOS_SPEW, "%02x ", idcode[i]);
490 printk(BIOS_SPEW, "\n");
493 manuf_id = idcode[0];
495 printk(BIOS_INFO, "Manufacturer: %02x\n", manuf_id);
497 /* If no result from RDID command and STMicro parts are enabled attempt
498 to wake the part from deep sleep and obtain alternative id info. */
499 if (CONFIG(SPI_FLASH_STMICRO) && manuf_id == 0xff) {
500 if (stmicro_release_deep_sleep_identify(spi, idcode))
501 return -1;
502 manuf_id = idcode[0];
505 id[0] = (idcode[1] << 8) | idcode[2];
506 id[1] = (idcode[3] << 8) | idcode[4];
508 return find_match(spi, flash, manuf_id, id);
511 int spi_flash_probe(unsigned int bus, unsigned int cs, struct spi_flash *flash)
513 struct spi_slave spi;
514 int ret = -1;
516 if (spi_setup_slave(bus, cs, &spi)) {
517 printk(BIOS_WARNING, "SF: Failed to set up slave\n");
518 return -1;
521 /* Try special programmer probe if any. */
522 if (spi.ctrlr->flash_probe)
523 ret = spi.ctrlr->flash_probe(&spi, flash);
525 /* If flash is not found, try generic spi flash probe. */
526 if (ret)
527 ret = spi_flash_generic_probe(&spi, flash);
529 /* Give up -- nothing more to try if flash is not found. */
530 if (ret) {
531 printk(BIOS_WARNING, "SF: Unsupported manufacturer!\n");
532 return -1;
535 const char *mode_string = "";
536 if (flash->flags.dual_io && spi.ctrlr->xfer_dual)
537 mode_string = " (Dual I/O mode)";
538 else if (flash->flags.dual_output && spi.ctrlr->xfer_dual)
539 mode_string = " (Dual Output mode)";
540 printk(BIOS_INFO,
541 "SF: Detected %02x %04x with sector size 0x%x, total 0x%x%s\n",
542 flash->vendor, flash->model, flash->sector_size, flash->size, mode_string);
543 if (bus == CONFIG_BOOT_DEVICE_SPI_FLASH_BUS
544 && flash->size != CONFIG_ROM_SIZE) {
545 printk(BIOS_ERR, "SF size 0x%x does not correspond to"
546 " CONFIG_ROM_SIZE 0x%x!!\n", flash->size,
547 CONFIG_ROM_SIZE);
550 if (CONFIG(SPI_FLASH_EXIT_4_BYTE_ADDR_MODE) && ENV_INITIAL_STAGE)
551 spi_flash_cmd(&flash->spi, CMD_EXIT_4BYTE_ADDR_MODE, NULL, 0);
553 return 0;
556 int spi_flash_read(const struct spi_flash *flash, u32 offset, size_t len,
557 void *buf)
559 return flash->ops->read(flash, offset, len, buf);
562 int spi_flash_write(const struct spi_flash *flash, u32 offset, size_t len,
563 const void *buf)
565 int ret;
567 if (spi_flash_volatile_group_begin(flash))
568 return -1;
570 ret = flash->ops->write(flash, offset, len, buf);
572 if (spi_flash_volatile_group_end(flash))
573 return -1;
575 return ret;
578 int spi_flash_erase(const struct spi_flash *flash, u32 offset, size_t len)
580 int ret;
582 if (spi_flash_volatile_group_begin(flash))
583 return -1;
585 ret = flash->ops->erase(flash, offset, len);
587 if (spi_flash_volatile_group_end(flash))
588 return -1;
590 return ret;
593 int spi_flash_status(const struct spi_flash *flash, u8 *reg)
595 if (flash->ops->status)
596 return flash->ops->status(flash, reg);
598 return -1;
601 int spi_flash_is_write_protected(const struct spi_flash *flash,
602 const struct region *region)
604 struct region flash_region = { 0 };
606 if (!flash || !region)
607 return -1;
609 flash_region.size = flash->size;
611 if (!region_is_subregion(&flash_region, region))
612 return -1;
614 if (!flash->prot_ops) {
615 printk(BIOS_WARNING, "SPI: Write-protection gathering not "
616 "implemented for this vendor.\n");
617 return -1;
620 return flash->prot_ops->get_write(flash, region);
623 int spi_flash_set_write_protected(const struct spi_flash *flash,
624 const struct region *region,
625 const enum spi_flash_status_reg_lockdown mode)
627 struct region flash_region = { 0 };
628 int ret;
630 if (!flash)
631 return -1;
633 flash_region.size = flash->size;
635 if (!region_is_subregion(&flash_region, region))
636 return -1;
638 if (!flash->prot_ops) {
639 printk(BIOS_WARNING, "SPI: Setting write-protection is not "
640 "implemented for this vendor.\n");
641 return -1;
644 ret = flash->prot_ops->set_write(flash, region, mode);
646 if (ret == 0 && mode != SPI_WRITE_PROTECTION_PRESERVE) {
647 printk(BIOS_INFO, "SPI: SREG lock-down was set to ");
648 switch (mode) {
649 case SPI_WRITE_PROTECTION_NONE:
650 printk(BIOS_INFO, "NEVER\n");
651 break;
652 case SPI_WRITE_PROTECTION_PIN:
653 printk(BIOS_INFO, "WP\n");
654 break;
655 case SPI_WRITE_PROTECTION_REBOOT:
656 printk(BIOS_INFO, "REBOOT\n");
657 break;
658 case SPI_WRITE_PROTECTION_PERMANENT:
659 printk(BIOS_INFO, "PERMANENT\n");
660 break;
661 default:
662 printk(BIOS_INFO, "UNKNOWN\n");
663 break;
667 return ret;
670 static uint32_t volatile_group_count;
672 int spi_flash_volatile_group_begin(const struct spi_flash *flash)
674 uint32_t count;
675 int ret = 0;
677 if (!CONFIG(SPI_FLASH_HAS_VOLATILE_GROUP))
678 return ret;
680 count = volatile_group_count;
681 if (count == 0)
682 ret = chipset_volatile_group_begin(flash);
684 count++;
685 volatile_group_count = count;
686 return ret;
689 int spi_flash_volatile_group_end(const struct spi_flash *flash)
691 uint32_t count;
692 int ret = 0;
694 if (!CONFIG(SPI_FLASH_HAS_VOLATILE_GROUP))
695 return ret;
697 count = volatile_group_count;
698 assert(count == 0);
699 count--;
700 volatile_group_count = count;
702 if (count == 0)
703 ret = chipset_volatile_group_end(flash);
705 return ret;
708 void lb_spi_flash(struct lb_header *header)
710 struct lb_spi_flash *flash;
711 const struct spi_flash *spi_flash_dev;
713 if (!CONFIG(BOOT_DEVICE_SPI_FLASH))
714 return;
716 flash = (struct lb_spi_flash *)lb_new_record(header);
718 flash->tag = LB_TAG_SPI_FLASH;
719 flash->size = sizeof(*flash);
721 spi_flash_dev = boot_device_spi_flash();
723 if (spi_flash_dev) {
724 flash->flash_size = spi_flash_dev->size;
725 flash->sector_size = spi_flash_dev->sector_size;
726 flash->erase_cmd = spi_flash_dev->erase_cmd;
727 } else {
728 flash->flash_size = CONFIG_ROM_SIZE;
729 /* Default 64k erase command should work on most flash.
730 * Uniform 4k erase only works on certain devices. */
731 flash->sector_size = 64 * KiB;
732 flash->erase_cmd = CMD_BLOCK_ERASE;
735 if (!CONFIG(BOOT_DEVICE_MEMORY_MAPPED)) {
736 flash->mmap_count = 0;
737 } else {
738 struct flash_mmap_window *table = (struct flash_mmap_window *)(flash + 1);
739 flash->mmap_count = spi_flash_get_mmap_windows(table);
740 flash->size += flash->mmap_count * sizeof(*table);
744 int spi_flash_ctrlr_protect_region(const struct spi_flash *flash,
745 const struct region *region,
746 const enum ctrlr_prot_type type)
748 const struct spi_ctrlr *ctrlr;
749 struct region flash_region = { 0 };
751 if (!flash)
752 return -1;
754 flash_region.size = flash->size;
756 if (!region_is_subregion(&flash_region, region))
757 return -1;
759 ctrlr = flash->spi.ctrlr;
761 if (!ctrlr)
762 return -1;
764 if (ctrlr->flash_protect)
765 return ctrlr->flash_protect(flash, region, type);
767 return -1;
770 int spi_flash_vector_helper(const struct spi_slave *slave,
771 struct spi_op vectors[], size_t count,
772 int (*func)(const struct spi_slave *slave, const void *dout,
773 size_t bytesout, void *din, size_t bytesin))
775 int ret;
776 void *din;
777 size_t bytes_in;
779 if (count < 1 || count > 2)
780 return -1;
782 /* SPI flash commands always have a command first... */
783 if (!vectors[0].dout || !vectors[0].bytesout)
784 return -1;
785 /* And not read any data during the command. */
786 if (vectors[0].din || vectors[0].bytesin)
787 return -1;
789 if (count == 2) {
790 /* If response bytes requested ensure the buffer is valid. */
791 if (vectors[1].bytesin && !vectors[1].din)
792 return -1;
793 /* No sends can accompany a receive. */
794 if (vectors[1].dout || vectors[1].bytesout)
795 return -1;
796 din = vectors[1].din;
797 bytes_in = vectors[1].bytesin;
798 } else {
799 din = NULL;
800 bytes_in = 0;
803 ret = func(slave, vectors[0].dout, vectors[0].bytesout, din, bytes_in);
805 if (ret) {
806 vectors[0].status = SPI_OP_FAILURE;
807 if (count == 2)
808 vectors[1].status = SPI_OP_FAILURE;
809 } else {
810 vectors[0].status = SPI_OP_SUCCESS;
811 if (count == 2)
812 vectors[1].status = SPI_OP_SUCCESS;
815 return ret;
818 const struct spi_flash_ops_descriptor spi_flash_pp_0x20_sector_desc = {
819 .erase_cmd = 0x20, /* Sector Erase */
820 .status_cmd = 0x05, /* Read Status */
821 .pp_cmd = 0x02, /* Page Program */
822 .wren_cmd = 0x06, /* Write Enable */
823 .ops = {
824 .read = spi_flash_cmd_read,
825 .write = spi_flash_cmd_write_page_program,
826 .erase = spi_flash_cmd_erase,
827 .status = spi_flash_cmd_status,
831 const struct spi_flash_ops_descriptor spi_flash_pp_0xd8_sector_desc = {
832 .erase_cmd = 0xd8, /* Sector Erase */
833 .status_cmd = 0x05, /* Read Status */
834 .pp_cmd = 0x02, /* Page Program */
835 .wren_cmd = 0x06, /* Write Enable */
836 .ops = {
837 .read = spi_flash_cmd_read,
838 .write = spi_flash_cmd_write_page_program,
839 .erase = spi_flash_cmd_erase,
840 .status = spi_flash_cmd_status,