summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRiku Viitanen <riku.viitanen@protonmail.com>2024-01-15 19:15:49 +0200
committerAnastasia Klimchuk <aklm@chromium.org>2024-03-01 07:01:23 +0000
commite8c350f55e596aae3ab2bbc210b68389e2301a6c (patch)
tree8081356b04185725765f9b092172162afd4b2955
parent6d128a4fff73a39e7f1134579bfebe1a2c1f6146 (diff)
downloadflashrom-e8c350f55e596aae3ab2bbc210b68389e2301a6c.tar.gz
flashrom-e8c350f55e596aae3ab2bbc210b68389e2301a6c.tar.bz2
flashrom-e8c350f55e596aae3ab2bbc210b68389e2301a6c.zip
serprog: Add support for multiple SPI chip selects
Tested with an EliteBook 8560w, Pi Pico, and my serprog firmware: https://codeberg.org/Riku_V/pico-serprog/ As seen on Flashprog: https://review.sourcearcade.org/c/flashprog/+/51 Change-Id: If8052bc6f5c314dcc493bc083bb8270723efaae7 Signed-off-by: Riku Viitanen <riku.viitanen@protonmail.com> Reviewed-on: https://review.coreboot.org/c/flashrom/+/80498 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Anastasia Klimchuk <aklm@chromium.org>
-rw-r--r--Documentation/serprog-protocol.txt4
-rw-r--r--doc/classic_cli_manpage.rst8
-rw-r--r--serprog.c28
3 files changed, 39 insertions, 1 deletions
diff --git a/Documentation/serprog-protocol.txt b/Documentation/serprog-protocol.txt
index 6b7e7e330..d58b8e98e 100644
--- a/Documentation/serprog-protocol.txt
+++ b/Documentation/serprog-protocol.txt
@@ -35,6 +35,7 @@ COMMAND Description Parameters Return Value
+ slen bytes of data
0x14 Set SPI clock frequency in Hz 32-bit requested frequency ACK + 32-bit set frequency / NAK
0x15 Toggle flash chip pin drivers 8-bit (0 disable, else enable) ACK / NAK
+0x16 Set SPI Chip Select 8-bit ACK / NAK
0x?? unimplemented command - invalid.
@@ -89,6 +90,9 @@ Additional information of the above commands:
remain attached to the flash chip even when the board is running. The user is responsible to
NOT connect VCC and other permanently externally driven signals to the programmer as needed.
If the value is 0, then the drivers should be disabled, otherwise they should be enabled.
+ 0x16 (S_SPI_CS):
+ Set which SPI Chip Select pin to use. This operation is immediate,
+ meaning it doesn't 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.
diff --git a/doc/classic_cli_manpage.rst b/doc/classic_cli_manpage.rst
index 0cd45caae..c46edf6f1 100644
--- a/doc/classic_cli_manpage.rst
+++ b/doc/classic_cli_manpage.rst
@@ -741,6 +741,14 @@ Example that sets the frequency to 2 MHz::
flashrom -p serprog:dev=/dev/device:baud,spispeed=2M
+Optional ``cs`` parameter can be used to switch which chip select number is used. This allows connecting multiple
+chips at once and selecting which one to flash by software means (rather than rewiring)::
+
+ flashrom -p serprog:dev=/dev/device:baud,cs=0
+
+The particular programmer implementation needs to support this feature, for it to work. If the requested chip
+select isn't available, flashrom will fail safely.
+
More information about serprog is available in **serprog-protocol.txt** in the source distribution.
diff --git a/serprog.c b/serprog.c
index b51f0cfe3..c2965c52b 100644
--- a/serprog.c
+++ b/serprog.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2009, 2011 Urja Rannikko <urjaman@gmail.com>
* Copyright (C) 2009 Carl-Daniel Hailfinger
+ * Copyright (C) 2024 Riku Viitanen <riku.viitanen@protonmail.com>
*
* 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
@@ -63,6 +64,7 @@
#define S_CMD_O_SPIOP 0x13 /* Perform SPI operation. */
#define S_CMD_S_SPI_FREQ 0x14 /* Set SPI clock frequency */
#define S_CMD_S_PIN_STATE 0x15 /* Enable/disable output drivers */
+#define S_CMD_S_SPI_CS 0x16 /* Set SPI chip select to use */
#define MSGHEADER "serprog: "
@@ -742,7 +744,7 @@ static int serprog_init(const struct programmer_cfg *cfg)
/* Check for the minimum operational set of commands. */
if (serprog_buses_supported & BUS_SPI) {
uint8_t bt = BUS_SPI;
- char *spispeed;
+ char *spispeed, *cs;
if (sp_check_commandavail(S_CMD_O_SPIOP) == 0) {
msg_perr("Error: SPI operation not supported while the "
"bustype is SPI\n");
@@ -822,6 +824,30 @@ static int serprog_init(const struct programmer_cfg *cfg)
}
}
free(spispeed);
+ cs = extract_programmer_param_str(cfg, "cs");
+ if (cs && strlen(cs)) {
+ char *endptr = NULL;
+ errno = 0;
+ unsigned long cs_num = strtoul(cs, &endptr, 0);
+ if (errno || *endptr || cs_num > 255) {
+ msg_perr("Error: Invalid chip select requested! "
+ "Only 0-255 are valid.\n");
+ free(cs);
+ goto init_err_cleanup_exit;
+ }
+ free(cs);
+ if (!sp_check_commandavail(S_CMD_S_SPI_CS)) {
+ msg_perr("Error: Setting SPI chip select is not supported!\n");
+ goto init_err_cleanup_exit;
+ }
+ msg_pdbg(MSGHEADER "Requested to use chip select %lu.\n", cs_num);
+ uint8_t cs_num8 = cs_num;
+ if (sp_docommand(S_CMD_S_SPI_CS, 1, &cs_num8, 0, NULL)) {
+ msg_perr("Error: Chip select %u not supported "
+ "by programmer!\n", cs_num8);
+ goto init_err_cleanup_exit;
+ }
+ }
bt = serprog_buses_supported;
if (sp_docommand(S_CMD_S_BUSTYPE, 1, &bt, 0, NULL))
goto init_err_cleanup_exit;