1 /* SPDX-License-Identifier: GPL-2.0-or-later */
4 #include <boot/coreboot_tables.h>
5 #include <commonlib/region.h>
6 #include <console/console.h>
8 #include <spi-generic.h>
13 #include "spi_flash_internal.h"
15 #if CONFIG(SPI_FLASH_FORCE_4_BYTE_ADDR_MODE)
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
)) {
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
)
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
);
57 ret
= spi_claim_bus(spi
);
61 ret
= spi_xfer_vector(spi
, vectors
, count
);
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
)
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
79 struct spi_op vector
= { .dout
= dout
, .bytesout
= bytes_out
,
80 .din
= NULL
, .bytesin
= 0 };
82 ret
= spi_claim_bus(spi
);
86 ret
= spi_xfer_vector(spi
, &vector
, 1);
89 ret
= spi
->ctrlr
->xfer_dual(spi
, NULL
, 0, din
, bytes_in
);
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
)
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
);
108 ret
= spi_xfer_vector(spi
, &vector
, 1);
111 ret
= spi
->ctrlr
->xfer_dual(spi
, &dout
[1], bytes_out
- 1, NULL
, 0);
114 ret
= spi
->ctrlr
->xfer_dual(spi
, NULL
, 0, din
, bytes_in
);
116 spi_release_bus(spi
);
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
);
124 printk(BIOS_WARNING
, "SF: Failed to send command %02x: %d\n", cmd
, 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="
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
)
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);
145 printk(BIOS_WARNING
, "SF: Failed to send write command (%zu bytes): %d\n",
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
];
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
;
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
;
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
);
191 "SF: Failed to send read command %#.2x(%#x, %#zx): %d\n",
192 cmd
[0], offset
, xfer_len
, ret
);
203 int spi_flash_cmd_poll_bit(const struct spi_flash
*flash
, unsigned long timeout
,
206 const struct spi_slave
*spi
= &flash
->spi
;
212 stopwatch_init_msecs_expire(&sw
, timeout
);
216 ret
= do_spi_flash_cmd(spi
, &cmd
, 1, &status
, 1);
219 "SF: SPI command failed on attempt %d with rc %d\n", attempt
,
224 if ((status
& poll_bit
) == 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
);
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
;
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");
253 printk(BIOS_WARNING
, "SF: Erase length cannot be 0\n");
257 cmd
[0] = flash
->erase_cmd
;
261 while (offset
< end
) {
262 spi_flash_addr(offset
, cmd
);
263 offset
+= erase_size
;
265 if (CONFIG(DEBUG_SPI_FLASH
)) {
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
);
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);
278 ret
= spi_flash_cmd_write(&flash
->spi
, cmd
, sizeof(cmd
), NULL
, 0);
282 ret
= spi_flash_cmd_wait_ready(flash
,
283 SPI_FLASH_PAGE_ERASE_TIMEOUT_MS
);
288 printk(BIOS_DEBUG
, "SF: Successfully erased %zu bytes @ %#x\n", len
, start
);
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
;
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
)) {
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],
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],
331 ret
= spi_flash_cmd(&flash
->spi
, flash
->wren_cmd
, NULL
, 0);
333 printk(BIOS_WARNING
, "SF: Enabling Write failed\n");
337 ret
= spi_flash_cmd_write(&flash
->spi
, cmd
, sizeof(cmd
),
338 buf
+ actual
, chunk_len
);
340 printk(BIOS_WARNING
, "SF: Page Program failed\n");
344 ret
= spi_flash_cmd_wait_ready(flash
, SPI_FLASH_PROG_TIMEOUT_MS
);
351 if (CONFIG(DEBUG_SPI_FLASH
))
352 printk(BIOS_SPEW
, "SF: : Successfully programmed %zu bytes @ 0x%lx\n",
353 len
, (unsigned long)(offset
- len
));
360 static const struct spi_flash_vendor_info
*spi_flash_vendors
[] = {
361 #if CONFIG(SPI_FLASH_ADESTO)
362 &spi_flash_adesto_vi
,
364 #if CONFIG(SPI_FLASH_AMIC)
367 #if CONFIG(SPI_FLASH_ATMEL)
370 #if CONFIG(SPI_FLASH_EON)
373 #if CONFIG(SPI_FLASH_GIGADEVICE)
374 &spi_flash_gigadevice_vi
,
376 #if CONFIG(SPI_FLASH_MACRONIX)
377 &spi_flash_macronix_vi
,
379 #if CONFIG(SPI_FLASH_SPANSION)
380 &spi_flash_spansion_ext1_vi
,
381 &spi_flash_spansion_ext2_vi
,
382 &spi_flash_spansion_vi
,
384 #if CONFIG(SPI_FLASH_SST)
385 &spi_flash_sst_ai_vi
,
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
,
394 #if CONFIG(SPI_FLASH_WINBOND)
395 &spi_flash_winbond_vi
,
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
;
424 return vi
->after_probe(flash
);
429 static const struct spi_flash_part_id
*find_part(const struct spi_flash_vendor_info
*vi
,
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])
448 static int find_match(const struct spi_slave
*spi
, struct spi_flash
*flash
,
449 uint8_t manuf_id
, uint16_t id
[2])
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
)
462 part
= find_part(vi
, id
);
467 return fill_spi_flash(spi
, flash
, vi
, part
);
473 int spi_flash_generic_probe(const struct spi_slave
*spi
,
474 struct spi_flash
*flash
)
477 u8 idcode
[IDCODE_LEN
];
481 /* Read the ID codes */
482 ret
= spi_flash_cmd(spi
, CMD_READ_ID
, idcode
, sizeof(idcode
));
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
))
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
;
516 if (spi_setup_slave(bus
, cs
, &spi
)) {
517 printk(BIOS_WARNING
, "SF: Failed to set up slave\n");
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. */
527 ret
= spi_flash_generic_probe(&spi
, flash
);
529 /* Give up -- nothing more to try if flash is not found. */
531 printk(BIOS_WARNING
, "SF: Unsupported manufacturer!\n");
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)";
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
,
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);
556 int spi_flash_read(const struct spi_flash
*flash
, u32 offset
, size_t len
,
559 return flash
->ops
->read(flash
, offset
, len
, buf
);
562 int spi_flash_write(const struct spi_flash
*flash
, u32 offset
, size_t len
,
567 if (spi_flash_volatile_group_begin(flash
))
570 ret
= flash
->ops
->write(flash
, offset
, len
, buf
);
572 if (spi_flash_volatile_group_end(flash
))
578 int spi_flash_erase(const struct spi_flash
*flash
, u32 offset
, size_t len
)
582 if (spi_flash_volatile_group_begin(flash
))
585 ret
= flash
->ops
->erase(flash
, offset
, len
);
587 if (spi_flash_volatile_group_end(flash
))
593 int spi_flash_status(const struct spi_flash
*flash
, u8
*reg
)
595 if (flash
->ops
->status
)
596 return flash
->ops
->status(flash
, reg
);
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
)
609 flash_region
.size
= flash
->size
;
611 if (!region_is_subregion(&flash_region
, region
))
614 if (!flash
->prot_ops
) {
615 printk(BIOS_WARNING
, "SPI: Write-protection gathering not "
616 "implemented for this vendor.\n");
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 };
633 flash_region
.size
= flash
->size
;
635 if (!region_is_subregion(&flash_region
, region
))
638 if (!flash
->prot_ops
) {
639 printk(BIOS_WARNING
, "SPI: Setting write-protection is not "
640 "implemented for this vendor.\n");
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 ");
649 case SPI_WRITE_PROTECTION_NONE
:
650 printk(BIOS_INFO
, "NEVER\n");
652 case SPI_WRITE_PROTECTION_PIN
:
653 printk(BIOS_INFO
, "WP\n");
655 case SPI_WRITE_PROTECTION_REBOOT
:
656 printk(BIOS_INFO
, "REBOOT\n");
658 case SPI_WRITE_PROTECTION_PERMANENT
:
659 printk(BIOS_INFO
, "PERMANENT\n");
662 printk(BIOS_INFO
, "UNKNOWN\n");
670 static uint32_t volatile_group_count
;
672 int spi_flash_volatile_group_begin(const struct spi_flash
*flash
)
677 if (!CONFIG(SPI_FLASH_HAS_VOLATILE_GROUP
))
680 count
= volatile_group_count
;
682 ret
= chipset_volatile_group_begin(flash
);
685 volatile_group_count
= count
;
689 int spi_flash_volatile_group_end(const struct spi_flash
*flash
)
694 if (!CONFIG(SPI_FLASH_HAS_VOLATILE_GROUP
))
697 count
= volatile_group_count
;
700 volatile_group_count
= count
;
703 ret
= chipset_volatile_group_end(flash
);
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
))
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();
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
;
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;
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 };
754 flash_region
.size
= flash
->size
;
756 if (!region_is_subregion(&flash_region
, region
))
759 ctrlr
= flash
->spi
.ctrlr
;
764 if (ctrlr
->flash_protect
)
765 return ctrlr
->flash_protect(flash
, region
, type
);
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
))
779 if (count
< 1 || count
> 2)
782 /* SPI flash commands always have a command first... */
783 if (!vectors
[0].dout
|| !vectors
[0].bytesout
)
785 /* And not read any data during the command. */
786 if (vectors
[0].din
|| vectors
[0].bytesin
)
790 /* If response bytes requested ensure the buffer is valid. */
791 if (vectors
[1].bytesin
&& !vectors
[1].din
)
793 /* No sends can accompany a receive. */
794 if (vectors
[1].dout
|| vectors
[1].bytesout
)
796 din
= vectors
[1].din
;
797 bytes_in
= vectors
[1].bytesin
;
803 ret
= func(slave
, vectors
[0].dout
, vectors
[0].bytesout
, din
, bytes_in
);
806 vectors
[0].status
= SPI_OP_FAILURE
;
808 vectors
[1].status
= SPI_OP_FAILURE
;
810 vectors
[0].status
= SPI_OP_SUCCESS
;
812 vectors
[1].status
= SPI_OP_SUCCESS
;
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 */
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 */
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
,