blob: 76ad9a753453be7dbfa733df2dadf68034422a85 [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
80int spi_prepare_io(struct flashctx *const flash, const enum preparation_steps prep)
81{
82 if (prep != PREPARE_FULL)
83 return 0;
84
85 int ret = spi_prepare_4ba(flash);
86 if (ret)
87 return ret;
88
89 return 0;
90}
91
92void spi_finish_io(struct flashctx *const flash)
93{
94}