mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-27 15:12:36 +02:00
spi25: Introduce spi_simple_write_cmd()
spi_simple_write_cmd() executes WREN plus a single byte write and polls WIP afterwards. It's used to replace current spi_erase_chip_*() imple- mentations. Change-Id: Ib244356fa471e15863b52e6037899d19113cb4a9 Signed-off-by: Nico Huber <nico.h@gmx.de> Reviewed-on: https://review.coreboot.org/22382 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: David Hendricks <david.hendricks@gmail.com>
This commit is contained in:
parent
c880173472
commit
a3140d0b18
1
flash.h
1
flash.h
@ -369,6 +369,7 @@ struct spi_command {
|
|||||||
const unsigned char *writearr;
|
const unsigned char *writearr;
|
||||||
unsigned char *readarr;
|
unsigned char *readarr;
|
||||||
};
|
};
|
||||||
|
#define NULL_SPI_CMD { 0, 0, NULL, NULL, }
|
||||||
int spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr);
|
int spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr);
|
||||||
int spi_send_multicommand(struct flashctx *flash, struct spi_command *cmds);
|
int spi_send_multicommand(struct flashctx *flash, struct spi_command *cmds);
|
||||||
uint32_t spi_get_valid_read_addr(struct flashctx *flash);
|
uint32_t spi_get_valid_read_addr(struct flashctx *flash);
|
||||||
|
133
spi25.c
133
spi25.c
@ -22,6 +22,7 @@
|
|||||||
* Contains the common SPI chip driver functions
|
* Contains the common SPI chip driver functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
#include "flashchips.h"
|
#include "flashchips.h"
|
||||||
@ -322,114 +323,56 @@ int probe_spi_at25f(struct flashctx *flash)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int spi_chip_erase_60(struct flashctx *flash)
|
/**
|
||||||
|
* Execute WREN plus another one byte `op`, optionally poll WIP afterwards.
|
||||||
|
*
|
||||||
|
* @param flash the flash chip's context
|
||||||
|
* @param op the operation to execute
|
||||||
|
* @param poll_delay interval in us for polling WIP, don't poll if zero
|
||||||
|
* @return 0 on success, non-zero otherwise
|
||||||
|
*/
|
||||||
|
static int spi_simple_write_cmd(struct flashctx *const flash, const uint8_t op, const unsigned int poll_delay)
|
||||||
{
|
{
|
||||||
int result;
|
|
||||||
struct spi_command cmds[] = {
|
struct spi_command cmds[] = {
|
||||||
{
|
{
|
||||||
.writecnt = JEDEC_WREN_OUTSIZE,
|
.writecnt = 1,
|
||||||
.writearr = (const unsigned char[]){ JEDEC_WREN },
|
.writearr = (const unsigned char[]){ JEDEC_WREN },
|
||||||
.readcnt = 0,
|
|
||||||
.readarr = NULL,
|
|
||||||
}, {
|
}, {
|
||||||
.writecnt = JEDEC_CE_60_OUTSIZE,
|
.writecnt = 1,
|
||||||
.writearr = (const unsigned char[]){ JEDEC_CE_60 },
|
.writearr = (const unsigned char[]){ op },
|
||||||
.readcnt = 0,
|
},
|
||||||
.readarr = NULL,
|
NULL_SPI_CMD,
|
||||||
}, {
|
};
|
||||||
.writecnt = 0,
|
|
||||||
.writearr = NULL,
|
const int result = spi_send_multicommand(flash, cmds);
|
||||||
.readcnt = 0,
|
if (result)
|
||||||
.readarr = NULL,
|
msg_cerr("%s failed during command execution\n", __func__);
|
||||||
}};
|
|
||||||
|
/* FIXME: We can't tell if spi_read_status_register() failed. */
|
||||||
result = spi_send_multicommand(flash, cmds);
|
/* FIXME: We don't time out. */
|
||||||
if (result) {
|
while (poll_delay && spi_read_status_register(flash) & SPI_SR_WIP)
|
||||||
msg_cerr("%s failed during command execution\n",
|
programmer_delay(poll_delay);
|
||||||
__func__);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
/* Wait until the Write-In-Progress bit is cleared.
|
|
||||||
* This usually takes 1-85 s, so wait in 1 s steps.
|
|
||||||
*/
|
|
||||||
/* FIXME: We assume spi_read_status_register will never fail. */
|
|
||||||
while (spi_read_status_register(flash) & SPI_SR_WIP)
|
|
||||||
programmer_delay(1000 * 1000);
|
|
||||||
/* FIXME: Check the status register for errors. */
|
/* FIXME: Check the status register for errors. */
|
||||||
return 0;
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int spi_chip_erase_60(struct flashctx *flash)
|
||||||
|
{
|
||||||
|
/* This usually takes 1-85s, so wait in 1s steps. */
|
||||||
|
return spi_simple_write_cmd(flash, 0x60, 1000 * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
int spi_chip_erase_62(struct flashctx *flash)
|
int spi_chip_erase_62(struct flashctx *flash)
|
||||||
{
|
{
|
||||||
int result;
|
/* This usually takes 2-5s, so wait in 100ms steps. */
|
||||||
struct spi_command cmds[] = {
|
return spi_simple_write_cmd(flash, 0x62, 100 * 1000);
|
||||||
{
|
|
||||||
.writecnt = JEDEC_WREN_OUTSIZE,
|
|
||||||
.writearr = (const unsigned char[]){ JEDEC_WREN },
|
|
||||||
.readcnt = 0,
|
|
||||||
.readarr = NULL,
|
|
||||||
}, {
|
|
||||||
.writecnt = JEDEC_CE_62_OUTSIZE,
|
|
||||||
.writearr = (const unsigned char[]){ JEDEC_CE_62 },
|
|
||||||
.readcnt = 0,
|
|
||||||
.readarr = NULL,
|
|
||||||
}, {
|
|
||||||
.writecnt = 0,
|
|
||||||
.writearr = NULL,
|
|
||||||
.readcnt = 0,
|
|
||||||
.readarr = NULL,
|
|
||||||
}};
|
|
||||||
|
|
||||||
result = spi_send_multicommand(flash, cmds);
|
|
||||||
if (result) {
|
|
||||||
msg_cerr("%s failed during command execution\n",
|
|
||||||
__func__);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
/* Wait until the Write-In-Progress bit is cleared.
|
|
||||||
* This usually takes 2-5 s, so wait in 100 ms steps.
|
|
||||||
*/
|
|
||||||
/* FIXME: We assume spi_read_status_register will never fail. */
|
|
||||||
while (spi_read_status_register(flash) & SPI_SR_WIP)
|
|
||||||
programmer_delay(100 * 1000);
|
|
||||||
/* FIXME: Check the status register for errors. */
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int spi_chip_erase_c7(struct flashctx *flash)
|
int spi_chip_erase_c7(struct flashctx *flash)
|
||||||
{
|
{
|
||||||
int result;
|
/* This usually takes 1-85s, so wait in 1s steps. */
|
||||||
struct spi_command cmds[] = {
|
return spi_simple_write_cmd(flash, 0xc7, 1000 * 1000);
|
||||||
{
|
|
||||||
.writecnt = JEDEC_WREN_OUTSIZE,
|
|
||||||
.writearr = (const unsigned char[]){ JEDEC_WREN },
|
|
||||||
.readcnt = 0,
|
|
||||||
.readarr = NULL,
|
|
||||||
}, {
|
|
||||||
.writecnt = JEDEC_CE_C7_OUTSIZE,
|
|
||||||
.writearr = (const unsigned char[]){ JEDEC_CE_C7 },
|
|
||||||
.readcnt = 0,
|
|
||||||
.readarr = NULL,
|
|
||||||
}, {
|
|
||||||
.writecnt = 0,
|
|
||||||
.writearr = NULL,
|
|
||||||
.readcnt = 0,
|
|
||||||
.readarr = NULL,
|
|
||||||
}};
|
|
||||||
|
|
||||||
result = spi_send_multicommand(flash, cmds);
|
|
||||||
if (result) {
|
|
||||||
msg_cerr("%s failed during command execution\n", __func__);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
/* Wait until the Write-In-Progress bit is cleared.
|
|
||||||
* This usually takes 1-85 s, so wait in 1 s steps.
|
|
||||||
*/
|
|
||||||
/* FIXME: We assume spi_read_status_register will never fail. */
|
|
||||||
while (spi_read_status_register(flash) & SPI_SR_WIP)
|
|
||||||
programmer_delay(1000 * 1000);
|
|
||||||
/* FIXME: Check the status register for errors. */
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int spi_block_erase_52(struct flashctx *flash, unsigned int addr,
|
int spi_block_erase_52(struct flashctx *flash, unsigned int addr,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user