drivers/spi: Add SPI_FLASH_FORCE_4_BYTE_ADDR_MODE

Add Kconfig option to force 4-byte addressing mode.

Some platforms require the flash to stay in 4-byte addressing mode where
it expects 4-byte addresses on regular commands.

Signed-off-by: Fred Reitberger <reitbergerfred@gmail.com>
Change-Id: I2e41da2a78285c23c1c1d97eaf3969749812327b
Reviewed-on: https://review.coreboot.org/c/coreboot/+/73860
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Matt DeVillier <matt.devillier@amd.corp-partner.google.com>
Reviewed-by: Martin L Roth <gaumless@gmail.com>
This commit is contained in:
Fred Reitberger 2023-03-21 15:37:06 -04:00 committed by Lean Sheng Tan
parent 75e720bf02
commit 52be7f6b10
2 changed files with 50 additions and 18 deletions

View File

@ -173,6 +173,14 @@ config SPI_FLASH_EXIT_4_BYTE_ADDR_MODE
On flashes that don't support 4-byte addressing mode or where it is already On flashes that don't support 4-byte addressing mode or where it is already
disabled, this command should be a no-op. disabled, this command should be a no-op.
config SPI_FLASH_FORCE_4_BYTE_ADDR_MODE
bool
default n
help
This will force coreboot to send addresses as 4-bytes instead of 3-bytes.
On some platforms with SPI flashes larger than 16MB, the SPI flash may need
to remain in 4-byte addressing mode.
endif # SPI_FLASH endif # SPI_FLASH
config HAVE_EM100PRO_SPI_CONSOLE_SUPPORT config HAVE_EM100PRO_SPI_CONSOLE_SUPPORT

View File

@ -12,12 +12,25 @@
#include "spi_flash_internal.h" #include "spi_flash_internal.h"
#if CONFIG(SPI_FLASH_FORCE_4_BYTE_ADDR_MODE)
#define ADDR_MOD 1
#else
#define ADDR_MOD 0
#endif
static void spi_flash_addr(u32 addr, u8 *cmd) static void spi_flash_addr(u32 addr, u8 *cmd)
{ {
/* cmd[0] is actual command */ /* cmd[0] is actual command */
if (CONFIG(SPI_FLASH_FORCE_4_BYTE_ADDR_MODE)) {
cmd[1] = addr >> 24;
cmd[2] = addr >> 16;
cmd[3] = addr >> 8;
cmd[4] = addr >> 0;
} else {
cmd[1] = addr >> 16; cmd[1] = addr >> 16;
cmd[2] = addr >> 8; cmd[2] = addr >> 8;
cmd[3] = addr >> 0; cmd[3] = addr >> 0;
}
} }
static int do_spi_flash_cmd(const struct spi_slave *spi, const u8 *dout, static int do_spi_flash_cmd(const struct spi_slave *spi, const u8 *dout,
@ -142,29 +155,29 @@ int spi_flash_cmd_write(const struct spi_slave *spi, const u8 *cmd,
int spi_flash_cmd_read(const struct spi_flash *flash, u32 offset, int spi_flash_cmd_read(const struct spi_flash *flash, u32 offset,
size_t len, void *buf) size_t len, void *buf)
{ {
u8 cmd[5]; u8 cmd[5 + ADDR_MOD];
int ret, cmd_len; int ret, cmd_len;
int (*do_cmd)(const struct spi_slave *spi, const u8 *din, int (*do_cmd)(const struct spi_slave *spi, const u8 *din,
size_t in_bytes, void *out, size_t out_bytes); size_t in_bytes, void *out, size_t out_bytes);
if (CONFIG(SPI_FLASH_NO_FAST_READ)) { if (CONFIG(SPI_FLASH_NO_FAST_READ)) {
cmd_len = 4; cmd_len = 4 + ADDR_MOD;
cmd[0] = CMD_READ_ARRAY_SLOW; cmd[0] = CMD_READ_ARRAY_SLOW;
do_cmd = do_spi_flash_cmd; do_cmd = do_spi_flash_cmd;
} else if (flash->flags.dual_io && flash->spi.ctrlr->xfer_dual) { } else if (flash->flags.dual_io && flash->spi.ctrlr->xfer_dual) {
cmd_len = 5; cmd_len = 5 + ADDR_MOD;
cmd[0] = CMD_READ_FAST_DUAL_IO; cmd[0] = CMD_READ_FAST_DUAL_IO;
cmd[4] = 0; cmd[4 + ADDR_MOD] = 0;
do_cmd = do_dual_io_cmd; do_cmd = do_dual_io_cmd;
} else if (flash->flags.dual_output && flash->spi.ctrlr->xfer_dual) { } else if (flash->flags.dual_output && flash->spi.ctrlr->xfer_dual) {
cmd_len = 5; cmd_len = 5 + ADDR_MOD;
cmd[0] = CMD_READ_FAST_DUAL_OUTPUT; cmd[0] = CMD_READ_FAST_DUAL_OUTPUT;
cmd[4] = 0; cmd[4 + ADDR_MOD] = 0;
do_cmd = do_dual_output_cmd; do_cmd = do_dual_output_cmd;
} else { } else {
cmd_len = 5; cmd_len = 5 + ADDR_MOD;
cmd[0] = CMD_READ_ARRAY_FAST; cmd[0] = CMD_READ_ARRAY_FAST;
cmd[4] = 0; cmd[4 + ADDR_MOD] = 0;
do_cmd = do_spi_flash_cmd; do_cmd = do_spi_flash_cmd;
} }
@ -229,7 +242,7 @@ int spi_flash_cmd_erase(const struct spi_flash *flash, u32 offset, size_t len)
{ {
u32 start, end, erase_size; u32 start, end, erase_size;
int ret = -1; int ret = -1;
u8 cmd[4]; u8 cmd[4 + ADDR_MOD];
erase_size = flash->sector_size; erase_size = flash->sector_size;
if (offset % erase_size || len % erase_size) { if (offset % erase_size || len % erase_size) {
@ -250,8 +263,12 @@ int spi_flash_cmd_erase(const struct spi_flash *flash, u32 offset, size_t len)
offset += erase_size; offset += erase_size;
#if CONFIG(DEBUG_SPI_FLASH) #if CONFIG(DEBUG_SPI_FLASH)
printk(BIOS_SPEW, "SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], if (ADDR_MOD)
cmd[2], cmd[3], offset); printk(BIOS_SPEW, "SF: erase %2x %2x %2x %2x %2x (%x)\n",
cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], offset);
else
printk(BIOS_SPEW, "SF: erase %2x %2x %2x %2x (%x)\n",
cmd[0], cmd[1], cmd[2], cmd[3], offset);
#endif #endif
ret = spi_flash_cmd(&flash->spi, CMD_WRITE_ENABLE, NULL, 0); ret = spi_flash_cmd(&flash->spi, CMD_WRITE_ENABLE, NULL, 0);
if (ret) if (ret)
@ -286,7 +303,7 @@ int spi_flash_cmd_write_page_program(const struct spi_flash *flash, u32 offset,
size_t chunk_len; size_t chunk_len;
size_t actual; size_t actual;
int ret = 0; int ret = 0;
u8 cmd[4]; u8 cmd[4 + ADDR_MOD];
page_size = flash->page_size; page_size = flash->page_size;
cmd[0] = flash->pp_cmd; cmd[0] = flash->pp_cmd;
@ -298,7 +315,14 @@ int spi_flash_cmd_write_page_program(const struct spi_flash *flash, u32 offset,
spi_flash_addr(offset, cmd); spi_flash_addr(offset, cmd);
if (CONFIG(DEBUG_SPI_FLASH)) { if (CONFIG(DEBUG_SPI_FLASH)) {
printk(BIOS_SPEW, "PP: %p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n", if (ADDR_MOD)
printk(BIOS_SPEW,
"PP: %p => cmd = { 0x%02x 0x%02x%02x%02x%02x } chunk_len = %zu\n",
buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4],
chunk_len);
else
printk(BIOS_SPEW,
"PP: %p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n",
buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], buf + actual, cmd[0], cmd[1], cmd[2], cmd[3],
chunk_len); chunk_len);
} }