blob: 284b374cfd3a3849a6f59644b0915987e361d91f [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"
31
David Hendricks57b75242015-11-20 15:54:07 -080032enum id_type {
33 RDID,
34 RDID4,
35 REMS,
36// RES1, /* TODO */
37 RES2,
38 NUM_ID_TYPES,
39};
40
41static struct {
42 int is_cached;
43 unsigned char bytes[4]; /* enough to hold largest ID type */
44} id_cache[NUM_ID_TYPES];
45
46void clear_spi_id_cache(void)
47{
48 memset(id_cache, 0, sizeof(id_cache));
49 return;
50}
51
snelson8913d082010-02-26 05:48:29 +000052static int spi_rdid(unsigned char *readarr, int bytes)
53{
krause2eb76212011-01-17 07:50:42 +000054 static const unsigned char cmd[JEDEC_RDID_OUTSIZE] = { JEDEC_RDID };
snelson8913d082010-02-26 05:48:29 +000055 int ret;
56 int i;
57
58 ret = spi_send_command(sizeof(cmd), bytes, cmd, readarr);
59 if (ret)
60 return ret;
snelsonfc007bb2010-03-24 23:14:32 +000061 msg_cspew("RDID returned");
snelson8913d082010-02-26 05:48:29 +000062 for (i = 0; i < bytes; i++)
snelsonfc007bb2010-03-24 23:14:32 +000063 msg_cspew(" 0x%02x", readarr[i]);
64 msg_cspew(". ");
snelson8913d082010-02-26 05:48:29 +000065 return 0;
66}
67
68static int spi_rems(unsigned char *readarr)
69{
70 unsigned char cmd[JEDEC_REMS_OUTSIZE] = { JEDEC_REMS, 0, 0, 0 };
71 uint32_t readaddr;
72 int ret;
73
74 ret = spi_send_command(sizeof(cmd), JEDEC_REMS_INSIZE, cmd, readarr);
75 if (ret == SPI_INVALID_ADDRESS) {
76 /* Find the lowest even address allowed for reads. */
77 readaddr = (spi_get_valid_read_addr() + 1) & ~1;
78 cmd[1] = (readaddr >> 16) & 0xff,
79 cmd[2] = (readaddr >> 8) & 0xff,
80 cmd[3] = (readaddr >> 0) & 0xff,
81 ret = spi_send_command(sizeof(cmd), JEDEC_REMS_INSIZE, cmd, readarr);
82 }
83 if (ret)
84 return ret;
stefanct371e7e82011-07-07 19:56:58 +000085 msg_cspew("REMS returned 0x%02x 0x%02x. ", readarr[0], readarr[1]);
snelson8913d082010-02-26 05:48:29 +000086 return 0;
87}
88
hailfinger59a83572010-05-28 17:07:57 +000089static int spi_res(unsigned char *readarr, int bytes)
snelson8913d082010-02-26 05:48:29 +000090{
91 unsigned char cmd[JEDEC_RES_OUTSIZE] = { JEDEC_RES, 0, 0, 0 };
92 uint32_t readaddr;
93 int ret;
hailfingercb0564e2010-06-20 10:39:33 +000094 int i;
snelson8913d082010-02-26 05:48:29 +000095
hailfinger59a83572010-05-28 17:07:57 +000096 ret = spi_send_command(sizeof(cmd), bytes, cmd, readarr);
snelson8913d082010-02-26 05:48:29 +000097 if (ret == SPI_INVALID_ADDRESS) {
98 /* Find the lowest even address allowed for reads. */
99 readaddr = (spi_get_valid_read_addr() + 1) & ~1;
100 cmd[1] = (readaddr >> 16) & 0xff,
101 cmd[2] = (readaddr >> 8) & 0xff,
102 cmd[3] = (readaddr >> 0) & 0xff,
hailfinger59a83572010-05-28 17:07:57 +0000103 ret = spi_send_command(sizeof(cmd), bytes, cmd, readarr);
snelson8913d082010-02-26 05:48:29 +0000104 }
105 if (ret)
106 return ret;
hailfingercb0564e2010-06-20 10:39:33 +0000107 msg_cspew("RES returned");
108 for (i = 0; i < bytes; i++)
109 msg_cspew(" 0x%02x", readarr[i]);
110 msg_cspew(". ");
snelson8913d082010-02-26 05:48:29 +0000111 return 0;
112}
113
114int spi_write_enable(void)
115{
krause2eb76212011-01-17 07:50:42 +0000116 static const unsigned char cmd[JEDEC_WREN_OUTSIZE] = { JEDEC_WREN };
snelson8913d082010-02-26 05:48:29 +0000117 int result;
118
119 /* Send WREN (Write Enable) */
120 result = spi_send_command(sizeof(cmd), 0, cmd, NULL);
121
122 if (result)
snelsonfc007bb2010-03-24 23:14:32 +0000123 msg_cerr("%s failed\n", __func__);
snelson8913d082010-02-26 05:48:29 +0000124
125 return result;
126}
127
128int spi_write_disable(void)
129{
krause2eb76212011-01-17 07:50:42 +0000130 static const unsigned char cmd[JEDEC_WRDI_OUTSIZE] = { JEDEC_WRDI };
snelson8913d082010-02-26 05:48:29 +0000131
132 /* Send WRDI (Write Disable) */
133 return spi_send_command(sizeof(cmd), 0, cmd, NULL);
134}
135
David Hendricks7f7c7112012-10-11 17:15:48 -0700136static void rdid_get_ids(unsigned char *readarr,
137 int bytes, uint32_t *id1, uint32_t *id2)
snelson8913d082010-02-26 05:48:29 +0000138{
snelson8913d082010-02-26 05:48:29 +0000139 if (!oddparity(readarr[0]))
snelsonfc007bb2010-03-24 23:14:32 +0000140 msg_cdbg("RDID byte 0 parity violation. ");
snelson8913d082010-02-26 05:48:29 +0000141
hailfingercb0564e2010-06-20 10:39:33 +0000142 /* Check if this is a continuation vendor ID.
143 * FIXME: Handle continuation device IDs.
144 */
snelson8913d082010-02-26 05:48:29 +0000145 if (readarr[0] == 0x7f) {
146 if (!oddparity(readarr[1]))
snelsonfc007bb2010-03-24 23:14:32 +0000147 msg_cdbg("RDID byte 1 parity violation. ");
David Hendricks7f7c7112012-10-11 17:15:48 -0700148 *id1 = (readarr[0] << 8) | readarr[1];
149 *id2 = readarr[2];
snelson8913d082010-02-26 05:48:29 +0000150 if (bytes > 3) {
David Hendricks7f7c7112012-10-11 17:15:48 -0700151 *id2 <<= 8;
152 *id2 |= readarr[3];
snelson8913d082010-02-26 05:48:29 +0000153 }
154 } else {
David Hendricks7f7c7112012-10-11 17:15:48 -0700155 *id1 = readarr[0];
156 *id2 = (readarr[1] << 8) | readarr[2];
snelson8913d082010-02-26 05:48:29 +0000157 }
David Hendricks7f7c7112012-10-11 17:15:48 -0700158}
snelson8913d082010-02-26 05:48:29 +0000159
David Hendricks7f7c7112012-10-11 17:15:48 -0700160static int compare_id(struct flashchip *flash, uint32_t id1, uint32_t id2)
161{
162 msg_cdbg("id1 0x%02x, id2 0x%02x\n", id1, id2);
snelson8913d082010-02-26 05:48:29 +0000163
164 if (id1 == flash->manufacture_id && id2 == flash->model_id) {
165 /* Print the status register to tell the
166 * user about possible write protection.
167 */
168 spi_prettyprint_status_register(flash);
169
170 return 1;
171 }
172
173 /* Test if this is a pure vendor match. */
174 if (id1 == flash->manufacture_id &&
175 GENERIC_DEVICE_ID == flash->model_id)
176 return 1;
177
178 /* Test if there is any vendor ID. */
179 if (GENERIC_MANUF_ID == flash->manufacture_id &&
180 id1 != 0xff)
181 return 1;
182
183 return 0;
184}
185
186int probe_spi_rdid(struct flashchip *flash)
187{
David Hendricks57b75242015-11-20 15:54:07 -0800188 uint32_t id1, id2;
David Hendricks7f7c7112012-10-11 17:15:48 -0700189
David Hendricks57b75242015-11-20 15:54:07 -0800190 if (!id_cache[RDID].is_cached) {
191 if (spi_rdid(id_cache[RDID].bytes, 3))
David Hendricks7f7c7112012-10-11 17:15:48 -0700192 return 0;
David Hendricks57b75242015-11-20 15:54:07 -0800193 id_cache[RDID].is_cached = 1;
David Hendricks7f7c7112012-10-11 17:15:48 -0700194 }
195
David Hendricks57b75242015-11-20 15:54:07 -0800196 rdid_get_ids(id_cache[RDID].bytes, 3, &id1, &id2);
David Hendricks7f7c7112012-10-11 17:15:48 -0700197 return compare_id(flash, id1, id2);
snelson8913d082010-02-26 05:48:29 +0000198}
199
snelson8913d082010-02-26 05:48:29 +0000200int probe_spi_rdid4(struct flashchip *flash)
201{
David Hendricks57b75242015-11-20 15:54:07 -0800202 uint32_t id1, id2;
David Hendricks7f7c7112012-10-11 17:15:48 -0700203
hailfingercb0564e2010-06-20 10:39:33 +0000204 /* Some SPI controllers do not support commands with writecnt=1 and
205 * readcnt=4.
206 */
mkarcherd264e9e2011-05-11 17:07:07 +0000207 switch (spi_programmer->type) {
hailfinger90c7d542010-05-31 15:27:27 +0000208#if CONFIG_INTERNAL == 1
hailfinger324a9cc2010-05-26 01:45:41 +0000209#if defined(__i386__) || defined(__x86_64__)
hailfingercb0564e2010-06-20 10:39:33 +0000210 case SPI_CONTROLLER_IT87XX:
snelson8913d082010-02-26 05:48:29 +0000211 case SPI_CONTROLLER_WBSIO:
hailfingercb0564e2010-06-20 10:39:33 +0000212 msg_cinfo("4 byte RDID not supported on this SPI controller\n");
hailfingercb0564e2010-06-20 10:39:33 +0000213 break;
snelson8913d082010-02-26 05:48:29 +0000214#endif
hailfinger324a9cc2010-05-26 01:45:41 +0000215#endif
snelson8913d082010-02-26 05:48:29 +0000216 default:
David Hendricks7f7c7112012-10-11 17:15:48 -0700217 break;
snelson8913d082010-02-26 05:48:29 +0000218 }
219
David Hendricks57b75242015-11-20 15:54:07 -0800220 if (!id_cache[RDID4].is_cached) {
221 if (spi_rdid(id_cache[RDID4].bytes, 4))
David Hendricks7f7c7112012-10-11 17:15:48 -0700222 return 0;
David Hendricks57b75242015-11-20 15:54:07 -0800223 id_cache[RDID4].is_cached = 1;
David Hendricks7f7c7112012-10-11 17:15:48 -0700224 }
David Hendricks57b75242015-11-20 15:54:07 -0800225
226 rdid_get_ids(id_cache[RDID4].bytes, 4, &id1, &id2);
David Hendricks7f7c7112012-10-11 17:15:48 -0700227 return compare_id(flash, id1, id2);
snelson8913d082010-02-26 05:48:29 +0000228}
229
230int probe_spi_rems(struct flashchip *flash)
231{
David Hendricks57b75242015-11-20 15:54:07 -0800232 uint32_t id1, id2;
snelson8913d082010-02-26 05:48:29 +0000233
David Hendricks57b75242015-11-20 15:54:07 -0800234 if (!id_cache[REMS].is_cached) {
235 if (spi_rems(id_cache[REMS].bytes))
David Hendricks7f7c7112012-10-11 17:15:48 -0700236 return 0;
David Hendricks57b75242015-11-20 15:54:07 -0800237 id_cache[REMS].is_cached = 1;
stefanct9e6b98a2011-05-28 02:37:14 +0000238 }
snelson8913d082010-02-26 05:48:29 +0000239
David Hendricks57b75242015-11-20 15:54:07 -0800240 id1 = id_cache[REMS].bytes[0];
241 id2 = id_cache[REMS].bytes[1];
David Hendricks7f7c7112012-10-11 17:15:48 -0700242 return compare_id(flash, id1, id2);
snelson8913d082010-02-26 05:48:29 +0000243}
244
hailfinger59a83572010-05-28 17:07:57 +0000245int probe_spi_res1(struct flashchip *flash)
snelson8913d082010-02-26 05:48:29 +0000246{
krause2eb76212011-01-17 07:50:42 +0000247 static const unsigned char allff[] = {0xff, 0xff, 0xff};
248 static const unsigned char all00[] = {0x00, 0x00, 0x00};
snelson8913d082010-02-26 05:48:29 +0000249 unsigned char readarr[3];
250 uint32_t id2;
snelson8913d082010-02-26 05:48:29 +0000251
hailfinger59a83572010-05-28 17:07:57 +0000252 /* We only want one-byte RES if RDID and REMS are unusable. */
253
snelson8913d082010-02-26 05:48:29 +0000254 /* Check if RDID is usable and does not return 0xff 0xff 0xff or
255 * 0x00 0x00 0x00. In that case, RES is pointless.
256 */
257 if (!spi_rdid(readarr, 3) && memcmp(readarr, allff, 3) &&
258 memcmp(readarr, all00, 3)) {
259 msg_cdbg("Ignoring RES in favour of RDID.\n");
260 return 0;
261 }
262 /* Check if REMS is usable and does not return 0xff 0xff or
263 * 0x00 0x00. In that case, RES is pointless.
264 */
265 if (!spi_rems(readarr) && memcmp(readarr, allff, JEDEC_REMS_INSIZE) &&
266 memcmp(readarr, all00, JEDEC_REMS_INSIZE)) {
267 msg_cdbg("Ignoring RES in favour of REMS.\n");
268 return 0;
269 }
270
stefanct9e6b98a2011-05-28 02:37:14 +0000271 if (spi_res(readarr, 1)) {
snelson8913d082010-02-26 05:48:29 +0000272 return 0;
stefanct9e6b98a2011-05-28 02:37:14 +0000273 }
snelson8913d082010-02-26 05:48:29 +0000274
snelson8913d082010-02-26 05:48:29 +0000275 id2 = readarr[0];
hailfinger59a83572010-05-28 17:07:57 +0000276
snelsonfc007bb2010-03-24 23:14:32 +0000277 msg_cdbg("%s: id 0x%x\n", __func__, id2);
hailfinger59a83572010-05-28 17:07:57 +0000278
stefanct20f99532011-05-28 22:59:05 +0000279 if (id2 != flash->model_id)
snelson8913d082010-02-26 05:48:29 +0000280 return 0;
281
282 /* Print the status register to tell the
283 * user about possible write protection.
284 */
285 spi_prettyprint_status_register(flash);
286 return 1;
287}
288
hailfinger59a83572010-05-28 17:07:57 +0000289int probe_spi_res2(struct flashchip *flash)
290{
hailfinger59a83572010-05-28 17:07:57 +0000291 uint32_t id1, id2;
292
David Hendricks57b75242015-11-20 15:54:07 -0800293 if (!id_cache[RES2].is_cached) {
294 if (spi_res(id_cache[RES2].bytes, 2))
295 return 0;
296 id_cache[RES2].is_cached = 1;
stefanct9e6b98a2011-05-28 02:37:14 +0000297 }
hailfinger59a83572010-05-28 17:07:57 +0000298
David Hendricks57b75242015-11-20 15:54:07 -0800299 id1 = id_cache[RES2].bytes[0];
300 id2 = id_cache[RES2].bytes[1];
hailfinger59a83572010-05-28 17:07:57 +0000301 msg_cdbg("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2);
302
303 if (id1 != flash->manufacture_id || id2 != flash->model_id)
304 return 0;
305
306 /* Print the status register to tell the
307 * user about possible write protection.
308 */
309 spi_prettyprint_status_register(flash);
310 return 1;
311}
312
snelson8913d082010-02-26 05:48:29 +0000313uint8_t spi_read_status_register(void)
314{
krause2eb76212011-01-17 07:50:42 +0000315 static const unsigned char cmd[JEDEC_RDSR_OUTSIZE] = { JEDEC_RDSR };
snelson8913d082010-02-26 05:48:29 +0000316 /* FIXME: No workarounds for driver/hardware bugs in generic code. */
317 unsigned char readarr[2]; /* JEDEC_RDSR_INSIZE=1 but wbsio needs 2 */
318 int ret;
319
320 /* Read Status Register */
321 ret = spi_send_command(sizeof(cmd), sizeof(readarr), cmd, readarr);
322 if (ret)
snelsonfc007bb2010-03-24 23:14:32 +0000323 msg_cerr("RDSR failed!\n");
snelson8913d082010-02-26 05:48:29 +0000324
325 return readarr[0];
326}
327
328/* Prettyprint the status register. Common definitions. */
hailfinger7533bc82011-05-19 00:06:06 +0000329void spi_prettyprint_status_register_welwip(uint8_t status)
hailfingerc33d4732010-07-29 13:09:18 +0000330{
331 msg_cdbg("Chip status register: Write Enable Latch (WEL) is "
332 "%sset\n", (status & (1 << 1)) ? "" : "not ");
333 msg_cdbg("Chip status register: Write In Progress (WIP/BUSY) is "
334 "%sset\n", (status & (1 << 0)) ? "" : "not ");
335}
336
337/* Prettyprint the status register. Common definitions. */
hailfinger7533bc82011-05-19 00:06:06 +0000338void spi_prettyprint_status_register_bp3210(uint8_t status, int bp)
339{
340 switch (bp) {
341 /* Fall through. */
342 case 3:
343 msg_cdbg("Chip status register: Bit 5 / Block Protect 3 (BP3) "
344 "is %sset\n", (status & (1 << 5)) ? "" : "not ");
345 case 2:
346 msg_cdbg("Chip status register: Bit 4 / Block Protect 2 (BP2) "
347 "is %sset\n", (status & (1 << 4)) ? "" : "not ");
348 case 1:
349 msg_cdbg("Chip status register: Bit 3 / Block Protect 1 (BP1) "
350 "is %sset\n", (status & (1 << 3)) ? "" : "not ");
351 case 0:
352 msg_cdbg("Chip status register: Bit 2 / Block Protect 0 (BP0) "
353 "is %sset\n", (status & (1 << 2)) ? "" : "not ");
354 }
355}
356
357/* Prettyprint the status register. Unnamed bits. */
358void spi_prettyprint_status_register_bit(uint8_t status, int bit)
359{
360 msg_cdbg("Chip status register: Bit %i "
361 "is %sset\n", bit, (status & (1 << bit)) ? "" : "not ");
362}
363
hailfingerc33d4732010-07-29 13:09:18 +0000364static void spi_prettyprint_status_register_common(uint8_t status)
snelson8913d082010-02-26 05:48:29 +0000365{
hailfinger7533bc82011-05-19 00:06:06 +0000366 spi_prettyprint_status_register_bp3210(status, 3);
hailfingerc33d4732010-07-29 13:09:18 +0000367 spi_prettyprint_status_register_welwip(status);
snelson8913d082010-02-26 05:48:29 +0000368}
369
370/* Prettyprint the status register. Works for
371 * ST M25P series
372 * MX MX25L series
373 */
374void spi_prettyprint_status_register_st_m25p(uint8_t status)
375{
snelsonfc007bb2010-03-24 23:14:32 +0000376 msg_cdbg("Chip status register: Status Register Write Disable "
snelson8913d082010-02-26 05:48:29 +0000377 "(SRWD) is %sset\n", (status & (1 << 7)) ? "" : "not ");
snelsonfc007bb2010-03-24 23:14:32 +0000378 msg_cdbg("Chip status register: Bit 6 is "
snelson8913d082010-02-26 05:48:29 +0000379 "%sset\n", (status & (1 << 6)) ? "" : "not ");
380 spi_prettyprint_status_register_common(status);
381}
382
383void spi_prettyprint_status_register_sst25(uint8_t status)
384{
snelsonfc007bb2010-03-24 23:14:32 +0000385 msg_cdbg("Chip status register: Block Protect Write Disable "
snelson8913d082010-02-26 05:48:29 +0000386 "(BPL) is %sset\n", (status & (1 << 7)) ? "" : "not ");
snelsonfc007bb2010-03-24 23:14:32 +0000387 msg_cdbg("Chip status register: Auto Address Increment Programming "
snelson8913d082010-02-26 05:48:29 +0000388 "(AAI) is %sset\n", (status & (1 << 6)) ? "" : "not ");
389 spi_prettyprint_status_register_common(status);
390}
391
392/* Prettyprint the status register. Works for
393 * SST 25VF016
394 */
395void spi_prettyprint_status_register_sst25vf016(uint8_t status)
396{
krause2eb76212011-01-17 07:50:42 +0000397 static const char *const bpt[] = {
snelson8913d082010-02-26 05:48:29 +0000398 "none",
399 "1F0000H-1FFFFFH",
400 "1E0000H-1FFFFFH",
401 "1C0000H-1FFFFFH",
402 "180000H-1FFFFFH",
403 "100000H-1FFFFFH",
404 "all", "all"
405 };
406 spi_prettyprint_status_register_sst25(status);
snelsonfc007bb2010-03-24 23:14:32 +0000407 msg_cdbg("Resulting block protection : %s\n",
snelson8913d082010-02-26 05:48:29 +0000408 bpt[(status & 0x1c) >> 2]);
409}
410
411void spi_prettyprint_status_register_sst25vf040b(uint8_t status)
412{
krause2eb76212011-01-17 07:50:42 +0000413 static const char *const bpt[] = {
snelson8913d082010-02-26 05:48:29 +0000414 "none",
415 "0x70000-0x7ffff",
416 "0x60000-0x7ffff",
417 "0x40000-0x7ffff",
418 "all blocks", "all blocks", "all blocks", "all blocks"
419 };
420 spi_prettyprint_status_register_sst25(status);
snelsonfc007bb2010-03-24 23:14:32 +0000421 msg_cdbg("Resulting block protection : %s\n",
snelson8913d082010-02-26 05:48:29 +0000422 bpt[(status & 0x1c) >> 2]);
423}
424
hailfinger7533bc82011-05-19 00:06:06 +0000425int spi_prettyprint_status_register(struct flashchip *flash)
snelson8913d082010-02-26 05:48:29 +0000426{
427 uint8_t status;
428
429 status = spi_read_status_register();
snelsonfc007bb2010-03-24 23:14:32 +0000430 msg_cdbg("Chip status register is %02x\n", status);
snelson8913d082010-02-26 05:48:29 +0000431 switch (flash->manufacture_id) {
432 case ST_ID:
433 if (((flash->model_id & 0xff00) == 0x2000) ||
434 ((flash->model_id & 0xff00) == 0x2500))
435 spi_prettyprint_status_register_st_m25p(status);
436 break;
mhmd3c80cd2010-09-15 23:31:03 +0000437 case MACRONIX_ID:
snelson8913d082010-02-26 05:48:29 +0000438 if ((flash->model_id & 0xff00) == 0x2000)
439 spi_prettyprint_status_register_st_m25p(status);
440 break;
441 case SST_ID:
442 switch (flash->model_id) {
443 case 0x2541:
444 spi_prettyprint_status_register_sst25vf016(status);
445 break;
446 case 0x8d:
447 case 0x258d:
448 spi_prettyprint_status_register_sst25vf040b(status);
449 break;
450 default:
451 spi_prettyprint_status_register_sst25(status);
452 break;
453 }
454 break;
455 }
hailfinger7533bc82011-05-19 00:06:06 +0000456 return 0;
snelson8913d082010-02-26 05:48:29 +0000457}
458
459int spi_chip_erase_60(struct flashchip *flash)
460{
461 int result;
462 struct spi_command cmds[] = {
463 {
464 .writecnt = JEDEC_WREN_OUTSIZE,
465 .writearr = (const unsigned char[]){ JEDEC_WREN },
466 .readcnt = 0,
467 .readarr = NULL,
468 }, {
469 .writecnt = JEDEC_CE_60_OUTSIZE,
470 .writearr = (const unsigned char[]){ JEDEC_CE_60 },
471 .readcnt = 0,
472 .readarr = NULL,
473 }, {
474 .writecnt = 0,
475 .writearr = NULL,
476 .readcnt = 0,
477 .readarr = NULL,
478 }};
479
snelson8913d082010-02-26 05:48:29 +0000480 result = spi_send_multicommand(cmds);
481 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000482 msg_cerr("%s failed during command execution\n",
snelson8913d082010-02-26 05:48:29 +0000483 __func__);
484 return result;
485 }
486 /* Wait until the Write-In-Progress bit is cleared.
487 * This usually takes 1-85 s, so wait in 1 s steps.
488 */
489 /* FIXME: We assume spi_read_status_register will never fail. */
490 while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
491 programmer_delay(1000 * 1000);
hailfingerac8e3182011-06-26 17:04:16 +0000492 /* FIXME: Check the status register for errors. */
snelson8913d082010-02-26 05:48:29 +0000493 return 0;
494}
495
496int spi_chip_erase_c7(struct flashchip *flash)
497{
498 int result;
499 struct spi_command cmds[] = {
500 {
501 .writecnt = JEDEC_WREN_OUTSIZE,
502 .writearr = (const unsigned char[]){ JEDEC_WREN },
503 .readcnt = 0,
504 .readarr = NULL,
505 }, {
506 .writecnt = JEDEC_CE_C7_OUTSIZE,
507 .writearr = (const unsigned char[]){ JEDEC_CE_C7 },
508 .readcnt = 0,
509 .readarr = NULL,
510 }, {
511 .writecnt = 0,
512 .writearr = NULL,
513 .readcnt = 0,
514 .readarr = NULL,
515 }};
516
snelson8913d082010-02-26 05:48:29 +0000517 result = spi_send_multicommand(cmds);
518 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000519 msg_cerr("%s failed during command execution\n", __func__);
snelson8913d082010-02-26 05:48:29 +0000520 return result;
521 }
522 /* Wait until the Write-In-Progress bit is cleared.
523 * This usually takes 1-85 s, so wait in 1 s steps.
524 */
525 /* FIXME: We assume spi_read_status_register will never fail. */
526 while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
527 programmer_delay(1000 * 1000);
hailfingerac8e3182011-06-26 17:04:16 +0000528 /* FIXME: Check the status register for errors. */
snelson8913d082010-02-26 05:48:29 +0000529 return 0;
530}
531
snelson8913d082010-02-26 05:48:29 +0000532int spi_block_erase_52(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
533{
534 int result;
535 struct spi_command cmds[] = {
536 {
537 .writecnt = JEDEC_WREN_OUTSIZE,
538 .writearr = (const unsigned char[]){ JEDEC_WREN },
539 .readcnt = 0,
540 .readarr = NULL,
541 }, {
542 .writecnt = JEDEC_BE_52_OUTSIZE,
543 .writearr = (const unsigned char[]){
544 JEDEC_BE_52,
545 (addr >> 16) & 0xff,
546 (addr >> 8) & 0xff,
547 (addr & 0xff)
548 },
549 .readcnt = 0,
550 .readarr = NULL,
551 }, {
552 .writecnt = 0,
553 .writearr = NULL,
554 .readcnt = 0,
555 .readarr = NULL,
556 }};
557
558 result = spi_send_multicommand(cmds);
559 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000560 msg_cerr("%s failed during command execution at address 0x%x\n",
snelson8913d082010-02-26 05:48:29 +0000561 __func__, addr);
562 return result;
563 }
564 /* Wait until the Write-In-Progress bit is cleared.
565 * This usually takes 100-4000 ms, so wait in 100 ms steps.
566 */
567 while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
568 programmer_delay(100 * 1000);
hailfingerac8e3182011-06-26 17:04:16 +0000569 /* FIXME: Check the status register for errors. */
snelson8913d082010-02-26 05:48:29 +0000570 return 0;
571}
572
573/* Block size is usually
574 * 64k for Macronix
575 * 32k for SST
576 * 4-32k non-uniform for EON
577 */
578int spi_block_erase_d8(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
579{
580 int result;
581 struct spi_command cmds[] = {
582 {
583 .writecnt = JEDEC_WREN_OUTSIZE,
584 .writearr = (const unsigned char[]){ JEDEC_WREN },
585 .readcnt = 0,
586 .readarr = NULL,
587 }, {
588 .writecnt = JEDEC_BE_D8_OUTSIZE,
589 .writearr = (const unsigned char[]){
590 JEDEC_BE_D8,
591 (addr >> 16) & 0xff,
592 (addr >> 8) & 0xff,
593 (addr & 0xff)
594 },
595 .readcnt = 0,
596 .readarr = NULL,
597 }, {
598 .writecnt = 0,
599 .writearr = NULL,
600 .readcnt = 0,
601 .readarr = NULL,
602 }};
603
604 result = spi_send_multicommand(cmds);
605 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000606 msg_cerr("%s failed during command execution at address 0x%x\n",
snelson8913d082010-02-26 05:48:29 +0000607 __func__, addr);
608 return result;
609 }
610 /* Wait until the Write-In-Progress bit is cleared.
611 * This usually takes 100-4000 ms, so wait in 100 ms steps.
612 */
613 while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
614 programmer_delay(100 * 1000);
hailfingerac8e3182011-06-26 17:04:16 +0000615 /* FIXME: Check the status register for errors. */
snelson8913d082010-02-26 05:48:29 +0000616 return 0;
617}
618
619/* Block size is usually
620 * 4k for PMC
621 */
622int spi_block_erase_d7(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
623{
624 int result;
625 struct spi_command cmds[] = {
626 {
627 .writecnt = JEDEC_WREN_OUTSIZE,
628 .writearr = (const unsigned char[]){ JEDEC_WREN },
629 .readcnt = 0,
630 .readarr = NULL,
631 }, {
632 .writecnt = JEDEC_BE_D7_OUTSIZE,
633 .writearr = (const unsigned char[]){
634 JEDEC_BE_D7,
635 (addr >> 16) & 0xff,
636 (addr >> 8) & 0xff,
637 (addr & 0xff)
638 },
639 .readcnt = 0,
640 .readarr = NULL,
641 }, {
642 .writecnt = 0,
643 .writearr = NULL,
644 .readcnt = 0,
645 .readarr = NULL,
646 }};
647
648 result = spi_send_multicommand(cmds);
649 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000650 msg_cerr("%s failed during command execution at address 0x%x\n",
snelson8913d082010-02-26 05:48:29 +0000651 __func__, addr);
652 return result;
653 }
654 /* Wait until the Write-In-Progress bit is cleared.
655 * This usually takes 100-4000 ms, so wait in 100 ms steps.
656 */
657 while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
658 programmer_delay(100 * 1000);
hailfingerac8e3182011-06-26 17:04:16 +0000659 /* FIXME: Check the status register for errors. */
snelson8913d082010-02-26 05:48:29 +0000660 return 0;
661}
662
snelson8913d082010-02-26 05:48:29 +0000663/* Sector size is usually 4k, though Macronix eliteflash has 64k */
664int spi_block_erase_20(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
665{
666 int result;
667 struct spi_command cmds[] = {
668 {
669 .writecnt = JEDEC_WREN_OUTSIZE,
670 .writearr = (const unsigned char[]){ JEDEC_WREN },
671 .readcnt = 0,
672 .readarr = NULL,
673 }, {
674 .writecnt = JEDEC_SE_OUTSIZE,
675 .writearr = (const unsigned char[]){
676 JEDEC_SE,
677 (addr >> 16) & 0xff,
678 (addr >> 8) & 0xff,
679 (addr & 0xff)
680 },
681 .readcnt = 0,
682 .readarr = NULL,
683 }, {
684 .writecnt = 0,
685 .writearr = NULL,
686 .readcnt = 0,
687 .readarr = NULL,
688 }};
689
690 result = spi_send_multicommand(cmds);
Stefan Reinauercce56d52010-11-22 18:22:21 -0800691
snelson8913d082010-02-26 05:48:29 +0000692 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000693 msg_cerr("%s failed during command execution at address 0x%x\n",
snelson8913d082010-02-26 05:48:29 +0000694 __func__, addr);
695 return result;
696 }
697 /* Wait until the Write-In-Progress bit is cleared.
698 * This usually takes 15-800 ms, so wait in 10 ms steps.
699 */
700 while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
701 programmer_delay(10 * 1000);
hailfingerac8e3182011-06-26 17:04:16 +0000702 /* FIXME: Check the status register for errors. */
snelson8913d082010-02-26 05:48:29 +0000703 return 0;
704}
705
706int spi_block_erase_60(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
707{
708 if ((addr != 0) || (blocklen != flash->total_size * 1024)) {
snelsonfc007bb2010-03-24 23:14:32 +0000709 msg_cerr("%s called with incorrect arguments\n",
snelson8913d082010-02-26 05:48:29 +0000710 __func__);
711 return -1;
712 }
713 return spi_chip_erase_60(flash);
714}
715
716int spi_block_erase_c7(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
717{
718 if ((addr != 0) || (blocklen != flash->total_size * 1024)) {
snelsonfc007bb2010-03-24 23:14:32 +0000719 msg_cerr("%s called with incorrect arguments\n",
snelson8913d082010-02-26 05:48:29 +0000720 __func__);
721 return -1;
722 }
723 return spi_chip_erase_c7(flash);
724}
725
726int spi_write_status_enable(void)
727{
krause2eb76212011-01-17 07:50:42 +0000728 static const unsigned char cmd[JEDEC_EWSR_OUTSIZE] = { JEDEC_EWSR };
snelson8913d082010-02-26 05:48:29 +0000729 int result;
730
731 /* Send EWSR (Enable Write Status Register). */
732 result = spi_send_command(sizeof(cmd), JEDEC_EWSR_INSIZE, cmd, NULL);
733
734 if (result)
snelsonfc007bb2010-03-24 23:14:32 +0000735 msg_cerr("%s failed\n", __func__);
snelson8913d082010-02-26 05:48:29 +0000736
737 return result;
738}
739
740/*
741 * This is according the SST25VF016 datasheet, who knows it is more
742 * generic that this...
743 */
David Hendricks2d6d1d52014-12-11 18:32:20 -0800744static int spi_write_status_register_ewsr(const struct flashchip *flash, int status)
snelson8913d082010-02-26 05:48:29 +0000745{
746 int result;
hailfingeree9ee132010-10-08 00:37:55 +0000747 int i = 0;
snelson8913d082010-02-26 05:48:29 +0000748 struct spi_command cmds[] = {
749 {
hailfingerc33d4732010-07-29 13:09:18 +0000750 /* WRSR requires either EWSR or WREN depending on chip type. */
snelson8913d082010-02-26 05:48:29 +0000751 .writecnt = JEDEC_EWSR_OUTSIZE,
752 .writearr = (const unsigned char[]){ JEDEC_EWSR },
753 .readcnt = 0,
754 .readarr = NULL,
755 }, {
756 .writecnt = JEDEC_WRSR_OUTSIZE,
757 .writearr = (const unsigned char[]){ JEDEC_WRSR, (unsigned char) status },
758 .readcnt = 0,
759 .readarr = NULL,
760 }, {
761 .writecnt = 0,
762 .writearr = NULL,
763 .readcnt = 0,
764 .readarr = NULL,
765 }};
766
767 result = spi_send_multicommand(cmds);
768 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000769 msg_cerr("%s failed during command execution\n",
snelson8913d082010-02-26 05:48:29 +0000770 __func__);
hailfingeree9ee132010-10-08 00:37:55 +0000771 /* No point in waiting for the command to complete if execution
772 * failed.
773 */
774 return result;
snelson8913d082010-02-26 05:48:29 +0000775 }
hailfingeree9ee132010-10-08 00:37:55 +0000776 /* WRSR performs a self-timed erase before the changes take effect.
777 * This may take 50-85 ms in most cases, and some chips apparently
778 * allow running RDSR only once. Therefore pick an initial delay of
779 * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed.
780 */
hailfingerc33d4732010-07-29 13:09:18 +0000781 programmer_delay(100 * 1000);
hailfingeree9ee132010-10-08 00:37:55 +0000782 while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP) {
783 if (++i > 490) {
784 msg_cerr("Error: WIP bit after WRSR never cleared\n");
785 return TIMEOUT_ERROR;
786 }
787 programmer_delay(10 * 1000);
788 }
789 return 0;
snelson8913d082010-02-26 05:48:29 +0000790}
791
David Hendricks2d6d1d52014-12-11 18:32:20 -0800792int spi_write_status_register_wren(const struct flashchip *flash, int status)
hailfingerc33d4732010-07-29 13:09:18 +0000793{
794 int result;
hailfingeree9ee132010-10-08 00:37:55 +0000795 int i = 0;
hailfingerc33d4732010-07-29 13:09:18 +0000796 struct spi_command cmds[] = {
797 {
798 /* WRSR requires either EWSR or WREN depending on chip type. */
799 .writecnt = JEDEC_WREN_OUTSIZE,
800 .writearr = (const unsigned char[]){ JEDEC_WREN },
801 .readcnt = 0,
802 .readarr = NULL,
803 }, {
804 .writecnt = JEDEC_WRSR_OUTSIZE,
805 .writearr = (const unsigned char[]){ JEDEC_WRSR, (unsigned char) status },
806 .readcnt = 0,
807 .readarr = NULL,
808 }, {
809 .writecnt = 0,
810 .writearr = NULL,
811 .readcnt = 0,
812 .readarr = NULL,
813 }};
814
815 result = spi_send_multicommand(cmds);
816 if (result) {
817 msg_cerr("%s failed during command execution\n",
818 __func__);
hailfingeree9ee132010-10-08 00:37:55 +0000819 /* No point in waiting for the command to complete if execution
820 * failed.
821 */
822 return result;
hailfingerc33d4732010-07-29 13:09:18 +0000823 }
hailfingeree9ee132010-10-08 00:37:55 +0000824 /* WRSR performs a self-timed erase before the changes take effect.
825 * This may take 50-85 ms in most cases, and some chips apparently
826 * allow running RDSR only once. Therefore pick an initial delay of
827 * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed.
828 */
hailfingerc33d4732010-07-29 13:09:18 +0000829 programmer_delay(100 * 1000);
hailfingeree9ee132010-10-08 00:37:55 +0000830 while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP) {
831 if (++i > 490) {
832 msg_cerr("Error: WIP bit after WRSR never cleared\n");
833 return TIMEOUT_ERROR;
834 }
835 programmer_delay(10 * 1000);
836 }
837 return 0;
hailfingerc33d4732010-07-29 13:09:18 +0000838}
839
David Hendricks2d6d1d52014-12-11 18:32:20 -0800840int spi_write_status_register(const struct flashchip *flash, int status)
hailfingerc33d4732010-07-29 13:09:18 +0000841{
842 int ret = 1;
843
hailfingerc33d4732010-07-29 13:09:18 +0000844 if (flash->feature_bits & FEATURE_WRSR_WREN)
845 ret = spi_write_status_register_wren(flash, status);
846 if (ret && (flash->feature_bits & FEATURE_WRSR_EWSR))
847 ret = spi_write_status_register_ewsr(flash, status);
848 return ret;
849}
850
stefanctc5eb8a92011-11-23 09:13:48 +0000851int spi_byte_program(unsigned int addr, uint8_t databyte)
snelson8913d082010-02-26 05:48:29 +0000852{
853 int result;
854 struct spi_command cmds[] = {
855 {
856 .writecnt = JEDEC_WREN_OUTSIZE,
857 .writearr = (const unsigned char[]){ JEDEC_WREN },
858 .readcnt = 0,
859 .readarr = NULL,
860 }, {
861 .writecnt = JEDEC_BYTE_PROGRAM_OUTSIZE,
862 .writearr = (const unsigned char[]){
863 JEDEC_BYTE_PROGRAM,
864 (addr >> 16) & 0xff,
865 (addr >> 8) & 0xff,
866 (addr & 0xff),
867 databyte
868 },
869 .readcnt = 0,
870 .readarr = NULL,
871 }, {
872 .writecnt = 0,
873 .writearr = NULL,
874 .readcnt = 0,
875 .readarr = NULL,
876 }};
877
878 result = spi_send_multicommand(cmds);
879 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000880 msg_cerr("%s failed during command execution at address 0x%x\n",
snelson8913d082010-02-26 05:48:29 +0000881 __func__, addr);
882 }
883 return result;
884}
885
stefanctc5eb8a92011-11-23 09:13:48 +0000886int spi_nbyte_program(unsigned int addr, uint8_t *bytes, unsigned int len)
snelson8913d082010-02-26 05:48:29 +0000887{
888 int result;
889 /* FIXME: Switch to malloc based on len unless that kills speed. */
890 unsigned char cmd[JEDEC_BYTE_PROGRAM_OUTSIZE - 1 + 256] = {
891 JEDEC_BYTE_PROGRAM,
892 (addr >> 16) & 0xff,
893 (addr >> 8) & 0xff,
894 (addr >> 0) & 0xff,
895 };
896 struct spi_command cmds[] = {
897 {
898 .writecnt = JEDEC_WREN_OUTSIZE,
899 .writearr = (const unsigned char[]){ JEDEC_WREN },
900 .readcnt = 0,
901 .readarr = NULL,
902 }, {
903 .writecnt = JEDEC_BYTE_PROGRAM_OUTSIZE - 1 + len,
904 .writearr = cmd,
905 .readcnt = 0,
906 .readarr = NULL,
907 }, {
908 .writecnt = 0,
909 .writearr = NULL,
910 .readcnt = 0,
911 .readarr = NULL,
912 }};
913
914 if (!len) {
snelsonfc007bb2010-03-24 23:14:32 +0000915 msg_cerr("%s called for zero-length write\n", __func__);
snelson8913d082010-02-26 05:48:29 +0000916 return 1;
917 }
918 if (len > 256) {
snelsonfc007bb2010-03-24 23:14:32 +0000919 msg_cerr("%s called for too long a write\n", __func__);
snelson8913d082010-02-26 05:48:29 +0000920 return 1;
921 }
922
923 memcpy(&cmd[4], bytes, len);
924
925 result = spi_send_multicommand(cmds);
926 if (result) {
David Hendricks1ed1d352011-11-23 17:54:37 -0800927 if (result != SPI_ACCESS_DENIED) {
928 msg_cerr("%s failed during command execution at address 0x%x\n",
929 __func__, addr);
930 }
snelson8913d082010-02-26 05:48:29 +0000931 }
932 return result;
933}
934
David Hendricksbf36f092010-11-02 23:39:29 -0700935int spi_restore_status(struct flashchip *flash, uint8_t status)
936{
937 msg_cdbg("restoring chip status (0x%02x)\n", status);
938 return spi_write_status_register(flash, status);
939}
940
hailfingerc33d4732010-07-29 13:09:18 +0000941/* A generic brute-force block protection disable works like this:
942 * Write 0x00 to the status register. Check if any locks are still set (that
943 * part is chip specific). Repeat once.
944 */
hailfingerb9560ee2010-07-14 20:21:22 +0000945int spi_disable_blockprotect(struct flashchip *flash)
snelson8913d082010-02-26 05:48:29 +0000946{
947 uint8_t status;
948 int result;
949
950 status = spi_read_status_register();
hailfingerc33d4732010-07-29 13:09:18 +0000951 /* If block protection is disabled, stop here. */
952 if ((status & 0x3c) == 0)
953 return 0;
954
David Hendricksbf36f092010-11-02 23:39:29 -0700955 /* restore status register content upon exit */
956 register_chip_restore(spi_restore_status, flash, status);
957
hailfingerc33d4732010-07-29 13:09:18 +0000958 msg_cdbg("Some block protection in effect, disabling\n");
959 result = spi_write_status_register(flash, status & ~0x3c);
960 if (result) {
961 msg_cerr("spi_write_status_register failed\n");
962 return result;
963 }
964 status = spi_read_status_register();
snelson8913d082010-02-26 05:48:29 +0000965 if ((status & 0x3c) != 0) {
hailfingerc33d4732010-07-29 13:09:18 +0000966 msg_cerr("Block protection could not be disabled!\n");
967 return 1;
968 }
969 return 0;
970}
971
stefanctc5eb8a92011-11-23 09:13:48 +0000972int spi_nbyte_read(unsigned int address, uint8_t *bytes, unsigned int len)
snelson8913d082010-02-26 05:48:29 +0000973{
974 const unsigned char cmd[JEDEC_READ_OUTSIZE] = {
975 JEDEC_READ,
976 (address >> 16) & 0xff,
977 (address >> 8) & 0xff,
978 (address >> 0) & 0xff,
979 };
980
981 /* Send Read */
982 return spi_send_command(sizeof(cmd), len, cmd, bytes);
983}
984
985/*
hailfinger39d159a2010-05-21 23:09:42 +0000986 * Read a part of the flash chip.
hailfingerc7d06c62010-07-14 16:19:05 +0000987 * FIXME: Use the chunk code from Michael Karcher instead.
snelson8913d082010-02-26 05:48:29 +0000988 * Each page is read separately in chunks with a maximum size of chunksize.
989 */
stefanctc5eb8a92011-11-23 09:13:48 +0000990int spi_read_chunked(struct flashchip *flash, uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize)
snelson8913d082010-02-26 05:48:29 +0000991{
David Hendricks1ed1d352011-11-23 17:54:37 -0800992 int rc = 0, chunk_status = 0;
stefanctc5eb8a92011-11-23 09:13:48 +0000993 unsigned int i, j, starthere, lenhere, toread;
994 unsigned int page_size = flash->page_size;
snelson8913d082010-02-26 05:48:29 +0000995
996 /* Warning: This loop has a very unusual condition and body.
997 * The loop needs to go through each page with at least one affected
998 * byte. The lowest page number is (start / page_size) since that
999 * division rounds down. The highest page number we want is the page
1000 * where the last byte of the range lives. That last byte has the
1001 * address (start + len - 1), thus the highest page number is
1002 * (start + len - 1) / page_size. Since we want to include that last
1003 * page as well, the loop condition uses <=.
1004 */
1005 for (i = start / page_size; i <= (start + len - 1) / page_size; i++) {
1006 /* Byte position of the first byte in the range in this page. */
1007 /* starthere is an offset to the base address of the chip. */
1008 starthere = max(start, i * page_size);
1009 /* Length of bytes in the range in this page. */
1010 lenhere = min(start + len, (i + 1) * page_size) - starthere;
1011 for (j = 0; j < lenhere; j += chunksize) {
1012 toread = min(chunksize, lenhere - j);
David Hendricks1ed1d352011-11-23 17:54:37 -08001013 chunk_status = spi_nbyte_read(starthere + j, buf + starthere - start + j, toread);
1014 if (chunk_status) {
1015 if (ignore_error(chunk_status)) {
1016 /* fill this chunk with 0xff bytes and
1017 let caller know about the error */
1018 memset(buf + starthere - start + j, 0xff, toread);
1019 rc = chunk_status;
1020 chunk_status = 0;
1021 continue;
1022 } else {
1023 rc = chunk_status;
1024 break;
1025 }
1026 }
snelson8913d082010-02-26 05:48:29 +00001027 }
David Hendricks1ed1d352011-11-23 17:54:37 -08001028 if (chunk_status)
snelson8913d082010-02-26 05:48:29 +00001029 break;
1030 }
1031
1032 return rc;
1033}
1034
1035/*
Duncan Laurie06ffd522015-10-26 12:56:08 -07001036 * Read a part of the flash chip.
1037 * Ignore pages and read the data continuously, the only bound is the chunksize.
1038 */
1039int spi_read_unbound(struct flashchip *flash, uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize)
1040{
1041 int rc = 0;
1042 unsigned int i;
1043
1044 for (i = start; i < (start + len); i += chunksize) {
David Hendricks37370ec2015-11-24 14:38:17 -08001045 int chunk_status = 0;
1046 unsigned int toread = min(chunksize, start + len - i);
1047
1048 chunk_status = spi_nbyte_read(i, buf + (i - start), toread);
1049 if (chunk_status) {
1050 if (ignore_error(chunk_status)) {
1051 /* fill this chunk with 0xff bytes and
1052 let caller know about the error */
1053 memset(buf + (i - start), 0xff, toread);
1054 rc = chunk_status;
1055 continue;
1056 } else {
1057 rc = chunk_status;
1058 break;
1059 }
1060 }
Duncan Laurie06ffd522015-10-26 12:56:08 -07001061 }
David Hendricks37370ec2015-11-24 14:38:17 -08001062
Duncan Laurie06ffd522015-10-26 12:56:08 -07001063 return rc;
1064}
1065
1066/*
hailfinger39d159a2010-05-21 23:09:42 +00001067 * Write a part of the flash chip.
hailfingerc7d06c62010-07-14 16:19:05 +00001068 * FIXME: Use the chunk code from Michael Karcher instead.
hailfinger39d159a2010-05-21 23:09:42 +00001069 * Each page is written separately in chunks with a maximum size of chunksize.
1070 */
stefanctc5eb8a92011-11-23 09:13:48 +00001071int spi_write_chunked(struct flashchip *flash, uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize)
hailfinger39d159a2010-05-21 23:09:42 +00001072{
1073 int rc = 0;
stefanctc5eb8a92011-11-23 09:13:48 +00001074 unsigned int i, j, starthere, lenhere, towrite;
hailfinger39d159a2010-05-21 23:09:42 +00001075 /* FIXME: page_size is the wrong variable. We need max_writechunk_size
1076 * in struct flashchip to do this properly. All chips using
1077 * spi_chip_write_256 have page_size set to max_writechunk_size, so
1078 * we're OK for now.
1079 */
stefanctc5eb8a92011-11-23 09:13:48 +00001080 unsigned int page_size = flash->page_size;
hailfinger39d159a2010-05-21 23:09:42 +00001081
1082 /* Warning: This loop has a very unusual condition and body.
1083 * The loop needs to go through each page with at least one affected
1084 * byte. The lowest page number is (start / page_size) since that
1085 * division rounds down. The highest page number we want is the page
1086 * where the last byte of the range lives. That last byte has the
1087 * address (start + len - 1), thus the highest page number is
1088 * (start + len - 1) / page_size. Since we want to include that last
1089 * page as well, the loop condition uses <=.
1090 */
1091 for (i = start / page_size; i <= (start + len - 1) / page_size; i++) {
1092 /* Byte position of the first byte in the range in this page. */
1093 /* starthere is an offset to the base address of the chip. */
1094 starthere = max(start, i * page_size);
1095 /* Length of bytes in the range in this page. */
1096 lenhere = min(start + len, (i + 1) * page_size) - starthere;
1097 for (j = 0; j < lenhere; j += chunksize) {
1098 towrite = min(chunksize, lenhere - j);
1099 rc = spi_nbyte_program(starthere + j, buf + starthere - start + j, towrite);
1100 if (rc)
1101 break;
1102 while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
1103 programmer_delay(10);
1104 }
1105 if (rc)
1106 break;
1107 }
1108
1109 return rc;
1110}
1111
1112/*
snelson8913d082010-02-26 05:48:29 +00001113 * Program chip using byte programming. (SLOW!)
1114 * This is for chips which can only handle one byte writes
1115 * and for chips where memory mapped programming is impossible
1116 * (e.g. due to size constraints in IT87* for over 512 kB)
1117 */
hailfingerc7d06c62010-07-14 16:19:05 +00001118/* real chunksize is 1, logical chunksize is 1 */
stefanctc5eb8a92011-11-23 09:13:48 +00001119int spi_chip_write_1(struct flashchip *flash, uint8_t *buf, unsigned int start, unsigned int len)
snelson8913d082010-02-26 05:48:29 +00001120{
stefanctc5eb8a92011-11-23 09:13:48 +00001121 unsigned int i;
1122 int result = 0;
snelson8913d082010-02-26 05:48:29 +00001123
hailfingerc7d06c62010-07-14 16:19:05 +00001124 for (i = start; i < start + len; i++) {
hailfingerdef852d2010-10-27 22:07:11 +00001125 result = spi_byte_program(i, buf[i - start]);
snelson8913d082010-02-26 05:48:29 +00001126 if (result)
1127 return 1;
1128 while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
1129 programmer_delay(10);
1130 }
1131
1132 return 0;
1133}
1134
stefanctc5eb8a92011-11-23 09:13:48 +00001135int spi_aai_write(struct flashchip *flash, uint8_t *buf, unsigned int start, unsigned int len)
hailfingerc7d06c62010-07-14 16:19:05 +00001136{
1137 uint32_t pos = start;
snelson8913d082010-02-26 05:48:29 +00001138 int result;
hailfinger19db0922010-06-20 10:41:35 +00001139 unsigned char cmd[JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE] = {
1140 JEDEC_AAI_WORD_PROGRAM,
1141 };
1142 struct spi_command cmds[] = {
1143 {
1144 .writecnt = JEDEC_WREN_OUTSIZE,
1145 .writearr = (const unsigned char[]){ JEDEC_WREN },
1146 .readcnt = 0,
1147 .readarr = NULL,
1148 }, {
1149 .writecnt = JEDEC_AAI_WORD_PROGRAM_OUTSIZE,
1150 .writearr = (const unsigned char[]){
1151 JEDEC_AAI_WORD_PROGRAM,
hailfingerc7d06c62010-07-14 16:19:05 +00001152 (start >> 16) & 0xff,
1153 (start >> 8) & 0xff,
1154 (start & 0xff),
hailfinger19db0922010-06-20 10:41:35 +00001155 buf[0],
1156 buf[1]
1157 },
1158 .readcnt = 0,
1159 .readarr = NULL,
1160 }, {
1161 .writecnt = 0,
1162 .writearr = NULL,
1163 .readcnt = 0,
1164 .readarr = NULL,
1165 }};
snelson8913d082010-02-26 05:48:29 +00001166
mkarcherd264e9e2011-05-11 17:07:07 +00001167 switch (spi_programmer->type) {
hailfinger90c7d542010-05-31 15:27:27 +00001168#if CONFIG_INTERNAL == 1
hailfinger324a9cc2010-05-26 01:45:41 +00001169#if defined(__i386__) || defined(__x86_64__)
hailfinger19db0922010-06-20 10:41:35 +00001170 case SPI_CONTROLLER_IT87XX:
snelson8913d082010-02-26 05:48:29 +00001171 case SPI_CONTROLLER_WBSIO:
hailfingerc7d06c62010-07-14 16:19:05 +00001172 msg_perr("%s: impossible with this SPI controller,"
snelson8913d082010-02-26 05:48:29 +00001173 " degrading to byte program\n", __func__);
hailfinger71e1bd42010-10-13 22:26:56 +00001174 return spi_chip_write_1(flash, buf, start, len);
snelson8913d082010-02-26 05:48:29 +00001175#endif
hailfinger324a9cc2010-05-26 01:45:41 +00001176#endif
snelson8913d082010-02-26 05:48:29 +00001177 default:
1178 break;
1179 }
hailfinger19db0922010-06-20 10:41:35 +00001180
hailfingerc7d06c62010-07-14 16:19:05 +00001181 /* The even start address and even length requirements can be either
1182 * honored outside this function, or we can call spi_byte_program
1183 * for the first and/or last byte and use AAI for the rest.
hailfinger71e1bd42010-10-13 22:26:56 +00001184 * FIXME: Move this to generic code.
hailfingerc7d06c62010-07-14 16:19:05 +00001185 */
hailfinger19db0922010-06-20 10:41:35 +00001186 /* The data sheet requires a start address with the low bit cleared. */
hailfingerc7d06c62010-07-14 16:19:05 +00001187 if (start % 2) {
hailfinger19db0922010-06-20 10:41:35 +00001188 msg_cerr("%s: start address not even! Please report a bug at "
1189 "flashrom@flashrom.org\n", __func__);
hailfinger71e1bd42010-10-13 22:26:56 +00001190 if (spi_chip_write_1(flash, buf, start, start % 2))
1191 return SPI_GENERIC_ERROR;
1192 pos += start % 2;
hailfingerdef852d2010-10-27 22:07:11 +00001193 cmds[1].writearr = (const unsigned char[]){
1194 JEDEC_AAI_WORD_PROGRAM,
1195 (pos >> 16) & 0xff,
1196 (pos >> 8) & 0xff,
1197 (pos & 0xff),
1198 buf[pos - start],
1199 buf[pos - start + 1]
1200 };
hailfinger71e1bd42010-10-13 22:26:56 +00001201 /* Do not return an error for now. */
1202 //return SPI_GENERIC_ERROR;
hailfinger19db0922010-06-20 10:41:35 +00001203 }
1204 /* The data sheet requires total AAI write length to be even. */
1205 if (len % 2) {
1206 msg_cerr("%s: total write length not even! Please report a "
1207 "bug at flashrom@flashrom.org\n", __func__);
hailfinger71e1bd42010-10-13 22:26:56 +00001208 /* Do not return an error for now. */
1209 //return SPI_GENERIC_ERROR;
hailfinger19db0922010-06-20 10:41:35 +00001210 }
1211
hailfinger19db0922010-06-20 10:41:35 +00001212
1213 result = spi_send_multicommand(cmds);
1214 if (result) {
1215 msg_cerr("%s failed during start command execution\n",
1216 __func__);
hailfingerc7d06c62010-07-14 16:19:05 +00001217 /* FIXME: Should we send WRDI here as well to make sure the chip
1218 * is not in AAI mode?
1219 */
snelson8913d082010-02-26 05:48:29 +00001220 return result;
snelson8913d082010-02-26 05:48:29 +00001221 }
hailfinger19db0922010-06-20 10:41:35 +00001222 while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
1223 programmer_delay(10);
1224
1225 /* We already wrote 2 bytes in the multicommand step. */
1226 pos += 2;
1227
hailfinger71e1bd42010-10-13 22:26:56 +00001228 /* Are there at least two more bytes to write? */
1229 while (pos < start + len - 1) {
hailfingerdef852d2010-10-27 22:07:11 +00001230 cmd[1] = buf[pos++ - start];
1231 cmd[2] = buf[pos++ - start];
hailfinger19db0922010-06-20 10:41:35 +00001232 spi_send_command(JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE, 0, cmd, NULL);
1233 while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
1234 programmer_delay(10);
1235 }
1236
hailfinger71e1bd42010-10-13 22:26:56 +00001237 /* Use WRDI to exit AAI mode. This needs to be done before issuing any
1238 * other non-AAI command.
1239 */
snelson8913d082010-02-26 05:48:29 +00001240 spi_write_disable();
hailfinger71e1bd42010-10-13 22:26:56 +00001241
1242 /* Write remaining byte (if any). */
1243 if (pos < start + len) {
hailfingerdef852d2010-10-27 22:07:11 +00001244 if (spi_chip_write_1(flash, buf + pos - start, pos, pos % 2))
hailfinger71e1bd42010-10-13 22:26:56 +00001245 return SPI_GENERIC_ERROR;
1246 pos += pos % 2;
1247 }
1248
snelson8913d082010-02-26 05:48:29 +00001249 return 0;
1250}