spi: Add function to read flash status register

Add a function that allows reading of the status register
from the SPI chip.  This can be used to determine whether
write protection is enabled on the chip.

BUG=chrome-os-partner:35209
BRANCH=haswell
TEST=build and boot on peppy

Signed-off-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/240702
Reviewed-by: Shawn N <shawnn@chromium.org>
(cherry picked from commit c58f17689162b291a7cdb57649a237de21b73545)

Change-Id: Ib7fead2cc4ea4339ece322dd18403362c9c79c7d
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: 9fbdf0d72892eef4a742a418a347ecf650c01ea5
Original-Change-Id: I2541b22c51e43f7b7542ee0f48618cf411976a98
Original-Signed-off-by: Duncan Laurie <dlaurie@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/241128
Original-Reviewed-by: Shawn N <shawnn@chromium.org>
Reviewed-on: http://review.coreboot.org/9730
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
Duncan Laurie 2015-01-15 15:28:46 -08:00 committed by Patrick Georgi
parent 1968b58010
commit fb032398d2
9 changed files with 24 additions and 0 deletions

View File

@ -168,11 +168,13 @@ struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode)
eon->flash.write = eon_write; eon->flash.write = eon_write;
eon->flash.erase = spi_flash_cmd_erase; eon->flash.erase = spi_flash_cmd_erase;
eon->flash.status = spi_flash_cmd_status;
eon->flash.read = spi_flash_cmd_read_fast; eon->flash.read = spi_flash_cmd_read_fast;
eon->flash.sector_size = params->page_size * params->pages_per_sector; eon->flash.sector_size = params->page_size * params->pages_per_sector;
eon->flash.size = params->page_size * params->pages_per_sector eon->flash.size = params->page_size * params->pages_per_sector
* params->nr_sectors; * params->nr_sectors;
eon->flash.erase_cmd = CMD_EN25_SE; eon->flash.erase_cmd = CMD_EN25_SE;
eon->flash.status_cmd = CMD_EN25_RDSR;
return &eon->flash; return &eon->flash;
} }

View File

@ -222,6 +222,7 @@ struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode)
stm.flash.write = gigadevice_write; stm.flash.write = gigadevice_write;
stm.flash.erase = spi_flash_cmd_erase; stm.flash.erase = spi_flash_cmd_erase;
stm.flash.status = spi_flash_cmd_status;
#if CONFIG_SPI_FLASH_NO_FAST_READ #if CONFIG_SPI_FLASH_NO_FAST_READ
stm.flash.read = spi_flash_cmd_read_slow; stm.flash.read = spi_flash_cmd_read_slow;
#else #else
@ -233,6 +234,7 @@ struct spi_flash *spi_flash_probe_gigadevice(struct spi_slave *spi, u8 *idcode)
* params->sectors_per_block * params->sectors_per_block
* params->nr_blocks; * params->nr_blocks;
stm.flash.erase_cmd = CMD_GD25_SE; stm.flash.erase_cmd = CMD_GD25_SE;
stm.flash.status_cmd = CMD_GD25_RDSR;
return &stm.flash; return &stm.flash;
} }

View File

@ -242,6 +242,7 @@ struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode)
mcx->flash.write = macronix_write; mcx->flash.write = macronix_write;
mcx->flash.erase = spi_flash_cmd_erase; mcx->flash.erase = spi_flash_cmd_erase;
mcx->flash.status = spi_flash_cmd_status;
#if CONFIG_SPI_FLASH_NO_FAST_READ #if CONFIG_SPI_FLASH_NO_FAST_READ
mcx->flash.read = spi_flash_cmd_read_slow; mcx->flash.read = spi_flash_cmd_read_slow;
#else #else
@ -251,6 +252,7 @@ struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode)
mcx->flash.size = mcx->flash.sector_size * params->sectors_per_block * mcx->flash.size = mcx->flash.sector_size * params->sectors_per_block *
params->nr_blocks; params->nr_blocks;
mcx->flash.erase_cmd = CMD_MX25XX_SE; mcx->flash.erase_cmd = CMD_MX25XX_SE;
mcx->flash.status_cmd = CMD_MX25XX_RDSR;
return &mcx->flash; return &mcx->flash;
} }

View File

@ -297,9 +297,11 @@ struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode)
spsn->flash.write = spansion_write; spsn->flash.write = spansion_write;
spsn->flash.erase = spi_flash_cmd_erase; spsn->flash.erase = spi_flash_cmd_erase;
spsn->flash.read = spi_flash_cmd_read_slow; spsn->flash.read = spi_flash_cmd_read_slow;
spsn->flash.status = spi_flash_cmd_status;
spsn->flash.sector_size = params->page_size * params->pages_per_sector; spsn->flash.sector_size = params->page_size * params->pages_per_sector;
spsn->flash.size = spsn->flash.sector_size * params->nr_sectors; spsn->flash.size = spsn->flash.sector_size * params->nr_sectors;
spsn->flash.erase_cmd = CMD_S25FLXX_SE; spsn->flash.erase_cmd = CMD_S25FLXX_SE;
spsn->flash.status_cmd = CMD_S25FLXX_RDSR;
return &spsn->flash; return &spsn->flash;
} }

View File

@ -234,6 +234,11 @@ out:
return ret; return ret;
} }
int spi_flash_cmd_status(struct spi_flash *flash, u8 *reg)
{
return spi_flash_cmd(flash->spi, flash->status_cmd, reg, sizeof(*reg));
}
/* /*
* The following table holds all device probe functions * The following table holds all device probe functions
* *
@ -372,6 +377,7 @@ flash_detected:
tseg_relocate((void **)&flash->read); tseg_relocate((void **)&flash->read);
tseg_relocate((void **)&flash->write); tseg_relocate((void **)&flash->write);
tseg_relocate((void **)&flash->erase); tseg_relocate((void **)&flash->erase);
tseg_relocate((void **)&flash->status);
tseg_relocate((void **)&flash->name); tseg_relocate((void **)&flash->name);
#endif #endif

View File

@ -60,6 +60,9 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout);
/* Erase sectors. */ /* Erase sectors. */
int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len); int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len);
/* Read status register. */
int spi_flash_cmd_status(struct spi_flash *flash, u8 *reg);
/* Manufacturer-specific probe functions */ /* Manufacturer-specific probe functions */
struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode); struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode);
struct spi_flash *spi_flash_probe_amic(struct spi_slave *spi, u8 *idcode); struct spi_flash *spi_flash_probe_amic(struct spi_slave *spi, u8 *idcode);

View File

@ -259,10 +259,12 @@ spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode)
stm->flash.write = sst_write; stm->flash.write = sst_write;
stm->flash.erase = spi_flash_cmd_erase; stm->flash.erase = spi_flash_cmd_erase;
stm->flash.status = spi_flash_cmd_status;
stm->flash.read = spi_flash_cmd_read_fast; stm->flash.read = spi_flash_cmd_read_fast;
stm->flash.sector_size = SST_SECTOR_SIZE; stm->flash.sector_size = SST_SECTOR_SIZE;
stm->flash.size = stm->flash.sector_size * params->nr_sectors; stm->flash.size = stm->flash.sector_size * params->nr_sectors;
stm->flash.erase_cmd = CMD_SST_SE; stm->flash.erase_cmd = CMD_SST_SE;
stm->flash.status_cmd = CMD_SST_RDSR;
/* Flash powers up read-only, so clear BP# bits */ /* Flash powers up read-only, so clear BP# bits */
sst_unlock(&stm->flash); sst_unlock(&stm->flash);

View File

@ -218,6 +218,7 @@ struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)
stm.flash.write = winbond_write; stm.flash.write = winbond_write;
stm.flash.erase = spi_flash_cmd_erase; stm.flash.erase = spi_flash_cmd_erase;
stm.flash.status = spi_flash_cmd_status;
#if CONFIG_SPI_FLASH_NO_FAST_READ #if CONFIG_SPI_FLASH_NO_FAST_READ
stm.flash.read = spi_flash_cmd_read_slow; stm.flash.read = spi_flash_cmd_read_slow;
#else #else
@ -229,6 +230,7 @@ struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode)
* params->sectors_per_block * params->sectors_per_block
* params->nr_blocks; * params->nr_blocks;
stm.flash.erase_cmd = CMD_W25_SE; stm.flash.erase_cmd = CMD_W25_SE;
stm.flash.status_cmd = CMD_W25_RDSR;
return &stm.flash; return &stm.flash;
} }

View File

@ -40,12 +40,15 @@ struct spi_flash {
u8 erase_cmd; u8 erase_cmd;
u8 status_cmd;
int (*read)(struct spi_flash *flash, u32 offset, int (*read)(struct spi_flash *flash, u32 offset,
size_t len, void *buf); size_t len, void *buf);
int (*write)(struct spi_flash *flash, u32 offset, int (*write)(struct spi_flash *flash, u32 offset,
size_t len, const void *buf); size_t len, const void *buf);
int (*erase)(struct spi_flash *flash, u32 offset, int (*erase)(struct spi_flash *flash, u32 offset,
size_t len); size_t len);
int (*status)(struct spi_flash *flash, u8 *reg);
}; };
struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs); struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs);