mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-27 23:22:37 +02:00
Introduce a generic SPI read function: spi_write_chunked()
Every SPI programmer driver had its own completely different chip write implementation, and all of them were insufficiently commented. Create spi_write_chunked as a copy of spi_read_chunked and convert all SPI programmers to use it. No functional changes except: - Bus Pirate uses 12 Byte writes instead of 8 Byte writes - SB600 uses 5 Byte writes instead of 1 Byte writes Corresponding to flashrom svn r1005. Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> Acked-by: Michael Karcher <flashrom@mkarcher.dialup.fu-berlin.de> Acked-by: David Hendricks <dhendrix@google.com>
This commit is contained in:
parent
d175e06ac3
commit
5824fbff01
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of the flashrom project.
|
||||
*
|
||||
* Copyright (C) 2009 Carl-Daniel Hailfinger
|
||||
* Copyright (C) 2009, 2010 Carl-Daniel Hailfinger
|
||||
*
|
||||
* 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
|
||||
@ -142,24 +142,7 @@ int bitbang_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len)
|
||||
int bitbang_spi_write_256(struct flashchip *flash, uint8_t *buf)
|
||||
{
|
||||
int total_size = 1024 * flash->total_size;
|
||||
int i;
|
||||
|
||||
msg_pdbg("total_size is %d\n", total_size);
|
||||
for (i = 0; i < total_size; i += 256) {
|
||||
int l, r;
|
||||
if (i + 256 <= total_size)
|
||||
l = 256;
|
||||
else
|
||||
l = total_size - i;
|
||||
|
||||
if ((r = spi_nbyte_program(i, &buf[i], l))) {
|
||||
msg_perr("%s: write fail %d\n", __func__, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
|
||||
/* loop */;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return spi_write_chunked(flash, buf, 0, total_size, 256);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of the flashrom project.
|
||||
*
|
||||
* Copyright (C) 2009 Carl-Daniel Hailfinger
|
||||
* Copyright (C) 2009, 2010 Carl-Daniel Hailfinger
|
||||
*
|
||||
* 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
|
||||
@ -319,7 +319,6 @@ int buspirate_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len
|
||||
int buspirate_spi_write_256(struct flashchip *flash, uint8_t *buf)
|
||||
{
|
||||
int total_size = 1024 * flash->total_size;
|
||||
int i;
|
||||
|
||||
spi_disable_blockprotect();
|
||||
/* Erase first. */
|
||||
@ -330,25 +329,5 @@ int buspirate_spi_write_256(struct flashchip *flash, uint8_t *buf)
|
||||
}
|
||||
msg_pinfo("done.\n");
|
||||
|
||||
/* FIXME: We could do 12 byte writes, but then we'd have to make sure
|
||||
* not to cross a 256 byte page boundary. This problem only applies to
|
||||
* writes, reads can cross page boundaries just fine.
|
||||
*/
|
||||
for (i = 0; i < total_size; i += 8) {
|
||||
int l, r;
|
||||
if (i + 8 <= total_size)
|
||||
l = 8;
|
||||
else
|
||||
l = total_size - i;
|
||||
|
||||
if ((r = spi_nbyte_program(i, &buf[i], l))) {
|
||||
msg_perr("%s: write fail %d\n", __func__, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
|
||||
/* loop */;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return spi_write_chunked(flash, buf, 0, total_size, 12);
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ int spi_byte_program(int addr, uint8_t databyte);
|
||||
int spi_nbyte_program(int addr, uint8_t *bytes, int len);
|
||||
int spi_nbyte_read(int addr, uint8_t *bytes, int len);
|
||||
int spi_read_chunked(struct flashchip *flash, uint8_t *buf, int start, int len, int chunksize);
|
||||
int spi_write_chunked(struct flashchip *flash, uint8_t *buf, int start, int len, int chunksize);
|
||||
int spi_aai_write(struct flashchip *flash, uint8_t *buf);
|
||||
|
||||
/* 82802ab.c */
|
||||
|
21
ft2232_spi.c
21
ft2232_spi.c
@ -2,7 +2,7 @@
|
||||
* This file is part of the flashrom project.
|
||||
*
|
||||
* Copyright (C) 2009 Paul Fox <pgf@laptop.org>
|
||||
* Copyright (C) 2009 Carl-Daniel Hailfinger
|
||||
* Copyright (C) 2009, 2010 Carl-Daniel Hailfinger
|
||||
*
|
||||
* 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
|
||||
@ -288,7 +288,6 @@ int ft2232_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len)
|
||||
int ft2232_spi_write_256(struct flashchip *flash, uint8_t *buf)
|
||||
{
|
||||
int total_size = 1024 * flash->total_size;
|
||||
int i;
|
||||
|
||||
spi_disable_blockprotect();
|
||||
/* Erase first. */
|
||||
@ -299,23 +298,7 @@ int ft2232_spi_write_256(struct flashchip *flash, uint8_t *buf)
|
||||
}
|
||||
msg_pinfo("done.\n");
|
||||
msg_pdbg("total_size is %d\n", total_size);
|
||||
for (i = 0; i < total_size; i += 256) {
|
||||
int l, r;
|
||||
if (i + 256 <= total_size)
|
||||
l = 256;
|
||||
else
|
||||
l = total_size - i;
|
||||
|
||||
if ((r = spi_nbyte_program(i, &buf[i], l))) {
|
||||
msg_perr("%s: write fail %d\n", __func__, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
|
||||
/* loop */;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return spi_write_chunked(flash, buf, 0, total_size, 256);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
46
ichspi.c
46
ichspi.c
@ -5,7 +5,7 @@
|
||||
* Copyright (C) 2008 Claus Gindhart <claus.gindhart@kontron.com>
|
||||
* Copyright (C) 2008 Dominik Geyer <dominik.geyer@kontron.com>
|
||||
* Copyright (C) 2008 coresystems GmbH <info@coresystems.de>
|
||||
* Copyright (C) 2009 Carl-Daniel Hailfinger
|
||||
* Copyright (C) 2009, 2010 Carl-Daniel Hailfinger
|
||||
*
|
||||
* 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
|
||||
@ -149,8 +149,6 @@ static int generate_opcodes(OPCODES * op);
|
||||
static int program_opcodes(OPCODES * op);
|
||||
static int run_opcode(OPCODE op, uint32_t offset,
|
||||
uint8_t datalength, uint8_t * data);
|
||||
static int ich_spi_write_page(struct flashchip *flash, uint8_t * bytes,
|
||||
int offset, int maxdata);
|
||||
|
||||
/* for pairing opcodes with their required preop */
|
||||
struct preop_opcode_pair {
|
||||
@ -636,28 +634,6 @@ static int run_opcode(OPCODE op, uint32_t offset,
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ich_spi_write_page(struct flashchip *flash, uint8_t * bytes,
|
||||
int offset, int maxdata)
|
||||
{
|
||||
int page_size = flash->page_size;
|
||||
uint32_t remaining = page_size;
|
||||
int towrite;
|
||||
|
||||
msg_pspew("ich_spi_write_page: offset=%d, number=%d, buf=%p\n",
|
||||
offset, page_size, bytes);
|
||||
|
||||
for (; remaining > 0; remaining -= towrite) {
|
||||
towrite = min(remaining, maxdata);
|
||||
if (spi_nbyte_program(offset + (page_size - remaining),
|
||||
&bytes[page_size - remaining], towrite)) {
|
||||
msg_perr("Error writing");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ich_spi_read(struct flashchip *flash, uint8_t * buf, int start, int len)
|
||||
{
|
||||
int maxdata = 64;
|
||||
@ -670,12 +646,14 @@ int ich_spi_read(struct flashchip *flash, uint8_t * buf, int start, int len)
|
||||
|
||||
int ich_spi_write_256(struct flashchip *flash, uint8_t * buf)
|
||||
{
|
||||
int i, j, rc = 0;
|
||||
int i, ret = 0;
|
||||
int total_size = flash->total_size * 1024;
|
||||
int page_size = flash->page_size;
|
||||
int erase_size = 64 * 1024;
|
||||
int maxdata = 64;
|
||||
|
||||
if (spi_controller == SPI_CONTROLLER_VIA)
|
||||
maxdata = 16;
|
||||
|
||||
spi_disable_blockprotect();
|
||||
/* Erase first */
|
||||
msg_pinfo("Erasing flash before programming... ");
|
||||
@ -687,19 +665,15 @@ int ich_spi_write_256(struct flashchip *flash, uint8_t * buf)
|
||||
|
||||
msg_pinfo("Programming page: \n");
|
||||
for (i = 0; i < total_size / erase_size; i++) {
|
||||
if (spi_controller == SPI_CONTROLLER_VIA)
|
||||
maxdata = 16;
|
||||
|
||||
for (j = 0; j < erase_size / page_size; j++) {
|
||||
ich_spi_write_page(flash,
|
||||
(void *)(buf + (i * erase_size) + (j * page_size)),
|
||||
(i * erase_size) + (j * page_size), maxdata);
|
||||
}
|
||||
ret = spi_write_chunked(flash, buf + (i * erase_size),
|
||||
i * erase_size, erase_size, maxdata);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
msg_pinfo("\n");
|
||||
|
||||
return rc;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ich_spi_send_command(unsigned int writecnt, unsigned int readcnt,
|
||||
|
16
sb600spi.c
16
sb600spi.c
@ -4,6 +4,7 @@
|
||||
* Copyright (C) 2008 Wang Qingpei <Qingpei.Wang@amd.com>
|
||||
* Copyright (C) 2008 Joe Bao <Zheng.Bao@amd.com>
|
||||
* Copyright (C) 2008 Advanced Micro Devices, Inc.
|
||||
* Copyright (C) 2009, 2010 Carl-Daniel Hailfinger
|
||||
*
|
||||
* 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
|
||||
@ -49,7 +50,6 @@ int sb600_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len)
|
||||
/* FIXME: SB600 can write 5 bytes per transaction. */
|
||||
int sb600_spi_write_1(struct flashchip *flash, uint8_t *buf)
|
||||
{
|
||||
int i;
|
||||
int total_size = flash->total_size * 1024;
|
||||
int result = 0;
|
||||
|
||||
@ -63,19 +63,7 @@ int sb600_spi_write_1(struct flashchip *flash, uint8_t *buf)
|
||||
msg_pinfo("done.\n");
|
||||
|
||||
msg_pinfo("Programming flash");
|
||||
for (i = 0; i < total_size; i++, buf++) {
|
||||
result = spi_nbyte_program(i, buf, 1);
|
||||
if (result) {
|
||||
msg_perr("Write error!\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
/* wait program complete. */
|
||||
if (i % 0x8000 == 0)
|
||||
msg_pspew(".");
|
||||
while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
|
||||
;
|
||||
}
|
||||
result = spi_write_chunked(flash, buf, 0, total_size, 5);
|
||||
msg_pinfo(" done.\n");
|
||||
return result;
|
||||
}
|
||||
|
50
spi25.c
50
spi25.c
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of the flashrom project.
|
||||
*
|
||||
* Copyright (C) 2007, 2008, 2009 Carl-Daniel Hailfinger
|
||||
* Copyright (C) 2007, 2008, 2009, 2010 Carl-Daniel Hailfinger
|
||||
* Copyright (C) 2008 coresystems GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@ -874,7 +874,7 @@ int spi_nbyte_read(int address, uint8_t *bytes, int len)
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a complete flash chip.
|
||||
* Read a part of the flash chip.
|
||||
* Each page is read separately in chunks with a maximum size of chunksize.
|
||||
*/
|
||||
int spi_read_chunked(struct flashchip *flash, uint8_t *buf, int start, int len, int chunksize)
|
||||
@ -912,6 +912,52 @@ int spi_read_chunked(struct flashchip *flash, uint8_t *buf, int start, int len,
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a part of the flash chip.
|
||||
* Each page is written separately in chunks with a maximum size of chunksize.
|
||||
*/
|
||||
int spi_write_chunked(struct flashchip *flash, uint8_t *buf, int start, int len, int chunksize)
|
||||
{
|
||||
int rc = 0;
|
||||
int i, j, starthere, lenhere;
|
||||
/* FIXME: page_size is the wrong variable. We need max_writechunk_size
|
||||
* in struct flashchip to do this properly. All chips using
|
||||
* spi_chip_write_256 have page_size set to max_writechunk_size, so
|
||||
* we're OK for now.
|
||||
*/
|
||||
int page_size = flash->page_size;
|
||||
int towrite;
|
||||
|
||||
/* Warning: This loop has a very unusual condition and body.
|
||||
* The loop needs to go through each page with at least one affected
|
||||
* byte. The lowest page number is (start / page_size) since that
|
||||
* division rounds down. The highest page number we want is the page
|
||||
* where the last byte of the range lives. That last byte has the
|
||||
* address (start + len - 1), thus the highest page number is
|
||||
* (start + len - 1) / page_size. Since we want to include that last
|
||||
* page as well, the loop condition uses <=.
|
||||
*/
|
||||
for (i = start / page_size; i <= (start + len - 1) / page_size; i++) {
|
||||
/* Byte position of the first byte in the range in this page. */
|
||||
/* starthere is an offset to the base address of the chip. */
|
||||
starthere = max(start, i * page_size);
|
||||
/* Length of bytes in the range in this page. */
|
||||
lenhere = min(start + len, (i + 1) * page_size) - starthere;
|
||||
for (j = 0; j < lenhere; j += chunksize) {
|
||||
towrite = min(chunksize, lenhere - j);
|
||||
rc = spi_nbyte_program(starthere + j, buf + starthere - start + j, towrite);
|
||||
if (rc)
|
||||
break;
|
||||
while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
|
||||
programmer_delay(10);
|
||||
}
|
||||
if (rc)
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Program chip using byte programming. (SLOW!)
|
||||
* This is for chips which can only handle one byte writes
|
||||
|
Loading…
x
Reference in New Issue
Block a user