blob: 766fa2b49ea002cf8678c8741138ad6651119c7e [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.
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
25#include <string.h>
26#include "flash.h"
27#include "flashchips.h"
28#include "chipdrivers.h"
hailfinger428f6852010-07-27 22:41:39 +000029#include "programmer.h"
snelson8913d082010-02-26 05:48:29 +000030#include "spi.h"
Boris Baykov1a2f5322016-06-11 18:29:00 +020031#include "spi4ba.h"
snelson8913d082010-02-26 05:48:29 +000032
David Hendricks57b75242015-11-20 15:54:07 -080033enum id_type {
34 RDID,
35 RDID4,
36 REMS,
37// RES1, /* TODO */
38 RES2,
39 NUM_ID_TYPES,
40};
41
42static struct {
43 int is_cached;
44 unsigned char bytes[4]; /* enough to hold largest ID type */
45} id_cache[NUM_ID_TYPES];
46
47void clear_spi_id_cache(void)
48{
49 memset(id_cache, 0, sizeof(id_cache));
50 return;
51}
52
Souvik Ghoshd75cd672016-06-17 14:21:39 -070053static int spi_rdid(struct flashctx *flash, unsigned char *readarr, int bytes)
snelson8913d082010-02-26 05:48:29 +000054{
krause2eb76212011-01-17 07:50:42 +000055 static const unsigned char cmd[JEDEC_RDID_OUTSIZE] = { JEDEC_RDID };
snelson8913d082010-02-26 05:48:29 +000056 int ret;
57 int i;
58
Souvik Ghoshd75cd672016-06-17 14:21:39 -070059 ret = spi_send_command(flash, sizeof(cmd), bytes, cmd, readarr);
snelson8913d082010-02-26 05:48:29 +000060 if (ret)
61 return ret;
snelsonfc007bb2010-03-24 23:14:32 +000062 msg_cspew("RDID returned");
snelson8913d082010-02-26 05:48:29 +000063 for (i = 0; i < bytes; i++)
snelsonfc007bb2010-03-24 23:14:32 +000064 msg_cspew(" 0x%02x", readarr[i]);
65 msg_cspew(". ");
snelson8913d082010-02-26 05:48:29 +000066 return 0;
67}
68
Souvik Ghoshd75cd672016-06-17 14:21:39 -070069static int spi_rems(struct flashctx *flash, unsigned char *readarr)
snelson8913d082010-02-26 05:48:29 +000070{
71 unsigned char cmd[JEDEC_REMS_OUTSIZE] = { JEDEC_REMS, 0, 0, 0 };
72 uint32_t readaddr;
73 int ret;
74
Souvik Ghoshd75cd672016-06-17 14:21:39 -070075 ret = spi_send_command(flash, sizeof(cmd), JEDEC_REMS_INSIZE, cmd, readarr);
snelson8913d082010-02-26 05:48:29 +000076 if (ret == SPI_INVALID_ADDRESS) {
77 /* Find the lowest even address allowed for reads. */
Souvik Ghoshd75cd672016-06-17 14:21:39 -070078 readaddr = (spi_get_valid_read_addr(flash) + 1) & ~1;
snelson8913d082010-02-26 05:48:29 +000079 cmd[1] = (readaddr >> 16) & 0xff,
80 cmd[2] = (readaddr >> 8) & 0xff,
81 cmd[3] = (readaddr >> 0) & 0xff,
Souvik Ghoshd75cd672016-06-17 14:21:39 -070082 ret = spi_send_command(flash, sizeof(cmd), JEDEC_REMS_INSIZE, cmd, readarr);
snelson8913d082010-02-26 05:48:29 +000083 }
84 if (ret)
85 return ret;
stefanct371e7e82011-07-07 19:56:58 +000086 msg_cspew("REMS returned 0x%02x 0x%02x. ", readarr[0], readarr[1]);
snelson8913d082010-02-26 05:48:29 +000087 return 0;
88}
89
Souvik Ghoshd75cd672016-06-17 14:21:39 -070090static int spi_res(struct flashctx *flash, unsigned char *readarr, int bytes)
snelson8913d082010-02-26 05:48:29 +000091{
92 unsigned char cmd[JEDEC_RES_OUTSIZE] = { JEDEC_RES, 0, 0, 0 };
93 uint32_t readaddr;
94 int ret;
hailfingercb0564e2010-06-20 10:39:33 +000095 int i;
snelson8913d082010-02-26 05:48:29 +000096
Souvik Ghoshd75cd672016-06-17 14:21:39 -070097 ret = spi_send_command(flash, sizeof(cmd), bytes, cmd, readarr);
snelson8913d082010-02-26 05:48:29 +000098 if (ret == SPI_INVALID_ADDRESS) {
99 /* Find the lowest even address allowed for reads. */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700100 readaddr = (spi_get_valid_read_addr(flash) + 1) & ~1;
snelson8913d082010-02-26 05:48:29 +0000101 cmd[1] = (readaddr >> 16) & 0xff,
102 cmd[2] = (readaddr >> 8) & 0xff,
103 cmd[3] = (readaddr >> 0) & 0xff,
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700104 ret = spi_send_command(flash, sizeof(cmd), bytes, cmd, readarr);
snelson8913d082010-02-26 05:48:29 +0000105 }
106 if (ret)
107 return ret;
hailfingercb0564e2010-06-20 10:39:33 +0000108 msg_cspew("RES returned");
109 for (i = 0; i < bytes; i++)
110 msg_cspew(" 0x%02x", readarr[i]);
111 msg_cspew(". ");
snelson8913d082010-02-26 05:48:29 +0000112 return 0;
113}
114
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700115int spi_write_enable(struct flashctx *flash)
snelson8913d082010-02-26 05:48:29 +0000116{
krause2eb76212011-01-17 07:50:42 +0000117 static const unsigned char cmd[JEDEC_WREN_OUTSIZE] = { JEDEC_WREN };
snelson8913d082010-02-26 05:48:29 +0000118 int result;
119
120 /* Send WREN (Write Enable) */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700121 result = spi_send_command(flash, sizeof(cmd), 0, cmd, NULL);
snelson8913d082010-02-26 05:48:29 +0000122
123 if (result)
snelsonfc007bb2010-03-24 23:14:32 +0000124 msg_cerr("%s failed\n", __func__);
snelson8913d082010-02-26 05:48:29 +0000125
126 return result;
127}
128
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700129int spi_write_disable(struct flashctx *flash)
snelson8913d082010-02-26 05:48:29 +0000130{
krause2eb76212011-01-17 07:50:42 +0000131 static const unsigned char cmd[JEDEC_WRDI_OUTSIZE] = { JEDEC_WRDI };
snelson8913d082010-02-26 05:48:29 +0000132
133 /* Send WRDI (Write Disable) */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700134 return spi_send_command(flash, sizeof(cmd), 0, cmd, NULL);
snelson8913d082010-02-26 05:48:29 +0000135}
136
David Hendricks7f7c7112012-10-11 17:15:48 -0700137static void rdid_get_ids(unsigned char *readarr,
138 int bytes, uint32_t *id1, uint32_t *id2)
snelson8913d082010-02-26 05:48:29 +0000139{
snelson8913d082010-02-26 05:48:29 +0000140 if (!oddparity(readarr[0]))
snelsonfc007bb2010-03-24 23:14:32 +0000141 msg_cdbg("RDID byte 0 parity violation. ");
snelson8913d082010-02-26 05:48:29 +0000142
hailfingercb0564e2010-06-20 10:39:33 +0000143 /* Check if this is a continuation vendor ID.
144 * FIXME: Handle continuation device IDs.
145 */
snelson8913d082010-02-26 05:48:29 +0000146 if (readarr[0] == 0x7f) {
147 if (!oddparity(readarr[1]))
snelsonfc007bb2010-03-24 23:14:32 +0000148 msg_cdbg("RDID byte 1 parity violation. ");
David Hendricks7f7c7112012-10-11 17:15:48 -0700149 *id1 = (readarr[0] << 8) | readarr[1];
150 *id2 = readarr[2];
snelson8913d082010-02-26 05:48:29 +0000151 if (bytes > 3) {
David Hendricks7f7c7112012-10-11 17:15:48 -0700152 *id2 <<= 8;
153 *id2 |= readarr[3];
snelson8913d082010-02-26 05:48:29 +0000154 }
155 } else {
David Hendricks7f7c7112012-10-11 17:15:48 -0700156 *id1 = readarr[0];
157 *id2 = (readarr[1] << 8) | readarr[2];
snelson8913d082010-02-26 05:48:29 +0000158 }
David Hendricks7f7c7112012-10-11 17:15:48 -0700159}
snelson8913d082010-02-26 05:48:29 +0000160
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700161static int compare_id(struct flashctx *flash, uint32_t id1, uint32_t id2)
David Hendricks7f7c7112012-10-11 17:15:48 -0700162{
163 msg_cdbg("id1 0x%02x, id2 0x%02x\n", id1, id2);
snelson8913d082010-02-26 05:48:29 +0000164
Patrick Georgif3fa2992017-02-02 16:24:44 +0100165 if (id1 == flash->chip->manufacture_id && id2 == flash->chip->model_id) {
snelson8913d082010-02-26 05:48:29 +0000166 /* Print the status register to tell the
167 * user about possible write protection.
168 */
169 spi_prettyprint_status_register(flash);
170
171 return 1;
172 }
173
174 /* Test if this is a pure vendor match. */
Patrick Georgif3fa2992017-02-02 16:24:44 +0100175 if (id1 == flash->chip->manufacture_id &&
176 GENERIC_DEVICE_ID == flash->chip->model_id)
snelson8913d082010-02-26 05:48:29 +0000177 return 1;
178
179 /* Test if there is any vendor ID. */
Patrick Georgif3fa2992017-02-02 16:24:44 +0100180 if (GENERIC_MANUF_ID == flash->chip->manufacture_id &&
snelson8913d082010-02-26 05:48:29 +0000181 id1 != 0xff)
182 return 1;
183
184 return 0;
185}
186
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700187int probe_spi_rdid(struct flashctx *flash)
snelson8913d082010-02-26 05:48:29 +0000188{
David Hendricks57b75242015-11-20 15:54:07 -0800189 uint32_t id1, id2;
David Hendricks7f7c7112012-10-11 17:15:48 -0700190
David Hendricks57b75242015-11-20 15:54:07 -0800191 if (!id_cache[RDID].is_cached) {
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700192 if (spi_rdid(flash, id_cache[RDID].bytes, 3))
David Hendricks7f7c7112012-10-11 17:15:48 -0700193 return 0;
David Hendricks57b75242015-11-20 15:54:07 -0800194 id_cache[RDID].is_cached = 1;
David Hendricks7f7c7112012-10-11 17:15:48 -0700195 }
196
David Hendricks57b75242015-11-20 15:54:07 -0800197 rdid_get_ids(id_cache[RDID].bytes, 3, &id1, &id2);
David Hendricks7f7c7112012-10-11 17:15:48 -0700198 return compare_id(flash, id1, id2);
snelson8913d082010-02-26 05:48:29 +0000199}
200
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700201int probe_spi_rdid4(struct flashctx *flash)
snelson8913d082010-02-26 05:48:29 +0000202{
David Hendricks57b75242015-11-20 15:54:07 -0800203 uint32_t id1, id2;
David Hendricks7f7c7112012-10-11 17:15:48 -0700204
hailfingercb0564e2010-06-20 10:39:33 +0000205 /* Some SPI controllers do not support commands with writecnt=1 and
206 * readcnt=4.
207 */
Patrick Georgif4f1e2f2017-03-10 17:38:40 +0100208 switch (spi_master->type) {
hailfinger90c7d542010-05-31 15:27:27 +0000209#if CONFIG_INTERNAL == 1
hailfinger324a9cc2010-05-26 01:45:41 +0000210#if defined(__i386__) || defined(__x86_64__)
hailfingercb0564e2010-06-20 10:39:33 +0000211 case SPI_CONTROLLER_IT87XX:
snelson8913d082010-02-26 05:48:29 +0000212 case SPI_CONTROLLER_WBSIO:
hailfingercb0564e2010-06-20 10:39:33 +0000213 msg_cinfo("4 byte RDID not supported on this SPI controller\n");
hailfingercb0564e2010-06-20 10:39:33 +0000214 break;
snelson8913d082010-02-26 05:48:29 +0000215#endif
hailfinger324a9cc2010-05-26 01:45:41 +0000216#endif
snelson8913d082010-02-26 05:48:29 +0000217 default:
David Hendricks7f7c7112012-10-11 17:15:48 -0700218 break;
snelson8913d082010-02-26 05:48:29 +0000219 }
220
David Hendricks57b75242015-11-20 15:54:07 -0800221 if (!id_cache[RDID4].is_cached) {
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700222 if (spi_rdid(flash, id_cache[RDID4].bytes, 4))
David Hendricks7f7c7112012-10-11 17:15:48 -0700223 return 0;
David Hendricks57b75242015-11-20 15:54:07 -0800224 id_cache[RDID4].is_cached = 1;
David Hendricks7f7c7112012-10-11 17:15:48 -0700225 }
David Hendricks57b75242015-11-20 15:54:07 -0800226
227 rdid_get_ids(id_cache[RDID4].bytes, 4, &id1, &id2);
David Hendricks7f7c7112012-10-11 17:15:48 -0700228 return compare_id(flash, id1, id2);
snelson8913d082010-02-26 05:48:29 +0000229}
230
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700231int probe_spi_rems(struct flashctx *flash)
snelson8913d082010-02-26 05:48:29 +0000232{
David Hendricks57b75242015-11-20 15:54:07 -0800233 uint32_t id1, id2;
snelson8913d082010-02-26 05:48:29 +0000234
David Hendricks57b75242015-11-20 15:54:07 -0800235 if (!id_cache[REMS].is_cached) {
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700236 if (spi_rems(flash, id_cache[REMS].bytes))
David Hendricks7f7c7112012-10-11 17:15:48 -0700237 return 0;
David Hendricks57b75242015-11-20 15:54:07 -0800238 id_cache[REMS].is_cached = 1;
stefanct9e6b98a2011-05-28 02:37:14 +0000239 }
snelson8913d082010-02-26 05:48:29 +0000240
David Hendricks57b75242015-11-20 15:54:07 -0800241 id1 = id_cache[REMS].bytes[0];
242 id2 = id_cache[REMS].bytes[1];
David Hendricks7f7c7112012-10-11 17:15:48 -0700243 return compare_id(flash, id1, id2);
snelson8913d082010-02-26 05:48:29 +0000244}
245
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700246int probe_spi_res1(struct flashctx *flash)
snelson8913d082010-02-26 05:48:29 +0000247{
krause2eb76212011-01-17 07:50:42 +0000248 static const unsigned char allff[] = {0xff, 0xff, 0xff};
249 static const unsigned char all00[] = {0x00, 0x00, 0x00};
snelson8913d082010-02-26 05:48:29 +0000250 unsigned char readarr[3];
251 uint32_t id2;
snelson8913d082010-02-26 05:48:29 +0000252
hailfinger59a83572010-05-28 17:07:57 +0000253 /* We only want one-byte RES if RDID and REMS are unusable. */
254
snelson8913d082010-02-26 05:48:29 +0000255 /* Check if RDID is usable and does not return 0xff 0xff 0xff or
256 * 0x00 0x00 0x00. In that case, RES is pointless.
257 */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700258 if (!spi_rdid(flash, readarr, 3) && memcmp(readarr, allff, 3) &&
snelson8913d082010-02-26 05:48:29 +0000259 memcmp(readarr, all00, 3)) {
260 msg_cdbg("Ignoring RES in favour of RDID.\n");
261 return 0;
262 }
263 /* Check if REMS is usable and does not return 0xff 0xff or
264 * 0x00 0x00. In that case, RES is pointless.
265 */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700266 if (!spi_rems(flash, readarr) && memcmp(readarr, allff, JEDEC_REMS_INSIZE) &&
snelson8913d082010-02-26 05:48:29 +0000267 memcmp(readarr, all00, JEDEC_REMS_INSIZE)) {
268 msg_cdbg("Ignoring RES in favour of REMS.\n");
269 return 0;
270 }
271
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700272 if (spi_res(flash, readarr, 1)) {
snelson8913d082010-02-26 05:48:29 +0000273 return 0;
stefanct9e6b98a2011-05-28 02:37:14 +0000274 }
snelson8913d082010-02-26 05:48:29 +0000275
snelson8913d082010-02-26 05:48:29 +0000276 id2 = readarr[0];
hailfinger59a83572010-05-28 17:07:57 +0000277
snelsonfc007bb2010-03-24 23:14:32 +0000278 msg_cdbg("%s: id 0x%x\n", __func__, id2);
hailfinger59a83572010-05-28 17:07:57 +0000279
Patrick Georgif3fa2992017-02-02 16:24:44 +0100280 if (id2 != flash->chip->model_id)
snelson8913d082010-02-26 05:48:29 +0000281 return 0;
282
283 /* Print the status register to tell the
284 * user about possible write protection.
285 */
286 spi_prettyprint_status_register(flash);
287 return 1;
288}
289
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700290int probe_spi_res2(struct flashctx *flash)
hailfinger59a83572010-05-28 17:07:57 +0000291{
hailfinger59a83572010-05-28 17:07:57 +0000292 uint32_t id1, id2;
293
David Hendricks57b75242015-11-20 15:54:07 -0800294 if (!id_cache[RES2].is_cached) {
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700295 if (spi_res(flash, id_cache[RES2].bytes, 2))
David Hendricks57b75242015-11-20 15:54:07 -0800296 return 0;
297 id_cache[RES2].is_cached = 1;
stefanct9e6b98a2011-05-28 02:37:14 +0000298 }
hailfinger59a83572010-05-28 17:07:57 +0000299
David Hendricks57b75242015-11-20 15:54:07 -0800300 id1 = id_cache[RES2].bytes[0];
301 id2 = id_cache[RES2].bytes[1];
hailfinger59a83572010-05-28 17:07:57 +0000302 msg_cdbg("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2);
303
Patrick Georgif3fa2992017-02-02 16:24:44 +0100304 if (id1 != flash->chip->manufacture_id || id2 != flash->chip->model_id)
hailfinger59a83572010-05-28 17:07:57 +0000305 return 0;
306
307 /* Print the status register to tell the
308 * user about possible write protection.
309 */
310 spi_prettyprint_status_register(flash);
311 return 1;
312}
313
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700314uint8_t spi_read_status_register(const struct flashctx *flash)
snelson8913d082010-02-26 05:48:29 +0000315{
krause2eb76212011-01-17 07:50:42 +0000316 static const unsigned char cmd[JEDEC_RDSR_OUTSIZE] = { JEDEC_RDSR };
snelson8913d082010-02-26 05:48:29 +0000317 /* FIXME: No workarounds for driver/hardware bugs in generic code. */
318 unsigned char readarr[2]; /* JEDEC_RDSR_INSIZE=1 but wbsio needs 2 */
319 int ret;
320
321 /* Read Status Register */
Patrick Georgif3fa2992017-02-02 16:24:44 +0100322 if (flash->chip->read_status)
323 ret = flash->chip->read_status(flash);
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530324 else
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700325 ret = spi_send_command(flash, sizeof(cmd), sizeof(readarr), cmd, readarr);
snelson8913d082010-02-26 05:48:29 +0000326 if (ret)
snelsonfc007bb2010-03-24 23:14:32 +0000327 msg_cerr("RDSR failed!\n");
snelson8913d082010-02-26 05:48:29 +0000328
329 return readarr[0];
330}
331
332/* Prettyprint the status register. Common definitions. */
hailfinger7533bc82011-05-19 00:06:06 +0000333void spi_prettyprint_status_register_welwip(uint8_t status)
hailfingerc33d4732010-07-29 13:09:18 +0000334{
335 msg_cdbg("Chip status register: Write Enable Latch (WEL) is "
336 "%sset\n", (status & (1 << 1)) ? "" : "not ");
337 msg_cdbg("Chip status register: Write In Progress (WIP/BUSY) is "
338 "%sset\n", (status & (1 << 0)) ? "" : "not ");
339}
340
341/* Prettyprint the status register. Common definitions. */
hailfinger7533bc82011-05-19 00:06:06 +0000342void spi_prettyprint_status_register_bp3210(uint8_t status, int bp)
343{
344 switch (bp) {
345 /* Fall through. */
346 case 3:
347 msg_cdbg("Chip status register: Bit 5 / Block Protect 3 (BP3) "
348 "is %sset\n", (status & (1 << 5)) ? "" : "not ");
349 case 2:
350 msg_cdbg("Chip status register: Bit 4 / Block Protect 2 (BP2) "
351 "is %sset\n", (status & (1 << 4)) ? "" : "not ");
352 case 1:
353 msg_cdbg("Chip status register: Bit 3 / Block Protect 1 (BP1) "
354 "is %sset\n", (status & (1 << 3)) ? "" : "not ");
355 case 0:
356 msg_cdbg("Chip status register: Bit 2 / Block Protect 0 (BP0) "
357 "is %sset\n", (status & (1 << 2)) ? "" : "not ");
358 }
359}
360
361/* Prettyprint the status register. Unnamed bits. */
362void spi_prettyprint_status_register_bit(uint8_t status, int bit)
363{
364 msg_cdbg("Chip status register: Bit %i "
365 "is %sset\n", bit, (status & (1 << bit)) ? "" : "not ");
366}
367
hailfingerc33d4732010-07-29 13:09:18 +0000368static void spi_prettyprint_status_register_common(uint8_t status)
snelson8913d082010-02-26 05:48:29 +0000369{
hailfinger7533bc82011-05-19 00:06:06 +0000370 spi_prettyprint_status_register_bp3210(status, 3);
hailfingerc33d4732010-07-29 13:09:18 +0000371 spi_prettyprint_status_register_welwip(status);
snelson8913d082010-02-26 05:48:29 +0000372}
373
374/* Prettyprint the status register. Works for
375 * ST M25P series
376 * MX MX25L series
377 */
378void spi_prettyprint_status_register_st_m25p(uint8_t status)
379{
snelsonfc007bb2010-03-24 23:14:32 +0000380 msg_cdbg("Chip status register: Status Register Write Disable "
snelson8913d082010-02-26 05:48:29 +0000381 "(SRWD) is %sset\n", (status & (1 << 7)) ? "" : "not ");
snelsonfc007bb2010-03-24 23:14:32 +0000382 msg_cdbg("Chip status register: Bit 6 is "
snelson8913d082010-02-26 05:48:29 +0000383 "%sset\n", (status & (1 << 6)) ? "" : "not ");
384 spi_prettyprint_status_register_common(status);
385}
386
387void spi_prettyprint_status_register_sst25(uint8_t status)
388{
snelsonfc007bb2010-03-24 23:14:32 +0000389 msg_cdbg("Chip status register: Block Protect Write Disable "
snelson8913d082010-02-26 05:48:29 +0000390 "(BPL) is %sset\n", (status & (1 << 7)) ? "" : "not ");
snelsonfc007bb2010-03-24 23:14:32 +0000391 msg_cdbg("Chip status register: Auto Address Increment Programming "
snelson8913d082010-02-26 05:48:29 +0000392 "(AAI) is %sset\n", (status & (1 << 6)) ? "" : "not ");
393 spi_prettyprint_status_register_common(status);
394}
395
396/* Prettyprint the status register. Works for
397 * SST 25VF016
398 */
399void spi_prettyprint_status_register_sst25vf016(uint8_t status)
400{
krause2eb76212011-01-17 07:50:42 +0000401 static const char *const bpt[] = {
snelson8913d082010-02-26 05:48:29 +0000402 "none",
403 "1F0000H-1FFFFFH",
404 "1E0000H-1FFFFFH",
405 "1C0000H-1FFFFFH",
406 "180000H-1FFFFFH",
407 "100000H-1FFFFFH",
408 "all", "all"
409 };
410 spi_prettyprint_status_register_sst25(status);
snelsonfc007bb2010-03-24 23:14:32 +0000411 msg_cdbg("Resulting block protection : %s\n",
snelson8913d082010-02-26 05:48:29 +0000412 bpt[(status & 0x1c) >> 2]);
413}
414
415void spi_prettyprint_status_register_sst25vf040b(uint8_t status)
416{
krause2eb76212011-01-17 07:50:42 +0000417 static const char *const bpt[] = {
snelson8913d082010-02-26 05:48:29 +0000418 "none",
419 "0x70000-0x7ffff",
420 "0x60000-0x7ffff",
421 "0x40000-0x7ffff",
422 "all blocks", "all blocks", "all blocks", "all blocks"
423 };
424 spi_prettyprint_status_register_sst25(status);
snelsonfc007bb2010-03-24 23:14:32 +0000425 msg_cdbg("Resulting block protection : %s\n",
snelson8913d082010-02-26 05:48:29 +0000426 bpt[(status & 0x1c) >> 2]);
427}
428
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700429int spi_prettyprint_status_register(struct flashctx *flash)
snelson8913d082010-02-26 05:48:29 +0000430{
431 uint8_t status;
432
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530433 status = spi_read_status_register(flash);
snelsonfc007bb2010-03-24 23:14:32 +0000434 msg_cdbg("Chip status register is %02x\n", status);
Patrick Georgif3fa2992017-02-02 16:24:44 +0100435 switch (flash->chip->manufacture_id) {
snelson8913d082010-02-26 05:48:29 +0000436 case ST_ID:
Patrick Georgif3fa2992017-02-02 16:24:44 +0100437 if (((flash->chip->model_id & 0xff00) == 0x2000) ||
438 ((flash->chip->model_id & 0xff00) == 0x2500))
snelson8913d082010-02-26 05:48:29 +0000439 spi_prettyprint_status_register_st_m25p(status);
440 break;
mhmd3c80cd2010-09-15 23:31:03 +0000441 case MACRONIX_ID:
Patrick Georgif3fa2992017-02-02 16:24:44 +0100442 if ((flash->chip->model_id & 0xff00) == 0x2000)
snelson8913d082010-02-26 05:48:29 +0000443 spi_prettyprint_status_register_st_m25p(status);
444 break;
445 case SST_ID:
Patrick Georgif3fa2992017-02-02 16:24:44 +0100446 switch (flash->chip->model_id) {
snelson8913d082010-02-26 05:48:29 +0000447 case 0x2541:
448 spi_prettyprint_status_register_sst25vf016(status);
449 break;
450 case 0x8d:
451 case 0x258d:
452 spi_prettyprint_status_register_sst25vf040b(status);
453 break;
454 default:
455 spi_prettyprint_status_register_sst25(status);
456 break;
457 }
458 break;
459 }
hailfinger7533bc82011-05-19 00:06:06 +0000460 return 0;
snelson8913d082010-02-26 05:48:29 +0000461}
462
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700463int spi_chip_erase_60(struct flashctx *flash)
snelson8913d082010-02-26 05:48:29 +0000464{
465 int result;
466 struct spi_command cmds[] = {
467 {
468 .writecnt = JEDEC_WREN_OUTSIZE,
469 .writearr = (const unsigned char[]){ JEDEC_WREN },
470 .readcnt = 0,
471 .readarr = NULL,
472 }, {
473 .writecnt = JEDEC_CE_60_OUTSIZE,
474 .writearr = (const unsigned char[]){ JEDEC_CE_60 },
475 .readcnt = 0,
476 .readarr = NULL,
477 }, {
478 .writecnt = 0,
479 .writearr = NULL,
480 .readcnt = 0,
481 .readarr = NULL,
482 }};
483
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700484 result = spi_send_multicommand(flash, cmds);
snelson8913d082010-02-26 05:48:29 +0000485 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000486 msg_cerr("%s failed during command execution\n",
snelson8913d082010-02-26 05:48:29 +0000487 __func__);
488 return result;
489 }
490 /* Wait until the Write-In-Progress bit is cleared.
491 * This usually takes 1-85 s, so wait in 1 s steps.
492 */
493 /* FIXME: We assume spi_read_status_register will never fail. */
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530494 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
snelson8913d082010-02-26 05:48:29 +0000495 programmer_delay(1000 * 1000);
hailfingerac8e3182011-06-26 17:04:16 +0000496 /* FIXME: Check the status register for errors. */
snelson8913d082010-02-26 05:48:29 +0000497 return 0;
498}
499
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700500int spi_chip_erase_c7(struct flashctx *flash)
snelson8913d082010-02-26 05:48:29 +0000501{
502 int result;
503 struct spi_command cmds[] = {
504 {
505 .writecnt = JEDEC_WREN_OUTSIZE,
506 .writearr = (const unsigned char[]){ JEDEC_WREN },
507 .readcnt = 0,
508 .readarr = NULL,
509 }, {
510 .writecnt = JEDEC_CE_C7_OUTSIZE,
511 .writearr = (const unsigned char[]){ JEDEC_CE_C7 },
512 .readcnt = 0,
513 .readarr = NULL,
514 }, {
515 .writecnt = 0,
516 .writearr = NULL,
517 .readcnt = 0,
518 .readarr = NULL,
519 }};
520
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700521 result = spi_send_multicommand(flash, cmds);
snelson8913d082010-02-26 05:48:29 +0000522 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000523 msg_cerr("%s failed during command execution\n", __func__);
snelson8913d082010-02-26 05:48:29 +0000524 return result;
525 }
526 /* Wait until the Write-In-Progress bit is cleared.
527 * This usually takes 1-85 s, so wait in 1 s steps.
528 */
529 /* FIXME: We assume spi_read_status_register will never fail. */
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530530 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
snelson8913d082010-02-26 05:48:29 +0000531 programmer_delay(1000 * 1000);
hailfingerac8e3182011-06-26 17:04:16 +0000532 /* FIXME: Check the status register for errors. */
snelson8913d082010-02-26 05:48:29 +0000533 return 0;
534}
535
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700536int spi_block_erase_52(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
snelson8913d082010-02-26 05:48:29 +0000537{
538 int result;
539 struct spi_command cmds[] = {
540 {
541 .writecnt = JEDEC_WREN_OUTSIZE,
542 .writearr = (const unsigned char[]){ JEDEC_WREN },
543 .readcnt = 0,
544 .readarr = NULL,
545 }, {
546 .writecnt = JEDEC_BE_52_OUTSIZE,
547 .writearr = (const unsigned char[]){
548 JEDEC_BE_52,
549 (addr >> 16) & 0xff,
550 (addr >> 8) & 0xff,
551 (addr & 0xff)
552 },
553 .readcnt = 0,
554 .readarr = NULL,
555 }, {
556 .writecnt = 0,
557 .writearr = NULL,
558 .readcnt = 0,
559 .readarr = NULL,
560 }};
561
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700562 result = spi_send_multicommand(flash, cmds);
snelson8913d082010-02-26 05:48:29 +0000563 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000564 msg_cerr("%s failed during command execution at address 0x%x\n",
snelson8913d082010-02-26 05:48:29 +0000565 __func__, addr);
566 return result;
567 }
568 /* Wait until the Write-In-Progress bit is cleared.
569 * This usually takes 100-4000 ms, so wait in 100 ms steps.
570 */
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530571 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
snelson8913d082010-02-26 05:48:29 +0000572 programmer_delay(100 * 1000);
hailfingerac8e3182011-06-26 17:04:16 +0000573 /* FIXME: Check the status register for errors. */
snelson8913d082010-02-26 05:48:29 +0000574 return 0;
575}
576
577/* Block size is usually
578 * 64k for Macronix
579 * 32k for SST
580 * 4-32k non-uniform for EON
581 */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700582int spi_block_erase_d8(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
snelson8913d082010-02-26 05:48:29 +0000583{
584 int result;
585 struct spi_command cmds[] = {
586 {
587 .writecnt = JEDEC_WREN_OUTSIZE,
588 .writearr = (const unsigned char[]){ JEDEC_WREN },
589 .readcnt = 0,
590 .readarr = NULL,
591 }, {
592 .writecnt = JEDEC_BE_D8_OUTSIZE,
593 .writearr = (const unsigned char[]){
594 JEDEC_BE_D8,
595 (addr >> 16) & 0xff,
596 (addr >> 8) & 0xff,
597 (addr & 0xff)
598 },
599 .readcnt = 0,
600 .readarr = NULL,
601 }, {
602 .writecnt = 0,
603 .writearr = NULL,
604 .readcnt = 0,
605 .readarr = NULL,
606 }};
607
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700608 result = spi_send_multicommand(flash, cmds);
snelson8913d082010-02-26 05:48:29 +0000609 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000610 msg_cerr("%s failed during command execution at address 0x%x\n",
snelson8913d082010-02-26 05:48:29 +0000611 __func__, addr);
612 return result;
613 }
614 /* Wait until the Write-In-Progress bit is cleared.
615 * This usually takes 100-4000 ms, so wait in 100 ms steps.
616 */
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530617 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
snelson8913d082010-02-26 05:48:29 +0000618 programmer_delay(100 * 1000);
hailfingerac8e3182011-06-26 17:04:16 +0000619 /* FIXME: Check the status register for errors. */
snelson8913d082010-02-26 05:48:29 +0000620 return 0;
621}
622
623/* Block size is usually
624 * 4k for PMC
625 */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700626int spi_block_erase_d7(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
snelson8913d082010-02-26 05:48:29 +0000627{
628 int result;
629 struct spi_command cmds[] = {
630 {
631 .writecnt = JEDEC_WREN_OUTSIZE,
632 .writearr = (const unsigned char[]){ JEDEC_WREN },
633 .readcnt = 0,
634 .readarr = NULL,
635 }, {
636 .writecnt = JEDEC_BE_D7_OUTSIZE,
637 .writearr = (const unsigned char[]){
638 JEDEC_BE_D7,
639 (addr >> 16) & 0xff,
640 (addr >> 8) & 0xff,
641 (addr & 0xff)
642 },
643 .readcnt = 0,
644 .readarr = NULL,
645 }, {
646 .writecnt = 0,
647 .writearr = NULL,
648 .readcnt = 0,
649 .readarr = NULL,
650 }};
651
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700652 result = spi_send_multicommand(flash, cmds);
snelson8913d082010-02-26 05:48:29 +0000653 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000654 msg_cerr("%s failed during command execution at address 0x%x\n",
snelson8913d082010-02-26 05:48:29 +0000655 __func__, addr);
656 return result;
657 }
658 /* Wait until the Write-In-Progress bit is cleared.
659 * This usually takes 100-4000 ms, so wait in 100 ms steps.
660 */
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530661 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
snelson8913d082010-02-26 05:48:29 +0000662 programmer_delay(100 * 1000);
hailfingerac8e3182011-06-26 17:04:16 +0000663 /* FIXME: Check the status register for errors. */
snelson8913d082010-02-26 05:48:29 +0000664 return 0;
665}
666
snelson8913d082010-02-26 05:48:29 +0000667/* Sector size is usually 4k, though Macronix eliteflash has 64k */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700668int spi_block_erase_20(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
snelson8913d082010-02-26 05:48:29 +0000669{
670 int result;
671 struct spi_command cmds[] = {
672 {
673 .writecnt = JEDEC_WREN_OUTSIZE,
674 .writearr = (const unsigned char[]){ JEDEC_WREN },
675 .readcnt = 0,
676 .readarr = NULL,
677 }, {
678 .writecnt = JEDEC_SE_OUTSIZE,
679 .writearr = (const unsigned char[]){
680 JEDEC_SE,
681 (addr >> 16) & 0xff,
682 (addr >> 8) & 0xff,
683 (addr & 0xff)
684 },
685 .readcnt = 0,
686 .readarr = NULL,
687 }, {
688 .writecnt = 0,
689 .writearr = NULL,
690 .readcnt = 0,
691 .readarr = NULL,
692 }};
693
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700694 result = spi_send_multicommand(flash, cmds);
Stefan Reinauercce56d52010-11-22 18:22:21 -0800695
snelson8913d082010-02-26 05:48:29 +0000696 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000697 msg_cerr("%s failed during command execution at address 0x%x\n",
snelson8913d082010-02-26 05:48:29 +0000698 __func__, addr);
699 return result;
700 }
701 /* Wait until the Write-In-Progress bit is cleared.
702 * This usually takes 15-800 ms, so wait in 10 ms steps.
703 */
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530704 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
snelson8913d082010-02-26 05:48:29 +0000705 programmer_delay(10 * 1000);
hailfingerac8e3182011-06-26 17:04:16 +0000706 /* FIXME: Check the status register for errors. */
snelson8913d082010-02-26 05:48:29 +0000707 return 0;
708}
709
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700710int spi_block_erase_60(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
snelson8913d082010-02-26 05:48:29 +0000711{
Patrick Georgif3fa2992017-02-02 16:24:44 +0100712 if ((addr != 0) || (blocklen != flash->chip->total_size * 1024)) {
snelsonfc007bb2010-03-24 23:14:32 +0000713 msg_cerr("%s called with incorrect arguments\n",
snelson8913d082010-02-26 05:48:29 +0000714 __func__);
715 return -1;
716 }
717 return spi_chip_erase_60(flash);
718}
719
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700720int spi_block_erase_c7(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
snelson8913d082010-02-26 05:48:29 +0000721{
Patrick Georgif3fa2992017-02-02 16:24:44 +0100722 if ((addr != 0) || (blocklen != flash->chip->total_size * 1024)) {
snelsonfc007bb2010-03-24 23:14:32 +0000723 msg_cerr("%s called with incorrect arguments\n",
snelson8913d082010-02-26 05:48:29 +0000724 __func__);
725 return -1;
726 }
727 return spi_chip_erase_c7(flash);
728}
729
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700730int spi_write_status_enable(struct flashctx *flash)
snelson8913d082010-02-26 05:48:29 +0000731{
krause2eb76212011-01-17 07:50:42 +0000732 static const unsigned char cmd[JEDEC_EWSR_OUTSIZE] = { JEDEC_EWSR };
snelson8913d082010-02-26 05:48:29 +0000733 int result;
734
735 /* Send EWSR (Enable Write Status Register). */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700736 result = spi_send_command(flash, sizeof(cmd), JEDEC_EWSR_INSIZE, cmd, NULL);
snelson8913d082010-02-26 05:48:29 +0000737
738 if (result)
snelsonfc007bb2010-03-24 23:14:32 +0000739 msg_cerr("%s failed\n", __func__);
snelson8913d082010-02-26 05:48:29 +0000740
741 return result;
742}
743
744/*
745 * This is according the SST25VF016 datasheet, who knows it is more
746 * generic that this...
747 */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700748static int spi_write_status_register_ewsr(const struct flashctx *flash, int status)
snelson8913d082010-02-26 05:48:29 +0000749{
750 int result;
hailfingeree9ee132010-10-08 00:37:55 +0000751 int i = 0;
snelson8913d082010-02-26 05:48:29 +0000752 struct spi_command cmds[] = {
753 {
hailfingerc33d4732010-07-29 13:09:18 +0000754 /* WRSR requires either EWSR or WREN depending on chip type. */
snelson8913d082010-02-26 05:48:29 +0000755 .writecnt = JEDEC_EWSR_OUTSIZE,
756 .writearr = (const unsigned char[]){ JEDEC_EWSR },
757 .readcnt = 0,
758 .readarr = NULL,
759 }, {
760 .writecnt = JEDEC_WRSR_OUTSIZE,
761 .writearr = (const unsigned char[]){ JEDEC_WRSR, (unsigned char) status },
762 .readcnt = 0,
763 .readarr = NULL,
764 }, {
765 .writecnt = 0,
766 .writearr = NULL,
767 .readcnt = 0,
768 .readarr = NULL,
769 }};
770
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700771 result = spi_send_multicommand(flash, cmds);
snelson8913d082010-02-26 05:48:29 +0000772 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000773 msg_cerr("%s failed during command execution\n",
snelson8913d082010-02-26 05:48:29 +0000774 __func__);
hailfingeree9ee132010-10-08 00:37:55 +0000775 /* No point in waiting for the command to complete if execution
776 * failed.
777 */
778 return result;
snelson8913d082010-02-26 05:48:29 +0000779 }
hailfingeree9ee132010-10-08 00:37:55 +0000780 /* WRSR performs a self-timed erase before the changes take effect.
781 * This may take 50-85 ms in most cases, and some chips apparently
782 * allow running RDSR only once. Therefore pick an initial delay of
783 * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed.
784 */
hailfingerc33d4732010-07-29 13:09:18 +0000785 programmer_delay(100 * 1000);
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530786 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) {
hailfingeree9ee132010-10-08 00:37:55 +0000787 if (++i > 490) {
788 msg_cerr("Error: WIP bit after WRSR never cleared\n");
789 return TIMEOUT_ERROR;
790 }
791 programmer_delay(10 * 1000);
792 }
793 return 0;
snelson8913d082010-02-26 05:48:29 +0000794}
795
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700796int spi_write_status_register_wren(const struct flashctx *flash, int status)
hailfingerc33d4732010-07-29 13:09:18 +0000797{
798 int result;
hailfingeree9ee132010-10-08 00:37:55 +0000799 int i = 0;
hailfingerc33d4732010-07-29 13:09:18 +0000800 struct spi_command cmds[] = {
801 {
802 /* WRSR requires either EWSR or WREN depending on chip type. */
803 .writecnt = JEDEC_WREN_OUTSIZE,
804 .writearr = (const unsigned char[]){ JEDEC_WREN },
805 .readcnt = 0,
806 .readarr = NULL,
807 }, {
808 .writecnt = JEDEC_WRSR_OUTSIZE,
809 .writearr = (const unsigned char[]){ JEDEC_WRSR, (unsigned char) status },
810 .readcnt = 0,
811 .readarr = NULL,
812 }, {
813 .writecnt = 0,
814 .writearr = NULL,
815 .readcnt = 0,
816 .readarr = NULL,
817 }};
818
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700819 result = spi_send_multicommand(flash, cmds);
hailfingerc33d4732010-07-29 13:09:18 +0000820 if (result) {
821 msg_cerr("%s failed during command execution\n",
822 __func__);
hailfingeree9ee132010-10-08 00:37:55 +0000823 /* No point in waiting for the command to complete if execution
824 * failed.
825 */
826 return result;
hailfingerc33d4732010-07-29 13:09:18 +0000827 }
hailfingeree9ee132010-10-08 00:37:55 +0000828 /* WRSR performs a self-timed erase before the changes take effect.
829 * This may take 50-85 ms in most cases, and some chips apparently
830 * allow running RDSR only once. Therefore pick an initial delay of
831 * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed.
832 */
hailfingerc33d4732010-07-29 13:09:18 +0000833 programmer_delay(100 * 1000);
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530834 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) {
hailfingeree9ee132010-10-08 00:37:55 +0000835 if (++i > 490) {
836 msg_cerr("Error: WIP bit after WRSR never cleared\n");
837 return TIMEOUT_ERROR;
838 }
839 programmer_delay(10 * 1000);
840 }
841 return 0;
hailfingerc33d4732010-07-29 13:09:18 +0000842}
843
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700844int spi_write_status_register(const struct flashctx *flash, int status)
hailfingerc33d4732010-07-29 13:09:18 +0000845{
846 int ret = 1;
847
Patrick Georgif3fa2992017-02-02 16:24:44 +0100848 if (flash->chip->write_status) {
849 ret = flash->chip->write_status(flash, status);
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530850 } else {
Patrick Georgif3fa2992017-02-02 16:24:44 +0100851 if (flash->chip->feature_bits & FEATURE_WRSR_WREN)
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530852 ret = spi_write_status_register_wren(flash, status);
Patrick Georgif3fa2992017-02-02 16:24:44 +0100853 if (ret && (flash->chip->feature_bits & FEATURE_WRSR_EWSR))
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530854 ret = spi_write_status_register_ewsr(flash, status);
855 }
856
hailfingerc33d4732010-07-29 13:09:18 +0000857 return ret;
858}
859
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700860int spi_byte_program(struct flashctx *flash, unsigned int addr, uint8_t databyte)
snelson8913d082010-02-26 05:48:29 +0000861{
862 int result;
863 struct spi_command cmds[] = {
864 {
865 .writecnt = JEDEC_WREN_OUTSIZE,
866 .writearr = (const unsigned char[]){ JEDEC_WREN },
867 .readcnt = 0,
868 .readarr = NULL,
869 }, {
870 .writecnt = JEDEC_BYTE_PROGRAM_OUTSIZE,
871 .writearr = (const unsigned char[]){
872 JEDEC_BYTE_PROGRAM,
873 (addr >> 16) & 0xff,
874 (addr >> 8) & 0xff,
875 (addr & 0xff),
876 databyte
877 },
878 .readcnt = 0,
879 .readarr = NULL,
880 }, {
881 .writecnt = 0,
882 .writearr = NULL,
883 .readcnt = 0,
884 .readarr = NULL,
885 }};
886
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700887 result = spi_send_multicommand(flash, cmds);
snelson8913d082010-02-26 05:48:29 +0000888 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000889 msg_cerr("%s failed during command execution at address 0x%x\n",
snelson8913d082010-02-26 05:48:29 +0000890 __func__, addr);
891 }
892 return result;
893}
894
Patrick Georgiab8353e2017-02-03 18:32:01 +0100895int spi_nbyte_program(struct flashctx *flash, unsigned int addr, const uint8_t *bytes, unsigned int len)
snelson8913d082010-02-26 05:48:29 +0000896{
897 int result;
898 /* FIXME: Switch to malloc based on len unless that kills speed. */
899 unsigned char cmd[JEDEC_BYTE_PROGRAM_OUTSIZE - 1 + 256] = {
900 JEDEC_BYTE_PROGRAM,
901 (addr >> 16) & 0xff,
902 (addr >> 8) & 0xff,
903 (addr >> 0) & 0xff,
904 };
905 struct spi_command cmds[] = {
906 {
907 .writecnt = JEDEC_WREN_OUTSIZE,
908 .writearr = (const unsigned char[]){ JEDEC_WREN },
909 .readcnt = 0,
910 .readarr = NULL,
911 }, {
912 .writecnt = JEDEC_BYTE_PROGRAM_OUTSIZE - 1 + len,
913 .writearr = cmd,
914 .readcnt = 0,
915 .readarr = NULL,
916 }, {
917 .writecnt = 0,
918 .writearr = NULL,
919 .readcnt = 0,
920 .readarr = NULL,
921 }};
922
923 if (!len) {
snelsonfc007bb2010-03-24 23:14:32 +0000924 msg_cerr("%s called for zero-length write\n", __func__);
snelson8913d082010-02-26 05:48:29 +0000925 return 1;
926 }
927 if (len > 256) {
snelsonfc007bb2010-03-24 23:14:32 +0000928 msg_cerr("%s called for too long a write\n", __func__);
snelson8913d082010-02-26 05:48:29 +0000929 return 1;
930 }
931
932 memcpy(&cmd[4], bytes, len);
933
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700934 result = spi_send_multicommand(flash, cmds);
snelson8913d082010-02-26 05:48:29 +0000935 if (result) {
David Hendricks1ed1d352011-11-23 17:54:37 -0800936 if (result != SPI_ACCESS_DENIED) {
937 msg_cerr("%s failed during command execution at address 0x%x\n",
938 __func__, addr);
939 }
snelson8913d082010-02-26 05:48:29 +0000940 }
941 return result;
942}
943
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700944int spi_restore_status(struct flashctx *flash, uint8_t status)
David Hendricksbf36f092010-11-02 23:39:29 -0700945{
946 msg_cdbg("restoring chip status (0x%02x)\n", status);
947 return spi_write_status_register(flash, status);
948}
949
hailfingerc33d4732010-07-29 13:09:18 +0000950/* A generic brute-force block protection disable works like this:
951 * Write 0x00 to the status register. Check if any locks are still set (that
952 * part is chip specific). Repeat once.
953 */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700954int spi_disable_blockprotect(struct flashctx *flash)
snelson8913d082010-02-26 05:48:29 +0000955{
956 uint8_t status;
957 int result;
958
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530959 status = spi_read_status_register(flash);
hailfingerc33d4732010-07-29 13:09:18 +0000960 /* If block protection is disabled, stop here. */
961 if ((status & 0x3c) == 0)
962 return 0;
963
David Hendricksbf36f092010-11-02 23:39:29 -0700964 /* restore status register content upon exit */
965 register_chip_restore(spi_restore_status, flash, status);
966
hailfingerc33d4732010-07-29 13:09:18 +0000967 msg_cdbg("Some block protection in effect, disabling\n");
968 result = spi_write_status_register(flash, status & ~0x3c);
969 if (result) {
970 msg_cerr("spi_write_status_register failed\n");
971 return result;
972 }
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530973 status = spi_read_status_register(flash);
snelson8913d082010-02-26 05:48:29 +0000974 if ((status & 0x3c) != 0) {
hailfingerc33d4732010-07-29 13:09:18 +0000975 msg_cerr("Block protection could not be disabled!\n");
976 return 1;
977 }
978 return 0;
979}
980
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700981int spi_nbyte_read(struct flashctx *flash, unsigned int address, uint8_t *bytes, unsigned int len)
snelson8913d082010-02-26 05:48:29 +0000982{
983 const unsigned char cmd[JEDEC_READ_OUTSIZE] = {
984 JEDEC_READ,
985 (address >> 16) & 0xff,
986 (address >> 8) & 0xff,
987 (address >> 0) & 0xff,
988 };
989
990 /* Send Read */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700991 return spi_send_command(flash, sizeof(cmd), len, cmd, bytes);
snelson8913d082010-02-26 05:48:29 +0000992}
993
994/*
hailfinger39d159a2010-05-21 23:09:42 +0000995 * Read a part of the flash chip.
hailfingerc7d06c62010-07-14 16:19:05 +0000996 * FIXME: Use the chunk code from Michael Karcher instead.
snelson8913d082010-02-26 05:48:29 +0000997 * Each page is read separately in chunks with a maximum size of chunksize.
998 */
Souvik Ghoshd75cd672016-06-17 14:21:39 -0700999int spi_read_chunked(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize)
snelson8913d082010-02-26 05:48:29 +00001000{
David Hendricks1ed1d352011-11-23 17:54:37 -08001001 int rc = 0, chunk_status = 0;
stefanctc5eb8a92011-11-23 09:13:48 +00001002 unsigned int i, j, starthere, lenhere, toread;
Patrick Georgif3fa2992017-02-02 16:24:44 +01001003 unsigned int page_size = flash->chip->page_size;
snelson8913d082010-02-26 05:48:29 +00001004
1005 /* Warning: This loop has a very unusual condition and body.
1006 * The loop needs to go through each page with at least one affected
1007 * byte. The lowest page number is (start / page_size) since that
1008 * division rounds down. The highest page number we want is the page
1009 * where the last byte of the range lives. That last byte has the
1010 * address (start + len - 1), thus the highest page number is
1011 * (start + len - 1) / page_size. Since we want to include that last
1012 * page as well, the loop condition uses <=.
1013 */
1014 for (i = start / page_size; i <= (start + len - 1) / page_size; i++) {
1015 /* Byte position of the first byte in the range in this page. */
1016 /* starthere is an offset to the base address of the chip. */
1017 starthere = max(start, i * page_size);
1018 /* Length of bytes in the range in this page. */
1019 lenhere = min(start + len, (i + 1) * page_size) - starthere;
1020 for (j = 0; j < lenhere; j += chunksize) {
1021 toread = min(chunksize, lenhere - j);
Boris Baykov1a2f5322016-06-11 18:29:00 +02001022 chunk_status = (flash->chip->feature_bits & FEATURE_4BA_SUPPORT) == 0
1023 ? spi_nbyte_read(flash, starthere + j, buf + starthere - start + j, toread)
1024 : flash->chip->four_bytes_addr_funcs.read_nbyte(flash, starthere + j,
1025 buf + starthere - start + j, toread);
David Hendricks1ed1d352011-11-23 17:54:37 -08001026 if (chunk_status) {
1027 if (ignore_error(chunk_status)) {
1028 /* fill this chunk with 0xff bytes and
1029 let caller know about the error */
1030 memset(buf + starthere - start + j, 0xff, toread);
1031 rc = chunk_status;
1032 chunk_status = 0;
1033 continue;
1034 } else {
1035 rc = chunk_status;
1036 break;
1037 }
1038 }
snelson8913d082010-02-26 05:48:29 +00001039 }
David Hendricks1ed1d352011-11-23 17:54:37 -08001040 if (chunk_status)
snelson8913d082010-02-26 05:48:29 +00001041 break;
1042 }
1043
1044 return rc;
1045}
1046
1047/*
Duncan Laurie06ffd522015-10-26 12:56:08 -07001048 * Read a part of the flash chip.
1049 * Ignore pages and read the data continuously, the only bound is the chunksize.
1050 */
Souvik Ghoshd75cd672016-06-17 14:21:39 -07001051int spi_read_unbound(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize)
Duncan Laurie06ffd522015-10-26 12:56:08 -07001052{
1053 int rc = 0;
1054 unsigned int i;
1055
1056 for (i = start; i < (start + len); i += chunksize) {
David Hendricks37370ec2015-11-24 14:38:17 -08001057 int chunk_status = 0;
1058 unsigned int toread = min(chunksize, start + len - i);
1059
Souvik Ghoshd75cd672016-06-17 14:21:39 -07001060 chunk_status = spi_nbyte_read(flash, i, buf + (i - start), toread);
David Hendricks37370ec2015-11-24 14:38:17 -08001061 if (chunk_status) {
1062 if (ignore_error(chunk_status)) {
1063 /* fill this chunk with 0xff bytes and
1064 let caller know about the error */
1065 memset(buf + (i - start), 0xff, toread);
1066 rc = chunk_status;
1067 continue;
1068 } else {
1069 rc = chunk_status;
1070 break;
1071 }
1072 }
Duncan Laurie06ffd522015-10-26 12:56:08 -07001073 }
David Hendricks37370ec2015-11-24 14:38:17 -08001074
Duncan Laurie06ffd522015-10-26 12:56:08 -07001075 return rc;
1076}
1077
1078/*
hailfinger39d159a2010-05-21 23:09:42 +00001079 * Write a part of the flash chip.
hailfingerc7d06c62010-07-14 16:19:05 +00001080 * FIXME: Use the chunk code from Michael Karcher instead.
hailfinger39d159a2010-05-21 23:09:42 +00001081 * Each page is written separately in chunks with a maximum size of chunksize.
1082 */
Patrick Georgiab8353e2017-02-03 18:32:01 +01001083int spi_write_chunked(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize)
hailfinger39d159a2010-05-21 23:09:42 +00001084{
1085 int rc = 0;
stefanctc5eb8a92011-11-23 09:13:48 +00001086 unsigned int i, j, starthere, lenhere, towrite;
hailfinger39d159a2010-05-21 23:09:42 +00001087 /* FIXME: page_size is the wrong variable. We need max_writechunk_size
Souvik Ghoshd75cd672016-06-17 14:21:39 -07001088 * in struct flashctx to do this properly. All chips using
hailfinger39d159a2010-05-21 23:09:42 +00001089 * spi_chip_write_256 have page_size set to max_writechunk_size, so
1090 * we're OK for now.
1091 */
Patrick Georgif3fa2992017-02-02 16:24:44 +01001092 unsigned int page_size = flash->chip->page_size;
hailfinger39d159a2010-05-21 23:09:42 +00001093
1094 /* Warning: This loop has a very unusual condition and body.
1095 * The loop needs to go through each page with at least one affected
1096 * byte. The lowest page number is (start / page_size) since that
1097 * division rounds down. The highest page number we want is the page
1098 * where the last byte of the range lives. That last byte has the
1099 * address (start + len - 1), thus the highest page number is
1100 * (start + len - 1) / page_size. Since we want to include that last
1101 * page as well, the loop condition uses <=.
1102 */
1103 for (i = start / page_size; i <= (start + len - 1) / page_size; i++) {
1104 /* Byte position of the first byte in the range in this page. */
1105 /* starthere is an offset to the base address of the chip. */
1106 starthere = max(start, i * page_size);
1107 /* Length of bytes in the range in this page. */
1108 lenhere = min(start + len, (i + 1) * page_size) - starthere;
1109 for (j = 0; j < lenhere; j += chunksize) {
1110 towrite = min(chunksize, lenhere - j);
Boris Baykov1a2f5322016-06-11 18:29:00 +02001111 rc = (flash->chip->feature_bits & FEATURE_4BA_SUPPORT) == 0
1112 ? spi_nbyte_program(flash, starthere + j, buf + starthere - start + j, towrite)
1113 : flash->chip->four_bytes_addr_funcs.program_nbyte(flash, starthere + j,
1114 buf + starthere - start + j, towrite);
hailfinger39d159a2010-05-21 23:09:42 +00001115 if (rc)
1116 break;
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301117 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
hailfinger39d159a2010-05-21 23:09:42 +00001118 programmer_delay(10);
1119 }
1120 if (rc)
1121 break;
1122 }
1123
1124 return rc;
1125}
1126
1127/*
snelson8913d082010-02-26 05:48:29 +00001128 * Program chip using byte programming. (SLOW!)
1129 * This is for chips which can only handle one byte writes
1130 * and for chips where memory mapped programming is impossible
1131 * (e.g. due to size constraints in IT87* for over 512 kB)
1132 */
hailfingerc7d06c62010-07-14 16:19:05 +00001133/* real chunksize is 1, logical chunksize is 1 */
Patrick Georgiab8353e2017-02-03 18:32:01 +01001134int spi_chip_write_1(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
snelson8913d082010-02-26 05:48:29 +00001135{
stefanctc5eb8a92011-11-23 09:13:48 +00001136 unsigned int i;
1137 int result = 0;
snelson8913d082010-02-26 05:48:29 +00001138
hailfingerc7d06c62010-07-14 16:19:05 +00001139 for (i = start; i < start + len; i++) {
Boris Baykov1a2f5322016-06-11 18:29:00 +02001140 result = (flash->chip->feature_bits & FEATURE_4BA_SUPPORT) == 0
1141 ? spi_byte_program(flash, i, buf[i - start])
1142 : flash->chip->four_bytes_addr_funcs.program_byte(flash, i, buf[i - start]);
snelson8913d082010-02-26 05:48:29 +00001143 if (result)
1144 return 1;
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301145 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
snelson8913d082010-02-26 05:48:29 +00001146 programmer_delay(10);
1147 }
1148
1149 return 0;
1150}
1151
Patrick Georgiab8353e2017-02-03 18:32:01 +01001152int spi_aai_write(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
hailfingerc7d06c62010-07-14 16:19:05 +00001153{
1154 uint32_t pos = start;
snelson8913d082010-02-26 05:48:29 +00001155 int result;
hailfinger19db0922010-06-20 10:41:35 +00001156 unsigned char cmd[JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE] = {
1157 JEDEC_AAI_WORD_PROGRAM,
1158 };
1159 struct spi_command cmds[] = {
1160 {
1161 .writecnt = JEDEC_WREN_OUTSIZE,
1162 .writearr = (const unsigned char[]){ JEDEC_WREN },
1163 .readcnt = 0,
1164 .readarr = NULL,
1165 }, {
1166 .writecnt = JEDEC_AAI_WORD_PROGRAM_OUTSIZE,
1167 .writearr = (const unsigned char[]){
1168 JEDEC_AAI_WORD_PROGRAM,
hailfingerc7d06c62010-07-14 16:19:05 +00001169 (start >> 16) & 0xff,
1170 (start >> 8) & 0xff,
1171 (start & 0xff),
hailfinger19db0922010-06-20 10:41:35 +00001172 buf[0],
1173 buf[1]
1174 },
1175 .readcnt = 0,
1176 .readarr = NULL,
1177 }, {
1178 .writecnt = 0,
1179 .writearr = NULL,
1180 .readcnt = 0,
1181 .readarr = NULL,
1182 }};
snelson8913d082010-02-26 05:48:29 +00001183
Patrick Georgif4f1e2f2017-03-10 17:38:40 +01001184 switch (spi_master->type) {
hailfinger90c7d542010-05-31 15:27:27 +00001185#if CONFIG_INTERNAL == 1
hailfinger324a9cc2010-05-26 01:45:41 +00001186#if defined(__i386__) || defined(__x86_64__)
hailfinger19db0922010-06-20 10:41:35 +00001187 case SPI_CONTROLLER_IT87XX:
snelson8913d082010-02-26 05:48:29 +00001188 case SPI_CONTROLLER_WBSIO:
hailfingerc7d06c62010-07-14 16:19:05 +00001189 msg_perr("%s: impossible with this SPI controller,"
snelson8913d082010-02-26 05:48:29 +00001190 " degrading to byte program\n", __func__);
hailfinger71e1bd42010-10-13 22:26:56 +00001191 return spi_chip_write_1(flash, buf, start, len);
snelson8913d082010-02-26 05:48:29 +00001192#endif
hailfinger324a9cc2010-05-26 01:45:41 +00001193#endif
snelson8913d082010-02-26 05:48:29 +00001194 default:
1195 break;
1196 }
hailfinger19db0922010-06-20 10:41:35 +00001197
hailfingerc7d06c62010-07-14 16:19:05 +00001198 /* The even start address and even length requirements can be either
1199 * honored outside this function, or we can call spi_byte_program
1200 * for the first and/or last byte and use AAI for the rest.
hailfinger71e1bd42010-10-13 22:26:56 +00001201 * FIXME: Move this to generic code.
hailfingerc7d06c62010-07-14 16:19:05 +00001202 */
hailfinger19db0922010-06-20 10:41:35 +00001203 /* The data sheet requires a start address with the low bit cleared. */
hailfingerc7d06c62010-07-14 16:19:05 +00001204 if (start % 2) {
hailfinger19db0922010-06-20 10:41:35 +00001205 msg_cerr("%s: start address not even! Please report a bug at "
1206 "flashrom@flashrom.org\n", __func__);
hailfinger71e1bd42010-10-13 22:26:56 +00001207 if (spi_chip_write_1(flash, buf, start, start % 2))
1208 return SPI_GENERIC_ERROR;
1209 pos += start % 2;
hailfingerdef852d2010-10-27 22:07:11 +00001210 cmds[1].writearr = (const unsigned char[]){
1211 JEDEC_AAI_WORD_PROGRAM,
1212 (pos >> 16) & 0xff,
1213 (pos >> 8) & 0xff,
1214 (pos & 0xff),
1215 buf[pos - start],
1216 buf[pos - start + 1]
1217 };
hailfinger71e1bd42010-10-13 22:26:56 +00001218 /* Do not return an error for now. */
1219 //return SPI_GENERIC_ERROR;
hailfinger19db0922010-06-20 10:41:35 +00001220 }
1221 /* The data sheet requires total AAI write length to be even. */
1222 if (len % 2) {
1223 msg_cerr("%s: total write length not even! Please report a "
1224 "bug at flashrom@flashrom.org\n", __func__);
hailfinger71e1bd42010-10-13 22:26:56 +00001225 /* Do not return an error for now. */
1226 //return SPI_GENERIC_ERROR;
hailfinger19db0922010-06-20 10:41:35 +00001227 }
1228
hailfinger19db0922010-06-20 10:41:35 +00001229
Souvik Ghoshd75cd672016-06-17 14:21:39 -07001230 result = spi_send_multicommand(flash, cmds);
hailfinger19db0922010-06-20 10:41:35 +00001231 if (result) {
1232 msg_cerr("%s failed during start command execution\n",
1233 __func__);
hailfingerc7d06c62010-07-14 16:19:05 +00001234 /* FIXME: Should we send WRDI here as well to make sure the chip
1235 * is not in AAI mode?
1236 */
snelson8913d082010-02-26 05:48:29 +00001237 return result;
snelson8913d082010-02-26 05:48:29 +00001238 }
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301239 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
hailfinger19db0922010-06-20 10:41:35 +00001240 programmer_delay(10);
1241
1242 /* We already wrote 2 bytes in the multicommand step. */
1243 pos += 2;
1244
hailfinger71e1bd42010-10-13 22:26:56 +00001245 /* Are there at least two more bytes to write? */
1246 while (pos < start + len - 1) {
hailfingerdef852d2010-10-27 22:07:11 +00001247 cmd[1] = buf[pos++ - start];
1248 cmd[2] = buf[pos++ - start];
Souvik Ghoshd75cd672016-06-17 14:21:39 -07001249 spi_send_command(flash, JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE, 0, cmd, NULL);
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301250 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
hailfinger19db0922010-06-20 10:41:35 +00001251 programmer_delay(10);
1252 }
1253
hailfinger71e1bd42010-10-13 22:26:56 +00001254 /* Use WRDI to exit AAI mode. This needs to be done before issuing any
1255 * other non-AAI command.
1256 */
Souvik Ghoshd75cd672016-06-17 14:21:39 -07001257 spi_write_disable(flash);
hailfinger71e1bd42010-10-13 22:26:56 +00001258
1259 /* Write remaining byte (if any). */
1260 if (pos < start + len) {
hailfingerdef852d2010-10-27 22:07:11 +00001261 if (spi_chip_write_1(flash, buf + pos - start, pos, pos % 2))
hailfinger71e1bd42010-10-13 22:26:56 +00001262 return SPI_GENERIC_ERROR;
1263 pos += pos % 2;
1264 }
1265
snelson8913d082010-02-26 05:48:29 +00001266 return 0;
1267}