blob: 279f2e48637bcf3856e35cfcff7d8729860ffd4d [file] [log] [blame]
Nico Huber8d0f4652024-05-04 18:52:51 +02001/*
2 * This file is part of the flashprog project.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <stdbool.h>
16#include "flash.h"
17#include "chipdrivers.h"
18#include "programmer.h"
19#include "spi_command.h"
20#include "spi.h"
21
22static int spi_enter_exit_4ba(struct flashctx *const flash, const bool enter)
23{
24 const unsigned char cmd = enter ? JEDEC_ENTER_4_BYTE_ADDR_MODE : JEDEC_EXIT_4_BYTE_ADDR_MODE;
25 int ret = 1;
26
27 if (flash->chip->feature_bits & FEATURE_4BA_ENTER)
28 ret = spi_send_command(flash, sizeof(cmd), 0, &cmd, NULL);
29 else if (flash->chip->feature_bits & FEATURE_4BA_ENTER_WREN)
30 ret = spi_simple_write_cmd(flash, cmd, 0);
31 else if (flash->chip->feature_bits & FEATURE_4BA_ENTER_EAR7)
32 ret = spi_set_extended_address(flash, enter ? 0x80 : 0x00);
33
34 if (!ret)
35 flash->in_4ba_mode = enter;
36 return ret;
37}
38
39static int spi_enter_4ba(struct flashctx *const flash)
40{
41 return spi_enter_exit_4ba(flash, true);
42}
43
44static int spi_exit_4ba(struct flashctx *flash)
45{
46 return spi_enter_exit_4ba(flash, false);
47}
48
Nico Huber930d4212024-05-04 18:59:15 +020049static int spi_prepare_4ba(struct flashctx *const flash)
Nico Huber8d0f4652024-05-04 18:52:51 +020050{
Nico Huber8d0f4652024-05-04 18:52:51 +020051 flash->address_high_byte = -1;
52 flash->in_4ba_mode = false;
53
54 /* Be careful about 4BA chips and broken masters */
55 if (flash->chip->total_size > 16 * 1024 && spi_master_no_4ba_modes(flash)) {
56 /* If we can't use native instructions, bail out */
57 if ((flash->chip->feature_bits & FEATURE_4BA_NATIVE) != FEATURE_4BA_NATIVE
58 || !spi_master_4ba(flash)) {
59 msg_cerr("Programmer doesn't support this chip. Aborting.\n");
60 return 1;
61 }
62 }
63
64 /* Enable/disable 4-byte addressing mode if flash chip supports it */
65 if (flash->chip->feature_bits & (FEATURE_4BA_ENTER | FEATURE_4BA_ENTER_WREN | FEATURE_4BA_ENTER_EAR7)) {
66 int ret;
67 if (spi_master_4ba(flash))
68 ret = spi_enter_4ba(flash);
69 else
70 ret = spi_exit_4ba(flash);
71 if (ret) {
72 msg_cerr("Failed to set correct 4BA mode! Aborting.\n");
73 return 1;
74 }
75 }
76
77 return 0;
78}
Nico Huber930d4212024-05-04 18:59:15 +020079
Nico Huber0c9af0a2024-05-05 12:20:22 +020080static int spi_prepare_quad_io(struct flashctx *const flash)
81{
82 if (!spi_master_quad(flash))
83 return 0;
84
85 /* Check QE bit if present */
86 if (flash->chip->reg_bits.qe.reg != INVALID_REG) {
87 const struct reg_bit_info qe = flash->chip->reg_bits.qe;
88 uint8_t reg_val;
89
90 if (spi_read_register(flash, qe.reg, &reg_val)) {
91 msg_cwarn("Failed read chip register!\n");
92 reg_val = 0;
93 }
94 if (!(reg_val & 1 << qe.bit_index)) {
95 msg_cinfo("Quad-enable (QE) bit is unknown or unset, disabling quad i/o.\n");
96 flash->chip->feature_bits &= ~FEATURE_ANY_QUAD;
97 } else {
98 msg_cdbg("Quad-enable (QE) bit is set.\n");
99 }
100 }
101
102 return 0;
103}
104
Nico Huber4760b6e2024-01-06 23:45:28 +0100105static const struct spi_read_op *select_spi_fast_read(const struct flashctx *flash)
106{
107 static const struct {
108 unsigned int feature_check;
109 unsigned int master_check;
110 struct spi_read_op op;
111 #define MIO_CHECKS(flash_feature, master_feature) \
112 FEATURE_FAST_READ_##flash_feature, SPI_MASTER_##master_feature
113 } mio[] = { /* flash master 4BA mode dummies */
114 { MIO_CHECKS(QIO, QUAD_IO), { QUAD_IO_1_4_4, true, JEDEC_FAST_READ_QIO_4BA, 0xff, 3 } },
115 { MIO_CHECKS(QOUT, QUAD_IN), { QUAD_OUT_1_1_4, true, JEDEC_FAST_READ_QOUT_4BA, 0x00, 4 } },
116 { MIO_CHECKS(DIO, DUAL_IO), { DUAL_IO_1_2_2, true, JEDEC_FAST_READ_DIO_4BA, 0xff, 1 } },
117 { MIO_CHECKS(DOUT, DUAL_IN), { DUAL_OUT_1_1_2, true, JEDEC_FAST_READ_DOUT_4BA, 0x00, 2 } },
118 { MIO_CHECKS(QIO, QUAD_IO), { QUAD_IO_1_4_4, false, JEDEC_FAST_READ_QIO, 0xff, 3 } },
119 { MIO_CHECKS(QOUT, QUAD_IN), { QUAD_OUT_1_1_4, false, JEDEC_FAST_READ_QOUT, 0x00, 4 } },
120 { MIO_CHECKS(DIO, DUAL_IO), { DUAL_IO_1_2_2, false, JEDEC_FAST_READ_DIO, 0xff, 1 } },
121 { MIO_CHECKS(DOUT, DUAL_IN), { DUAL_OUT_1_1_2, false, JEDEC_FAST_READ_DOUT, 0x00, 2 } },
122 };
123
124 unsigned int i;
125 for (i = 0; i < ARRAY_SIZE(mio); ++i) {
126 if (mio[i].op.native_4ba && !(flash->chip->feature_bits & FEATURE_4BA_FAST_READ))
127 continue;
128 if ((flash->chip->feature_bits & mio[i].feature_check) != mio[i].feature_check)
129 continue;
130 if ((flash->mst.spi->features & mio[i].master_check) != mio[i].master_check)
131 continue;
132 if (mio[i].op.native_4ba && !spi_master_4ba(flash))
133 continue;
134 if (flash->mst.spi->probe_opcode(flash, mio[i].op.opcode))
135 return &mio[i].op;
136 }
137
138 return NULL;
139}
140
Nico Huber930d4212024-05-04 18:59:15 +0200141int spi_prepare_io(struct flashctx *const flash, const enum preparation_steps prep)
142{
143 if (prep != PREPARE_FULL)
144 return 0;
145
146 int ret = spi_prepare_4ba(flash);
147 if (ret)
148 return ret;
149
Nico Huber0c9af0a2024-05-05 12:20:22 +0200150 ret = spi_prepare_quad_io(flash);
151 if (ret)
152 return ret;
153
Nico Huber4760b6e2024-01-06 23:45:28 +0100154 flash->spi_fast_read = select_spi_fast_read(flash);
155
Nico Huber930d4212024-05-04 18:59:15 +0200156 return 0;
157}
158
159void spi_finish_io(struct flashctx *const flash)
160{
161}