blob: c49f2512c47eb63882ba468e9b0df1b229867cf6 [file] [log] [blame]
Sean Nelson14ba6682010-02-26 05:48:29 +00001/*
2 * This file is part of the flashrom project.
3 *
Carl-Daniel Hailfinger5824fbf2010-05-21 23:09:42 +00004 * Copyright (C) 2007, 2008, 2009, 2010 Carl-Daniel Hailfinger
Sean Nelson14ba6682010-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.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21/*
22 * Contains the common SPI chip driver functions
23 */
24
Nico Hubera3140d02017-10-15 11:20:58 +020025#include <stddef.h>
Sean Nelson14ba6682010-02-26 05:48:29 +000026#include <string.h>
Nico Hubera1672f82017-10-14 18:00:20 +020027#include <stdbool.h>
Sean Nelson14ba6682010-02-26 05:48:29 +000028#include "flash.h"
29#include "flashchips.h"
30#include "chipdrivers.h"
Carl-Daniel Hailfinger5b997c32010-07-27 22:41:39 +000031#include "programmer.h"
Sean Nelson14ba6682010-02-26 05:48:29 +000032#include "spi.h"
33
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +000034static int spi_rdid(struct flashctx *flash, unsigned char *readarr, int bytes)
Sean Nelson14ba6682010-02-26 05:48:29 +000035{
Mathias Krausea60faab2011-01-17 07:50:42 +000036 static const unsigned char cmd[JEDEC_RDID_OUTSIZE] = { JEDEC_RDID };
Sean Nelson14ba6682010-02-26 05:48:29 +000037 int ret;
38 int i;
39
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +000040 ret = spi_send_command(flash, sizeof(cmd), bytes, cmd, readarr);
Sean Nelson14ba6682010-02-26 05:48:29 +000041 if (ret)
42 return ret;
Sean Nelsoned479d22010-03-24 23:14:32 +000043 msg_cspew("RDID returned");
Sean Nelson14ba6682010-02-26 05:48:29 +000044 for (i = 0; i < bytes; i++)
Sean Nelsoned479d22010-03-24 23:14:32 +000045 msg_cspew(" 0x%02x", readarr[i]);
46 msg_cspew(". ");
Sean Nelson14ba6682010-02-26 05:48:29 +000047 return 0;
48}
49
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +000050static int spi_rems(struct flashctx *flash, unsigned char *readarr)
Sean Nelson14ba6682010-02-26 05:48:29 +000051{
52 unsigned char cmd[JEDEC_REMS_OUTSIZE] = { JEDEC_REMS, 0, 0, 0 };
53 uint32_t readaddr;
54 int ret;
55
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +000056 ret = spi_send_command(flash, sizeof(cmd), JEDEC_REMS_INSIZE, cmd,
57 readarr);
Sean Nelson14ba6682010-02-26 05:48:29 +000058 if (ret == SPI_INVALID_ADDRESS) {
59 /* Find the lowest even address allowed for reads. */
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +000060 readaddr = (spi_get_valid_read_addr(flash) + 1) & ~1;
Sean Nelson14ba6682010-02-26 05:48:29 +000061 cmd[1] = (readaddr >> 16) & 0xff,
62 cmd[2] = (readaddr >> 8) & 0xff,
63 cmd[3] = (readaddr >> 0) & 0xff,
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +000064 ret = spi_send_command(flash, sizeof(cmd), JEDEC_REMS_INSIZE,
65 cmd, readarr);
Sean Nelson14ba6682010-02-26 05:48:29 +000066 }
67 if (ret)
68 return ret;
Cristian Măgherușan-Stanciu9932c7b2011-07-07 19:56:58 +000069 msg_cspew("REMS returned 0x%02x 0x%02x. ", readarr[0], readarr[1]);
Sean Nelson14ba6682010-02-26 05:48:29 +000070 return 0;
71}
72
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +000073static int spi_res(struct flashctx *flash, unsigned char *readarr, int bytes)
Sean Nelson14ba6682010-02-26 05:48:29 +000074{
75 unsigned char cmd[JEDEC_RES_OUTSIZE] = { JEDEC_RES, 0, 0, 0 };
76 uint32_t readaddr;
77 int ret;
Carl-Daniel Hailfinger8ae500e2010-06-20 10:39:33 +000078 int i;
Sean Nelson14ba6682010-02-26 05:48:29 +000079
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +000080 ret = spi_send_command(flash, sizeof(cmd), bytes, cmd, readarr);
Sean Nelson14ba6682010-02-26 05:48:29 +000081 if (ret == SPI_INVALID_ADDRESS) {
82 /* Find the lowest even address allowed for reads. */
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +000083 readaddr = (spi_get_valid_read_addr(flash) + 1) & ~1;
Sean Nelson14ba6682010-02-26 05:48:29 +000084 cmd[1] = (readaddr >> 16) & 0xff,
85 cmd[2] = (readaddr >> 8) & 0xff,
86 cmd[3] = (readaddr >> 0) & 0xff,
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +000087 ret = spi_send_command(flash, sizeof(cmd), bytes, cmd, readarr);
Sean Nelson14ba6682010-02-26 05:48:29 +000088 }
89 if (ret)
90 return ret;
Carl-Daniel Hailfinger8ae500e2010-06-20 10:39:33 +000091 msg_cspew("RES returned");
92 for (i = 0; i < bytes; i++)
93 msg_cspew(" 0x%02x", readarr[i]);
94 msg_cspew(". ");
Sean Nelson14ba6682010-02-26 05:48:29 +000095 return 0;
96}
97
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +000098int spi_write_enable(struct flashctx *flash)
Sean Nelson14ba6682010-02-26 05:48:29 +000099{
Mathias Krausea60faab2011-01-17 07:50:42 +0000100 static const unsigned char cmd[JEDEC_WREN_OUTSIZE] = { JEDEC_WREN };
Sean Nelson14ba6682010-02-26 05:48:29 +0000101 int result;
102
103 /* Send WREN (Write Enable) */
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000104 result = spi_send_command(flash, sizeof(cmd), 0, cmd, NULL);
Sean Nelson14ba6682010-02-26 05:48:29 +0000105
106 if (result)
Sean Nelsoned479d22010-03-24 23:14:32 +0000107 msg_cerr("%s failed\n", __func__);
Sean Nelson14ba6682010-02-26 05:48:29 +0000108
109 return result;
110}
111
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000112int spi_write_disable(struct flashctx *flash)
Sean Nelson14ba6682010-02-26 05:48:29 +0000113{
Mathias Krausea60faab2011-01-17 07:50:42 +0000114 static const unsigned char cmd[JEDEC_WRDI_OUTSIZE] = { JEDEC_WRDI };
Sean Nelson14ba6682010-02-26 05:48:29 +0000115
116 /* Send WRDI (Write Disable) */
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000117 return spi_send_command(flash, sizeof(cmd), 0, cmd, NULL);
Sean Nelson14ba6682010-02-26 05:48:29 +0000118}
119
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +0000120static int probe_spi_rdid_generic(struct flashctx *flash, int bytes)
Sean Nelson14ba6682010-02-26 05:48:29 +0000121{
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000122 const struct flashchip *chip = flash->chip;
Sean Nelson14ba6682010-02-26 05:48:29 +0000123 unsigned char readarr[4];
124 uint32_t id1;
125 uint32_t id2;
126
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000127 if (spi_rdid(flash, readarr, bytes)) {
Sean Nelson14ba6682010-02-26 05:48:29 +0000128 return 0;
Stefan Tauner355cbfd2011-05-28 02:37:14 +0000129 }
Sean Nelson14ba6682010-02-26 05:48:29 +0000130
131 if (!oddparity(readarr[0]))
Sean Nelsoned479d22010-03-24 23:14:32 +0000132 msg_cdbg("RDID byte 0 parity violation. ");
Sean Nelson14ba6682010-02-26 05:48:29 +0000133
Carl-Daniel Hailfinger8ae500e2010-06-20 10:39:33 +0000134 /* Check if this is a continuation vendor ID.
135 * FIXME: Handle continuation device IDs.
136 */
Sean Nelson14ba6682010-02-26 05:48:29 +0000137 if (readarr[0] == 0x7f) {
138 if (!oddparity(readarr[1]))
Sean Nelsoned479d22010-03-24 23:14:32 +0000139 msg_cdbg("RDID byte 1 parity violation. ");
Sean Nelson14ba6682010-02-26 05:48:29 +0000140 id1 = (readarr[0] << 8) | readarr[1];
141 id2 = readarr[2];
142 if (bytes > 3) {
143 id2 <<= 8;
144 id2 |= readarr[3];
145 }
146 } else {
147 id1 = readarr[0];
148 id2 = (readarr[1] << 8) | readarr[2];
149 }
150
Sean Nelsoned479d22010-03-24 23:14:32 +0000151 msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2);
Sean Nelson14ba6682010-02-26 05:48:29 +0000152
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000153 if (id1 == chip->manufacture_id && id2 == chip->model_id)
Sean Nelson14ba6682010-02-26 05:48:29 +0000154 return 1;
Sean Nelson14ba6682010-02-26 05:48:29 +0000155
156 /* Test if this is a pure vendor match. */
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000157 if (id1 == chip->manufacture_id && GENERIC_DEVICE_ID == chip->model_id)
Sean Nelson14ba6682010-02-26 05:48:29 +0000158 return 1;
159
160 /* Test if there is any vendor ID. */
Urja Rannikko0a5f6e42015-06-22 23:59:15 +0000161 if (GENERIC_MANUF_ID == chip->manufacture_id && id1 != 0xff && id1 != 0x00)
Sean Nelson14ba6682010-02-26 05:48:29 +0000162 return 1;
163
164 return 0;
165}
166
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +0000167int probe_spi_rdid(struct flashctx *flash)
Sean Nelson14ba6682010-02-26 05:48:29 +0000168{
169 return probe_spi_rdid_generic(flash, 3);
170}
171
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +0000172int probe_spi_rdid4(struct flashctx *flash)
Sean Nelson14ba6682010-02-26 05:48:29 +0000173{
Carl-Daniel Hailfinger8ae500e2010-06-20 10:39:33 +0000174 /* Some SPI controllers do not support commands with writecnt=1 and
175 * readcnt=4.
176 */
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000177 switch (flash->mst->spi.type) {
Carl-Daniel Hailfinger71127722010-05-31 15:27:27 +0000178#if CONFIG_INTERNAL == 1
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000179#if defined(__i386__) || defined(__x86_64__)
Carl-Daniel Hailfinger8ae500e2010-06-20 10:39:33 +0000180 case SPI_CONTROLLER_IT87XX:
Sean Nelson14ba6682010-02-26 05:48:29 +0000181 case SPI_CONTROLLER_WBSIO:
Carl-Daniel Hailfinger8ae500e2010-06-20 10:39:33 +0000182 msg_cinfo("4 byte RDID not supported on this SPI controller\n");
183 return 0;
184 break;
Sean Nelson14ba6682010-02-26 05:48:29 +0000185#endif
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000186#endif
Sean Nelson14ba6682010-02-26 05:48:29 +0000187 default:
Carl-Daniel Hailfinger8ae500e2010-06-20 10:39:33 +0000188 return probe_spi_rdid_generic(flash, 4);
Sean Nelson14ba6682010-02-26 05:48:29 +0000189 }
190
191 return 0;
192}
193
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +0000194int probe_spi_rems(struct flashctx *flash)
Sean Nelson14ba6682010-02-26 05:48:29 +0000195{
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000196 const struct flashchip *chip = flash->chip;
Sean Nelson14ba6682010-02-26 05:48:29 +0000197 unsigned char readarr[JEDEC_REMS_INSIZE];
198 uint32_t id1, id2;
199
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000200 if (spi_rems(flash, readarr)) {
Sean Nelson14ba6682010-02-26 05:48:29 +0000201 return 0;
Stefan Tauner355cbfd2011-05-28 02:37:14 +0000202 }
Sean Nelson14ba6682010-02-26 05:48:29 +0000203
204 id1 = readarr[0];
205 id2 = readarr[1];
206
Sean Nelsoned479d22010-03-24 23:14:32 +0000207 msg_cdbg("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2);
Sean Nelson14ba6682010-02-26 05:48:29 +0000208
Stefan Tauner6ee37e22012-12-29 15:03:51 +0000209 if (id1 == chip->manufacture_id && id2 == chip->model_id)
Sean Nelson14ba6682010-02-26 05:48:29 +0000210 return 1;
Sean Nelson14ba6682010-02-26 05:48:29 +0000211
212 /* Test if this is a pure vendor match. */
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000213 if (id1 == chip->manufacture_id && GENERIC_DEVICE_ID == chip->model_id)
Sean Nelson14ba6682010-02-26 05:48:29 +0000214 return 1;
215
216 /* Test if there is any vendor ID. */
Urja Rannikko0a5f6e42015-06-22 23:59:15 +0000217 if (GENERIC_MANUF_ID == chip->manufacture_id && id1 != 0xff && id1 != 0x00)
Sean Nelson14ba6682010-02-26 05:48:29 +0000218 return 1;
219
220 return 0;
221}
222
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +0000223int probe_spi_res1(struct flashctx *flash)
Sean Nelson14ba6682010-02-26 05:48:29 +0000224{
Mathias Krausea60faab2011-01-17 07:50:42 +0000225 static const unsigned char allff[] = {0xff, 0xff, 0xff};
226 static const unsigned char all00[] = {0x00, 0x00, 0x00};
Sean Nelson14ba6682010-02-26 05:48:29 +0000227 unsigned char readarr[3];
228 uint32_t id2;
Sean Nelson14ba6682010-02-26 05:48:29 +0000229
Carl-Daniel Hailfingerdc1cda12010-05-28 17:07:57 +0000230 /* We only want one-byte RES if RDID and REMS are unusable. */
231
Sean Nelson14ba6682010-02-26 05:48:29 +0000232 /* Check if RDID is usable and does not return 0xff 0xff 0xff or
233 * 0x00 0x00 0x00. In that case, RES is pointless.
234 */
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000235 if (!spi_rdid(flash, readarr, 3) && memcmp(readarr, allff, 3) &&
Sean Nelson14ba6682010-02-26 05:48:29 +0000236 memcmp(readarr, all00, 3)) {
237 msg_cdbg("Ignoring RES in favour of RDID.\n");
238 return 0;
239 }
240 /* Check if REMS is usable and does not return 0xff 0xff or
241 * 0x00 0x00. In that case, RES is pointless.
242 */
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000243 if (!spi_rems(flash, readarr) &&
244 memcmp(readarr, allff, JEDEC_REMS_INSIZE) &&
Sean Nelson14ba6682010-02-26 05:48:29 +0000245 memcmp(readarr, all00, JEDEC_REMS_INSIZE)) {
246 msg_cdbg("Ignoring RES in favour of REMS.\n");
247 return 0;
248 }
249
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000250 if (spi_res(flash, readarr, 1)) {
Sean Nelson14ba6682010-02-26 05:48:29 +0000251 return 0;
Stefan Tauner355cbfd2011-05-28 02:37:14 +0000252 }
Sean Nelson14ba6682010-02-26 05:48:29 +0000253
Sean Nelson14ba6682010-02-26 05:48:29 +0000254 id2 = readarr[0];
Carl-Daniel Hailfingerdc1cda12010-05-28 17:07:57 +0000255
Sean Nelsoned479d22010-03-24 23:14:32 +0000256 msg_cdbg("%s: id 0x%x\n", __func__, id2);
Carl-Daniel Hailfingerdc1cda12010-05-28 17:07:57 +0000257
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000258 if (id2 != flash->chip->model_id)
Sean Nelson14ba6682010-02-26 05:48:29 +0000259 return 0;
260
Sean Nelson14ba6682010-02-26 05:48:29 +0000261 return 1;
262}
263
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +0000264int probe_spi_res2(struct flashctx *flash)
Carl-Daniel Hailfingerdc1cda12010-05-28 17:07:57 +0000265{
266 unsigned char readarr[2];
267 uint32_t id1, id2;
268
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000269 if (spi_res(flash, readarr, 2)) {
Carl-Daniel Hailfingerdc1cda12010-05-28 17:07:57 +0000270 return 0;
Stefan Tauner355cbfd2011-05-28 02:37:14 +0000271 }
Carl-Daniel Hailfingerdc1cda12010-05-28 17:07:57 +0000272
273 id1 = readarr[0];
274 id2 = readarr[1];
275
276 msg_cdbg("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2);
277
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000278 if (id1 != flash->chip->manufacture_id || id2 != flash->chip->model_id)
Carl-Daniel Hailfingerdc1cda12010-05-28 17:07:57 +0000279 return 0;
280
Carl-Daniel Hailfingerdc1cda12010-05-28 17:07:57 +0000281 return 1;
282}
283
Stefan Tauner3f5e35d2013-04-19 01:58:33 +0000284int probe_spi_res3(struct flashctx *flash)
285{
286 unsigned char readarr[3];
287 uint32_t id1, id2;
288
289 if (spi_res(flash, readarr, 3)) {
290 return 0;
291 }
292
293 id1 = (readarr[0] << 8) | readarr[1];
294 id2 = readarr[2];
295
296 msg_cdbg("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2);
297
298 if (id1 != flash->chip->manufacture_id || id2 != flash->chip->model_id)
299 return 0;
300
301 return 1;
302}
303
Stefan Tauner57794ac2012-12-29 15:04:20 +0000304/* Only used for some Atmel chips. */
305int probe_spi_at25f(struct flashctx *flash)
306{
307 static const unsigned char cmd[AT25F_RDID_OUTSIZE] = { AT25F_RDID };
308 unsigned char readarr[AT25F_RDID_INSIZE];
309 uint32_t id1;
310 uint32_t id2;
311
312 if (spi_send_command(flash, sizeof(cmd), sizeof(readarr), cmd, readarr))
313 return 0;
314
315 id1 = readarr[0];
316 id2 = readarr[1];
317
318 msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2);
319
320 if (id1 == flash->chip->manufacture_id && id2 == flash->chip->model_id)
321 return 1;
322
323 return 0;
324}
325
Nico Huber0ecbacb2017-10-14 16:50:43 +0200326static int spi_poll_wip(struct flashctx *const flash, const unsigned int poll_delay)
327{
328 /* FIXME: We can't tell if spi_read_status_register() failed. */
329 /* FIXME: We don't time out. */
330 while (spi_read_status_register(flash) & SPI_SR_WIP)
331 programmer_delay(poll_delay);
332 /* FIXME: Check the status register for errors. */
333 return 0;
334}
335
Nico Hubera3140d02017-10-15 11:20:58 +0200336/**
337 * Execute WREN plus another one byte `op`, optionally poll WIP afterwards.
338 *
339 * @param flash the flash chip's context
340 * @param op the operation to execute
341 * @param poll_delay interval in us for polling WIP, don't poll if zero
342 * @return 0 on success, non-zero otherwise
343 */
344static int spi_simple_write_cmd(struct flashctx *const flash, const uint8_t op, const unsigned int poll_delay)
Sean Nelson14ba6682010-02-26 05:48:29 +0000345{
Sean Nelson14ba6682010-02-26 05:48:29 +0000346 struct spi_command cmds[] = {
347 {
Nico Hubera3140d02017-10-15 11:20:58 +0200348 .writecnt = 1,
349 .writearr = (const unsigned char[]){ JEDEC_WREN },
Sean Nelson14ba6682010-02-26 05:48:29 +0000350 }, {
Nico Hubera3140d02017-10-15 11:20:58 +0200351 .writecnt = 1,
352 .writearr = (const unsigned char[]){ op },
353 },
354 NULL_SPI_CMD,
355 };
356
357 const int result = spi_send_multicommand(flash, cmds);
358 if (result)
359 msg_cerr("%s failed during command execution\n", __func__);
360
Nico Huber0ecbacb2017-10-14 16:50:43 +0200361 const int status = poll_delay ? spi_poll_wip(flash, poll_delay) : 0;
Nico Hubera3140d02017-10-15 11:20:58 +0200362
Nico Huber0ecbacb2017-10-14 16:50:43 +0200363 return result ? result : status;
364}
365
Nico Huber7e3c81a2017-10-14 18:56:50 +0200366static int spi_write_extended_address_register(struct flashctx *const flash, const uint8_t regdata)
367{
368 struct spi_command cmds[] = {
369 {
370 .writecnt = 1,
371 .writearr = (const unsigned char[]){ JEDEC_WREN },
372 }, {
373 .writecnt = 2,
374 .writearr = (const unsigned char[]){ JEDEC_WRITE_EXT_ADDR_REG, regdata },
375 },
376 NULL_SPI_CMD,
377 };
378
379 const int result = spi_send_multicommand(flash, cmds);
380 if (result)
381 msg_cerr("%s failed during command execution\n", __func__);
382 return result;
383}
384
Nico Huberf43c6542017-10-14 17:47:28 +0200385static int spi_set_extended_address(struct flashctx *const flash, const uint8_t addr_high)
386{
387 if (flash->address_high_byte != addr_high &&
388 spi_write_extended_address_register(flash, addr_high))
389 return -1;
390 flash->address_high_byte = addr_high;
391 return 0;
392}
393
Nico Hubera1672f82017-10-14 18:00:20 +0200394static int spi_prepare_address(struct flashctx *const flash, uint8_t cmd_buf[],
395 const bool native_4ba, const unsigned int addr)
Nico Huber0ecbacb2017-10-14 16:50:43 +0200396{
Nico Hubera1672f82017-10-14 18:00:20 +0200397 if (native_4ba || flash->in_4ba_mode) {
Nico Huberf43c6542017-10-14 17:47:28 +0200398 cmd_buf[1] = (addr >> 24) & 0xff;
399 cmd_buf[2] = (addr >> 16) & 0xff;
400 cmd_buf[3] = (addr >> 8) & 0xff;
401 cmd_buf[4] = (addr >> 0) & 0xff;
402 return 4;
403 } else {
404 if (flash->chip->feature_bits & FEATURE_4BA_EXT_ADDR) {
405 if (spi_set_extended_address(flash, addr >> 24))
406 return -1;
407 } else {
408 if (addr >> 24)
409 return -1;
410 }
411 cmd_buf[1] = (addr >> 16) & 0xff;
412 cmd_buf[2] = (addr >> 8) & 0xff;
413 cmd_buf[3] = (addr >> 0) & 0xff;
414 return 3;
415 }
Nico Huber0ecbacb2017-10-14 16:50:43 +0200416}
417
418/**
419 * Execute WREN plus another `op` that takes an address and
420 * optional data, poll WIP afterwards.
421 *
422 * @param flash the flash chip's context
423 * @param op the operation to execute
Nico Hubera1672f82017-10-14 18:00:20 +0200424 * @param native_4ba whether `op` always takes a 4-byte address
Nico Huber0ecbacb2017-10-14 16:50:43 +0200425 * @param addr the address parameter to `op`
426 * @param out_bytes bytes to send after the address,
427 * may be NULL if and only if `out_bytes` is 0
428 * @param out_bytes number of bytes to send, 256 at most, may be zero
429 * @param poll_delay interval in us for polling WIP
430 * @return 0 on success, non-zero otherwise
431 */
Nico Hubera1672f82017-10-14 18:00:20 +0200432static int spi_write_cmd(struct flashctx *const flash, const uint8_t op,
433 const bool native_4ba, const unsigned int addr,
Nico Huber0ecbacb2017-10-14 16:50:43 +0200434 const uint8_t *const out_bytes, const size_t out_len,
435 const unsigned int poll_delay)
436{
437 uint8_t cmd[1 + JEDEC_MAX_ADDR_LEN + 256];
438 struct spi_command cmds[] = {
439 {
440 .writecnt = 1,
441 .writearr = (const unsigned char[]){ JEDEC_WREN },
442 }, {
443 .writearr = cmd,
444 },
445 NULL_SPI_CMD,
446 };
447
448 cmd[0] = op;
Nico Hubera1672f82017-10-14 18:00:20 +0200449 const int addr_len = spi_prepare_address(flash, cmd, native_4ba, addr);
Nico Huber0ecbacb2017-10-14 16:50:43 +0200450 if (addr_len < 0)
451 return 1;
452
453 if (1 + addr_len + out_len > sizeof(cmd)) {
454 msg_cerr("%s called for too long a write\n", __func__);
455 return 1;
456 }
457
458 memcpy(cmd + 1 + addr_len, out_bytes, out_len);
459 cmds[1].writecnt = 1 + addr_len + out_len;
460
461 const int result = spi_send_multicommand(flash, cmds);
462 if (result)
463 msg_cerr("%s failed during command execution at address 0x%x\n", __func__, addr);
464
465 const int status = spi_poll_wip(flash, poll_delay);
466
467 return result ? result : status;
Nico Hubera3140d02017-10-15 11:20:58 +0200468}
469
470int spi_chip_erase_60(struct flashctx *flash)
471{
472 /* This usually takes 1-85s, so wait in 1s steps. */
473 return spi_simple_write_cmd(flash, 0x60, 1000 * 1000);
Sean Nelson14ba6682010-02-26 05:48:29 +0000474}
475
Stefan Tauner3c0fcd02012-09-21 12:46:56 +0000476int spi_chip_erase_62(struct flashctx *flash)
477{
Nico Hubera3140d02017-10-15 11:20:58 +0200478 /* This usually takes 2-5s, so wait in 100ms steps. */
479 return spi_simple_write_cmd(flash, 0x62, 100 * 1000);
Stefan Tauner3c0fcd02012-09-21 12:46:56 +0000480}
481
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +0000482int spi_chip_erase_c7(struct flashctx *flash)
Sean Nelson14ba6682010-02-26 05:48:29 +0000483{
Nico Hubera3140d02017-10-15 11:20:58 +0200484 /* This usually takes 1-85s, so wait in 1s steps. */
485 return spi_simple_write_cmd(flash, 0xc7, 1000 * 1000);
Sean Nelson14ba6682010-02-26 05:48:29 +0000486}
487
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000488int spi_block_erase_52(struct flashctx *flash, unsigned int addr,
489 unsigned int blocklen)
Sean Nelson14ba6682010-02-26 05:48:29 +0000490{
Nico Huber0ecbacb2017-10-14 16:50:43 +0200491 /* This usually takes 100-4000ms, so wait in 100ms steps. */
Nico Hubera1672f82017-10-14 18:00:20 +0200492 return spi_write_cmd(flash, 0x52, false, addr, NULL, 0, 100 * 1000);
Sean Nelson14ba6682010-02-26 05:48:29 +0000493}
494
495/* Block size is usually
Nikolay Nikolaev6f59b0b2013-06-28 21:29:51 +0000496 * 32M (one die) for Micron
497 */
498int spi_block_erase_c4(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
499{
Nico Huber0ecbacb2017-10-14 16:50:43 +0200500 /* This usually takes 240-480s, so wait in 500ms steps. */
Nico Hubera1672f82017-10-14 18:00:20 +0200501 return spi_write_cmd(flash, 0xc4, false, addr, NULL, 0, 500 * 1000);
Nikolay Nikolaev6f59b0b2013-06-28 21:29:51 +0000502}
503
504/* Block size is usually
Sean Nelson14ba6682010-02-26 05:48:29 +0000505 * 64k for Macronix
506 * 32k for SST
507 * 4-32k non-uniform for EON
508 */
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000509int spi_block_erase_d8(struct flashctx *flash, unsigned int addr,
510 unsigned int blocklen)
Sean Nelson14ba6682010-02-26 05:48:29 +0000511{
Nico Huber0ecbacb2017-10-14 16:50:43 +0200512 /* This usually takes 100-4000ms, so wait in 100ms steps. */
Nico Hubera1672f82017-10-14 18:00:20 +0200513 return spi_write_cmd(flash, 0xd8, false, addr, NULL, 0, 100 * 1000);
Sean Nelson14ba6682010-02-26 05:48:29 +0000514}
515
516/* Block size is usually
517 * 4k for PMC
518 */
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000519int spi_block_erase_d7(struct flashctx *flash, unsigned int addr,
520 unsigned int blocklen)
Sean Nelson14ba6682010-02-26 05:48:29 +0000521{
Nico Huber0ecbacb2017-10-14 16:50:43 +0200522 /* This usually takes 100-4000ms, so wait in 100ms steps. */
Nico Hubera1672f82017-10-14 18:00:20 +0200523 return spi_write_cmd(flash, 0xd7, false, addr, NULL, 0, 100 * 1000);
Sean Nelson14ba6682010-02-26 05:48:29 +0000524}
525
Nikolay Nikolaev579f1e02013-06-28 21:28:37 +0000526/* Page erase (usually 256B blocks) */
527int spi_block_erase_db(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
528{
Nico Huber0ecbacb2017-10-14 16:50:43 +0200529 /* This takes up to 20ms usually (on worn out devices
530 up to the 0.5s range), so wait in 1ms steps. */
Nico Hubera1672f82017-10-14 18:00:20 +0200531 return spi_write_cmd(flash, 0xdb, false, addr, NULL, 0, 1 * 1000);
Nikolay Nikolaev579f1e02013-06-28 21:28:37 +0000532}
533
Sean Nelson14ba6682010-02-26 05:48:29 +0000534/* Sector size is usually 4k, though Macronix eliteflash has 64k */
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000535int spi_block_erase_20(struct flashctx *flash, unsigned int addr,
536 unsigned int blocklen)
Sean Nelson14ba6682010-02-26 05:48:29 +0000537{
Nico Huber0ecbacb2017-10-14 16:50:43 +0200538 /* This usually takes 15-800ms, so wait in 10ms steps. */
Nico Hubera1672f82017-10-14 18:00:20 +0200539 return spi_write_cmd(flash, 0x20, false, addr, NULL, 0, 10 * 1000);
Sean Nelson14ba6682010-02-26 05:48:29 +0000540}
541
Stefan Tauner94b39b42012-10-27 00:06:02 +0000542int spi_block_erase_50(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
543{
Nico Huber0ecbacb2017-10-14 16:50:43 +0200544 /* This usually takes 10ms, so wait in 1ms steps. */
Nico Hubera1672f82017-10-14 18:00:20 +0200545 return spi_write_cmd(flash, 0x50, false, addr, NULL, 0, 1 * 1000);
Stefan Tauner94b39b42012-10-27 00:06:02 +0000546}
547
548int spi_block_erase_81(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
549{
Nico Huber0ecbacb2017-10-14 16:50:43 +0200550 /* This usually takes 8ms, so wait in 1ms steps. */
Nico Hubera1672f82017-10-14 18:00:20 +0200551 return spi_write_cmd(flash, 0x81, false, addr, NULL, 0, 1 * 1000);
Stefan Tauner94b39b42012-10-27 00:06:02 +0000552}
553
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000554int spi_block_erase_60(struct flashctx *flash, unsigned int addr,
555 unsigned int blocklen)
Sean Nelson14ba6682010-02-26 05:48:29 +0000556{
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000557 if ((addr != 0) || (blocklen != flash->chip->total_size * 1024)) {
Sean Nelsoned479d22010-03-24 23:14:32 +0000558 msg_cerr("%s called with incorrect arguments\n",
Sean Nelson14ba6682010-02-26 05:48:29 +0000559 __func__);
560 return -1;
561 }
562 return spi_chip_erase_60(flash);
563}
564
Stefan Tauner3c0fcd02012-09-21 12:46:56 +0000565int spi_block_erase_62(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
566{
567 if ((addr != 0) || (blocklen != flash->chip->total_size * 1024)) {
568 msg_cerr("%s called with incorrect arguments\n",
569 __func__);
570 return -1;
571 }
572 return spi_chip_erase_62(flash);
573}
574
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000575int spi_block_erase_c7(struct flashctx *flash, unsigned int addr,
576 unsigned int blocklen)
Sean Nelson14ba6682010-02-26 05:48:29 +0000577{
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000578 if ((addr != 0) || (blocklen != flash->chip->total_size * 1024)) {
Sean Nelsoned479d22010-03-24 23:14:32 +0000579 msg_cerr("%s called with incorrect arguments\n",
Sean Nelson14ba6682010-02-26 05:48:29 +0000580 __func__);
581 return -1;
582 }
583 return spi_chip_erase_c7(flash);
584}
585
Nico Huber7e3c81a2017-10-14 18:56:50 +0200586/* Erase 4 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes) */
587int spi_block_erase_21(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
588{
589 /* This usually takes 15-800ms, so wait in 10ms steps. */
590 return spi_write_cmd(flash, 0x21, true, addr, NULL, 0, 10 * 1000);
591}
592
593/* Erase 32 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes) */
594int spi_block_erase_5c(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
595{
596 /* This usually takes 100-4000ms, so wait in 100ms steps. */
597 return spi_write_cmd(flash, 0x5c, true, addr, NULL, 0, 100 * 1000);
598}
599
600/* Erase 64 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes) */
601int spi_block_erase_dc(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
602{
603 /* This usually takes 100-4000ms, so wait in 100ms steps. */
604 return spi_write_cmd(flash, 0xdc, true, addr, NULL, 0, 100 * 1000);
605}
606
Stefan Taunerac1b4c82012-02-17 14:51:04 +0000607erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode)
608{
609 switch(opcode){
610 case 0xff:
611 case 0x00:
612 /* Not specified, assuming "not supported". */
613 return NULL;
614 case 0x20:
615 return &spi_block_erase_20;
Nico Huber7e3c81a2017-10-14 18:56:50 +0200616 case 0x21:
617 return &spi_block_erase_21;
Stefan Tauner730e7e72013-05-01 14:04:19 +0000618 case 0x50:
619 return &spi_block_erase_50;
Stefan Taunerac1b4c82012-02-17 14:51:04 +0000620 case 0x52:
621 return &spi_block_erase_52;
Nico Huber7e3c81a2017-10-14 18:56:50 +0200622 case 0x5c:
623 return &spi_block_erase_5c;
Stefan Taunerac1b4c82012-02-17 14:51:04 +0000624 case 0x60:
625 return &spi_block_erase_60;
Stefan Tauner730e7e72013-05-01 14:04:19 +0000626 case 0x62:
627 return &spi_block_erase_62;
628 case 0x81:
629 return &spi_block_erase_81;
Nikolay Nikolaev6f59b0b2013-06-28 21:29:51 +0000630 case 0xc4:
631 return &spi_block_erase_c4;
Stefan Taunerac1b4c82012-02-17 14:51:04 +0000632 case 0xc7:
633 return &spi_block_erase_c7;
634 case 0xd7:
635 return &spi_block_erase_d7;
636 case 0xd8:
637 return &spi_block_erase_d8;
Nikolay Nikolaev579f1e02013-06-28 21:28:37 +0000638 case 0xdb:
639 return &spi_block_erase_db;
Nico Huber7e3c81a2017-10-14 18:56:50 +0200640 case 0xdc:
641 return &spi_block_erase_dc;
Stefan Taunerac1b4c82012-02-17 14:51:04 +0000642 default:
643 msg_cinfo("%s: unknown erase opcode (0x%02x). Please report "
644 "this at flashrom@flashrom.org\n", __func__, opcode);
645 return NULL;
646 }
647}
648
Nico Huber0ecbacb2017-10-14 16:50:43 +0200649static int spi_nbyte_program(struct flashctx *flash, unsigned int addr, const uint8_t *bytes, unsigned int len)
Sean Nelson14ba6682010-02-26 05:48:29 +0000650{
Nico Hubera1672f82017-10-14 18:00:20 +0200651 const bool native_4ba = !!(flash->chip->feature_bits & FEATURE_4BA_WRITE);
652 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);
Sean Nelson14ba6682010-02-26 05:48:29 +0000654}
655
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000656int spi_nbyte_read(struct flashctx *flash, unsigned int address, uint8_t *bytes,
657 unsigned int len)
Sean Nelson14ba6682010-02-26 05:48:29 +0000658{
Nico Hubera1672f82017-10-14 18:00:20 +0200659 const bool native_4ba = !!(flash->chip->feature_bits & FEATURE_4BA_READ);
660 uint8_t cmd[1 + JEDEC_MAX_ADDR_LEN] = { native_4ba ? JEDEC_READ_4BA : JEDEC_READ, };
Nico Huber0ecbacb2017-10-14 16:50:43 +0200661
Nico Hubera1672f82017-10-14 18:00:20 +0200662 const int addr_len = spi_prepare_address(flash, cmd, native_4ba, address);
Nico Huber0ecbacb2017-10-14 16:50:43 +0200663 if (addr_len < 0)
664 return 1;
Sean Nelson14ba6682010-02-26 05:48:29 +0000665
666 /* Send Read */
Nico Huber0ecbacb2017-10-14 16:50:43 +0200667 return spi_send_command(flash, 1 + addr_len, len, cmd, bytes);
Sean Nelson14ba6682010-02-26 05:48:29 +0000668}
669
670/*
Carl-Daniel Hailfinger5824fbf2010-05-21 23:09:42 +0000671 * Read a part of the flash chip.
Carl-Daniel Hailfinger9a795d82010-07-14 16:19:05 +0000672 * FIXME: Use the chunk code from Michael Karcher instead.
Urja Rannikko731316a2017-06-15 13:32:01 +0300673 * Each naturally aligned area is read separately in chunks with a maximum size of chunksize.
Sean Nelson14ba6682010-02-26 05:48:29 +0000674 */
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000675int spi_read_chunked(struct flashctx *flash, uint8_t *buf, unsigned int start,
676 unsigned int len, unsigned int chunksize)
Sean Nelson14ba6682010-02-26 05:48:29 +0000677{
678 int rc = 0;
Stefan Taunerc69c9c82011-11-23 09:13:48 +0000679 unsigned int i, j, starthere, lenhere, toread;
Urja Rannikko731316a2017-06-15 13:32:01 +0300680 /* Limit for multi-die 4-byte-addressing chips. */
681 unsigned int area_size = min(flash->chip->total_size * 1024, 16 * 1024 * 1024);
Sean Nelson14ba6682010-02-26 05:48:29 +0000682
683 /* Warning: This loop has a very unusual condition and body.
Urja Rannikko731316a2017-06-15 13:32:01 +0300684 * 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
Sean Nelson14ba6682010-02-26 05:48:29 +0000687 * where the last byte of the range lives. That last byte has the
Urja Rannikko731316a2017-06-15 13:32:01 +0300688 * 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 <=.
Sean Nelson14ba6682010-02-26 05:48:29 +0000691 */
Urja Rannikko731316a2017-06-15 13:32:01 +0300692 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. */
Sean Nelson14ba6682010-02-26 05:48:29 +0000694 /* starthere is an offset to the base address of the chip. */
Urja Rannikko731316a2017-06-15 13:32:01 +0300695 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;
Sean Nelson14ba6682010-02-26 05:48:29 +0000698 for (j = 0; j < lenhere; j += chunksize) {
699 toread = min(chunksize, lenhere - j);
Nico Huber7a077222017-10-14 18:18:30 +0200700 rc = spi_nbyte_read(flash, starthere + j, buf + starthere - start + j, toread);
Sean Nelson14ba6682010-02-26 05:48:29 +0000701 if (rc)
702 break;
703 }
704 if (rc)
705 break;
706 }
707
708 return rc;
709}
710
711/*
Carl-Daniel Hailfinger5824fbf2010-05-21 23:09:42 +0000712 * Write a part of the flash chip.
Carl-Daniel Hailfinger9a795d82010-07-14 16:19:05 +0000713 * FIXME: Use the chunk code from Michael Karcher instead.
Carl-Daniel Hailfinger5824fbf2010-05-21 23:09:42 +0000714 * Each page is written separately in chunks with a maximum size of chunksize.
715 */
Mark Marshallf20b7be2014-05-09 21:16:21 +0000716int spi_write_chunked(struct flashctx *flash, const uint8_t *buf, unsigned int start,
Carl-Daniel Hailfinger8a3c60c2011-12-18 15:01:24 +0000717 unsigned int len, unsigned int chunksize)
Carl-Daniel Hailfinger5824fbf2010-05-21 23:09:42 +0000718{
Stefan Taunerc69c9c82011-11-23 09:13:48 +0000719 unsigned int i, j, starthere, lenhere, towrite;
Carl-Daniel Hailfinger5824fbf2010-05-21 23:09:42 +0000720 /* FIXME: page_size is the wrong variable. We need max_writechunk_size
Carl-Daniel Hailfinger63fd9022011-12-14 22:25:15 +0000721 * in struct flashctx to do this properly. All chips using
Carl-Daniel Hailfinger5824fbf2010-05-21 23:09:42 +0000722 * spi_chip_write_256 have page_size set to max_writechunk_size, so
723 * we're OK for now.
724 */
Carl-Daniel Hailfinger5a7cb842012-08-25 01:17:58 +0000725 unsigned int page_size = flash->chip->page_size;
Carl-Daniel Hailfinger5824fbf2010-05-21 23:09:42 +0000726
727 /* Warning: This loop has a very unusual condition and body.
728 * The loop needs to go through each page with at least one affected
729 * byte. The lowest page number is (start / page_size) since that
730 * division rounds down. The highest page number we want is the page
731 * where the last byte of the range lives. That last byte has the
732 * address (start + len - 1), thus the highest page number is
733 * (start + len - 1) / page_size. Since we want to include that last
734 * page as well, the loop condition uses <=.
735 */
736 for (i = start / page_size; i <= (start + len - 1) / page_size; i++) {
737 /* Byte position of the first byte in the range in this page. */
738 /* starthere is an offset to the base address of the chip. */
739 starthere = max(start, i * page_size);
740 /* Length of bytes in the range in this page. */
741 lenhere = min(start + len, (i + 1) * page_size) - starthere;
742 for (j = 0; j < lenhere; j += chunksize) {
Nico Huber7a077222017-10-14 18:18:30 +0200743 int rc;
744
Carl-Daniel Hailfinger5824fbf2010-05-21 23:09:42 +0000745 towrite = min(chunksize, lenhere - j);
Nico Huber7a077222017-10-14 18:18:30 +0200746 rc = spi_nbyte_program(flash, starthere + j, buf + starthere - start + j, towrite);
Carl-Daniel Hailfinger5824fbf2010-05-21 23:09:42 +0000747 if (rc)
Nico Huber7a077222017-10-14 18:18:30 +0200748 return rc;
Carl-Daniel Hailfinger5824fbf2010-05-21 23:09:42 +0000749 }
Carl-Daniel Hailfinger5824fbf2010-05-21 23:09:42 +0000750 }
751
Nico Huber7a077222017-10-14 18:18:30 +0200752 return 0;
Carl-Daniel Hailfinger5824fbf2010-05-21 23:09:42 +0000753}
754
755/*
Sean Nelson14ba6682010-02-26 05:48:29 +0000756 * Program chip using byte programming. (SLOW!)
757 * This is for chips which can only handle one byte writes
758 * and for chips where memory mapped programming is impossible
759 * (e.g. due to size constraints in IT87* for over 512 kB)
760 */
Carl-Daniel Hailfinger9a795d82010-07-14 16:19:05 +0000761/* real chunksize is 1, logical chunksize is 1 */
Mark Marshallf20b7be2014-05-09 21:16:21 +0000762int spi_chip_write_1(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
Sean Nelson14ba6682010-02-26 05:48:29 +0000763{
Stefan Taunerc69c9c82011-11-23 09:13:48 +0000764 unsigned int i;
Sean Nelson14ba6682010-02-26 05:48:29 +0000765
Carl-Daniel Hailfinger9a795d82010-07-14 16:19:05 +0000766 for (i = start; i < start + len; i++) {
Nico Huber7a077222017-10-14 18:18:30 +0200767 if (spi_nbyte_program(flash, i, buf + i - start, 1))
Sean Nelson14ba6682010-02-26 05:48:29 +0000768 return 1;
Sean Nelson14ba6682010-02-26 05:48:29 +0000769 }
Sean Nelson14ba6682010-02-26 05:48:29 +0000770 return 0;
771}
772
Mark Marshallf20b7be2014-05-09 21:16:21 +0000773int default_spi_write_aai(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
Carl-Daniel Hailfinger9a795d82010-07-14 16:19:05 +0000774{
775 uint32_t pos = start;
Sean Nelson14ba6682010-02-26 05:48:29 +0000776 int result;
Carl-Daniel Hailfinger9c62d112010-06-20 10:41:35 +0000777 unsigned char cmd[JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE] = {
778 JEDEC_AAI_WORD_PROGRAM,
779 };
Sean Nelson14ba6682010-02-26 05:48:29 +0000780
Carl-Daniel Hailfingera5bcbce2014-07-19 22:03:29 +0000781 switch (flash->mst->spi.type) {
Carl-Daniel Hailfinger71127722010-05-31 15:27:27 +0000782#if CONFIG_INTERNAL == 1
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000783#if defined(__i386__) || defined(__x86_64__)
Carl-Daniel Hailfinger9c62d112010-06-20 10:41:35 +0000784 case SPI_CONTROLLER_IT87XX:
Sean Nelson14ba6682010-02-26 05:48:29 +0000785 case SPI_CONTROLLER_WBSIO:
Carl-Daniel Hailfinger9a795d82010-07-14 16:19:05 +0000786 msg_perr("%s: impossible with this SPI controller,"
Sean Nelson14ba6682010-02-26 05:48:29 +0000787 " degrading to byte program\n", __func__);
Carl-Daniel Hailfinger75a58f92010-10-13 22:26:56 +0000788 return spi_chip_write_1(flash, buf, start, len);
Sean Nelson14ba6682010-02-26 05:48:29 +0000789#endif
Carl-Daniel Hailfingercceafa22010-05-26 01:45:41 +0000790#endif
Sean Nelson14ba6682010-02-26 05:48:29 +0000791 default:
792 break;
793 }
Carl-Daniel Hailfinger9c62d112010-06-20 10:41:35 +0000794
Carl-Daniel Hailfinger9a795d82010-07-14 16:19:05 +0000795 /* The even start address and even length requirements can be either
796 * honored outside this function, or we can call spi_byte_program
797 * for the first and/or last byte and use AAI for the rest.
Carl-Daniel Hailfinger75a58f92010-10-13 22:26:56 +0000798 * FIXME: Move this to generic code.
Carl-Daniel Hailfinger9a795d82010-07-14 16:19:05 +0000799 */
Carl-Daniel Hailfinger9c62d112010-06-20 10:41:35 +0000800 /* The data sheet requires a start address with the low bit cleared. */
Carl-Daniel Hailfinger9a795d82010-07-14 16:19:05 +0000801 if (start % 2) {
Carl-Daniel Hailfinger9c62d112010-06-20 10:41:35 +0000802 msg_cerr("%s: start address not even! Please report a bug at "
803 "flashrom@flashrom.org\n", __func__);
Carl-Daniel Hailfinger75a58f92010-10-13 22:26:56 +0000804 if (spi_chip_write_1(flash, buf, start, start % 2))
805 return SPI_GENERIC_ERROR;
806 pos += start % 2;
807 /* Do not return an error for now. */
808 //return SPI_GENERIC_ERROR;
Carl-Daniel Hailfinger9c62d112010-06-20 10:41:35 +0000809 }
810 /* The data sheet requires total AAI write length to be even. */
811 if (len % 2) {
812 msg_cerr("%s: total write length not even! Please report a "
813 "bug at flashrom@flashrom.org\n", __func__);
Carl-Daniel Hailfinger75a58f92010-10-13 22:26:56 +0000814 /* Do not return an error for now. */
815 //return SPI_GENERIC_ERROR;
Carl-Daniel Hailfinger9c62d112010-06-20 10:41:35 +0000816 }
817
Nico Hubera1672f82017-10-14 18:00:20 +0200818 result = spi_write_cmd(flash, JEDEC_AAI_WORD_PROGRAM, false, start, buf + pos - start, 2, 10);
Nico Huber0ecbacb2017-10-14 16:50:43 +0200819 if (result)
Stefan Reinauer87ace662014-04-26 16:12:55 +0000820 goto bailout;
Carl-Daniel Hailfinger9c62d112010-06-20 10:41:35 +0000821
822 /* We already wrote 2 bytes in the multicommand step. */
823 pos += 2;
824
Carl-Daniel Hailfinger75a58f92010-10-13 22:26:56 +0000825 /* Are there at least two more bytes to write? */
826 while (pos < start + len - 1) {
Carl-Daniel Hailfingerccfe0ac2010-10-27 22:07:11 +0000827 cmd[1] = buf[pos++ - start];
828 cmd[2] = buf[pos++ - start];
Stefan Reinauer87ace662014-04-26 16:12:55 +0000829 result = spi_send_command(flash, JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE, 0, cmd, NULL);
830 if (result != 0) {
831 msg_cerr("%s failed during followup AAI command execution: %d\n", __func__, result);
832 goto bailout;
833 }
Nico Huber0ecbacb2017-10-14 16:50:43 +0200834 if (spi_poll_wip(flash, 10))
835 goto bailout;
Carl-Daniel Hailfinger9c62d112010-06-20 10:41:35 +0000836 }
837
Stefan Tauner59c4d792014-04-26 16:13:09 +0000838 /* Use WRDI to exit AAI mode. This needs to be done before issuing any other non-AAI command. */
839 result = spi_write_disable(flash);
840 if (result != 0) {
841 msg_cerr("%s failed to disable AAI mode.\n", __func__);
842 return SPI_GENERIC_ERROR;
843 }
Carl-Daniel Hailfinger75a58f92010-10-13 22:26:56 +0000844
845 /* Write remaining byte (if any). */
846 if (pos < start + len) {
Carl-Daniel Hailfingerccfe0ac2010-10-27 22:07:11 +0000847 if (spi_chip_write_1(flash, buf + pos - start, pos, pos % 2))
Carl-Daniel Hailfinger75a58f92010-10-13 22:26:56 +0000848 return SPI_GENERIC_ERROR;
849 pos += pos % 2;
850 }
851
Sean Nelson14ba6682010-02-26 05:48:29 +0000852 return 0;
Stefan Reinauer87ace662014-04-26 16:12:55 +0000853
854bailout:
Stefan Tauner59c4d792014-04-26 16:13:09 +0000855 result = spi_write_disable(flash);
856 if (result != 0)
857 msg_cerr("%s failed to disable AAI mode.\n", __func__);
Stefan Reinauer87ace662014-04-26 16:12:55 +0000858 return SPI_GENERIC_ERROR;
Sean Nelson14ba6682010-02-26 05:48:29 +0000859}
Nico Huber7e3c81a2017-10-14 18:56:50 +0200860
861/* Enter 4-bytes addressing mode (without sending WREN before) */
862int spi_enter_4ba_b7(struct flashctx *flash)
863{
864 const unsigned char cmd = JEDEC_ENTER_4_BYTE_ADDR_MODE;
865
866 const int ret = spi_send_command(flash, sizeof(cmd), 0, &cmd, NULL);
867 if (!ret)
868 flash->in_4ba_mode = true;
869 return ret;
870}
871
872/* Enter 4-bytes addressing mode with sending WREN before */
873int spi_enter_4ba_b7_we(struct flashctx *flash)
874{
875 const int ret = spi_simple_write_cmd(flash, JEDEC_ENTER_4_BYTE_ADDR_MODE, 0);
876 if (!ret)
877 flash->in_4ba_mode = true;
878 return ret;
879}
880
881/* Exit 4-bytes addressing mode (without sending WREN before) */
882int spi_exit_4ba_e9(struct flashctx *flash)
883{
884 const unsigned char cmd = JEDEC_EXIT_4_BYTE_ADDR_MODE;
885
886 const int ret = spi_send_command(flash, sizeof(cmd), 0, &cmd, NULL);
887 if (!ret)
888 flash->in_4ba_mode = false;
889 return ret;
890}
891
892/* Exit 4-bytes addressing mode with sending WREN before */
893int spi_exit_4ba_e9_we(struct flashctx *flash)
894{
895 const int ret = spi_simple_write_cmd(flash, JEDEC_EXIT_4_BYTE_ADDR_MODE, 0);
896 if (!ret)
897 flash->in_4ba_mode = false;
898 return ret;
899}