blob: 2e80e178efbba5d9ca45384e93b6d295edf8ffd6 [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
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530313uint8_t spi_read_status_register(const struct flashchip *flash)
snelson8913d082010-02-26 05:48:29 +0000314{
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 */
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530321 if (flash->read_status)
322 ret = flash->read_status(flash);
323 else
324 ret = spi_send_command(sizeof(cmd), sizeof(readarr), cmd, readarr);
snelson8913d082010-02-26 05:48:29 +0000325 if (ret)
snelsonfc007bb2010-03-24 23:14:32 +0000326 msg_cerr("RDSR failed!\n");
snelson8913d082010-02-26 05:48:29 +0000327
328 return readarr[0];
329}
330
331/* Prettyprint the status register. Common definitions. */
hailfinger7533bc82011-05-19 00:06:06 +0000332void spi_prettyprint_status_register_welwip(uint8_t status)
hailfingerc33d4732010-07-29 13:09:18 +0000333{
334 msg_cdbg("Chip status register: Write Enable Latch (WEL) is "
335 "%sset\n", (status & (1 << 1)) ? "" : "not ");
336 msg_cdbg("Chip status register: Write In Progress (WIP/BUSY) is "
337 "%sset\n", (status & (1 << 0)) ? "" : "not ");
338}
339
340/* Prettyprint the status register. Common definitions. */
hailfinger7533bc82011-05-19 00:06:06 +0000341void spi_prettyprint_status_register_bp3210(uint8_t status, int bp)
342{
343 switch (bp) {
344 /* Fall through. */
345 case 3:
346 msg_cdbg("Chip status register: Bit 5 / Block Protect 3 (BP3) "
347 "is %sset\n", (status & (1 << 5)) ? "" : "not ");
348 case 2:
349 msg_cdbg("Chip status register: Bit 4 / Block Protect 2 (BP2) "
350 "is %sset\n", (status & (1 << 4)) ? "" : "not ");
351 case 1:
352 msg_cdbg("Chip status register: Bit 3 / Block Protect 1 (BP1) "
353 "is %sset\n", (status & (1 << 3)) ? "" : "not ");
354 case 0:
355 msg_cdbg("Chip status register: Bit 2 / Block Protect 0 (BP0) "
356 "is %sset\n", (status & (1 << 2)) ? "" : "not ");
357 }
358}
359
360/* Prettyprint the status register. Unnamed bits. */
361void spi_prettyprint_status_register_bit(uint8_t status, int bit)
362{
363 msg_cdbg("Chip status register: Bit %i "
364 "is %sset\n", bit, (status & (1 << bit)) ? "" : "not ");
365}
366
hailfingerc33d4732010-07-29 13:09:18 +0000367static void spi_prettyprint_status_register_common(uint8_t status)
snelson8913d082010-02-26 05:48:29 +0000368{
hailfinger7533bc82011-05-19 00:06:06 +0000369 spi_prettyprint_status_register_bp3210(status, 3);
hailfingerc33d4732010-07-29 13:09:18 +0000370 spi_prettyprint_status_register_welwip(status);
snelson8913d082010-02-26 05:48:29 +0000371}
372
373/* Prettyprint the status register. Works for
374 * ST M25P series
375 * MX MX25L series
376 */
377void spi_prettyprint_status_register_st_m25p(uint8_t status)
378{
snelsonfc007bb2010-03-24 23:14:32 +0000379 msg_cdbg("Chip status register: Status Register Write Disable "
snelson8913d082010-02-26 05:48:29 +0000380 "(SRWD) is %sset\n", (status & (1 << 7)) ? "" : "not ");
snelsonfc007bb2010-03-24 23:14:32 +0000381 msg_cdbg("Chip status register: Bit 6 is "
snelson8913d082010-02-26 05:48:29 +0000382 "%sset\n", (status & (1 << 6)) ? "" : "not ");
383 spi_prettyprint_status_register_common(status);
384}
385
386void spi_prettyprint_status_register_sst25(uint8_t status)
387{
snelsonfc007bb2010-03-24 23:14:32 +0000388 msg_cdbg("Chip status register: Block Protect Write Disable "
snelson8913d082010-02-26 05:48:29 +0000389 "(BPL) is %sset\n", (status & (1 << 7)) ? "" : "not ");
snelsonfc007bb2010-03-24 23:14:32 +0000390 msg_cdbg("Chip status register: Auto Address Increment Programming "
snelson8913d082010-02-26 05:48:29 +0000391 "(AAI) is %sset\n", (status & (1 << 6)) ? "" : "not ");
392 spi_prettyprint_status_register_common(status);
393}
394
395/* Prettyprint the status register. Works for
396 * SST 25VF016
397 */
398void spi_prettyprint_status_register_sst25vf016(uint8_t status)
399{
krause2eb76212011-01-17 07:50:42 +0000400 static const char *const bpt[] = {
snelson8913d082010-02-26 05:48:29 +0000401 "none",
402 "1F0000H-1FFFFFH",
403 "1E0000H-1FFFFFH",
404 "1C0000H-1FFFFFH",
405 "180000H-1FFFFFH",
406 "100000H-1FFFFFH",
407 "all", "all"
408 };
409 spi_prettyprint_status_register_sst25(status);
snelsonfc007bb2010-03-24 23:14:32 +0000410 msg_cdbg("Resulting block protection : %s\n",
snelson8913d082010-02-26 05:48:29 +0000411 bpt[(status & 0x1c) >> 2]);
412}
413
414void spi_prettyprint_status_register_sst25vf040b(uint8_t status)
415{
krause2eb76212011-01-17 07:50:42 +0000416 static const char *const bpt[] = {
snelson8913d082010-02-26 05:48:29 +0000417 "none",
418 "0x70000-0x7ffff",
419 "0x60000-0x7ffff",
420 "0x40000-0x7ffff",
421 "all blocks", "all blocks", "all blocks", "all blocks"
422 };
423 spi_prettyprint_status_register_sst25(status);
snelsonfc007bb2010-03-24 23:14:32 +0000424 msg_cdbg("Resulting block protection : %s\n",
snelson8913d082010-02-26 05:48:29 +0000425 bpt[(status & 0x1c) >> 2]);
426}
427
hailfinger7533bc82011-05-19 00:06:06 +0000428int spi_prettyprint_status_register(struct flashchip *flash)
snelson8913d082010-02-26 05:48:29 +0000429{
430 uint8_t status;
431
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530432 status = spi_read_status_register(flash);
snelsonfc007bb2010-03-24 23:14:32 +0000433 msg_cdbg("Chip status register is %02x\n", status);
snelson8913d082010-02-26 05:48:29 +0000434 switch (flash->manufacture_id) {
435 case ST_ID:
436 if (((flash->model_id & 0xff00) == 0x2000) ||
437 ((flash->model_id & 0xff00) == 0x2500))
438 spi_prettyprint_status_register_st_m25p(status);
439 break;
mhmd3c80cd2010-09-15 23:31:03 +0000440 case MACRONIX_ID:
snelson8913d082010-02-26 05:48:29 +0000441 if ((flash->model_id & 0xff00) == 0x2000)
442 spi_prettyprint_status_register_st_m25p(status);
443 break;
444 case SST_ID:
445 switch (flash->model_id) {
446 case 0x2541:
447 spi_prettyprint_status_register_sst25vf016(status);
448 break;
449 case 0x8d:
450 case 0x258d:
451 spi_prettyprint_status_register_sst25vf040b(status);
452 break;
453 default:
454 spi_prettyprint_status_register_sst25(status);
455 break;
456 }
457 break;
458 }
hailfinger7533bc82011-05-19 00:06:06 +0000459 return 0;
snelson8913d082010-02-26 05:48:29 +0000460}
461
462int spi_chip_erase_60(struct flashchip *flash)
463{
464 int result;
465 struct spi_command cmds[] = {
466 {
467 .writecnt = JEDEC_WREN_OUTSIZE,
468 .writearr = (const unsigned char[]){ JEDEC_WREN },
469 .readcnt = 0,
470 .readarr = NULL,
471 }, {
472 .writecnt = JEDEC_CE_60_OUTSIZE,
473 .writearr = (const unsigned char[]){ JEDEC_CE_60 },
474 .readcnt = 0,
475 .readarr = NULL,
476 }, {
477 .writecnt = 0,
478 .writearr = NULL,
479 .readcnt = 0,
480 .readarr = NULL,
481 }};
482
snelson8913d082010-02-26 05:48:29 +0000483 result = spi_send_multicommand(cmds);
484 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000485 msg_cerr("%s failed during command execution\n",
snelson8913d082010-02-26 05:48:29 +0000486 __func__);
487 return result;
488 }
489 /* Wait until the Write-In-Progress bit is cleared.
490 * This usually takes 1-85 s, so wait in 1 s steps.
491 */
492 /* FIXME: We assume spi_read_status_register will never fail. */
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530493 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
snelson8913d082010-02-26 05:48:29 +0000494 programmer_delay(1000 * 1000);
hailfingerac8e3182011-06-26 17:04:16 +0000495 /* FIXME: Check the status register for errors. */
snelson8913d082010-02-26 05:48:29 +0000496 return 0;
497}
498
499int spi_chip_erase_c7(struct flashchip *flash)
500{
501 int result;
502 struct spi_command cmds[] = {
503 {
504 .writecnt = JEDEC_WREN_OUTSIZE,
505 .writearr = (const unsigned char[]){ JEDEC_WREN },
506 .readcnt = 0,
507 .readarr = NULL,
508 }, {
509 .writecnt = JEDEC_CE_C7_OUTSIZE,
510 .writearr = (const unsigned char[]){ JEDEC_CE_C7 },
511 .readcnt = 0,
512 .readarr = NULL,
513 }, {
514 .writecnt = 0,
515 .writearr = NULL,
516 .readcnt = 0,
517 .readarr = NULL,
518 }};
519
snelson8913d082010-02-26 05:48:29 +0000520 result = spi_send_multicommand(cmds);
521 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000522 msg_cerr("%s failed during command execution\n", __func__);
snelson8913d082010-02-26 05:48:29 +0000523 return result;
524 }
525 /* Wait until the Write-In-Progress bit is cleared.
526 * This usually takes 1-85 s, so wait in 1 s steps.
527 */
528 /* FIXME: We assume spi_read_status_register will never fail. */
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530529 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
snelson8913d082010-02-26 05:48:29 +0000530 programmer_delay(1000 * 1000);
hailfingerac8e3182011-06-26 17:04:16 +0000531 /* FIXME: Check the status register for errors. */
snelson8913d082010-02-26 05:48:29 +0000532 return 0;
533}
534
snelson8913d082010-02-26 05:48:29 +0000535int spi_block_erase_52(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
536{
537 int result;
538 struct spi_command cmds[] = {
539 {
540 .writecnt = JEDEC_WREN_OUTSIZE,
541 .writearr = (const unsigned char[]){ JEDEC_WREN },
542 .readcnt = 0,
543 .readarr = NULL,
544 }, {
545 .writecnt = JEDEC_BE_52_OUTSIZE,
546 .writearr = (const unsigned char[]){
547 JEDEC_BE_52,
548 (addr >> 16) & 0xff,
549 (addr >> 8) & 0xff,
550 (addr & 0xff)
551 },
552 .readcnt = 0,
553 .readarr = NULL,
554 }, {
555 .writecnt = 0,
556 .writearr = NULL,
557 .readcnt = 0,
558 .readarr = NULL,
559 }};
560
561 result = spi_send_multicommand(cmds);
562 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000563 msg_cerr("%s failed during command execution at address 0x%x\n",
snelson8913d082010-02-26 05:48:29 +0000564 __func__, addr);
565 return result;
566 }
567 /* Wait until the Write-In-Progress bit is cleared.
568 * This usually takes 100-4000 ms, so wait in 100 ms steps.
569 */
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530570 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
snelson8913d082010-02-26 05:48:29 +0000571 programmer_delay(100 * 1000);
hailfingerac8e3182011-06-26 17:04:16 +0000572 /* FIXME: Check the status register for errors. */
snelson8913d082010-02-26 05:48:29 +0000573 return 0;
574}
575
576/* Block size is usually
577 * 64k for Macronix
578 * 32k for SST
579 * 4-32k non-uniform for EON
580 */
581int spi_block_erase_d8(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
582{
583 int result;
584 struct spi_command cmds[] = {
585 {
586 .writecnt = JEDEC_WREN_OUTSIZE,
587 .writearr = (const unsigned char[]){ JEDEC_WREN },
588 .readcnt = 0,
589 .readarr = NULL,
590 }, {
591 .writecnt = JEDEC_BE_D8_OUTSIZE,
592 .writearr = (const unsigned char[]){
593 JEDEC_BE_D8,
594 (addr >> 16) & 0xff,
595 (addr >> 8) & 0xff,
596 (addr & 0xff)
597 },
598 .readcnt = 0,
599 .readarr = NULL,
600 }, {
601 .writecnt = 0,
602 .writearr = NULL,
603 .readcnt = 0,
604 .readarr = NULL,
605 }};
606
607 result = spi_send_multicommand(cmds);
608 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000609 msg_cerr("%s failed during command execution at address 0x%x\n",
snelson8913d082010-02-26 05:48:29 +0000610 __func__, addr);
611 return result;
612 }
613 /* Wait until the Write-In-Progress bit is cleared.
614 * This usually takes 100-4000 ms, so wait in 100 ms steps.
615 */
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530616 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
snelson8913d082010-02-26 05:48:29 +0000617 programmer_delay(100 * 1000);
hailfingerac8e3182011-06-26 17:04:16 +0000618 /* FIXME: Check the status register for errors. */
snelson8913d082010-02-26 05:48:29 +0000619 return 0;
620}
621
622/* Block size is usually
623 * 4k for PMC
624 */
625int spi_block_erase_d7(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
626{
627 int result;
628 struct spi_command cmds[] = {
629 {
630 .writecnt = JEDEC_WREN_OUTSIZE,
631 .writearr = (const unsigned char[]){ JEDEC_WREN },
632 .readcnt = 0,
633 .readarr = NULL,
634 }, {
635 .writecnt = JEDEC_BE_D7_OUTSIZE,
636 .writearr = (const unsigned char[]){
637 JEDEC_BE_D7,
638 (addr >> 16) & 0xff,
639 (addr >> 8) & 0xff,
640 (addr & 0xff)
641 },
642 .readcnt = 0,
643 .readarr = NULL,
644 }, {
645 .writecnt = 0,
646 .writearr = NULL,
647 .readcnt = 0,
648 .readarr = NULL,
649 }};
650
651 result = spi_send_multicommand(cmds);
652 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000653 msg_cerr("%s failed during command execution at address 0x%x\n",
snelson8913d082010-02-26 05:48:29 +0000654 __func__, addr);
655 return result;
656 }
657 /* Wait until the Write-In-Progress bit is cleared.
658 * This usually takes 100-4000 ms, so wait in 100 ms steps.
659 */
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530660 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
snelson8913d082010-02-26 05:48:29 +0000661 programmer_delay(100 * 1000);
hailfingerac8e3182011-06-26 17:04:16 +0000662 /* FIXME: Check the status register for errors. */
snelson8913d082010-02-26 05:48:29 +0000663 return 0;
664}
665
snelson8913d082010-02-26 05:48:29 +0000666/* Sector size is usually 4k, though Macronix eliteflash has 64k */
667int spi_block_erase_20(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
668{
669 int result;
670 struct spi_command cmds[] = {
671 {
672 .writecnt = JEDEC_WREN_OUTSIZE,
673 .writearr = (const unsigned char[]){ JEDEC_WREN },
674 .readcnt = 0,
675 .readarr = NULL,
676 }, {
677 .writecnt = JEDEC_SE_OUTSIZE,
678 .writearr = (const unsigned char[]){
679 JEDEC_SE,
680 (addr >> 16) & 0xff,
681 (addr >> 8) & 0xff,
682 (addr & 0xff)
683 },
684 .readcnt = 0,
685 .readarr = NULL,
686 }, {
687 .writecnt = 0,
688 .writearr = NULL,
689 .readcnt = 0,
690 .readarr = NULL,
691 }};
692
693 result = spi_send_multicommand(cmds);
Stefan Reinauercce56d52010-11-22 18:22:21 -0800694
snelson8913d082010-02-26 05:48:29 +0000695 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000696 msg_cerr("%s failed during command execution at address 0x%x\n",
snelson8913d082010-02-26 05:48:29 +0000697 __func__, addr);
698 return result;
699 }
700 /* Wait until the Write-In-Progress bit is cleared.
701 * This usually takes 15-800 ms, so wait in 10 ms steps.
702 */
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530703 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
snelson8913d082010-02-26 05:48:29 +0000704 programmer_delay(10 * 1000);
hailfingerac8e3182011-06-26 17:04:16 +0000705 /* FIXME: Check the status register for errors. */
snelson8913d082010-02-26 05:48:29 +0000706 return 0;
707}
708
709int spi_block_erase_60(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
710{
711 if ((addr != 0) || (blocklen != flash->total_size * 1024)) {
snelsonfc007bb2010-03-24 23:14:32 +0000712 msg_cerr("%s called with incorrect arguments\n",
snelson8913d082010-02-26 05:48:29 +0000713 __func__);
714 return -1;
715 }
716 return spi_chip_erase_60(flash);
717}
718
719int spi_block_erase_c7(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
720{
721 if ((addr != 0) || (blocklen != flash->total_size * 1024)) {
snelsonfc007bb2010-03-24 23:14:32 +0000722 msg_cerr("%s called with incorrect arguments\n",
snelson8913d082010-02-26 05:48:29 +0000723 __func__);
724 return -1;
725 }
726 return spi_chip_erase_c7(flash);
727}
728
729int spi_write_status_enable(void)
730{
krause2eb76212011-01-17 07:50:42 +0000731 static const unsigned char cmd[JEDEC_EWSR_OUTSIZE] = { JEDEC_EWSR };
snelson8913d082010-02-26 05:48:29 +0000732 int result;
733
734 /* Send EWSR (Enable Write Status Register). */
735 result = spi_send_command(sizeof(cmd), JEDEC_EWSR_INSIZE, cmd, NULL);
736
737 if (result)
snelsonfc007bb2010-03-24 23:14:32 +0000738 msg_cerr("%s failed\n", __func__);
snelson8913d082010-02-26 05:48:29 +0000739
740 return result;
741}
742
743/*
744 * This is according the SST25VF016 datasheet, who knows it is more
745 * generic that this...
746 */
David Hendricks2d6d1d52014-12-11 18:32:20 -0800747static int spi_write_status_register_ewsr(const struct flashchip *flash, int status)
snelson8913d082010-02-26 05:48:29 +0000748{
749 int result;
hailfingeree9ee132010-10-08 00:37:55 +0000750 int i = 0;
snelson8913d082010-02-26 05:48:29 +0000751 struct spi_command cmds[] = {
752 {
hailfingerc33d4732010-07-29 13:09:18 +0000753 /* WRSR requires either EWSR or WREN depending on chip type. */
snelson8913d082010-02-26 05:48:29 +0000754 .writecnt = JEDEC_EWSR_OUTSIZE,
755 .writearr = (const unsigned char[]){ JEDEC_EWSR },
756 .readcnt = 0,
757 .readarr = NULL,
758 }, {
759 .writecnt = JEDEC_WRSR_OUTSIZE,
760 .writearr = (const unsigned char[]){ JEDEC_WRSR, (unsigned char) status },
761 .readcnt = 0,
762 .readarr = NULL,
763 }, {
764 .writecnt = 0,
765 .writearr = NULL,
766 .readcnt = 0,
767 .readarr = NULL,
768 }};
769
770 result = spi_send_multicommand(cmds);
771 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000772 msg_cerr("%s failed during command execution\n",
snelson8913d082010-02-26 05:48:29 +0000773 __func__);
hailfingeree9ee132010-10-08 00:37:55 +0000774 /* No point in waiting for the command to complete if execution
775 * failed.
776 */
777 return result;
snelson8913d082010-02-26 05:48:29 +0000778 }
hailfingeree9ee132010-10-08 00:37:55 +0000779 /* WRSR performs a self-timed erase before the changes take effect.
780 * This may take 50-85 ms in most cases, and some chips apparently
781 * allow running RDSR only once. Therefore pick an initial delay of
782 * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed.
783 */
hailfingerc33d4732010-07-29 13:09:18 +0000784 programmer_delay(100 * 1000);
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530785 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) {
hailfingeree9ee132010-10-08 00:37:55 +0000786 if (++i > 490) {
787 msg_cerr("Error: WIP bit after WRSR never cleared\n");
788 return TIMEOUT_ERROR;
789 }
790 programmer_delay(10 * 1000);
791 }
792 return 0;
snelson8913d082010-02-26 05:48:29 +0000793}
794
David Hendricks2d6d1d52014-12-11 18:32:20 -0800795int spi_write_status_register_wren(const struct flashchip *flash, int status)
hailfingerc33d4732010-07-29 13:09:18 +0000796{
797 int result;
hailfingeree9ee132010-10-08 00:37:55 +0000798 int i = 0;
hailfingerc33d4732010-07-29 13:09:18 +0000799 struct spi_command cmds[] = {
800 {
801 /* WRSR requires either EWSR or WREN depending on chip type. */
802 .writecnt = JEDEC_WREN_OUTSIZE,
803 .writearr = (const unsigned char[]){ JEDEC_WREN },
804 .readcnt = 0,
805 .readarr = NULL,
806 }, {
807 .writecnt = JEDEC_WRSR_OUTSIZE,
808 .writearr = (const unsigned char[]){ JEDEC_WRSR, (unsigned char) status },
809 .readcnt = 0,
810 .readarr = NULL,
811 }, {
812 .writecnt = 0,
813 .writearr = NULL,
814 .readcnt = 0,
815 .readarr = NULL,
816 }};
817
818 result = spi_send_multicommand(cmds);
819 if (result) {
820 msg_cerr("%s failed during command execution\n",
821 __func__);
hailfingeree9ee132010-10-08 00:37:55 +0000822 /* No point in waiting for the command to complete if execution
823 * failed.
824 */
825 return result;
hailfingerc33d4732010-07-29 13:09:18 +0000826 }
hailfingeree9ee132010-10-08 00:37:55 +0000827 /* WRSR performs a self-timed erase before the changes take effect.
828 * This may take 50-85 ms in most cases, and some chips apparently
829 * allow running RDSR only once. Therefore pick an initial delay of
830 * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed.
831 */
hailfingerc33d4732010-07-29 13:09:18 +0000832 programmer_delay(100 * 1000);
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530833 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP) {
hailfingeree9ee132010-10-08 00:37:55 +0000834 if (++i > 490) {
835 msg_cerr("Error: WIP bit after WRSR never cleared\n");
836 return TIMEOUT_ERROR;
837 }
838 programmer_delay(10 * 1000);
839 }
840 return 0;
hailfingerc33d4732010-07-29 13:09:18 +0000841}
842
David Hendricks2d6d1d52014-12-11 18:32:20 -0800843int spi_write_status_register(const struct flashchip *flash, int status)
hailfingerc33d4732010-07-29 13:09:18 +0000844{
845 int ret = 1;
846
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530847 if (flash->write_status) {
848 ret = flash->write_status(flash, status);
849 } else {
850 if (flash->feature_bits & FEATURE_WRSR_WREN)
851 ret = spi_write_status_register_wren(flash, status);
852 if (ret && (flash->feature_bits & FEATURE_WRSR_EWSR))
853 ret = spi_write_status_register_ewsr(flash, status);
854 }
855
hailfingerc33d4732010-07-29 13:09:18 +0000856 return ret;
857}
858
stefanctc5eb8a92011-11-23 09:13:48 +0000859int spi_byte_program(unsigned int addr, uint8_t databyte)
snelson8913d082010-02-26 05:48:29 +0000860{
861 int result;
862 struct spi_command cmds[] = {
863 {
864 .writecnt = JEDEC_WREN_OUTSIZE,
865 .writearr = (const unsigned char[]){ JEDEC_WREN },
866 .readcnt = 0,
867 .readarr = NULL,
868 }, {
869 .writecnt = JEDEC_BYTE_PROGRAM_OUTSIZE,
870 .writearr = (const unsigned char[]){
871 JEDEC_BYTE_PROGRAM,
872 (addr >> 16) & 0xff,
873 (addr >> 8) & 0xff,
874 (addr & 0xff),
875 databyte
876 },
877 .readcnt = 0,
878 .readarr = NULL,
879 }, {
880 .writecnt = 0,
881 .writearr = NULL,
882 .readcnt = 0,
883 .readarr = NULL,
884 }};
885
886 result = spi_send_multicommand(cmds);
887 if (result) {
snelsonfc007bb2010-03-24 23:14:32 +0000888 msg_cerr("%s failed during command execution at address 0x%x\n",
snelson8913d082010-02-26 05:48:29 +0000889 __func__, addr);
890 }
891 return result;
892}
893
stefanctc5eb8a92011-11-23 09:13:48 +0000894int spi_nbyte_program(unsigned int addr, uint8_t *bytes, unsigned int len)
snelson8913d082010-02-26 05:48:29 +0000895{
896 int result;
897 /* FIXME: Switch to malloc based on len unless that kills speed. */
898 unsigned char cmd[JEDEC_BYTE_PROGRAM_OUTSIZE - 1 + 256] = {
899 JEDEC_BYTE_PROGRAM,
900 (addr >> 16) & 0xff,
901 (addr >> 8) & 0xff,
902 (addr >> 0) & 0xff,
903 };
904 struct spi_command cmds[] = {
905 {
906 .writecnt = JEDEC_WREN_OUTSIZE,
907 .writearr = (const unsigned char[]){ JEDEC_WREN },
908 .readcnt = 0,
909 .readarr = NULL,
910 }, {
911 .writecnt = JEDEC_BYTE_PROGRAM_OUTSIZE - 1 + len,
912 .writearr = cmd,
913 .readcnt = 0,
914 .readarr = NULL,
915 }, {
916 .writecnt = 0,
917 .writearr = NULL,
918 .readcnt = 0,
919 .readarr = NULL,
920 }};
921
922 if (!len) {
snelsonfc007bb2010-03-24 23:14:32 +0000923 msg_cerr("%s called for zero-length write\n", __func__);
snelson8913d082010-02-26 05:48:29 +0000924 return 1;
925 }
926 if (len > 256) {
snelsonfc007bb2010-03-24 23:14:32 +0000927 msg_cerr("%s called for too long a write\n", __func__);
snelson8913d082010-02-26 05:48:29 +0000928 return 1;
929 }
930
931 memcpy(&cmd[4], bytes, len);
932
933 result = spi_send_multicommand(cmds);
934 if (result) {
David Hendricks1ed1d352011-11-23 17:54:37 -0800935 if (result != SPI_ACCESS_DENIED) {
936 msg_cerr("%s failed during command execution at address 0x%x\n",
937 __func__, addr);
938 }
snelson8913d082010-02-26 05:48:29 +0000939 }
940 return result;
941}
942
David Hendricksbf36f092010-11-02 23:39:29 -0700943int spi_restore_status(struct flashchip *flash, uint8_t status)
944{
945 msg_cdbg("restoring chip status (0x%02x)\n", status);
946 return spi_write_status_register(flash, status);
947}
948
hailfingerc33d4732010-07-29 13:09:18 +0000949/* A generic brute-force block protection disable works like this:
950 * Write 0x00 to the status register. Check if any locks are still set (that
951 * part is chip specific). Repeat once.
952 */
hailfingerb9560ee2010-07-14 20:21:22 +0000953int spi_disable_blockprotect(struct flashchip *flash)
snelson8913d082010-02-26 05:48:29 +0000954{
955 uint8_t status;
956 int result;
957
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530958 status = spi_read_status_register(flash);
hailfingerc33d4732010-07-29 13:09:18 +0000959 /* If block protection is disabled, stop here. */
960 if ((status & 0x3c) == 0)
961 return 0;
962
David Hendricksbf36f092010-11-02 23:39:29 -0700963 /* restore status register content upon exit */
964 register_chip_restore(spi_restore_status, flash, status);
965
hailfingerc33d4732010-07-29 13:09:18 +0000966 msg_cdbg("Some block protection in effect, disabling\n");
967 result = spi_write_status_register(flash, status & ~0x3c);
968 if (result) {
969 msg_cerr("spi_write_status_register failed\n");
970 return result;
971 }
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +0530972 status = spi_read_status_register(flash);
snelson8913d082010-02-26 05:48:29 +0000973 if ((status & 0x3c) != 0) {
hailfingerc33d4732010-07-29 13:09:18 +0000974 msg_cerr("Block protection could not be disabled!\n");
975 return 1;
976 }
977 return 0;
978}
979
stefanctc5eb8a92011-11-23 09:13:48 +0000980int spi_nbyte_read(unsigned int address, uint8_t *bytes, unsigned int len)
snelson8913d082010-02-26 05:48:29 +0000981{
982 const unsigned char cmd[JEDEC_READ_OUTSIZE] = {
983 JEDEC_READ,
984 (address >> 16) & 0xff,
985 (address >> 8) & 0xff,
986 (address >> 0) & 0xff,
987 };
988
989 /* Send Read */
990 return spi_send_command(sizeof(cmd), len, cmd, bytes);
991}
992
993/*
hailfinger39d159a2010-05-21 23:09:42 +0000994 * Read a part of the flash chip.
hailfingerc7d06c62010-07-14 16:19:05 +0000995 * FIXME: Use the chunk code from Michael Karcher instead.
snelson8913d082010-02-26 05:48:29 +0000996 * Each page is read separately in chunks with a maximum size of chunksize.
997 */
stefanctc5eb8a92011-11-23 09:13:48 +0000998int spi_read_chunked(struct flashchip *flash, uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize)
snelson8913d082010-02-26 05:48:29 +0000999{
David Hendricks1ed1d352011-11-23 17:54:37 -08001000 int rc = 0, chunk_status = 0;
stefanctc5eb8a92011-11-23 09:13:48 +00001001 unsigned int i, j, starthere, lenhere, toread;
1002 unsigned int page_size = flash->page_size;
snelson8913d082010-02-26 05:48:29 +00001003
1004 /* Warning: This loop has a very unusual condition and body.
1005 * The loop needs to go through each page with at least one affected
1006 * byte. The lowest page number is (start / page_size) since that
1007 * division rounds down. The highest page number we want is the page
1008 * where the last byte of the range lives. That last byte has the
1009 * address (start + len - 1), thus the highest page number is
1010 * (start + len - 1) / page_size. Since we want to include that last
1011 * page as well, the loop condition uses <=.
1012 */
1013 for (i = start / page_size; i <= (start + len - 1) / page_size; i++) {
1014 /* Byte position of the first byte in the range in this page. */
1015 /* starthere is an offset to the base address of the chip. */
1016 starthere = max(start, i * page_size);
1017 /* Length of bytes in the range in this page. */
1018 lenhere = min(start + len, (i + 1) * page_size) - starthere;
1019 for (j = 0; j < lenhere; j += chunksize) {
1020 toread = min(chunksize, lenhere - j);
David Hendricks1ed1d352011-11-23 17:54:37 -08001021 chunk_status = spi_nbyte_read(starthere + j, buf + starthere - start + j, toread);
1022 if (chunk_status) {
1023 if (ignore_error(chunk_status)) {
1024 /* fill this chunk with 0xff bytes and
1025 let caller know about the error */
1026 memset(buf + starthere - start + j, 0xff, toread);
1027 rc = chunk_status;
1028 chunk_status = 0;
1029 continue;
1030 } else {
1031 rc = chunk_status;
1032 break;
1033 }
1034 }
snelson8913d082010-02-26 05:48:29 +00001035 }
David Hendricks1ed1d352011-11-23 17:54:37 -08001036 if (chunk_status)
snelson8913d082010-02-26 05:48:29 +00001037 break;
1038 }
1039
1040 return rc;
1041}
1042
1043/*
Duncan Laurie06ffd522015-10-26 12:56:08 -07001044 * Read a part of the flash chip.
1045 * Ignore pages and read the data continuously, the only bound is the chunksize.
1046 */
1047int spi_read_unbound(struct flashchip *flash, uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize)
1048{
1049 int rc = 0;
1050 unsigned int i;
1051
1052 for (i = start; i < (start + len); i += chunksize) {
David Hendricks37370ec2015-11-24 14:38:17 -08001053 int chunk_status = 0;
1054 unsigned int toread = min(chunksize, start + len - i);
1055
1056 chunk_status = spi_nbyte_read(i, buf + (i - start), toread);
1057 if (chunk_status) {
1058 if (ignore_error(chunk_status)) {
1059 /* fill this chunk with 0xff bytes and
1060 let caller know about the error */
1061 memset(buf + (i - start), 0xff, toread);
1062 rc = chunk_status;
1063 continue;
1064 } else {
1065 rc = chunk_status;
1066 break;
1067 }
1068 }
Duncan Laurie06ffd522015-10-26 12:56:08 -07001069 }
David Hendricks37370ec2015-11-24 14:38:17 -08001070
Duncan Laurie06ffd522015-10-26 12:56:08 -07001071 return rc;
1072}
1073
1074/*
hailfinger39d159a2010-05-21 23:09:42 +00001075 * Write a part of the flash chip.
hailfingerc7d06c62010-07-14 16:19:05 +00001076 * FIXME: Use the chunk code from Michael Karcher instead.
hailfinger39d159a2010-05-21 23:09:42 +00001077 * Each page is written separately in chunks with a maximum size of chunksize.
1078 */
stefanctc5eb8a92011-11-23 09:13:48 +00001079int spi_write_chunked(struct flashchip *flash, uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize)
hailfinger39d159a2010-05-21 23:09:42 +00001080{
1081 int rc = 0;
stefanctc5eb8a92011-11-23 09:13:48 +00001082 unsigned int i, j, starthere, lenhere, towrite;
hailfinger39d159a2010-05-21 23:09:42 +00001083 /* FIXME: page_size is the wrong variable. We need max_writechunk_size
1084 * in struct flashchip to do this properly. All chips using
1085 * spi_chip_write_256 have page_size set to max_writechunk_size, so
1086 * we're OK for now.
1087 */
stefanctc5eb8a92011-11-23 09:13:48 +00001088 unsigned int page_size = flash->page_size;
hailfinger39d159a2010-05-21 23:09:42 +00001089
1090 /* Warning: This loop has a very unusual condition and body.
1091 * The loop needs to go through each page with at least one affected
1092 * byte. The lowest page number is (start / page_size) since that
1093 * division rounds down. The highest page number we want is the page
1094 * where the last byte of the range lives. That last byte has the
1095 * address (start + len - 1), thus the highest page number is
1096 * (start + len - 1) / page_size. Since we want to include that last
1097 * page as well, the loop condition uses <=.
1098 */
1099 for (i = start / page_size; i <= (start + len - 1) / page_size; i++) {
1100 /* Byte position of the first byte in the range in this page. */
1101 /* starthere is an offset to the base address of the chip. */
1102 starthere = max(start, i * page_size);
1103 /* Length of bytes in the range in this page. */
1104 lenhere = min(start + len, (i + 1) * page_size) - starthere;
1105 for (j = 0; j < lenhere; j += chunksize) {
1106 towrite = min(chunksize, lenhere - j);
1107 rc = spi_nbyte_program(starthere + j, buf + starthere - start + j, towrite);
1108 if (rc)
1109 break;
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301110 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
hailfinger39d159a2010-05-21 23:09:42 +00001111 programmer_delay(10);
1112 }
1113 if (rc)
1114 break;
1115 }
1116
1117 return rc;
1118}
1119
1120/*
snelson8913d082010-02-26 05:48:29 +00001121 * Program chip using byte programming. (SLOW!)
1122 * This is for chips which can only handle one byte writes
1123 * and for chips where memory mapped programming is impossible
1124 * (e.g. due to size constraints in IT87* for over 512 kB)
1125 */
hailfingerc7d06c62010-07-14 16:19:05 +00001126/* real chunksize is 1, logical chunksize is 1 */
stefanctc5eb8a92011-11-23 09:13:48 +00001127int spi_chip_write_1(struct flashchip *flash, uint8_t *buf, unsigned int start, unsigned int len)
snelson8913d082010-02-26 05:48:29 +00001128{
stefanctc5eb8a92011-11-23 09:13:48 +00001129 unsigned int i;
1130 int result = 0;
snelson8913d082010-02-26 05:48:29 +00001131
hailfingerc7d06c62010-07-14 16:19:05 +00001132 for (i = start; i < start + len; i++) {
hailfingerdef852d2010-10-27 22:07:11 +00001133 result = spi_byte_program(i, buf[i - start]);
snelson8913d082010-02-26 05:48:29 +00001134 if (result)
1135 return 1;
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301136 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
snelson8913d082010-02-26 05:48:29 +00001137 programmer_delay(10);
1138 }
1139
1140 return 0;
1141}
1142
stefanctc5eb8a92011-11-23 09:13:48 +00001143int spi_aai_write(struct flashchip *flash, uint8_t *buf, unsigned int start, unsigned int len)
hailfingerc7d06c62010-07-14 16:19:05 +00001144{
1145 uint32_t pos = start;
snelson8913d082010-02-26 05:48:29 +00001146 int result;
hailfinger19db0922010-06-20 10:41:35 +00001147 unsigned char cmd[JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE] = {
1148 JEDEC_AAI_WORD_PROGRAM,
1149 };
1150 struct spi_command cmds[] = {
1151 {
1152 .writecnt = JEDEC_WREN_OUTSIZE,
1153 .writearr = (const unsigned char[]){ JEDEC_WREN },
1154 .readcnt = 0,
1155 .readarr = NULL,
1156 }, {
1157 .writecnt = JEDEC_AAI_WORD_PROGRAM_OUTSIZE,
1158 .writearr = (const unsigned char[]){
1159 JEDEC_AAI_WORD_PROGRAM,
hailfingerc7d06c62010-07-14 16:19:05 +00001160 (start >> 16) & 0xff,
1161 (start >> 8) & 0xff,
1162 (start & 0xff),
hailfinger19db0922010-06-20 10:41:35 +00001163 buf[0],
1164 buf[1]
1165 },
1166 .readcnt = 0,
1167 .readarr = NULL,
1168 }, {
1169 .writecnt = 0,
1170 .writearr = NULL,
1171 .readcnt = 0,
1172 .readarr = NULL,
1173 }};
snelson8913d082010-02-26 05:48:29 +00001174
mkarcherd264e9e2011-05-11 17:07:07 +00001175 switch (spi_programmer->type) {
hailfinger90c7d542010-05-31 15:27:27 +00001176#if CONFIG_INTERNAL == 1
hailfinger324a9cc2010-05-26 01:45:41 +00001177#if defined(__i386__) || defined(__x86_64__)
hailfinger19db0922010-06-20 10:41:35 +00001178 case SPI_CONTROLLER_IT87XX:
snelson8913d082010-02-26 05:48:29 +00001179 case SPI_CONTROLLER_WBSIO:
hailfingerc7d06c62010-07-14 16:19:05 +00001180 msg_perr("%s: impossible with this SPI controller,"
snelson8913d082010-02-26 05:48:29 +00001181 " degrading to byte program\n", __func__);
hailfinger71e1bd42010-10-13 22:26:56 +00001182 return spi_chip_write_1(flash, buf, start, len);
snelson8913d082010-02-26 05:48:29 +00001183#endif
hailfinger324a9cc2010-05-26 01:45:41 +00001184#endif
snelson8913d082010-02-26 05:48:29 +00001185 default:
1186 break;
1187 }
hailfinger19db0922010-06-20 10:41:35 +00001188
hailfingerc7d06c62010-07-14 16:19:05 +00001189 /* The even start address and even length requirements can be either
1190 * honored outside this function, or we can call spi_byte_program
1191 * for the first and/or last byte and use AAI for the rest.
hailfinger71e1bd42010-10-13 22:26:56 +00001192 * FIXME: Move this to generic code.
hailfingerc7d06c62010-07-14 16:19:05 +00001193 */
hailfinger19db0922010-06-20 10:41:35 +00001194 /* The data sheet requires a start address with the low bit cleared. */
hailfingerc7d06c62010-07-14 16:19:05 +00001195 if (start % 2) {
hailfinger19db0922010-06-20 10:41:35 +00001196 msg_cerr("%s: start address not even! Please report a bug at "
1197 "flashrom@flashrom.org\n", __func__);
hailfinger71e1bd42010-10-13 22:26:56 +00001198 if (spi_chip_write_1(flash, buf, start, start % 2))
1199 return SPI_GENERIC_ERROR;
1200 pos += start % 2;
hailfingerdef852d2010-10-27 22:07:11 +00001201 cmds[1].writearr = (const unsigned char[]){
1202 JEDEC_AAI_WORD_PROGRAM,
1203 (pos >> 16) & 0xff,
1204 (pos >> 8) & 0xff,
1205 (pos & 0xff),
1206 buf[pos - start],
1207 buf[pos - start + 1]
1208 };
hailfinger71e1bd42010-10-13 22:26:56 +00001209 /* Do not return an error for now. */
1210 //return SPI_GENERIC_ERROR;
hailfinger19db0922010-06-20 10:41:35 +00001211 }
1212 /* The data sheet requires total AAI write length to be even. */
1213 if (len % 2) {
1214 msg_cerr("%s: total write length not even! Please report a "
1215 "bug at flashrom@flashrom.org\n", __func__);
hailfinger71e1bd42010-10-13 22:26:56 +00001216 /* Do not return an error for now. */
1217 //return SPI_GENERIC_ERROR;
hailfinger19db0922010-06-20 10:41:35 +00001218 }
1219
hailfinger19db0922010-06-20 10:41:35 +00001220
1221 result = spi_send_multicommand(cmds);
1222 if (result) {
1223 msg_cerr("%s failed during start command execution\n",
1224 __func__);
hailfingerc7d06c62010-07-14 16:19:05 +00001225 /* FIXME: Should we send WRDI here as well to make sure the chip
1226 * is not in AAI mode?
1227 */
snelson8913d082010-02-26 05:48:29 +00001228 return result;
snelson8913d082010-02-26 05:48:29 +00001229 }
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301230 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
hailfinger19db0922010-06-20 10:41:35 +00001231 programmer_delay(10);
1232
1233 /* We already wrote 2 bytes in the multicommand step. */
1234 pos += 2;
1235
hailfinger71e1bd42010-10-13 22:26:56 +00001236 /* Are there at least two more bytes to write? */
1237 while (pos < start + len - 1) {
hailfingerdef852d2010-10-27 22:07:11 +00001238 cmd[1] = buf[pos++ - start];
1239 cmd[2] = buf[pos++ - start];
hailfinger19db0922010-06-20 10:41:35 +00001240 spi_send_command(JEDEC_AAI_WORD_PROGRAM_CONT_OUTSIZE, 0, cmd, NULL);
Ramya Vijaykumar4af3f822016-01-27 11:51:27 +05301241 while (spi_read_status_register(flash) & JEDEC_RDSR_BIT_WIP)
hailfinger19db0922010-06-20 10:41:35 +00001242 programmer_delay(10);
1243 }
1244
hailfinger71e1bd42010-10-13 22:26:56 +00001245 /* Use WRDI to exit AAI mode. This needs to be done before issuing any
1246 * other non-AAI command.
1247 */
snelson8913d082010-02-26 05:48:29 +00001248 spi_write_disable();
hailfinger71e1bd42010-10-13 22:26:56 +00001249
1250 /* Write remaining byte (if any). */
1251 if (pos < start + len) {
hailfingerdef852d2010-10-27 22:07:11 +00001252 if (spi_chip_write_1(flash, buf + pos - start, pos, pos % 2))
hailfinger71e1bd42010-10-13 22:26:56 +00001253 return SPI_GENERIC_ERROR;
1254 pos += pos % 2;
1255 }
1256
snelson8913d082010-02-26 05:48:29 +00001257 return 0;
1258}