1
0
mirror of https://review.coreboot.org/flashrom.git synced 2025-04-27 23:22:37 +02:00

spi25: Merge remainder of spi4ba in

Change-Id: If581e24347e45cbb27002ea99ffd70e334c110cf
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.coreboot.org/22388
Reviewed-by: David Hendricks <david.hendricks@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Nico Huber 2017-10-14 18:56:50 +02:00
parent 0ee2dc0683
commit 7e3c81ae71
7 changed files with 119 additions and 466 deletions

View File

@ -519,7 +519,7 @@ endif
CHIP_OBJS = jedec.o stm50.o w39.o w29ee011.o \ CHIP_OBJS = jedec.o stm50.o w39.o w29ee011.o \
sst28sf040.o 82802ab.o \ sst28sf040.o 82802ab.o \
sst49lfxxxc.o sst_fwhub.o flashchips.o spi.o spi25.o spi25_statusreg.o \ sst49lfxxxc.o sst_fwhub.o flashchips.o spi.o spi25.o spi25_statusreg.o \
spi4ba.o opaque.o sfdp.o en29lv640b.o at45db.o opaque.o sfdp.o en29lv640b.o at45db.o
############################################################################### ###############################################################################
# Library code. # Library code.

View File

@ -43,8 +43,10 @@ int probe_spi_at25f(struct flashctx *flash);
int spi_write_enable(struct flashctx *flash); int spi_write_enable(struct flashctx *flash);
int spi_write_disable(struct flashctx *flash); int spi_write_disable(struct flashctx *flash);
int spi_block_erase_20(struct flashctx *flash, unsigned int addr, unsigned int blocklen); int spi_block_erase_20(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_21(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_50(struct flashctx *flash, unsigned int addr, unsigned int blocklen); int spi_block_erase_50(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_52(struct flashctx *flash, unsigned int addr, unsigned int blocklen); int spi_block_erase_52(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_5c(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_60(struct flashctx *flash, unsigned int addr, unsigned int blocklen); int spi_block_erase_60(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_62(struct flashctx *flash, unsigned int addr, unsigned int blocklen); int spi_block_erase_62(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_81(struct flashctx *flash, unsigned int addr, unsigned int blocklen); int spi_block_erase_81(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
@ -53,11 +55,17 @@ int spi_block_erase_c7(struct flashctx *flash, unsigned int addr, unsigned int b
int spi_block_erase_d7(struct flashctx *flash, unsigned int addr, unsigned int blocklen); int spi_block_erase_d7(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_d8(struct flashctx *flash, unsigned int addr, unsigned int blocklen); int spi_block_erase_d8(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_db(struct flashctx *flash, unsigned int addr, unsigned int blocklen); int spi_block_erase_db(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_dc(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode); erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode);
int spi_chip_write_1(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len); int spi_chip_write_1(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
int spi_nbyte_read(struct flashctx *flash, unsigned int addr, uint8_t *bytes, unsigned int len); int spi_nbyte_read(struct flashctx *flash, unsigned int addr, uint8_t *bytes, unsigned int len);
int spi_read_chunked(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize); int spi_read_chunked(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize);
int spi_write_chunked(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize); int spi_write_chunked(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize);
int spi_enter_4ba_b7(struct flashctx *flash);
int spi_enter_4ba_b7_we(struct flashctx *flash);
int spi_exit_4ba_e9(struct flashctx *flash);
int spi_exit_4ba_e9_we(struct flashctx *flash);
/* spi25_statusreg.c */ /* spi25_statusreg.c */
uint8_t spi_read_status_register(struct flashctx *flash); uint8_t spi_read_status_register(struct flashctx *flash);
@ -193,28 +201,4 @@ int erase_sector_stm50(struct flashctx *flash, unsigned int block, unsigned int
int probe_en29lv640b(struct flashctx *flash); int probe_en29lv640b(struct flashctx *flash);
int write_en29lv640b(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len); int write_en29lv640b(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
/* spi4ba.c */
int spi_enter_4ba_b7(struct flashctx *flash);
int spi_enter_4ba_b7_we(struct flashctx *flash);
int spi_exit_4ba_e9(struct flashctx *flash);
int spi_exit_4ba_e9_we(struct flashctx *flash);
int spi_byte_program_4ba(struct flashctx *flash, unsigned int addr, uint8_t databyte);
int spi_nbyte_program_4ba(struct flashctx *flash, unsigned int addr, const uint8_t *bytes, unsigned int len);
int spi_nbyte_read_4ba(struct flashctx *flash, unsigned int addr, uint8_t *bytes, unsigned int len);
int spi_block_erase_20_4ba(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_52_4ba(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_d8_4ba(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_byte_program_4ba_ereg(struct flashctx *flash, unsigned int addr, uint8_t databyte);
int spi_nbyte_program_4ba_ereg(struct flashctx *flash, unsigned int addr, const uint8_t *bytes, unsigned int len);
int spi_nbyte_read_4ba_ereg(struct flashctx *flash, unsigned int addr, uint8_t *bytes, unsigned int len);
int spi_block_erase_20_4ba_ereg(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_52_4ba_ereg(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_d8_4ba_ereg(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_byte_program_4ba_direct(struct flashctx *flash, unsigned int addr, uint8_t databyte);
int spi_nbyte_program_4ba_direct(struct flashctx *flash, unsigned int addr, const uint8_t *bytes, unsigned int len);
int spi_nbyte_read_4ba_direct(struct flashctx *flash, unsigned int addr, uint8_t *bytes, unsigned int len);
int spi_block_erase_21_4ba_direct(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_5c_4ba_direct(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_dc_4ba_direct(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
#endif /* !__CHIPDRIVERS_H__ */ #endif /* !__CHIPDRIVERS_H__ */

View File

@ -9923,10 +9923,10 @@ const struct flashchip flashchips[] = {
.block_erasers = { .block_erasers = {
{ {
.eraseblocks = { {4 * 1024, 8192} }, .eraseblocks = { {4 * 1024, 8192} },
.block_erase = spi_block_erase_21_4ba_direct, .block_erase = spi_block_erase_21,
}, { }, {
.eraseblocks = { {64 * 1024, 512} }, .eraseblocks = { {64 * 1024, 512} },
.block_erase = spi_block_erase_dc_4ba_direct, .block_erase = spi_block_erase_dc,
}, { }, {
.eraseblocks = { {32768 * 1024, 1} }, .eraseblocks = { {32768 * 1024, 1} },
.block_erase = spi_block_erase_c7, .block_erase = spi_block_erase_c7,
@ -9956,10 +9956,10 @@ const struct flashchip flashchips[] = {
.block_erasers = { .block_erasers = {
{ {
.eraseblocks = { {4 * 1024, 16384} }, .eraseblocks = { {4 * 1024, 16384} },
.block_erase = spi_block_erase_21_4ba_direct, .block_erase = spi_block_erase_21,
}, { }, {
.eraseblocks = { {64 * 1024, 1024} }, .eraseblocks = { {64 * 1024, 1024} },
.block_erase = spi_block_erase_dc_4ba_direct, .block_erase = spi_block_erase_dc,
}, { }, {
.eraseblocks = { {65536 * 1024, 1} }, .eraseblocks = { {65536 * 1024, 1} },
.block_erase = spi_block_erase_c7, .block_erase = spi_block_erase_c7,

20
spi.h
View File

@ -138,6 +138,18 @@
#define JEDEC_WRSR_OUTSIZE 0x02 #define JEDEC_WRSR_OUTSIZE 0x02
#define JEDEC_WRSR_INSIZE 0x00 #define JEDEC_WRSR_INSIZE 0x00
/* Enter 4-byte Address Mode */
#define JEDEC_ENTER_4_BYTE_ADDR_MODE 0xB7
/* Exit 4-byte Address Mode */
#define JEDEC_EXIT_4_BYTE_ADDR_MODE 0xE9
/* Write Extended Address Register */
#define JEDEC_WRITE_EXT_ADDR_REG 0xC5
/* Read Extended Address Register */
#define JEDEC_READ_EXT_ADDR_REG 0xC8
/* Read the memory */ /* Read the memory */
#define JEDEC_READ 0x03 #define JEDEC_READ 0x03
#define JEDEC_READ_OUTSIZE 0x04 #define JEDEC_READ_OUTSIZE 0x04
@ -154,6 +166,14 @@
#define JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE 0x03 #define JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE 0x03
#define JEDEC_AAI_WORD_PROGRAM_INSIZE 0x00 #define JEDEC_AAI_WORD_PROGRAM_INSIZE 0x00
/* Read the memory with 4-byte address
From ANY mode (3-bytes or 4-bytes) it works with 4-byte address */
#define JEDEC_READ_4BA 0x13
/* Write memory byte with 4-byte address
From ANY mode (3-bytes or 4-bytes) it works with 4-byte address */
#define JEDEC_BYTE_PROGRAM_4BA 0x12
/* Error codes */ /* Error codes */
#define SPI_GENERIC_ERROR -1 #define SPI_GENERIC_ERROR -1
#define SPI_INVALID_OPCODE -2 #define SPI_INVALID_OPCODE -2

87
spi25.c
View File

@ -30,7 +30,6 @@
#include "chipdrivers.h" #include "chipdrivers.h"
#include "programmer.h" #include "programmer.h"
#include "spi.h" #include "spi.h"
#include "spi4ba.h"
static int spi_rdid(struct flashctx *flash, unsigned char *readarr, int bytes) static int spi_rdid(struct flashctx *flash, unsigned char *readarr, int bytes)
{ {
@ -364,6 +363,25 @@ static int spi_simple_write_cmd(struct flashctx *const flash, const uint8_t op,
return result ? result : status; return result ? result : status;
} }
static int spi_write_extended_address_register(struct flashctx *const flash, const uint8_t regdata)
{
struct spi_command cmds[] = {
{
.writecnt = 1,
.writearr = (const unsigned char[]){ JEDEC_WREN },
}, {
.writecnt = 2,
.writearr = (const unsigned char[]){ JEDEC_WRITE_EXT_ADDR_REG, regdata },
},
NULL_SPI_CMD,
};
const int result = spi_send_multicommand(flash, cmds);
if (result)
msg_cerr("%s failed during command execution\n", __func__);
return result;
}
static int spi_set_extended_address(struct flashctx *const flash, const uint8_t addr_high) static int spi_set_extended_address(struct flashctx *const flash, const uint8_t addr_high)
{ {
if (flash->address_high_byte != addr_high && if (flash->address_high_byte != addr_high &&
@ -565,6 +583,27 @@ int spi_block_erase_c7(struct flashctx *flash, unsigned int addr,
return spi_chip_erase_c7(flash); return spi_chip_erase_c7(flash);
} }
/* Erase 4 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes) */
int spi_block_erase_21(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
{
/* This usually takes 15-800ms, so wait in 10ms steps. */
return spi_write_cmd(flash, 0x21, true, addr, NULL, 0, 10 * 1000);
}
/* Erase 32 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes) */
int spi_block_erase_5c(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
{
/* This usually takes 100-4000ms, so wait in 100ms steps. */
return spi_write_cmd(flash, 0x5c, true, addr, NULL, 0, 100 * 1000);
}
/* Erase 64 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes) */
int spi_block_erase_dc(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
{
/* This usually takes 100-4000ms, so wait in 100ms steps. */
return spi_write_cmd(flash, 0xdc, true, addr, NULL, 0, 100 * 1000);
}
erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode) erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode)
{ {
switch(opcode){ switch(opcode){
@ -574,10 +613,14 @@ erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode)
return NULL; return NULL;
case 0x20: case 0x20:
return &spi_block_erase_20; return &spi_block_erase_20;
case 0x21:
return &spi_block_erase_21;
case 0x50: case 0x50:
return &spi_block_erase_50; return &spi_block_erase_50;
case 0x52: case 0x52:
return &spi_block_erase_52; return &spi_block_erase_52;
case 0x5c:
return &spi_block_erase_5c;
case 0x60: case 0x60:
return &spi_block_erase_60; return &spi_block_erase_60;
case 0x62: case 0x62:
@ -594,6 +637,8 @@ erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode)
return &spi_block_erase_d8; return &spi_block_erase_d8;
case 0xdb: case 0xdb:
return &spi_block_erase_db; return &spi_block_erase_db;
case 0xdc:
return &spi_block_erase_dc;
default: default:
msg_cinfo("%s: unknown erase opcode (0x%02x). Please report " msg_cinfo("%s: unknown erase opcode (0x%02x). Please report "
"this at flashrom@flashrom.org\n", __func__, opcode); "this at flashrom@flashrom.org\n", __func__, opcode);
@ -812,3 +857,43 @@ bailout:
msg_cerr("%s failed to disable AAI mode.\n", __func__); msg_cerr("%s failed to disable AAI mode.\n", __func__);
return SPI_GENERIC_ERROR; return SPI_GENERIC_ERROR;
} }
/* Enter 4-bytes addressing mode (without sending WREN before) */
int spi_enter_4ba_b7(struct flashctx *flash)
{
const unsigned char cmd = JEDEC_ENTER_4_BYTE_ADDR_MODE;
const int ret = spi_send_command(flash, sizeof(cmd), 0, &cmd, NULL);
if (!ret)
flash->in_4ba_mode = true;
return ret;
}
/* Enter 4-bytes addressing mode with sending WREN before */
int spi_enter_4ba_b7_we(struct flashctx *flash)
{
const int ret = spi_simple_write_cmd(flash, JEDEC_ENTER_4_BYTE_ADDR_MODE, 0);
if (!ret)
flash->in_4ba_mode = true;
return ret;
}
/* Exit 4-bytes addressing mode (without sending WREN before) */
int spi_exit_4ba_e9(struct flashctx *flash)
{
const unsigned char cmd = JEDEC_EXIT_4_BYTE_ADDR_MODE;
const int ret = spi_send_command(flash, sizeof(cmd), 0, &cmd, NULL);
if (!ret)
flash->in_4ba_mode = false;
return ret;
}
/* Exit 4-bytes addressing mode with sending WREN before */
int spi_exit_4ba_e9_we(struct flashctx *flash)
{
const int ret = spi_simple_write_cmd(flash, JEDEC_EXIT_4_BYTE_ADDR_MODE, 0);
if (!ret)
flash->in_4ba_mode = false;
return ret;
}

317
spi4ba.c
View File

@ -1,317 +0,0 @@
/*
* This file is part of the flashrom project.
*
* Copyright (C) 2014 Boris Baykov
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* SPI chip driver functions for 4-bytes addressing
*/
#include <string.h>
#include "flash.h"
#include "chipdrivers.h"
#include "spi.h"
#include "programmer.h"
#include "spi4ba.h"
/* #define MSG_TRACE_4BA_FUNCS 1 */
#ifdef MSG_TRACE_4BA_FUNCS
#define msg_trace(...) print(MSG_DEBUG, __VA_ARGS__)
#else
#define msg_trace(...)
#endif
/* Enter 4-bytes addressing mode (without sending WREN before) */
int spi_enter_4ba_b7(struct flashctx *flash)
{
int result;
const unsigned char cmd[JEDEC_ENTER_4_BYTE_ADDR_MODE_OUTSIZE] = { JEDEC_ENTER_4_BYTE_ADDR_MODE };
msg_trace("-> %s\n", __func__);
/* Switch to 4-bytes addressing mode */
result = spi_send_command(flash, sizeof(cmd), 0, cmd, NULL);
if (!result)
flash->in_4ba_mode = true;
return result;
}
/* Enter 4-bytes addressing mode with sending WREN before */
int spi_enter_4ba_b7_we(struct flashctx *flash)
{
int result;
struct spi_command cmds[] = {
{
.writecnt = JEDEC_WREN_OUTSIZE,
.writearr = (const unsigned char[]){ JEDEC_WREN },
.readcnt = 0,
.readarr = NULL,
}, {
.writecnt = JEDEC_ENTER_4_BYTE_ADDR_MODE_OUTSIZE,
.writearr = (const unsigned char[]){ JEDEC_ENTER_4_BYTE_ADDR_MODE },
.readcnt = 0,
.readarr = NULL,
}, {
.writecnt = 0,
.writearr = NULL,
.readcnt = 0,
.readarr = NULL,
}};
msg_trace("-> %s\n", __func__);
/* Switch to 4-bytes addressing mode */
result = spi_send_multicommand(flash, cmds);
if (result)
msg_cerr("%s failed during command execution\n", __func__);
else
flash->in_4ba_mode = true;
return result;
}
/* Exit 4-bytes addressing mode (without sending WREN before) */
int spi_exit_4ba_e9(struct flashctx *flash)
{
int result;
const unsigned char cmd[JEDEC_EXIT_4_BYTE_ADDR_MODE_OUTSIZE] = { JEDEC_EXIT_4_BYTE_ADDR_MODE };
msg_trace("-> %s\n", __func__);
/* Switch to 3-bytes addressing mode */
result = spi_send_command(flash, sizeof(cmd), 0, cmd, NULL);
if (!result)
flash->in_4ba_mode = false;
return result;
}
/* Exit 4-bytes addressing mode with sending WREN before */
int spi_exit_4ba_e9_we(struct flashctx *flash)
{
int result;
struct spi_command cmds[] = {
{
.writecnt = JEDEC_WREN_OUTSIZE,
.writearr = (const unsigned char[]){ JEDEC_WREN },
.readcnt = 0,
.readarr = NULL,
}, {
.writecnt = JEDEC_EXIT_4_BYTE_ADDR_MODE_OUTSIZE,
.writearr = (const unsigned char[]){ JEDEC_EXIT_4_BYTE_ADDR_MODE },
.readcnt = 0,
.readarr = NULL,
}, {
.writecnt = 0,
.writearr = NULL,
.readcnt = 0,
.readarr = NULL,
}};
msg_trace("-> %s\n", __func__);
/* Switch to 3-bytes addressing mode */
result = spi_send_multicommand(flash, cmds);
if (result)
msg_cerr("%s failed during command execution\n", __func__);
else
flash->in_4ba_mode = false;
return result;
}
/* Write Extended Address Register value */
int spi_write_extended_address_register(struct flashctx *flash, uint8_t regdata)
{
int result;
struct spi_command cmds[] = {
{
.writecnt = JEDEC_WREN_OUTSIZE,
.writearr = (const unsigned char[]){ JEDEC_WREN },
.readcnt = 0,
.readarr = NULL,
}, {
.writecnt = JEDEC_WRITE_EXT_ADDR_REG_OUTSIZE,
.writearr = (const unsigned char[]){
JEDEC_WRITE_EXT_ADDR_REG,
regdata
},
.readcnt = 0,
.readarr = NULL,
}, {
.writecnt = 0,
.writearr = NULL,
.readcnt = 0,
.readarr = NULL,
}};
msg_trace("-> %s (%02X)\n", __func__, regdata);
result = spi_send_multicommand(flash, cmds);
if (result) {
msg_cerr("%s failed during command execution\n", __func__);
return result;
}
return 0;
}
/* Erase 4 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes)
JEDEC_SE_4BA (21h) instruction is new for 4-bytes addressing flash chips.
The presence of this instruction for an exact chip should be checked
by its datasheet or from SFDP 4-Bytes Address Instruction Table (JESD216B). */
int spi_block_erase_21_4ba_direct(struct flashctx *flash, unsigned int addr,
unsigned int blocklen)
{
int result;
struct spi_command cmds[] = {
{
.writecnt = JEDEC_WREN_OUTSIZE,
.writearr = (const unsigned char[]){ JEDEC_WREN },
.readcnt = 0,
.readarr = NULL,
}, {
.writecnt = JEDEC_SE_4BA_OUTSIZE,
.writearr = (const unsigned char[]){
JEDEC_SE_4BA,
(addr >> 24) & 0xff,
(addr >> 16) & 0xff,
(addr >> 8) & 0xff,
(addr & 0xff)
},
.readcnt = 0,
.readarr = NULL,
}, {
.writecnt = 0,
.writearr = NULL,
.readcnt = 0,
.readarr = NULL,
}};
msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
result = spi_send_multicommand(flash, cmds);
if (result) {
msg_cerr("%s failed during command execution at address 0x%x\n",
__func__, addr);
return result;
}
/* Wait until the Write-In-Progress bit is cleared.
* This usually takes 15-800 ms, so wait in 10 ms steps.
*/
while (spi_read_status_register(flash) & SPI_SR_WIP)
programmer_delay(10 * 1000);
/* FIXME: Check the status register for errors. */
return 0;
}
/* Erase 32 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes)
JEDEC_BE_5C_4BA (5Ch) instruction is new for 4-bytes addressing flash chips.
The presence of this instruction for an exact chip should be checked
by its datasheet or from SFDP 4-Bytes Address Instruction Table (JESD216B). */
int spi_block_erase_5c_4ba_direct(struct flashctx *flash, unsigned int addr,
unsigned int blocklen)
{
int result;
struct spi_command cmds[] = {
{
.writecnt = JEDEC_WREN_OUTSIZE,
.writearr = (const unsigned char[]){ JEDEC_WREN },
.readcnt = 0,
.readarr = NULL,
}, {
.writecnt = JEDEC_BE_5C_4BA_OUTSIZE,
.writearr = (const unsigned char[]){
JEDEC_BE_5C_4BA,
(addr >> 24) & 0xff,
(addr >> 16) & 0xff,
(addr >> 8) & 0xff,
(addr & 0xff)
},
.readcnt = 0,
.readarr = NULL,
}, {
.writecnt = 0,
.writearr = NULL,
.readcnt = 0,
.readarr = NULL,
}};
msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
result = spi_send_multicommand(flash, cmds);
if (result) {
msg_cerr("%s failed during command execution at address 0x%x\n",
__func__, addr);
return result;
}
/* Wait until the Write-In-Progress bit is cleared.
* This usually takes 100-4000 ms, so wait in 100 ms steps.
*/
while (spi_read_status_register(flash) & SPI_SR_WIP)
programmer_delay(100 * 1000);
/* FIXME: Check the status register for errors. */
return 0;
}
/* Erase 64 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes)
JEDEC_BE_DC_4BA (DCh) instruction is new for 4-bytes addressing flash chips.
The presence of this instruction for an exact chip should be checked
by its datasheet or from SFDP 4-Bytes Address Instruction Table (JESD216B). */
int spi_block_erase_dc_4ba_direct(struct flashctx *flash, unsigned int addr,
unsigned int blocklen)
{
int result;
struct spi_command cmds[] = {
{
.writecnt = JEDEC_WREN_OUTSIZE,
.writearr = (const unsigned char[]){ JEDEC_WREN },
.readcnt = 0,
.readarr = NULL,
}, {
.writecnt = JEDEC_BE_DC_4BA_OUTSIZE,
.writearr = (const unsigned char[]){
JEDEC_BE_DC_4BA,
(addr >> 24) & 0xff,
(addr >> 16) & 0xff,
(addr >> 8) & 0xff,
(addr & 0xff)
},
.readcnt = 0,
.readarr = NULL,
}, {
.writecnt = 0,
.writearr = NULL,
.readcnt = 0,
.readarr = NULL,
}};
msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
result = spi_send_multicommand(flash, cmds);
if (result) {
msg_cerr("%s failed during command execution at address 0x%x\n",
__func__, addr);
return result;
}
/* Wait until the Write-In-Progress bit is cleared.
* This usually takes 100-4000 ms, so wait in 100 ms steps.
*/
while (spi_read_status_register(flash) & SPI_SR_WIP)
programmer_delay(100 * 1000);
/* FIXME: Check the status register for errors. */
return 0;
}

119
spi4ba.h
View File

@ -1,119 +0,0 @@
/*
* This file is part of the flashrom project.
*
* Copyright (C) 2014 Boris Baykov
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* JEDEC flash chips instructions for 4-bytes addressing
* SPI chip driver functions for 4-bytes addressing
*/
#ifndef __SPI_4BA_H__
#define __SPI_4BA_H__ 1
/* Enter 4-byte Address Mode */
#define JEDEC_ENTER_4_BYTE_ADDR_MODE 0xB7
#define JEDEC_ENTER_4_BYTE_ADDR_MODE_OUTSIZE 0x01
#define JEDEC_ENTER_4_BYTE_ADDR_MODE_INSIZE 0x00
/* Exit 4-byte Address Mode */
#define JEDEC_EXIT_4_BYTE_ADDR_MODE 0xE9
#define JEDEC_EXIT_4_BYTE_ADDR_MODE_OUTSIZE 0x01
#define JEDEC_EXIT_4_BYTE_ADDR_MODE_INSIZE 0x00
/* Write Extended Address Register */
#define JEDEC_WRITE_EXT_ADDR_REG 0xC5
#define JEDEC_WRITE_EXT_ADDR_REG_OUTSIZE 0x02
#define JEDEC_WRITE_EXT_ADDR_REG_INSIZE 0x00
/* Read Extended Address Register */
#define JEDEC_READ_EXT_ADDR_REG 0xC8
#define JEDEC_READ_EXT_ADDR_REG_OUTSIZE 0x01
#define JEDEC_READ_EXT_ADDR_REG_INSIZE 0x01
/* Read the memory with 4-byte address
From ANY mode (3-bytes or 4-bytes) it works with 4-byte address */
#define JEDEC_READ_4BA 0x13
#define JEDEC_READ_4BA_OUTSIZE 0x05
/* JEDEC_READ_4BA_INSIZE : any length */
/* Write memory byte with 4-byte address
From ANY mode (3-bytes or 4-bytes) it works with 4-byte address */
#define JEDEC_BYTE_PROGRAM_4BA 0x12
#define JEDEC_BYTE_PROGRAM_4BA_OUTSIZE 0x06
#define JEDEC_BYTE_PROGRAM_4BA_INSIZE 0x00
/* Sector Erase 0x21 (with 4-byte address), usually 4k size.
From ANY mode (3-bytes or 4-bytes) it works with 4-byte address */
#define JEDEC_SE_4BA 0x21
#define JEDEC_SE_4BA_OUTSIZE 0x05
#define JEDEC_SE_4BA_INSIZE 0x00
/* Block Erase 0x5C (with 4-byte address), usually 32k size.
From ANY mode (3-bytes or 4-bytes) it works with 4-byte address */
#define JEDEC_BE_5C_4BA 0x5C
#define JEDEC_BE_5C_4BA_OUTSIZE 0x05
#define JEDEC_BE_5C_4BA_INSIZE 0x00
/* Block Erase 0xDC (with 4-byte address), usually 64k size.
From ANY mode (3-bytes or 4-bytes) it works with 4-byte address */
#define JEDEC_BE_DC_4BA 0xdc
#define JEDEC_BE_DC_4BA_OUTSIZE 0x05
#define JEDEC_BE_DC_4BA_INSIZE 0x00
/* enter 4-bytes addressing mode */
int spi_enter_4ba_b7(struct flashctx *flash);
int spi_enter_4ba_b7_we(struct flashctx *flash);
/* exit 4-bytes addressing mode */
int spi_exit_4ba_e9(struct flashctx *flash);
int spi_exit_4ba_e9_we(struct flashctx *flash);
/* read/write flash bytes in 4-bytes addressing mode */
int spi_byte_program_4ba(struct flashctx *flash, unsigned int addr, uint8_t databyte);
int spi_nbyte_program_4ba(struct flashctx *flash, unsigned int addr, const uint8_t *bytes, unsigned int len);
int spi_nbyte_read_4ba(struct flashctx *flash, unsigned int addr, uint8_t *bytes, unsigned int len);
/* erase flash bytes in 4-bytes addressing mode */
int spi_block_erase_20_4ba(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_52_4ba(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_d8_4ba(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
/* read/write flash bytes from 3-bytes addressing mode using extended address register */
int spi_byte_program_4ba_ereg(struct flashctx *flash, unsigned int addr, uint8_t databyte);
int spi_nbyte_program_4ba_ereg(struct flashctx *flash, unsigned int addr, const uint8_t *bytes, unsigned int len);
int spi_nbyte_read_4ba_ereg(struct flashctx *flash, unsigned int addr, uint8_t *bytes, unsigned int len);
/* erase flash bytes from 3-bytes addressing mode using extended address register */
int spi_block_erase_20_4ba_ereg(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_52_4ba_ereg(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_d8_4ba_ereg(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
/* read/write flash bytes with 4-bytes address from any mode (3-byte or 4-byte) */
int spi_byte_program_4ba_direct(struct flashctx *flash, unsigned int addr, uint8_t databyte);
int spi_nbyte_program_4ba_direct(struct flashctx *flash, unsigned int addr, const uint8_t *bytes, unsigned int len);
int spi_nbyte_read_4ba_direct(struct flashctx *flash, unsigned int addr, uint8_t *bytes, unsigned int len);
/* erase flash bytes with 4-bytes address from any mode (3-byte or 4-byte) */
int spi_block_erase_21_4ba_direct(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_5c_4ba_direct(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_dc_4ba_direct(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_write_extended_address_register(struct flashctx *flash, uint8_t regdata);
#endif /* __SPI_4BA_H__ */