blob: 7fb1a10475c07b67e0c46713d61303a16e82047d [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
49int spi_prepare_4ba(struct flashctx *const flash, const enum preparation_steps prep)
50{
51 if (prep != PREPARE_FULL)
52 return 0;
53
54 flash->address_high_byte = -1;
55 flash->in_4ba_mode = false;
56
57 /* Be careful about 4BA chips and broken masters */
58 if (flash->chip->total_size > 16 * 1024 && spi_master_no_4ba_modes(flash)) {
59 /* If we can't use native instructions, bail out */
60 if ((flash->chip->feature_bits & FEATURE_4BA_NATIVE) != FEATURE_4BA_NATIVE
61 || !spi_master_4ba(flash)) {
62 msg_cerr("Programmer doesn't support this chip. Aborting.\n");
63 return 1;
64 }
65 }
66
67 /* Enable/disable 4-byte addressing mode if flash chip supports it */
68 if (flash->chip->feature_bits & (FEATURE_4BA_ENTER | FEATURE_4BA_ENTER_WREN | FEATURE_4BA_ENTER_EAR7)) {
69 int ret;
70 if (spi_master_4ba(flash))
71 ret = spi_enter_4ba(flash);
72 else
73 ret = spi_exit_4ba(flash);
74 if (ret) {
75 msg_cerr("Failed to set correct 4BA mode! Aborting.\n");
76 return 1;
77 }
78 }
79
80 return 0;
81}