summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNico Huber <nico.huber@secunet.com>2012-06-19 12:06:53 +0000
committerCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>2012-06-19 12:06:53 +0000
commite5f46a6326912497dc74d56e6959e3bd850cd738 (patch)
treefdb9e146313348cde47775f013ba46b5601c6b29
parent5b74ad19c37b7f03a8ad46cf10fc3fcd6067143a (diff)
downloadflashrom-e5f46a6326912497dc74d56e6959e3bd850cd738.zip
flashrom-e5f46a6326912497dc74d56e6959e3bd850cd738.tar.gz
Add native SPI AAI write support to the Dediprog SF100 driver
To tell the programmer how to handle the data on the spi bus, a flag in the fourth byte sent with the usb command is used. The second word was mistaken for the size of the chunks sent over usb earlier. The third byte (first of the second word) is now set to zero. This also adds some checks for the size of data chunks sent over usb. Corresponding to flashrom svn r1546. Signed-off-by: Nico Huber <nico.huber@secunet.com> Acked-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
-rw-r--r--dediprog.c67
1 files changed, 47 insertions, 20 deletions
diff --git a/dediprog.c b/dediprog.c
index cdd27b0..9559eed 100644
--- a/dediprog.c
+++ b/dediprog.c
@@ -31,6 +31,9 @@ static usb_dev_handle *dediprog_handle;
static int dediprog_firmwareversion;
static int dediprog_endpoint;
+#define DEDI_SPI_CMD_PAGEWRITE 0x1
+#define DEDI_SPI_CMD_AAIWRITE 0x4
+
#if 0
/* Might be useful for other pieces of code as well. */
static void print_hex(void *buf, size_t len)
@@ -307,13 +310,15 @@ static int dediprog_spi_read(struct flashctx *flash, uint8_t *buf,
return 0;
}
-/* Bulk write interface, will write multiple page_size byte chunks aligned to page_size bytes.
- * @start start address
- * @len length
- * @return 0 on success, 1 on failure
+/* Bulk write interface, will write multiple chunksize byte chunks aligned to chunksize bytes.
+ * @chunksize length of data chunks, only 256 supported by now
+ * @start start address
+ * @len length
+ * @dedi_spi_cmd dediprog specific write command for spi bus
+ * @return 0 on success, 1 on failure
*/
-static int dediprog_spi_bulk_write(struct flashctx *flash, uint8_t *buf,
- unsigned int start, unsigned int len)
+static int dediprog_spi_bulk_write(struct flashctx *flash, uint8_t *buf, unsigned int chunksize,
+ unsigned int start, unsigned int len, uint8_t dedi_spi_cmd)
{
int ret;
unsigned int i;
@@ -321,14 +326,21 @@ static int dediprog_spi_bulk_write(struct flashctx *flash, uint8_t *buf,
* chunksize is the real data size per USB bulk transfer. The remaining
* space in a USB bulk transfer must be filled with 0xff padding.
*/
- const unsigned int chunksize = flash->page_size;
const unsigned int count = len / chunksize;
- const char count_and_chunk[] = {count & 0xff,
- (count >> 8) & 0xff,
- chunksize & 0xff,
- (chunksize >> 8) & 0xff};
+ const char count_and_cmd[] = {count & 0xff, (count >> 8) & 0xff, 0x00, dedi_spi_cmd};
char usbbuf[512];
+ /*
+ * We should change this check to
+ * chunksize > 512
+ * once we know how to handle different chunk sizes.
+ */
+ if (chunksize != 256) {
+ msg_perr("%s: Chunk sizes other than 256 bytes are unsupported, chunksize=%u!\n"
+ "Please report a bug at flashrom@flashrom.org\n", __func__, chunksize);
+ return 1;
+ }
+
if ((start % chunksize) || (len % chunksize)) {
msg_perr("%s: Unaligned start=%i, len=%i! Please report a bug "
"at flashrom@flashrom.org\n", __func__, start, len);
@@ -341,10 +353,9 @@ static int dediprog_spi_bulk_write(struct flashctx *flash, uint8_t *buf,
/* Command Write SPI Bulk. No idea which write command is used on the
* SPI side.
*/
- ret = usb_control_msg(dediprog_handle, 0x42, 0x30, start % 0x10000,
- start / 0x10000, (char *)count_and_chunk,
- sizeof(count_and_chunk), DEFAULT_TIMEOUT);
- if (ret != sizeof(count_and_chunk)) {
+ ret = usb_control_msg(dediprog_handle, 0x42, 0x30, start % 0x10000, start / 0x10000,
+ (char *)count_and_cmd, sizeof(count_and_cmd), DEFAULT_TIMEOUT);
+ if (ret != sizeof(count_and_cmd)) {
msg_perr("Command Write SPI Bulk failed, %i %s!\n", ret,
usb_strerror());
return 1;
@@ -366,8 +377,8 @@ static int dediprog_spi_bulk_write(struct flashctx *flash, uint8_t *buf,
return 0;
}
-static int dediprog_spi_write_256(struct flashctx *flash, uint8_t *buf,
- unsigned int start, unsigned int len)
+static int dediprog_spi_write(struct flashctx *flash, uint8_t *buf,
+ unsigned int start, unsigned int len, uint8_t dedi_spi_cmd)
{
int ret;
const unsigned int chunksize = flash->page_size;
@@ -376,6 +387,13 @@ static int dediprog_spi_write_256(struct flashctx *flash, uint8_t *buf,
dediprog_set_leds(PASS_OFF|BUSY_ON|ERROR_OFF);
+ if (chunksize != 256) {
+ msg_pdbg("Page sizes other than 256 bytes are unsupported as "
+ "we don't know how dediprog\nhandles them.\n");
+ /* Write everything like it was residue. */
+ residue = len;
+ }
+
if (residue) {
msg_pdbg("Slow write for partial block from 0x%x, length 0x%x\n",
start, residue);
@@ -389,8 +407,7 @@ static int dediprog_spi_write_256(struct flashctx *flash, uint8_t *buf,
/* Round down. */
bulklen = (len - residue) / chunksize * chunksize;
- ret = dediprog_spi_bulk_write(flash, buf + residue, start + residue,
- bulklen);
+ ret = dediprog_spi_bulk_write(flash, buf + residue, chunksize, start + residue, bulklen, dedi_spi_cmd);
if (ret) {
dediprog_set_leds(PASS_OFF|BUSY_OFF|ERROR_ON);
return ret;
@@ -412,6 +429,16 @@ static int dediprog_spi_write_256(struct flashctx *flash, uint8_t *buf,
return 0;
}
+static int dediprog_spi_write_256(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len)
+{
+ return dediprog_spi_write(flash, buf, start, len, DEDI_SPI_CMD_PAGEWRITE);
+}
+
+static int dediprog_spi_write_aai(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len)
+{
+ return dediprog_spi_write(flash, buf, start, len, DEDI_SPI_CMD_AAIWRITE);
+}
+
static int dediprog_spi_send_command(struct flashctx *flash,
unsigned int writecnt,
unsigned int readcnt,
@@ -717,7 +744,7 @@ static const struct spi_programmer spi_programmer_dediprog = {
.multicommand = default_spi_send_multicommand,
.read = dediprog_spi_read,
.write_256 = dediprog_spi_write_256,
- .write_aai = default_spi_write_aai,
+ .write_aai = dediprog_spi_write_aai,
};
static int dediprog_shutdown(void *data)
OpenPOWER on IntegriCloud