mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-27 07:02:34 +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:
parent
0ee2dc0683
commit
7e3c81ae71
2
Makefile
2
Makefile
@ -519,7 +519,7 @@ endif
|
||||
CHIP_OBJS = jedec.o stm50.o w39.o w29ee011.o \
|
||||
sst28sf040.o 82802ab.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.
|
||||
|
@ -43,8 +43,10 @@ int probe_spi_at25f(struct flashctx *flash);
|
||||
int spi_write_enable(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_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_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_62(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_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_dc(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
|
||||
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_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_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 */
|
||||
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 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__ */
|
||||
|
@ -9923,10 +9923,10 @@ const struct flashchip flashchips[] = {
|
||||
.block_erasers = {
|
||||
{
|
||||
.eraseblocks = { {4 * 1024, 8192} },
|
||||
.block_erase = spi_block_erase_21_4ba_direct,
|
||||
.block_erase = spi_block_erase_21,
|
||||
}, {
|
||||
.eraseblocks = { {64 * 1024, 512} },
|
||||
.block_erase = spi_block_erase_dc_4ba_direct,
|
||||
.block_erase = spi_block_erase_dc,
|
||||
}, {
|
||||
.eraseblocks = { {32768 * 1024, 1} },
|
||||
.block_erase = spi_block_erase_c7,
|
||||
@ -9956,10 +9956,10 @@ const struct flashchip flashchips[] = {
|
||||
.block_erasers = {
|
||||
{
|
||||
.eraseblocks = { {4 * 1024, 16384} },
|
||||
.block_erase = spi_block_erase_21_4ba_direct,
|
||||
.block_erase = spi_block_erase_21,
|
||||
}, {
|
||||
.eraseblocks = { {64 * 1024, 1024} },
|
||||
.block_erase = spi_block_erase_dc_4ba_direct,
|
||||
.block_erase = spi_block_erase_dc,
|
||||
}, {
|
||||
.eraseblocks = { {65536 * 1024, 1} },
|
||||
.block_erase = spi_block_erase_c7,
|
||||
|
20
spi.h
20
spi.h
@ -138,6 +138,18 @@
|
||||
#define JEDEC_WRSR_OUTSIZE 0x02
|
||||
#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 */
|
||||
#define JEDEC_READ 0x03
|
||||
#define JEDEC_READ_OUTSIZE 0x04
|
||||
@ -154,6 +166,14 @@
|
||||
#define JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE 0x03
|
||||
#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 */
|
||||
#define SPI_GENERIC_ERROR -1
|
||||
#define SPI_INVALID_OPCODE -2
|
||||
|
87
spi25.c
87
spi25.c
@ -30,7 +30,6 @@
|
||||
#include "chipdrivers.h"
|
||||
#include "programmer.h"
|
||||
#include "spi.h"
|
||||
#include "spi4ba.h"
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
switch(opcode){
|
||||
@ -574,10 +613,14 @@ erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode)
|
||||
return NULL;
|
||||
case 0x20:
|
||||
return &spi_block_erase_20;
|
||||
case 0x21:
|
||||
return &spi_block_erase_21;
|
||||
case 0x50:
|
||||
return &spi_block_erase_50;
|
||||
case 0x52:
|
||||
return &spi_block_erase_52;
|
||||
case 0x5c:
|
||||
return &spi_block_erase_5c;
|
||||
case 0x60:
|
||||
return &spi_block_erase_60;
|
||||
case 0x62:
|
||||
@ -594,6 +637,8 @@ erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode)
|
||||
return &spi_block_erase_d8;
|
||||
case 0xdb:
|
||||
return &spi_block_erase_db;
|
||||
case 0xdc:
|
||||
return &spi_block_erase_dc;
|
||||
default:
|
||||
msg_cinfo("%s: unknown erase opcode (0x%02x). Please report "
|
||||
"this at flashrom@flashrom.org\n", __func__, opcode);
|
||||
@ -812,3 +857,43 @@ bailout:
|
||||
msg_cerr("%s failed to disable AAI mode.\n", __func__);
|
||||
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
317
spi4ba.c
@ -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
119
spi4ba.h
@ -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__ */
|
Loading…
x
Reference in New Issue
Block a user