Skip to content

Commit 9fd3d3f

Browse files
committed
Add support for selecting the SPI mode
This serprog spec addition added support for selecting the SPI mode for SPI_OP commands: https://review.coreboot.org/c/flashrom/+/81428 This commit adds support for the 0x17 S_SPI_MODE command.
1 parent 8b10a19 commit 9fd3d3f

File tree

2 files changed

+59
-2
lines changed

2 files changed

+59
-2
lines changed

main.c

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,18 @@
4040
(1 << S_CMD_S_BUSTYPE) | \
4141
(1 << S_CMD_S_SPI_FREQ) | \
4242
(1 << S_CMD_S_PIN_STATE) | \
43-
(1 << S_CMD_S_SPI_CS) \
43+
(1 << S_CMD_S_SPI_CS) | \
44+
(1 << S_CMD_S_SPI_MODE) \
4445
)
4546

47+
enum spi_mode {
48+
SPI_MODE_HALF_DUPLEX = 0,
49+
SPI_MODE_FULL_DUPLEX = 1,
50+
SPI_MODE_MAX = SPI_MODE_FULL_DUPLEX,
51+
};
52+
53+
enum spi_mode current_spi_mode = SPI_MODE_HALF_DUPLEX;
54+
4655
uint active_cs_pin = 0;
4756
#define NUM_CS_AVAILABLE 4 // Number of usable chip selects
4857
uint8_t cs_pins[NUM_CS_AVAILABLE] = { PIN_CS_0, PIN_CS_1, PIN_CS_2, PIN_CS_3 };
@@ -110,6 +119,33 @@ void spi_half_duplex(const pio_spi_inst_t *spi, uint32_t wlen, uint32_t rlen) {
110119
}
111120
}
112121

122+
void spi_full_duplex(const pio_spi_inst_t *spi, uint32_t wlen, uint32_t rlen) {
123+
uint8_t buffer[128];
124+
125+
putchar(S_ACK);
126+
127+
while (wlen || rlen) {
128+
size_t len = MIN(rlen, wlen);
129+
size_t chunk_size = MIN(sizeof(buffer), len);
130+
memset(buffer, 0, chunk_size);
131+
132+
if (wlen) {
133+
size_t chunk = MIN(wlen, chunk_size);
134+
fread(buffer, 1, chunk, stdin);
135+
wlen -= chunk;
136+
}
137+
138+
pio_spi_write8_read8_blocking(spi, buffer, buffer, chunk_size);
139+
140+
if (rlen) {
141+
size_t chunk = MIN(rlen, chunk_size);
142+
fwrite(buffer, 1, chunk, stdout);
143+
rlen -= chunk;
144+
}
145+
}
146+
fflush(stdout);
147+
}
148+
113149
void process(const pio_spi_inst_t *spi, int command) {
114150
static bool pin_state = false;
115151

@@ -165,7 +201,16 @@ void process(const pio_spi_inst_t *spi, int command) {
165201
uint32_t rlen = getu24();
166202

167203
cs_select(active_cs_pin);
168-
spi_half_duplex(spi, wlen, rlen);
204+
switch (current_spi_mode) {
205+
case SPI_MODE_HALF_DUPLEX:
206+
spi_half_duplex(spi, wlen, rlen);
207+
break;
208+
case SPI_MODE_FULL_DUPLEX:
209+
spi_full_duplex(spi, wlen, rlen);
210+
break;
211+
default:
212+
break;
213+
}
169214
cs_deselect(active_cs_pin);
170215
}
171216
break;
@@ -197,6 +242,17 @@ void process(const pio_spi_inst_t *spi, int command) {
197242
}
198243
break;
199244
}
245+
case S_CMD_S_SPI_MODE:
246+
{
247+
uint8_t spi_mode = getchar();
248+
if (spi_mode <= SPI_MODE_MAX) {
249+
current_spi_mode = spi_mode;
250+
putchar(S_ACK);
251+
} else {
252+
putchar(S_NAK);
253+
}
254+
break;
255+
}
200256
default:
201257
putchar(S_NAK);
202258
}

spi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@
2424
#define S_CMD_S_SPI_FREQ 0x14 /* Set SPI clock frequency */
2525
#define S_CMD_S_PIN_STATE 0x15 /* Enable/disable output drivers */
2626
#define S_CMD_S_SPI_CS 0x16 /* Set SPI chip select to use */
27+
#define S_CMD_S_SPI_MODE 0x17 /* Sets the spi mode used by S_CMD_O_SPIOP */

0 commit comments

Comments
 (0)