blob: 4c57d7e1ccb7cea2a11bb037a61e8e93ef196d6f [file] [log] [blame]
Nico Huberd5185632024-01-05 18:44:41 +01001/*
2 * This file is part of the flashrom project.
3 *
Nico Huber9512c9c2025-01-30 22:38:18 +01004 * Copyright (C) 2024 Nico Huber <nico.h@gmx.de>
5 *
Nico Huberd5185632024-01-05 18:44:41 +01006 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#ifndef __SPI_COMMAND_H__
18#define __SPI_COMMAND_H__ 1
19
20#include <stdlib.h>
21#include <stdbool.h>
22
23/*
24 * Modern SPI flashes support dual and quad i/o modes. However, there are
25 * subtle differences about which parts of a transactions are transferred
26 * in which mode. The transaction is generally divided into three phases:
27 * * opcode
28 * * address
29 * * data
30 *
31 * For each phase, the number of concurrently transferred bits is specified,
32 * hence we get a triple like
33 * * 1-1-1
34 * which tells us that all three phases are transferred in single i/o
35 * mode. Or, for instance,
36 * * 1-4-4
37 * which tells us the opcode is transferred in single i/o mode, but
38 * the address and data are transferred in quad i/o mode.
39 *
40 * There are a few common combinations, often chips support all of them:
41 * * 1-1-1 single i/o
42 * * 1-1-2 dual output (for reads, only the flash outputs two bits at once)
43 * * 1-2-2 dual i/o (both controller and flash can transfer two bits at once)
44 * * 1-1-4 quad output (for reads, only the flash outputs four bits at once)
45 * * 1-4-4 quad i/o (both controller and flash can transfer four bits at once)
46 * * 4-4-4 QPI
47 * In all modes that transfer the opcode in single i/o, the opcode tells the
48 * flash what to expect, i.e. how further bytes will be transferred. This
49 * achieves backwards compatibility with simple SPI controllers. The QPI
50 * mode, OTOH, is not backwards compatible and usually needs to be entered
51 * first with a special opcode. In QPI mode, only fast-read instructions
52 * (w/ dummy cycles) are supported; the number of dummy cycles is often
53 * configurable.
54 *
55 * For dual i/o, MOSI and MISO lines are bidirectional. So this can work
56 * without any special setup, if both controller and flash are compatible.
57 *
58 * For quad i/o, usually the flash's /HOLD and /WP pins are re-purposed, and
59 * the controller needs additional pins. The pin muxes inside the flash are
60 * usually controlled by a quad-enable (QE) bit in the status register. This
61 * is *not* to be confused with entering QPI mode. Quad-enable merely says
62 * that the pins are available for data transfer.
63 */
64enum io_mode {
65 SINGLE_IO_1_1_1,
66 DUAL_OUT_1_1_2,
67 DUAL_IO_1_2_2,
68 QUAD_OUT_1_1_4,
69 QUAD_IO_1_4_4,
70 QPI_4_4_4,
71};
72
Nico Huber1b1deda2024-04-18 00:35:48 +020073enum io_mode spi_current_io_mode(const struct flashctx *);
74
Nico Huber4760b6e2024-01-06 23:45:28 +010075/* describes properties of a read operation */
76struct spi_read_op {
77 enum io_mode io_mode;
78 bool native_4ba;
79 uint8_t opcode;
80 uint8_t mode_byte; /* optional byte to send after the address, if != 0 */
81 uint8_t dummy_len; /* dummy bytes (including optional mode byte) */
82};
83
Nico Hubera1b7f352024-03-25 18:32:11 +010084const struct spi_read_op *get_spi_read_op(const struct flashctx *);
85
86static inline unsigned int spi_dummy_cycles(const struct spi_read_op *const op)
87{
88 return op->dummy_len * 8
89 / (op->io_mode == SINGLE_IO_1_1_1 ? 1
90 : (op->io_mode <= DUAL_IO_1_2_2 ? 2 : 4));
91}
92
Nico Huberd5185632024-01-05 18:44:41 +010093struct spi_command {
94 enum io_mode io_mode;
95 size_t opcode_len; /* bytes to write in opcode i/o phase */
96 size_t address_len; /* bytes to write in address i/o phase */
97 size_t write_len; /* bytes to write in data i/o phase */
98 size_t high_z_len; /* dummy bytes to skip in data i/o phase */
99 size_t read_len; /* bytes to read in data i/o phase */
100 const unsigned char *writearr;
101 unsigned char *readarr;
102};
103#define NULL_SPI_CMD { 0, 0, 0, 0, 0, 0, NULL, NULL, }
104
105static inline size_t spi_write_len(const struct spi_command *const cmd)
106{
107 return cmd->opcode_len + cmd->address_len + cmd->write_len;
108}
109
110static inline size_t spi_read_len(const struct spi_command *const cmd)
111{
112 return cmd->high_z_len + cmd->read_len;
113}
114
115static inline bool spi_is_empty(const struct spi_command *const cmd)
116{
117 return !spi_write_len(cmd) && !spi_read_len(cmd);
118}
119
120int spi_send_command(const struct flashctx *, unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr);
121int spi_send_multicommand(const struct flashctx *, struct spi_command *cmds);
122
123#endif /* !__SPI_COMMAND_H__ */