Add SPI support to serprog protocol. Signed-off-by: Urja Rannikko <[email protected]>
-- Urja Rannikko
Index: serprog-protocol.txt =================================================================== --- serprog-protocol.txt (revision 1299) +++ serprog-protocol.txt (working copy) @@ -31,6 +31,8 @@ 0x10 Sync NOP none NAK + ACK (for synchronization) 0x11 Query maximum read-n length none ACK + 24-bit length (0==2^24) / NAK 0x12 Set used bustype 8-bit flags (as with 0x05) ACK / NAK +0x13 Perform SPI operation 24-bit slen + 24-bit rlen ACK + rlen bytes of data / NAK + + slen bytes of data 0x?? unimplemented command - invalid. @@ -50,7 +52,7 @@ it should return a big bogus value - eg 0xFFFF. 0x05 (Q_BUSTYPE): The bit's are defined as follows: - bit 0: PARALLEL, bit 1: LPC, bit 2: FWH, bit 3: SPI (if ever supported). + bit 0: PARALLEL, bit 1: LPC, bit 2: FWH, bit 3: SPI. 0x06 (Q_CHIPSIZE): Only applicable to parallel programmers. An LPC/FWH/SPI-programmer can report this as not supported in the command bitmap. @@ -66,6 +68,10 @@ Set's the used bustype if the programmer can support more than one flash protocol. Sending a byte with more than 1 bit set will make the programmer decide among them on it's own. Bit values as with Q_BUSTYPE. + 0x13 (O_SPIOP): + Maximum slen is Q_WRNMAXLEN result after Q_BUSTYPE returns + only SPI or S_BUSTYPE == SPI is used. Same for rlen and Q_RDNMAXLEN. + This operation is immediate, meaning it doesnt use the operation buffer. About mandatory commands: The only truly mandatory commands for any device are 0x00, 0x01, 0x02 and 0x10, but one can't really do anything with these commands. @@ -99,3 +105,4 @@ #define S_CMD_SYNCNOP 0x10 /* Special no-operation that returns NAK+ACK */ #define S_CMD_Q_RDNMAXLEN 0x11 /* Query read-n maximum length */ #define S_CMD_S_BUSTYPE 0x12 /* Set used bustype(s). */ +#define S_CMD_O_SPIOP 0x13 /* Perform SPI operation. */ Index: serprog.c =================================================================== --- serprog.c (revision 1299) +++ serprog.c (working copy) @@ -1,7 +1,7 @@ /* * This file is part of the flashrom project. * - * Copyright (C) 2009 Urja Rannikko <[email protected]> + * Copyright (C) 2009,2011 Urja Rannikko <[email protected]> * Copyright (C) 2009 Carl-Daniel Hailfinger * * This program is free software; you can redistribute it and/or modify @@ -60,6 +60,7 @@ #define S_CMD_SYNCNOP 0x10 /* Special no-operation that returns NAK+ACK */ #define S_CMD_Q_RDNMAXLEN 0x11 /* Query read-n maximum length */ #define S_CMD_S_BUSTYPE 0x12 /* Set used bustype(s). */ +#define S_CMD_O_SPIOP 0x13 /* Perform SPI operation. */ static uint16_t sp_device_serbuf_size = 16; static uint16_t sp_device_opbuf_size = 300; @@ -295,6 +296,19 @@ return 0; } +static const struct spi_programmer spi_programmer_serprog = { + .type = SPI_CONTROLLER_SERPROG, + .max_data_read = MAX_DATA_READ_UNLIMITED, + .max_data_write = MAX_DATA_WRITE_UNLIMITED, + .command = serprog_spi_send_command, + .multicommand = default_spi_send_multicommand, + .read = default_spi_read, + .write_256 = default_spi_write_256, +}; + +/* TODO: Support SPI max read & write data length reporting by the programmer, + currently we cannot do that because we dont have access to curent flashchip data. */ + int serprog_init(void) { uint16_t iface; @@ -318,7 +332,7 @@ msg_perr("Error: No baudrate specified.\n" "Use flashrom -p serprog:dev=/dev/device:baud\n"); free(device); - return 1; + return 1; } if (strlen(device)) { sp_fd = sp_openserport(device, atoi(baudport)); @@ -351,7 +365,7 @@ msg_perr("Error: No port specified.\n" "Use flashrom -p serprog:ip=ipaddr:port\n"); free(device); - return 1; + return 1; } if (strlen(device)) { sp_fd = sp_opensocket(device, atoi(baudport)); @@ -400,37 +414,58 @@ sp_check_avail_automatic = 1; + + if (sp_docommand(S_CMD_Q_BUSTYPE, 0, NULL, 1, &c)) { + msg_perr("Warning: NAK to query supported buses\n"); + c = CHIP_BUSTYPE_NONSPI; /* A reasonable default for now. */ + } + buses_supported = c; + /* Check for the minimum operational set of commands */ - if (sp_check_commandavail(S_CMD_R_BYTE) == 0) { - msg_perr("Error: Single byte read not supported\n"); - exit(1); - } - /* This could be translated to single byte reads (if missing), * - * but now we dont support that. */ - if (sp_check_commandavail(S_CMD_R_NBYTES) == 0) { - msg_perr("Error: Read n bytes not supported\n"); - exit(1); - } + /* In the future one could switch to read-only mode if these * * are not available. */ if (sp_check_commandavail(S_CMD_O_INIT) == 0) { msg_perr("Error: Initialize operation buffer not supported\n"); exit(1); } - if (sp_check_commandavail(S_CMD_O_WRITEB) == 0) { - msg_perr("Error: Write to opbuf: write byte not supported\n"); - exit(1); - } + if (sp_check_commandavail(S_CMD_O_DELAY) == 0) { msg_perr("Error: Write to opbuf: delay not supported\n"); exit(1); } + if (sp_check_commandavail(S_CMD_O_EXEC) == 0) { msg_perr( "Error: Execute operation buffer not supported\n"); exit(1); } + if (buses_supported & CHIP_BUSTYPE_SPI) { + if (sp_check_commandavail(S_CMD_O_SPIOP) == 0) { + msg_perr("Error: SPI operation not supported while the SPI bustype is\n"); + exit(1); + } + register_spi_programmer(&spi_programmer_serprog); + } + + if (buses_supported & CHIP_BUSTYPE_NONSPI) { + if (sp_check_commandavail(S_CMD_R_BYTE) == 0) { + msg_perr("Error: Single byte read not supported\n"); + exit(1); + } + /* This could be translated to single byte reads (if missing), * + * but now we dont support that. */ + if (sp_check_commandavail(S_CMD_R_NBYTES) == 0) { + msg_perr("Error: Read n bytes not supported\n"); + exit(1); + } + if (sp_check_commandavail(S_CMD_O_WRITEB) == 0) { + msg_perr("Error: Write to opbuf: write byte not supported\n"); + exit(1); + } + } + if (sp_docommand(S_CMD_Q_PGMNAME, 0, NULL, 16, pgmname)) { msg_perr("Warning: NAK to query programmer name\n"); strcpy((char *)pgmname, "(unknown)"); @@ -450,12 +485,6 @@ msg_pdbg(MSGHEADER "operation buffer size %d\n", sp_device_opbuf_size); - if (sp_docommand(S_CMD_Q_BUSTYPE, 0, NULL, 1, &c)) { - msg_perr("Warning: NAK to query supported buses\n"); - c = CHIP_BUSTYPE_NONSPI; /* A reasonable default for now. */ - } - buses_supported = c; - if (sp_docommand(S_CMD_O_INIT, 0, NULL, 0, NULL)) { msg_perr("Error: NAK to initialize operation buffer\n"); exit(1); @@ -468,6 +497,7 @@ sp_max_write_n = ((unsigned int)(rbuf[0]) << 0); sp_max_write_n |= ((unsigned int)(rbuf[1]) << 8); sp_max_write_n |= ((unsigned int)(rbuf[2]) << 16); + if (!sp_max_write_n) sp_max_write_n = (1<<24); msg_pdbg(MSGHEADER "Maximum write-n length %d\n", sp_max_write_n); sp_write_n_buf = malloc(sp_max_write_n); @@ -477,7 +507,7 @@ } sp_write_n_bytes = 0; } - + if ((sp_check_commandavail(S_CMD_Q_RDNMAXLEN)) &&((sp_docommand(S_CMD_Q_RDNMAXLEN,0,NULL, 3, rbuf) == 0))) { sp_max_read_n = ((unsigned int)(rbuf[0]) << 0); @@ -680,3 +710,25 @@ sp_opbuf_usage += 5; sp_prev_was_write = 0; } + +int serprog_spi_send_command(unsigned int writecnt, unsigned int readcnt, + const unsigned char *writearr, unsigned char *readarr) +{ + unsigned char *parmbuf; + int ret; + msg_pspew("%s, writecnt=%i, readcnt=%i\n", __func__, writecnt, readcnt); + if ((sp_opbuf_usage) || (sp_max_write_n && sp_write_n_bytes)) + sp_execute_opbuf(); + parmbuf = malloc(writecnt+6); + if (!parmbuf) sp_die("Error: cannot malloc SPI send param buffer"); + parmbuf[0] = (writecnt >> 0) & 0xFF; + parmbuf[1] = (writecnt >> 8) & 0xFF; + parmbuf[2] = (writecnt >> 16) & 0xFF; + parmbuf[3] = (readcnt >> 0) & 0xFF; + parmbuf[4] = (readcnt >> 8) & 0xFF; + parmbuf[5] = (readcnt >> 16) & 0xFF; + memcpy(&(parmbuf[6]),writearr,writecnt); + ret = sp_docommand(S_CMD_O_SPIOP, writecnt+6, parmbuf, readcnt, readarr); + free(parmbuf); + return ret; +} Index: programmer.h =================================================================== --- programmer.h (revision 1299) +++ programmer.h (working copy) @@ -560,6 +560,9 @@ #if CONFIG_OGP_SPI == 1 || CONFIG_NICINTEL_SPI == 1 || CONFIG_RAYER_SPI == 1 || (CONFIG_INTERNAL == 1 && (defined(__i386__) || defined(__x86_64__))) SPI_CONTROLLER_BITBANG, #endif +#if CONFIG_SERPROG == 1 + SPI_CONTROLLER_SERPROG, +#endif }; extern const int spi_programmer_count; @@ -622,6 +625,8 @@ uint8_t serprog_chip_readb(const chipaddr addr); void serprog_chip_readn(uint8_t *buf, const chipaddr addr, size_t len); void serprog_delay(int delay); +int serprog_spi_send_command(unsigned int writecnt, unsigned int readcnt, + const unsigned char *writearr, unsigned char *readarr); /* serial.c */ #if _WIN32
_______________________________________________ flashrom mailing list [email protected] http://www.flashrom.org/mailman/listinfo/flashrom
