mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-27 15:12:36 +02:00
Implement on-the-fly reprogramming of the ICH SPI OPCODE table
Corresponding to flashrom svn r1193. Signed-off-by: Helge Wagner <helge.wagner@ge.com> Acked-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
This commit is contained in:
parent
17da61ea32
commit
738e252112
99
ichspi.c
99
ichspi.c
@ -30,6 +30,7 @@
|
|||||||
* ST M25P32 already tested
|
* ST M25P32 already tested
|
||||||
* ST M25P64
|
* ST M25P64
|
||||||
* AT 25DF321 already tested
|
* AT 25DF321 already tested
|
||||||
|
* ... and many more SPI flash devices
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -197,8 +198,76 @@ static OPCODES O_ST_M25P = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* List of opcodes with their corresponding spi_type
|
||||||
|
* It is used to reprogram the chipset OPCODE table on-the-fly if an opcode
|
||||||
|
* is needed which is currently not in the chipset OPCODE table
|
||||||
|
*/
|
||||||
|
static OPCODE POSSIBLE_OPCODES[] = {
|
||||||
|
{JEDEC_BYTE_PROGRAM, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Write Byte
|
||||||
|
{JEDEC_READ, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Read Data
|
||||||
|
{JEDEC_BE_D8, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Erase Sector
|
||||||
|
{JEDEC_RDSR, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read Device Status Reg
|
||||||
|
{JEDEC_REMS, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Read Electronic Manufacturer Signature
|
||||||
|
{JEDEC_WRSR, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Write Status Register
|
||||||
|
{JEDEC_RDID, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read JDEC ID
|
||||||
|
{JEDEC_CE_C7, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Bulk erase
|
||||||
|
{JEDEC_SE, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Sector erase
|
||||||
|
{JEDEC_BE_52, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Block erase
|
||||||
|
{JEDEC_AAI_WORD_PROGRAM, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Auto Address Increment
|
||||||
|
};
|
||||||
|
|
||||||
static OPCODES O_EXISTING = {};
|
static OPCODES O_EXISTING = {};
|
||||||
|
|
||||||
|
static uint8_t lookup_spi_type(uint8_t opcode)
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
|
||||||
|
for (a = 0; a < sizeof(POSSIBLE_OPCODES)/sizeof(POSSIBLE_OPCODES[0]); a++) {
|
||||||
|
if (POSSIBLE_OPCODES[a].opcode == opcode)
|
||||||
|
return POSSIBLE_OPCODES[a].spi_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int reprogram_opcode_on_the_fly(uint8_t opcode, unsigned int writecnt, unsigned int readcnt)
|
||||||
|
{
|
||||||
|
uint8_t spi_type;
|
||||||
|
|
||||||
|
spi_type = lookup_spi_type(opcode);
|
||||||
|
if (spi_type > 3) {
|
||||||
|
/* Try to guess spi type from read/write sizes.
|
||||||
|
* The following valid writecnt/readcnt combinations exist:
|
||||||
|
* writecnt = 4, readcnt >= 0
|
||||||
|
* writecnt = 1, readcnt >= 0
|
||||||
|
* writecnt >= 4, readcnt = 0
|
||||||
|
* writecnt >= 1, readcnt = 0
|
||||||
|
* writecnt >= 1 is guaranteed for all commands.
|
||||||
|
*/
|
||||||
|
if (readcnt == 0)
|
||||||
|
/* if readcnt=0 and writecount >= 4, we don't know if it is WRITE_NO_ADDRESS
|
||||||
|
* or WRITE_WITH_ADDRESS. But if we use WRITE_NO_ADDRESS and the first 3 data
|
||||||
|
* bytes are actual the address, they go to the bus anyhow
|
||||||
|
*/
|
||||||
|
spi_type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS;
|
||||||
|
else if (writecnt == 1) // and readcnt is > 0
|
||||||
|
spi_type = SPI_OPCODE_TYPE_READ_NO_ADDRESS;
|
||||||
|
else if (writecnt == 4) // and readcnt is > 0
|
||||||
|
spi_type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
|
||||||
|
// else we have an invalid case, will be handled below
|
||||||
|
}
|
||||||
|
if (spi_type <= 3) {
|
||||||
|
int oppos=2; // use original JEDEC_BE_D8 offset
|
||||||
|
curopcodes->opcode[oppos].opcode = opcode;
|
||||||
|
curopcodes->opcode[oppos].spi_type = spi_type;
|
||||||
|
program_opcodes(curopcodes);
|
||||||
|
oppos = find_opcode(curopcodes, opcode);
|
||||||
|
msg_pdbg ("on-the-fly OPCODE (0x%02X) re-programmed, op-pos=%d\n", opcode, oppos);
|
||||||
|
return oppos;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int find_opcode(OPCODES *op, uint8_t opcode)
|
static int find_opcode(OPCODES *op, uint8_t opcode)
|
||||||
{
|
{
|
||||||
int a;
|
int a;
|
||||||
@ -710,11 +779,12 @@ int ich_spi_send_command(unsigned int writecnt, unsigned int readcnt,
|
|||||||
/* find cmd in opcodes-table */
|
/* find cmd in opcodes-table */
|
||||||
opcode_index = find_opcode(curopcodes, cmd);
|
opcode_index = find_opcode(curopcodes, cmd);
|
||||||
if (opcode_index == -1) {
|
if (opcode_index == -1) {
|
||||||
/* FIXME: Reprogram opcodes if possible. Autodetect type of
|
if (!ichspi_lock)
|
||||||
* opcode by checking readcnt/writecnt.
|
opcode_index = reprogram_opcode_on_the_fly(cmd, writecnt, readcnt);
|
||||||
*/
|
if (opcode_index == -1) {
|
||||||
msg_pdbg("Invalid OPCODE 0x%02x\n", cmd);
|
msg_pdbg("Invalid OPCODE 0x%02x\n", cmd);
|
||||||
return SPI_INVALID_OPCODE;
|
return SPI_INVALID_OPCODE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
opcode = &(curopcodes->opcode[opcode_index]);
|
opcode = &(curopcodes->opcode[opcode_index]);
|
||||||
@ -827,21 +897,10 @@ int ich_spi_send_multicommand(struct spi_command *cmds)
|
|||||||
* No need to bother with fixups.
|
* No need to bother with fixups.
|
||||||
*/
|
*/
|
||||||
if (!ichspi_lock) {
|
if (!ichspi_lock) {
|
||||||
msg_pdbg("%s: FIXME: Add on-the-fly"
|
oppos = reprogram_opcode_on_the_fly((cmds + 1)->writearr[0], (cmds + 1)->writecnt, (cmds + 1)->readcnt);
|
||||||
" reprogramming of the "
|
if (oppos == -1)
|
||||||
"chipset opcode list.\n",
|
continue;
|
||||||
__func__);
|
curopcodes->opcode[oppos].atomic = preoppos + 1;
|
||||||
/* FIXME: Reprogram opcode menu.
|
|
||||||
* Find a less-useful opcode, replace it
|
|
||||||
* with the wanted opcode, detect optype
|
|
||||||
* and reprogram the opcode menu.
|
|
||||||
* Update oppos so the next if-statement
|
|
||||||
* can do something useful.
|
|
||||||
*/
|
|
||||||
//curopcodes.opcode[lessusefulindex] = (cmds + 1)->writearr[0]);
|
|
||||||
//update_optypes(curopcodes);
|
|
||||||
//program_opcodes(curopcodes);
|
|
||||||
//oppos = find_opcode(curopcodes, (cmds + 1)->writearr[0]);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user