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:
parent
0ee2dc0683
commit
7e3c81ae71
2
Makefile
2
Makefile
@ -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.
|
||||||
|
@ -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__ */
|
||||||
|
@ -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
20
spi.h
@ -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
87
spi25.c
@ -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
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