blob: ea24b93027910f11490fb1b13b03e3112ecb132a [file] [log] [blame]
snelson8913d082010-02-26 05:48:29 +00001/*
2 * This file is part of the flashrom project.
3 *
hailfinger39d159a2010-05-21 23:09:42 +00004 * Copyright (C) 2007, 2008, 2009, 2010 Carl-Daniel Hailfinger
snelson8913d082010-02-26 05:48:29 +00005 * Copyright (C) 2008 coresystems GmbH
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
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.
snelson8913d082010-02-26 05:48:29 +000015 */
16
17/*
18 * Contains the common SPI chip driver functions
19 */
20
Nico Huber4c8a9562017-10-15 11:20:58 +020021#include <stddef.h>
snelson8913d082010-02-26 05:48:29 +000022#include <string.h>
Edward O'Callaghan031831d2019-06-19 16:27:43 +100023#include <stdbool.h>
snelson8913d082010-02-26 05:48:29 +000024#include "flash.h"
25#include "flashchips.h"
26#include "chipdrivers.h"
hailfinger428f6852010-07-27 22:41:39 +000027#include "programmer.h"
snelson8913d082010-02-26 05:48:29 +000028#include "spi.h"
Boris Baykov1a2f5322016-06-11 18:29:00 +020029#include "spi4ba.h"
snelson8913d082010-02-26 05:48:29 +000030
David Hendricks57b75242015-11-20 15:54:07 -080031enum id_type {
32 RDID,
33 RDID4,
34 REMS,
35// RES1, /* TODO */
36 RES2,
37 NUM_ID_TYPES,
38};
39
40static struct {
41 int is_cached;
42 unsigned char bytes[4]; /* enough to hold largest ID type */
43} id_cache[NUM_ID_TYPES];
44
45void clear_spi_id_cache(void)
46{
47 memset(id_cache, 0, sizeof(id_cache));
48 return;
49}
50
Souvik Ghoshd75cd672016-06-17 14:21:39 -070051static int spi_rdid(struct flashctx *flash, unsigned char *readarr, int bytes)
snelson8913d082010-02-26 05:48:29 +000052{
krause2eb76212011-01-17 07:50:42 +000053 static const unsigned char cmd[JEDEC_RDID_OUTSIZE] = { JEDEC_RDID };
snelson8913d082010-02-26 05:48:29 +000054 int ret;
55 int i;
56
Souvik Ghoshd75cd672016-06-17 14:21:39 -070057 ret = spi_send_command(flash, sizeof(cmd), bytes, cmd, readarr);
snelson8913d082010-02-26 05:48:29 +000058 if (ret)
59 return ret;
snelsonfc007bb2010-03-24 23:14:32 +000060 msg_cspew("RDID returned");
snelson8913d082010-02-26 05:48:29 +000061 for (i = 0; i < bytes; i++)
snelsonfc007bb2010-03-24 23:14:32 +000062 msg_cspew(" 0x%02x", readarr[i]);
63 msg_cspew(". ");
snelson8913d082010-02-26 05:48:29 +000064 return 0;
65}
66
Souvik Ghoshd75cd672016-06-17 14:21:39 -070067static int spi_rems(struct flashctx *flash, unsigned char *readarr)
snelson8913d082010-02-26 05:48:29 +000068{
69 unsigned char cmd[JEDEC_REMS_OUTSIZE] = { JEDEC_REMS, 0, 0, 0 };
70 uint32_t readaddr;
71 int ret;
72
Souvik Ghoshd75cd672016-06-17 14:21:39 -070073 ret = spi_send_command(flash, sizeof(cmd), JEDEC_REMS_INSIZE, cmd, readarr);
snelson8913d082010-02-26 05:48:29 +000074 if (ret == SPI_INVALID_ADDRESS) {
75 /* Find the lowest even address allowed for reads. */
Souvik Ghoshd75cd672016-06-17 14:21:39 -070076 readaddr = (spi_get_valid_read_addr(flash) + 1) & ~1;
snelson8913d082010-02-26 05:48:29 +000077 cmd[1] = (readaddr >> 16) & 0xff,
78 cmd[2] = (readaddr >> 8) & 0xff,
79 cmd[3] = (readaddr >> 0) & 0xff,
Souvik Ghoshd75cd672016-06-17 14:21:39 -070080 ret = spi_send_command(flash, sizeof(cmd), JEDEC_REMS_INSIZE, cmd, readarr);
snelson8913d082010-02-26 05:48:29 +000081 }
82 if (ret)
83 return ret;
stefanct371e7e82011-07-07 19:56:58 +000084 msg_cspew("REMS returned 0x%02x 0x%02x. ", readarr[0], readarr[1]);
snelson8913d082010-02-26 05:48:29 +000085 return 0;
86}
87
Souvik Ghoshd75cd672016-06-17 14:21:39 -070088static int spi_res(struct flashctx *flash, unsigned char *readarr, int bytes)
snelson8913d082010-02-26 05:48:29 +000089{
90 unsigned char cmd[JEDEC_RES_OUTSIZE] = { JEDEC_RES, 0, 0, 0 };
91 uint32_t readaddr;
92 int ret;
hailfingercb0564e2010-06-20 10:39:33 +000093 int i;
snelson8913d082010-02-26 05:48:29 +000094
Souvik Ghoshd75cd672016-06-17 14:21:39 -070095 ret = spi_send_command(flash, sizeof(cmd), bytes, cmd, readarr);
snelson8913d082010-02-26 05:48:29 +000096 if (ret == SPI_INVALID_ADDRESS) {
97 /* Find the lowest even address allowed for reads. */
Souvik Ghoshd75cd672016-06-17 14:21:39 -070098 readaddr = (spi_get_valid_read_addr(flash) + 1) & ~1;
snelson8913d082010-02-26 05:48:29 +000099 cmd[1] = (readaddr >> 16) & 0xff,
100 cmd[2] = (readaddr >> 8) & 0xff,
101 cmd[3] = (readaddr >> 0) & 0xff,
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700102 ret = spi_send_command(flash, sizeof(cmd), bytes, cmd, readarr);
snelson8913d082010-02-26 05:48:29 +0000103 }
104 if (ret)
105 return ret;
hailfingercb0564e2010-06-20 10:39:33 +0000106 msg_cspew("RES returned");
107 for (i = 0; i < bytes; i++)
108 msg_cspew(" 0x%02x", readarr[i]);
109 msg_cspew(". ");
snelson8913d082010-02-26 05:48:29 +0000110 return 0;
111}
112
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700113int spi_write_enable(struct flashctx *flash)
snelson8913d082010-02-26 05:48:29 +0000114{
krause2eb76212011-01-17 07:50:42 +0000115 static const unsigned char cmd[JEDEC_WREN_OUTSIZE] = { JEDEC_WREN };
snelson8913d082010-02-26 05:48:29 +0000116 int result;
117
118 /* Send WREN (Write Enable) */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700119 result = spi_send_command(flash, sizeof(cmd), 0, cmd, NULL);
snelson8913d082010-02-26 05:48:29 +0000120
121 if (result)
snelsonfc007bb2010-03-24 23:14:32 +0000122 msg_cerr("%s failed\n", __func__);
snelson8913d082010-02-26 05:48:29 +0000123
124 return result;
125}
126
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700127int spi_write_disable(struct flashctx *flash)
snelson8913d082010-02-26 05:48:29 +0000128{
krause2eb76212011-01-17 07:50:42 +0000129 static const unsigned char cmd[JEDEC_WRDI_OUTSIZE] = { JEDEC_WRDI };
snelson8913d082010-02-26 05:48:29 +0000130
131 /* Send WRDI (Write Disable) */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700132 return spi_send_command(flash, sizeof(cmd), 0, cmd, NULL);
snelson8913d082010-02-26 05:48:29 +0000133}
134
David Hendricks7f7c7112012-10-11 17:15:48 -0700135static void rdid_get_ids(unsigned char *readarr,
136 int bytes, uint32_t *id1, uint32_t *id2)
snelson8913d082010-02-26 05:48:29 +0000137{
snelson8913d082010-02-26 05:48:29 +0000138 if (!oddparity(readarr[0]))
snelsonfc007bb2010-03-24 23:14:32 +0000139 msg_cdbg("RDID byte 0 parity violation. ");
snelson8913d082010-02-26 05:48:29 +0000140
hailfingercb0564e2010-06-20 10:39:33 +0000141 /* Check if this is a continuation vendor ID.
142 * FIXME: Handle continuation device IDs.
143 */
snelson8913d082010-02-26 05:48:29 +0000144 if (readarr[0] == 0x7f) {
145 if (!oddparity(readarr[1]))
snelsonfc007bb2010-03-24 23:14:32 +0000146 msg_cdbg("RDID byte 1 parity violation. ");
David Hendricks7f7c7112012-10-11 17:15:48 -0700147 *id1 = (readarr[0] << 8) | readarr[1];
148 *id2 = readarr[2];
snelson8913d082010-02-26 05:48:29 +0000149 if (bytes > 3) {
David Hendricks7f7c7112012-10-11 17:15:48 -0700150 *id2 <<= 8;
151 *id2 |= readarr[3];
snelson8913d082010-02-26 05:48:29 +0000152 }
153 } else {
David Hendricks7f7c7112012-10-11 17:15:48 -0700154 *id1 = readarr[0];
155 *id2 = (readarr[1] << 8) | readarr[2];
snelson8913d082010-02-26 05:48:29 +0000156 }
David Hendricks7f7c7112012-10-11 17:15:48 -0700157}
snelson8913d082010-02-26 05:48:29 +0000158
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700159static int compare_id(struct flashctx *flash, uint32_t id1, uint32_t id2)
David Hendricks7f7c7112012-10-11 17:15:48 -0700160{
161 msg_cdbg("id1 0x%02x, id2 0x%02x\n", id1, id2);
snelson8913d082010-02-26 05:48:29 +0000162
Edward O'Callaghan71e23142019-03-03 23:08:22 +1100163 if (id1 == flash->chip->manufacture_id && id2 == flash->chip->model_id)
snelson8913d082010-02-26 05:48:29 +0000164 return 1;
snelson8913d082010-02-26 05:48:29 +0000165
166 /* Test if this is a pure vendor match. */
Patrick Georgif3fa2992017-02-02 16:24:44 +0100167 if (id1 == flash->chip->manufacture_id &&
168 GENERIC_DEVICE_ID == flash->chip->model_id)
snelson8913d082010-02-26 05:48:29 +0000169 return 1;
170
171 /* Test if there is any vendor ID. */
Patrick Georgif3fa2992017-02-02 16:24:44 +0100172 if (GENERIC_MANUF_ID == flash->chip->manufacture_id &&
snelson8913d082010-02-26 05:48:29 +0000173 id1 != 0xff)
174 return 1;
175
176 return 0;
177}
178
Edward O'Callaghanc2a12a92020-05-14 17:58:32 +1000179static int probe_spi_rdid_generic(struct flashctx *flash, int bytes)
snelson8913d082010-02-26 05:48:29 +0000180{
David Hendricks57b75242015-11-20 15:54:07 -0800181 uint32_t id1, id2;
Edward O'Callaghanc2a12a92020-05-14 17:58:32 +1000182 enum id_type idty = bytes == 3 ? RDID : RDID4;
David Hendricks7f7c7112012-10-11 17:15:48 -0700183
Edward O'Callaghanc2a12a92020-05-14 17:58:32 +1000184 if (!id_cache[idty].is_cached) {
185 const int ret = spi_rdid(flash, id_cache[idty].bytes, bytes);
186 if (ret == SPI_INVALID_LENGTH)
187 msg_cinfo("%d byte RDID not supported on this SPI controller\n", bytes);
188 if (ret)
David Hendricks7f7c7112012-10-11 17:15:48 -0700189 return 0;
Edward O'Callaghanc2a12a92020-05-14 17:58:32 +1000190 id_cache[idty].is_cached = 1;
David Hendricks7f7c7112012-10-11 17:15:48 -0700191 }
192
Edward O'Callaghanc2a12a92020-05-14 17:58:32 +1000193 rdid_get_ids(id_cache[idty].bytes, bytes, &id1, &id2);
David Hendricks7f7c7112012-10-11 17:15:48 -0700194 return compare_id(flash, id1, id2);
snelson8913d082010-02-26 05:48:29 +0000195}
196
Edward O'Callaghanc2a12a92020-05-14 17:58:32 +1000197int probe_spi_rdid(struct flashctx *flash)
198{
199 return probe_spi_rdid_generic(flash, 3);
200}
201
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700202int probe_spi_rdid4(struct flashctx *flash)
snelson8913d082010-02-26 05:48:29 +0000203{
Edward O'Callaghanc2a12a92020-05-14 17:58:32 +1000204 return probe_spi_rdid_generic(flash, 4);
snelson8913d082010-02-26 05:48:29 +0000205}
206
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700207int probe_spi_rems(struct flashctx *flash)
snelson8913d082010-02-26 05:48:29 +0000208{
David Hendricks57b75242015-11-20 15:54:07 -0800209 uint32_t id1, id2;
snelson8913d082010-02-26 05:48:29 +0000210
David Hendricks57b75242015-11-20 15:54:07 -0800211 if (!id_cache[REMS].is_cached) {
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700212 if (spi_rems(flash, id_cache[REMS].bytes))
David Hendricks7f7c7112012-10-11 17:15:48 -0700213 return 0;
David Hendricks57b75242015-11-20 15:54:07 -0800214 id_cache[REMS].is_cached = 1;
stefanct9e6b98a2011-05-28 02:37:14 +0000215 }
snelson8913d082010-02-26 05:48:29 +0000216
David Hendricks57b75242015-11-20 15:54:07 -0800217 id1 = id_cache[REMS].bytes[0];
218 id2 = id_cache[REMS].bytes[1];
David Hendricks7f7c7112012-10-11 17:15:48 -0700219 return compare_id(flash, id1, id2);
snelson8913d082010-02-26 05:48:29 +0000220}
221
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700222int probe_spi_res1(struct flashctx *flash)
snelson8913d082010-02-26 05:48:29 +0000223{
krause2eb76212011-01-17 07:50:42 +0000224 static const unsigned char allff[] = {0xff, 0xff, 0xff};
225 static const unsigned char all00[] = {0x00, 0x00, 0x00};
snelson8913d082010-02-26 05:48:29 +0000226 unsigned char readarr[3];
227 uint32_t id2;
snelson8913d082010-02-26 05:48:29 +0000228
hailfinger59a83572010-05-28 17:07:57 +0000229 /* We only want one-byte RES if RDID and REMS are unusable. */
230
snelson8913d082010-02-26 05:48:29 +0000231 /* Check if RDID is usable and does not return 0xff 0xff 0xff or
232 * 0x00 0x00 0x00. In that case, RES is pointless.
233 */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700234 if (!spi_rdid(flash, readarr, 3) && memcmp(readarr, allff, 3) &&
snelson8913d082010-02-26 05:48:29 +0000235 memcmp(readarr, all00, 3)) {
236 msg_cdbg("Ignoring RES in favour of RDID.\n");
237 return 0;
238 }
239 /* Check if REMS is usable and does not return 0xff 0xff or
240 * 0x00 0x00. In that case, RES is pointless.
241 */
Edward O'Callaghan3eaadb02019-10-14 16:08:23 +1100242 if (!spi_rems(flash, readarr) &&
243 memcmp(readarr, allff, JEDEC_REMS_INSIZE) &&
snelson8913d082010-02-26 05:48:29 +0000244 memcmp(readarr, all00, JEDEC_REMS_INSIZE)) {
245 msg_cdbg("Ignoring RES in favour of REMS.\n");
246 return 0;
247 }
248
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700249 if (spi_res(flash, readarr, 1)) {
snelson8913d082010-02-26 05:48:29 +0000250 return 0;
stefanct9e6b98a2011-05-28 02:37:14 +0000251 }
snelson8913d082010-02-26 05:48:29 +0000252
snelson8913d082010-02-26 05:48:29 +0000253 id2 = readarr[0];
hailfinger59a83572010-05-28 17:07:57 +0000254
snelsonfc007bb2010-03-24 23:14:32 +0000255 msg_cdbg("%s: id 0x%x\n", __func__, id2);
hailfinger59a83572010-05-28 17:07:57 +0000256
Patrick Georgif3fa2992017-02-02 16:24:44 +0100257 if (id2 != flash->chip->model_id)
snelson8913d082010-02-26 05:48:29 +0000258 return 0;
259
snelson8913d082010-02-26 05:48:29 +0000260 return 1;
261}
262
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700263int probe_spi_res2(struct flashctx *flash)
hailfinger59a83572010-05-28 17:07:57 +0000264{
hailfinger59a83572010-05-28 17:07:57 +0000265 uint32_t id1, id2;
266
David Hendricks57b75242015-11-20 15:54:07 -0800267 if (!id_cache[RES2].is_cached) {
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700268 if (spi_res(flash, id_cache[RES2].bytes, 2))
David Hendricks57b75242015-11-20 15:54:07 -0800269 return 0;
270 id_cache[RES2].is_cached = 1;
stefanct9e6b98a2011-05-28 02:37:14 +0000271 }
hailfinger59a83572010-05-28 17:07:57 +0000272
David Hendricks57b75242015-11-20 15:54:07 -0800273 id1 = id_cache[RES2].bytes[0];
274 id2 = id_cache[RES2].bytes[1];
hailfinger59a83572010-05-28 17:07:57 +0000275 msg_cdbg("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2);
276
Patrick Georgif3fa2992017-02-02 16:24:44 +0100277 if (id1 != flash->chip->manufacture_id || id2 != flash->chip->model_id)
hailfinger59a83572010-05-28 17:07:57 +0000278 return 0;
279
hailfinger59a83572010-05-28 17:07:57 +0000280 return 1;
281}
282
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000283static int spi_poll_wip(struct flashctx *const flash, const unsigned int poll_delay)
284{
285 /* FIXME: We can't tell if spi_read_status_register() failed. */
286 /* FIXME: We don't time out. */
287 while (spi_read_status_register(flash) & SPI_SR_WIP)
288 programmer_delay(poll_delay);
289 /* FIXME: Check the status register for errors. */
290 return 0;
291}
292
Nico Huber4c8a9562017-10-15 11:20:58 +0200293/**
294 * Execute WREN plus another one byte `op`, optionally poll WIP afterwards.
295 *
296 * @param flash the flash chip's context
297 * @param op the operation to execute
298 * @param poll_delay interval in us for polling WIP, don't poll if zero
299 * @return 0 on success, non-zero otherwise
300 */
301static int spi_simple_write_cmd(struct flashctx *const flash, const uint8_t op, const unsigned int poll_delay)
snelson8913d082010-02-26 05:48:29 +0000302{
snelson8913d082010-02-26 05:48:29 +0000303 struct spi_command cmds[] = {
304 {
Nico Huber4c8a9562017-10-15 11:20:58 +0200305 .writecnt = 1,
306 .writearr = (const unsigned char[]){ JEDEC_WREN },
snelson8913d082010-02-26 05:48:29 +0000307 }, {
Nico Huber4c8a9562017-10-15 11:20:58 +0200308 .writecnt = 1,
309 .writearr = (const unsigned char[]){ op },
310 },
311 NULL_SPI_CMD,
312 };
snelson8913d082010-02-26 05:48:29 +0000313
Nico Huber4c8a9562017-10-15 11:20:58 +0200314 const int result = spi_send_multicommand(flash, cmds);
snelson8913d082010-02-26 05:48:29 +0000315 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000316 msg_cerr("%s failed during command execution\n", __func__);
snelson8913d082010-02-26 05:48:29 +0000317 return result;
318 }
319 /* Wait until the Write-In-Progress bit is cleared.
320 * This usually takes 1-85 s, so wait in 1 s steps.
321 */
Nico Huber4c8a9562017-10-15 11:20:58 +0200322
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000323 const int status = poll_delay ? spi_poll_wip(flash, poll_delay) : 0;
324
325 return result ? result : status;
326}
327
Edward O'Callaghana74ffcd2019-06-17 14:59:55 +1000328static int spi_set_extended_address(struct flashctx *const flash, const uint8_t addr_high)
329{
330 if (flash->address_high_byte != addr_high &&
331 spi_write_extended_address_register(flash, addr_high))
332 return -1;
333 flash->address_high_byte = addr_high;
334 return 0;
335}
336
Edward O'Callaghan031831d2019-06-19 16:27:43 +1000337static int spi_prepare_address(struct flashctx *const flash, uint8_t cmd_buf[],
338 const bool native_4ba, const unsigned int addr)
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000339{
Edward O'Callaghan031831d2019-06-19 16:27:43 +1000340 if (native_4ba || flash->in_4ba_mode) {
Edward O'Callaghana6673bd2019-06-24 15:22:28 +1000341 if (!spi_master_4ba(flash)) {
342 msg_cwarn("4-byte address requested but master can't handle 4-byte addresses.\n");
343 return -1;
344 }
Edward O'Callaghana74ffcd2019-06-17 14:59:55 +1000345 cmd_buf[1] = (addr >> 24) & 0xff;
346 cmd_buf[2] = (addr >> 16) & 0xff;
347 cmd_buf[3] = (addr >> 8) & 0xff;
348 cmd_buf[4] = (addr >> 0) & 0xff;
349 return 4;
350 } else {
351 if (flash->chip->feature_bits & FEATURE_4BA_EXT_ADDR) {
352 if (spi_set_extended_address(flash, addr >> 24))
353 return -1;
Edward O'Callaghana6673bd2019-06-24 15:22:28 +1000354 } else if (addr >> 24) {
355 msg_cerr("Can't handle 4-byte address for opcode '0x%02x'\n"
356 "with this chip/programmer combination.\n", cmd_buf[0]);
Edward O'Callaghan3eaadb02019-10-14 16:08:23 +1100357 return -1;
Edward O'Callaghana74ffcd2019-06-17 14:59:55 +1000358 }
359 cmd_buf[1] = (addr >> 16) & 0xff;
360 cmd_buf[2] = (addr >> 8) & 0xff;
361 cmd_buf[3] = (addr >> 0) & 0xff;
362 return 3;
363 }
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000364}
365
366/**
367 * Execute WREN plus another `op` that takes an address and
368 * optional data, poll WIP afterwards.
369 *
370 * @param flash the flash chip's context
371 * @param op the operation to execute
Edward O'Callaghan3eaadb02019-10-14 16:08:23 +1100372 * @param native_4ba whether `op` always takes a 4-byte address
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000373 * @param addr the address parameter to `op`
374 * @param out_bytes bytes to send after the address,
375 * may be NULL if and only if `out_bytes` is 0
376 * @param out_bytes number of bytes to send, 256 at most, may be zero
377 * @param poll_delay interval in us for polling WIP
378 * @return 0 on success, non-zero otherwise
379 */
Edward O'Callaghan031831d2019-06-19 16:27:43 +1000380static int spi_write_cmd(struct flashctx *const flash, const uint8_t op,
381 const bool native_4ba, const unsigned int addr,
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000382 const uint8_t *const out_bytes, const size_t out_len,
383 const unsigned int poll_delay)
384{
385 uint8_t cmd[1 + JEDEC_MAX_ADDR_LEN + 256];
386 struct spi_command cmds[] = {
387 {
388 .writecnt = 1,
389 .writearr = (const unsigned char[]){ JEDEC_WREN },
390 }, {
391 .writearr = cmd,
392 },
393 NULL_SPI_CMD,
394 };
395
396 cmd[0] = op;
Edward O'Callaghan031831d2019-06-19 16:27:43 +1000397 const int addr_len = spi_prepare_address(flash, cmd, native_4ba, addr);
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000398 if (addr_len < 0)
399 return 1;
400
401 if (1 + addr_len + out_len > sizeof(cmd)) {
402 msg_cerr("%s called for too long a write\n", __func__);
403 return 1;
404 }
Angel Pons6bfd9e62020-03-31 15:32:10 +0200405 if (!out_bytes && out_len > 0)
406 return 1;
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000407
408 memcpy(cmd + 1 + addr_len, out_bytes, out_len);
409 cmds[1].writecnt = 1 + addr_len + out_len;
410
411 const int result = spi_send_multicommand(flash, cmds);
412 if (result)
413 msg_cerr("%s failed during command execution at address 0x%x\n", __func__, addr);
414
415 const int status = spi_poll_wip(flash, poll_delay);
416
417 return result ? result : status;
Nico Huber4c8a9562017-10-15 11:20:58 +0200418}
419
420int spi_chip_erase_60(struct flashctx *flash)
421{
422 /* This usually takes 1-85s, so wait in 1s steps. */
423 return spi_simple_write_cmd(flash, 0x60, 1000 * 1000);
424}
425
426int spi_chip_erase_62(struct flashctx *flash)
427{
428 /* This usually takes 2-5s, so wait in 100ms steps. */
429 return spi_simple_write_cmd(flash, 0x62, 100 * 1000);
430}
431
432int spi_chip_erase_c7(struct flashctx *flash)
433{
434 /* This usually takes 1-85s, so wait in 1s steps. */
435 return spi_simple_write_cmd(flash, 0xc7, 1000 * 1000);
snelson8913d082010-02-26 05:48:29 +0000436}
437
Edward O'Callaghan3eaadb02019-10-14 16:08:23 +1100438int spi_block_erase_52(struct flashctx *flash, unsigned int addr,
439 unsigned int blocklen)
snelson8913d082010-02-26 05:48:29 +0000440{
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000441 /* This usually takes 100-4000ms, so wait in 100ms steps. */
Edward O'Callaghan031831d2019-06-19 16:27:43 +1000442 return spi_write_cmd(flash, 0x52, false, addr, NULL, 0, 100 * 1000);
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000443}
snelson8913d082010-02-26 05:48:29 +0000444
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000445/* Block size is usually
446 * 32M (one die) for Micron
447 */
448int spi_block_erase_c4(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
449{
450 /* This usually takes 240-480s, so wait in 500ms steps. */
Edward O'Callaghan031831d2019-06-19 16:27:43 +1000451 return spi_write_cmd(flash, 0xc4, false, addr, NULL, 0, 500 * 1000);
snelson8913d082010-02-26 05:48:29 +0000452}
453
454/* Block size is usually
455 * 64k for Macronix
456 * 32k for SST
457 * 4-32k non-uniform for EON
458 */
Edward O'Callaghan3eaadb02019-10-14 16:08:23 +1100459int spi_block_erase_d8(struct flashctx *flash, unsigned int addr,
460 unsigned int blocklen)
snelson8913d082010-02-26 05:48:29 +0000461{
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000462 /* This usually takes 100-4000ms, so wait in 100ms steps. */
Edward O'Callaghan031831d2019-06-19 16:27:43 +1000463 return spi_write_cmd(flash, 0xd8, false, addr, NULL, 0, 100 * 1000);
snelson8913d082010-02-26 05:48:29 +0000464}
465
466/* Block size is usually
467 * 4k for PMC
468 */
Edward O'Callaghan3eaadb02019-10-14 16:08:23 +1100469int spi_block_erase_d7(struct flashctx *flash, unsigned int addr,
470 unsigned int blocklen)
snelson8913d082010-02-26 05:48:29 +0000471{
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000472 /* This usually takes 100-4000ms, so wait in 100ms steps. */
Edward O'Callaghan031831d2019-06-19 16:27:43 +1000473 return spi_write_cmd(flash, 0xd7, false, addr, NULL, 0, 100 * 1000);
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000474}
snelson8913d082010-02-26 05:48:29 +0000475
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000476/* Page erase (usually 256B blocks) */
477int spi_block_erase_db(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
478{
479 /* This takes up to 20ms usually (on worn out devices
480 up to the 0.5s range), so wait in 1ms steps. */
Edward O'Callaghan031831d2019-06-19 16:27:43 +1000481 return spi_write_cmd(flash, 0xdb, false, addr, NULL, 0, 1 * 1000);
snelson8913d082010-02-26 05:48:29 +0000482}
483
snelson8913d082010-02-26 05:48:29 +0000484/* Sector size is usually 4k, though Macronix eliteflash has 64k */
Edward O'Callaghan3eaadb02019-10-14 16:08:23 +1100485int spi_block_erase_20(struct flashctx *flash, unsigned int addr,
486 unsigned int blocklen)
snelson8913d082010-02-26 05:48:29 +0000487{
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000488 /* This usually takes 15-800ms, so wait in 10ms steps. */
Edward O'Callaghan031831d2019-06-19 16:27:43 +1000489 return spi_write_cmd(flash, 0x20, false, addr, NULL, 0, 10 * 1000);
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000490}
snelson8913d082010-02-26 05:48:29 +0000491
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000492int spi_block_erase_50(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
493{
494 /* This usually takes 10ms, so wait in 1ms steps. */
Edward O'Callaghan031831d2019-06-19 16:27:43 +1000495 return spi_write_cmd(flash, 0x50, false, addr, NULL, 0, 1 * 1000);
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000496}
Stefan Reinauercce56d52010-11-22 18:22:21 -0800497
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000498int spi_block_erase_81(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
499{
500 /* This usually takes 8ms, so wait in 1ms steps. */
Edward O'Callaghan031831d2019-06-19 16:27:43 +1000501 return spi_write_cmd(flash, 0x81, false, addr, NULL, 0, 1 * 1000);
snelson8913d082010-02-26 05:48:29 +0000502}
503
Edward O'Callaghan3eaadb02019-10-14 16:08:23 +1100504int spi_block_erase_60(struct flashctx *flash, unsigned int addr,
505 unsigned int blocklen)
snelson8913d082010-02-26 05:48:29 +0000506{
Patrick Georgif3fa2992017-02-02 16:24:44 +0100507 if ((addr != 0) || (blocklen != flash->chip->total_size * 1024)) {
snelsonfc007bb2010-03-24 23:14:32 +0000508 msg_cerr("%s called with incorrect arguments\n",
snelson8913d082010-02-26 05:48:29 +0000509 __func__);
510 return -1;
511 }
512 return spi_chip_erase_60(flash);
513}
514
Alan Green5d709732019-09-16 12:32:25 +1000515int spi_block_erase_62(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
516{
517 if ((addr != 0) || (blocklen != flash->chip->total_size * 1024)) {
518 msg_cerr("%s called with incorrect arguments\n",
519 __func__);
520 return -1;
521 }
522 return spi_chip_erase_62(flash);
523}
524
Edward O'Callaghan3eaadb02019-10-14 16:08:23 +1100525int spi_block_erase_c7(struct flashctx *flash, unsigned int addr,
526 unsigned int blocklen)
snelson8913d082010-02-26 05:48:29 +0000527{
Patrick Georgif3fa2992017-02-02 16:24:44 +0100528 if ((addr != 0) || (blocklen != flash->chip->total_size * 1024)) {
snelsonfc007bb2010-03-24 23:14:32 +0000529 msg_cerr("%s called with incorrect arguments\n",
snelson8913d082010-02-26 05:48:29 +0000530 __func__);
531 return -1;
532 }
533 return spi_chip_erase_c7(flash);
534}
535
Edward O'Callaghan94934e82019-06-19 17:44:19 +1000536/* Erase 4 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes)
537 JEDEC_SE_4BA (21h) instruction is new for 4-bytes addressing flash chips.
538 The presence of this instruction for an exact chip should be checked
539 by its datasheet or from SFDP 4-Bytes Address Instruction Table (JESD216B). */
540int spi_block_erase_21(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
541{
542 /* This usually takes 15-800ms, so wait in 10ms steps. */
543 return spi_write_cmd(flash, 0x21, true, addr, NULL, 0, 10 * 1000);
544}
545
546/* Erase 32 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes)
547 JEDEC_BE_5C_4BA (5Ch) instruction is new for 4-bytes addressing flash chips.
548 The presence of this instruction for an exact chip should be checked
549 by its datasheet or from SFDP 4-Bytes Address Instruction Table (JESD216B). */
550int spi_block_erase_5c(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
551{
552 /* This usually takes 100-4000ms, so wait in 100ms steps. */
553 return spi_write_cmd(flash, 0x5c, true, addr, NULL, 0, 100 * 1000);
554}
555
556/* Erase 64 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes)
557 JEDEC_BE_DC_4BA (DCh) instruction is new for 4-bytes addressing flash chips.
558 The presence of this instruction for an exact chip should be checked
559 by its datasheet or from SFDP 4-Bytes Address Instruction Table (JESD216B). */
560int spi_block_erase_dc(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
561{
562 /* This usually takes 100-4000ms, so wait in 100ms steps. */
563 return spi_write_cmd(flash, 0xdc, true, addr, NULL, 0, 100 * 1000);
564}
565
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700566int spi_write_status_register_wren(const struct flashctx *flash, int status)
hailfingerc33d4732010-07-29 13:09:18 +0000567{
568 int result;
hailfingeree9ee132010-10-08 00:37:55 +0000569 int i = 0;
hailfingerc33d4732010-07-29 13:09:18 +0000570 struct spi_command cmds[] = {
571 {
572 /* WRSR requires either EWSR or WREN depending on chip type. */
573 .writecnt = JEDEC_WREN_OUTSIZE,
574 .writearr = (const unsigned char[]){ JEDEC_WREN },
575 .readcnt = 0,
576 .readarr = NULL,
577 }, {
578 .writecnt = JEDEC_WRSR_OUTSIZE,
579 .writearr = (const unsigned char[]){ JEDEC_WRSR, (unsigned char) status },
580 .readcnt = 0,
581 .readarr = NULL,
582 }, {
583 .writecnt = 0,
584 .writearr = NULL,
585 .readcnt = 0,
586 .readarr = NULL,
587 }};
588
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700589 result = spi_send_multicommand(flash, cmds);
hailfingerc33d4732010-07-29 13:09:18 +0000590 if (result) {
591 msg_cerr("%s failed during command execution\n",
592 __func__);
hailfingeree9ee132010-10-08 00:37:55 +0000593 /* No point in waiting for the command to complete if execution
594 * failed.
595 */
596 return result;
hailfingerc33d4732010-07-29 13:09:18 +0000597 }
hailfingeree9ee132010-10-08 00:37:55 +0000598 /* WRSR performs a self-timed erase before the changes take effect.
599 * This may take 50-85 ms in most cases, and some chips apparently
600 * allow running RDSR only once. Therefore pick an initial delay of
601 * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed.
602 */
hailfingerc33d4732010-07-29 13:09:18 +0000603 programmer_delay(100 * 1000);
Edward O'Callaghan8b5e4732019-03-05 15:27:53 +1100604 while (spi_read_status_register(flash) & SPI_SR_WIP) {
hailfingeree9ee132010-10-08 00:37:55 +0000605 if (++i > 490) {
606 msg_cerr("Error: WIP bit after WRSR never cleared\n");
607 return TIMEOUT_ERROR;
608 }
609 programmer_delay(10 * 1000);
610 }
611 return 0;
hailfingerc33d4732010-07-29 13:09:18 +0000612}
613
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700614int spi_byte_program(struct flashctx *flash, unsigned int addr, uint8_t databyte)
snelson8913d082010-02-26 05:48:29 +0000615{
616 int result;
617 struct spi_command cmds[] = {
618 {
619 .writecnt = JEDEC_WREN_OUTSIZE,
620 .writearr = (const unsigned char[]){ JEDEC_WREN },
621 .readcnt = 0,
622 .readarr = NULL,
623 }, {
624 .writecnt = JEDEC_BYTE_PROGRAM_OUTSIZE,
625 .writearr = (const unsigned char[]){
626 JEDEC_BYTE_PROGRAM,
627 (addr >> 16) & 0xff,
628 (addr >> 8) & 0xff,
629 (addr & 0xff),
630 databyte
631 },
632 .readcnt = 0,
633 .readarr = NULL,
634 }, {
635 .writecnt = 0,
636 .writearr = NULL,
637 .readcnt = 0,
638 .readarr = NULL,
639 }};
640
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700641 result = spi_send_multicommand(flash, cmds);
snelson8913d082010-02-26 05:48:29 +0000642 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000643 msg_cerr("%s failed during command execution at address 0x%x\n",
snelson8913d082010-02-26 05:48:29 +0000644 __func__, addr);
645 }
646 return result;
647}
648
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000649static int spi_nbyte_program(struct flashctx *flash, unsigned int addr, const uint8_t *bytes, unsigned int len)
snelson8913d082010-02-26 05:48:29 +0000650{
Edward O'Callaghana6673bd2019-06-24 15:22:28 +1000651 const bool native_4ba = flash->chip->feature_bits & FEATURE_4BA_WRITE && spi_master_4ba(flash);
Edward O'Callaghan031831d2019-06-19 16:27:43 +1000652 const uint8_t op = native_4ba ? JEDEC_BYTE_PROGRAM_4BA : JEDEC_BYTE_PROGRAM;
653 return spi_write_cmd(flash, op, native_4ba, addr, bytes, len, 10);
snelson8913d082010-02-26 05:48:29 +0000654}
655
Edward O'Callaghan3eaadb02019-10-14 16:08:23 +1100656int spi_nbyte_read(struct flashctx *flash, unsigned int address, uint8_t *bytes,
657 unsigned int len)
snelson8913d082010-02-26 05:48:29 +0000658{
Edward O'Callaghana6673bd2019-06-24 15:22:28 +1000659 const bool native_4ba = flash->chip->feature_bits & FEATURE_4BA_READ && spi_master_4ba(flash);
Edward O'Callaghan031831d2019-06-19 16:27:43 +1000660 uint8_t cmd[1 + JEDEC_MAX_ADDR_LEN] = { native_4ba ? JEDEC_READ_4BA : JEDEC_READ, };
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000661
Edward O'Callaghan031831d2019-06-19 16:27:43 +1000662 const int addr_len = spi_prepare_address(flash, cmd, native_4ba, address);
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000663 if (addr_len < 0)
664 return 1;
snelson8913d082010-02-26 05:48:29 +0000665
666 /* Send Read */
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000667 return spi_send_command(flash, 1 + addr_len, len, cmd, bytes);
snelson8913d082010-02-26 05:48:29 +0000668}
669
670/*
hailfinger39d159a2010-05-21 23:09:42 +0000671 * Read a part of the flash chip.
hailfingerc7d06c62010-07-14 16:19:05 +0000672 * FIXME: Use the chunk code from Michael Karcher instead.
Edward O'Callaghand825ac02019-07-26 21:36:16 +1000673 * Each naturally aligned area is read separately in chunks with a maximum size of chunksize.
snelson8913d082010-02-26 05:48:29 +0000674 */
Edward O'Callaghan3eaadb02019-10-14 16:08:23 +1100675int spi_read_chunked(struct flashctx *flash, uint8_t *buf, unsigned int start,
676 unsigned int len, unsigned int chunksize)
snelson8913d082010-02-26 05:48:29 +0000677{
David Hendricks1ed1d352011-11-23 17:54:37 -0800678 int rc = 0, chunk_status = 0;
stefanctc5eb8a92011-11-23 09:13:48 +0000679 unsigned int i, j, starthere, lenhere, toread;
Edward O'Callaghand825ac02019-07-26 21:36:16 +1000680 /* Limit for multi-die 4-byte-addressing chips. */
681 unsigned int area_size = min(flash->chip->total_size * 1024, 16 * 1024 * 1024);
snelson8913d082010-02-26 05:48:29 +0000682
683 /* Warning: This loop has a very unusual condition and body.
Edward O'Callaghand825ac02019-07-26 21:36:16 +1000684 * The loop needs to go through each area with at least one affected
685 * byte. The lowest area number is (start / area_size) since that
686 * division rounds down. The highest area number we want is the area
snelson8913d082010-02-26 05:48:29 +0000687 * where the last byte of the range lives. That last byte has the
Edward O'Callaghand825ac02019-07-26 21:36:16 +1000688 * address (start + len - 1), thus the highest area number is
689 * (start + len - 1) / area_size. Since we want to include that last
690 * area as well, the loop condition uses <=.
snelson8913d082010-02-26 05:48:29 +0000691 */
Edward O'Callaghand825ac02019-07-26 21:36:16 +1000692 for (i = start / area_size; i <= (start + len - 1) / area_size; i++) {
693 /* Byte position of the first byte in the range in this area. */
snelson8913d082010-02-26 05:48:29 +0000694 /* starthere is an offset to the base address of the chip. */
Edward O'Callaghand825ac02019-07-26 21:36:16 +1000695 starthere = max(start, i * area_size);
696 /* Length of bytes in the range in this area. */
697 lenhere = min(start + len, (i + 1) * area_size) - starthere;
snelson8913d082010-02-26 05:48:29 +0000698 for (j = 0; j < lenhere; j += chunksize) {
699 toread = min(chunksize, lenhere - j);
Edward O'Callaghan4fe3a972019-06-19 16:56:10 +1000700 chunk_status = spi_nbyte_read(flash, starthere + j, buf + starthere - start + j, toread);
David Hendricks1ed1d352011-11-23 17:54:37 -0800701 if (chunk_status) {
702 if (ignore_error(chunk_status)) {
703 /* fill this chunk with 0xff bytes and
704 let caller know about the error */
705 memset(buf + starthere - start + j, 0xff, toread);
706 rc = chunk_status;
707 chunk_status = 0;
708 continue;
709 } else {
710 rc = chunk_status;
711 break;
712 }
713 }
snelson8913d082010-02-26 05:48:29 +0000714 }
David Hendricks1ed1d352011-11-23 17:54:37 -0800715 if (chunk_status)
snelson8913d082010-02-26 05:48:29 +0000716 break;
717 }
718
719 return rc;
720}
721
722/*
hailfinger39d159a2010-05-21 23:09:42 +0000723 * Write a part of the flash chip.
hailfingerc7d06c62010-07-14 16:19:05 +0000724 * FIXME: Use the chunk code from Michael Karcher instead.
hailfinger39d159a2010-05-21 23:09:42 +0000725 * Each page is written separately in chunks with a maximum size of chunksize.
726 */
Edward O'Callaghan3eaadb02019-10-14 16:08:23 +1100727int spi_write_chunked(struct flashctx *flash, const uint8_t *buf, unsigned int start,
728 unsigned int len, unsigned int chunksize)
hailfinger39d159a2010-05-21 23:09:42 +0000729{
stefanctc5eb8a92011-11-23 09:13:48 +0000730 unsigned int i, j, starthere, lenhere, towrite;
hailfinger39d159a2010-05-21 23:09:42 +0000731 /* FIXME: page_size is the wrong variable. We need max_writechunk_size
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700732 * in struct flashctx to do this properly. All chips using
hailfinger39d159a2010-05-21 23:09:42 +0000733 * spi_chip_write_256 have page_size set to max_writechunk_size, so
734 * we're OK for now.
735 */
Patrick Georgif3fa2992017-02-02 16:24:44 +0100736 unsigned int page_size = flash->chip->page_size;
hailfinger39d159a2010-05-21 23:09:42 +0000737
738 /* Warning: This loop has a very unusual condition and body.
739 * The loop needs to go through each page with at least one affected
740 * byte. The lowest page number is (start / page_size) since that
741 * division rounds down. The highest page number we want is the page
742 * where the last byte of the range lives. That last byte has the
743 * address (start + len - 1), thus the highest page number is
744 * (start + len - 1) / page_size. Since we want to include that last
745 * page as well, the loop condition uses <=.
746 */
747 for (i = start / page_size; i <= (start + len - 1) / page_size; i++) {
748 /* Byte position of the first byte in the range in this page. */
749 /* starthere is an offset to the base address of the chip. */
750 starthere = max(start, i * page_size);
751 /* Length of bytes in the range in this page. */
752 lenhere = min(start + len, (i + 1) * page_size) - starthere;
753 for (j = 0; j < lenhere; j += chunksize) {
Edward O'Callaghan4fe3a972019-06-19 16:56:10 +1000754 int rc;
Edward O'Callaghan3eaadb02019-10-14 16:08:23 +1100755
hailfinger39d159a2010-05-21 23:09:42 +0000756 towrite = min(chunksize, lenhere - j);
Edward O'Callaghan4fe3a972019-06-19 16:56:10 +1000757 rc = spi_nbyte_program(flash, starthere + j, buf + starthere - start + j, towrite);
hailfinger39d159a2010-05-21 23:09:42 +0000758 if (rc)
Edward O'Callaghan4fe3a972019-06-19 16:56:10 +1000759 return rc;
hailfinger39d159a2010-05-21 23:09:42 +0000760 }
hailfinger39d159a2010-05-21 23:09:42 +0000761 }
762
Edward O'Callaghan4fe3a972019-06-19 16:56:10 +1000763 return 0;
hailfinger39d159a2010-05-21 23:09:42 +0000764}
765
766/*
snelson8913d082010-02-26 05:48:29 +0000767 * Program chip using byte programming. (SLOW!)
768 * This is for chips which can only handle one byte writes
769 * and for chips where memory mapped programming is impossible
770 * (e.g. due to size constraints in IT87* for over 512 kB)
771 */
hailfingerc7d06c62010-07-14 16:19:05 +0000772/* real chunksize is 1, logical chunksize is 1 */
Patrick Georgiab8353e2017-02-03 18:32:01 +0100773int spi_chip_write_1(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
snelson8913d082010-02-26 05:48:29 +0000774{
stefanctc5eb8a92011-11-23 09:13:48 +0000775 unsigned int i;
snelson8913d082010-02-26 05:48:29 +0000776
hailfingerc7d06c62010-07-14 16:19:05 +0000777 for (i = start; i < start + len; i++) {
Edward O'Callaghan4fe3a972019-06-19 16:56:10 +1000778 if (spi_nbyte_program(flash, i, buf + i - start, 1))
snelson8913d082010-02-26 05:48:29 +0000779 return 1;
snelson8913d082010-02-26 05:48:29 +0000780 }
snelson8913d082010-02-26 05:48:29 +0000781 return 0;
782}
783
Patrick Georgiab8353e2017-02-03 18:32:01 +0100784int spi_aai_write(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
hailfingerc7d06c62010-07-14 16:19:05 +0000785{
786 uint32_t pos = start;
snelson8913d082010-02-26 05:48:29 +0000787 int result;
hailfinger19db0922010-06-20 10:41:35 +0000788 unsigned char cmd[JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE] = {
789 JEDEC_AAI_WORD_PROGRAM,
790 };
snelson8913d082010-02-26 05:48:29 +0000791
hailfingerc7d06c62010-07-14 16:19:05 +0000792 /* The even start address and even length requirements can be either
793 * honored outside this function, or we can call spi_byte_program
794 * for the first and/or last byte and use AAI for the rest.
hailfinger71e1bd42010-10-13 22:26:56 +0000795 * FIXME: Move this to generic code.
hailfingerc7d06c62010-07-14 16:19:05 +0000796 */
hailfinger19db0922010-06-20 10:41:35 +0000797 /* The data sheet requires a start address with the low bit cleared. */
hailfingerc7d06c62010-07-14 16:19:05 +0000798 if (start % 2) {
hailfinger19db0922010-06-20 10:41:35 +0000799 msg_cerr("%s: start address not even! Please report a bug at "
800 "flashrom@flashrom.org\n", __func__);
hailfinger71e1bd42010-10-13 22:26:56 +0000801 if (spi_chip_write_1(flash, buf, start, start % 2))
802 return SPI_GENERIC_ERROR;
803 pos += start % 2;
804 /* Do not return an error for now. */
805 //return SPI_GENERIC_ERROR;
hailfinger19db0922010-06-20 10:41:35 +0000806 }
807 /* The data sheet requires total AAI write length to be even. */
808 if (len % 2) {
809 msg_cerr("%s: total write length not even! Please report a "
810 "bug at flashrom@flashrom.org\n", __func__);
hailfinger71e1bd42010-10-13 22:26:56 +0000811 /* Do not return an error for now. */
812 //return SPI_GENERIC_ERROR;
hailfinger19db0922010-06-20 10:41:35 +0000813 }
814
Edward O'Callaghan031831d2019-06-19 16:27:43 +1000815 result = spi_write_cmd(flash, JEDEC_AAI_WORD_PROGRAM, false, start, buf + pos - start, 2, 10);
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000816 if (result)
Edward O'Callaghan633cbd62019-06-17 15:43:56 +1000817 goto bailout;
hailfinger19db0922010-06-20 10:41:35 +0000818
819 /* We already wrote 2 bytes in the multicommand step. */
820 pos += 2;
821
hailfinger71e1bd42010-10-13 22:26:56 +0000822 /* Are there at least two more bytes to write? */
823 while (pos < start + len - 1) {
hailfingerdef852d2010-10-27 22:07:11 +0000824 cmd[1] = buf[pos++ - start];
825 cmd[2] = buf[pos++ - start];
Edward O'Callaghan633cbd62019-06-17 15:43:56 +1000826 result = spi_send_command(flash, JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE, 0, cmd, NULL);
Edward O'Callaghan3eaadb02019-10-14 16:08:23 +1100827 if (result != 0) {
Edward O'Callaghan633cbd62019-06-17 15:43:56 +1000828 msg_cerr("%s failed during followup AAI command execution: %d\n", __func__, result);
829 goto bailout;
830 }
Edward O'Callaghane5190df2019-06-17 15:23:26 +1000831 if (spi_poll_wip(flash, 10))
832 goto bailout;
hailfinger19db0922010-06-20 10:41:35 +0000833 }
834
hailfinger71e1bd42010-10-13 22:26:56 +0000835 /* Use WRDI to exit AAI mode. This needs to be done before issuing any
836 * other non-AAI command.
837 */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700838 spi_write_disable(flash);
hailfinger71e1bd42010-10-13 22:26:56 +0000839
840 /* Write remaining byte (if any). */
841 if (pos < start + len) {
hailfingerdef852d2010-10-27 22:07:11 +0000842 if (spi_chip_write_1(flash, buf + pos - start, pos, pos % 2))
hailfinger71e1bd42010-10-13 22:26:56 +0000843 return SPI_GENERIC_ERROR;
hailfinger71e1bd42010-10-13 22:26:56 +0000844 }
845
snelson8913d082010-02-26 05:48:29 +0000846 return 0;
Edward O'Callaghan633cbd62019-06-17 15:43:56 +1000847
848bailout:
849 spi_write_disable(flash);
850 return SPI_GENERIC_ERROR;
snelson8913d082010-02-26 05:48:29 +0000851}