blob: 902f073094a5cb71168c849f24d52fa404632de7 [file] [log] [blame]
Boris Baykov50a56602016-06-11 18:28:59 +02001/*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2014 Boris Baykov
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20/*
21 * SPI chip driver functions for 4-bytes addressing
22 */
23
24#include <string.h>
25#include "flash.h"
26#include "chipdrivers.h"
27#include "spi.h"
28#include "programmer.h"
29#include "spi4ba.h"
30
31/* #define MSG_TRACE_4BA_FUNCS 1 */
32
33#ifdef MSG_TRACE_4BA_FUNCS
34#define msg_trace(...) print(MSG_DEBUG, __VA_ARGS__)
35#else
36#define msg_trace(...)
37#endif
38
39/* Enter 4-bytes addressing mode (without sending WREN before) */
40int spi_enter_4ba_b7(struct flashctx *flash)
41{
Nico Huberf43c6542017-10-14 17:47:28 +020042 int result;
Boris Baykov50a56602016-06-11 18:28:59 +020043 const unsigned char cmd[JEDEC_ENTER_4_BYTE_ADDR_MODE_OUTSIZE] = { JEDEC_ENTER_4_BYTE_ADDR_MODE };
44
45 msg_trace("-> %s\n", __func__);
46
Boris Baykovb1f88362016-06-11 18:28:59 +020047 /* Switch to 4-bytes addressing mode */
Nico Huberf43c6542017-10-14 17:47:28 +020048 result = spi_send_command(flash, sizeof(cmd), 0, cmd, NULL);
49 if (!result)
50 flash->in_4ba_mode = true;
51
52 return result;
Boris Baykov50a56602016-06-11 18:28:59 +020053}
54
55/* Enter 4-bytes addressing mode with sending WREN before */
56int spi_enter_4ba_b7_we(struct flashctx *flash)
57{
58 int result;
59 struct spi_command cmds[] = {
60 {
61 .writecnt = JEDEC_WREN_OUTSIZE,
62 .writearr = (const unsigned char[]){ JEDEC_WREN },
63 .readcnt = 0,
64 .readarr = NULL,
65 }, {
66 .writecnt = JEDEC_ENTER_4_BYTE_ADDR_MODE_OUTSIZE,
67 .writearr = (const unsigned char[]){ JEDEC_ENTER_4_BYTE_ADDR_MODE },
68 .readcnt = 0,
69 .readarr = NULL,
70 }, {
71 .writecnt = 0,
72 .writearr = NULL,
73 .readcnt = 0,
74 .readarr = NULL,
75 }};
76
77 msg_trace("-> %s\n", __func__);
78
Boris Baykovb1f88362016-06-11 18:28:59 +020079 /* Switch to 4-bytes addressing mode */
Boris Baykov50a56602016-06-11 18:28:59 +020080 result = spi_send_multicommand(flash, cmds);
Boris Baykovb1f88362016-06-11 18:28:59 +020081 if (result)
Boris Baykov50a56602016-06-11 18:28:59 +020082 msg_cerr("%s failed during command execution\n", __func__);
Nico Huberf43c6542017-10-14 17:47:28 +020083 else
84 flash->in_4ba_mode = true;
Boris Baykov50a56602016-06-11 18:28:59 +020085 return result;
86}
87
Ed Swierkd94d2542017-07-03 13:02:18 -070088/* Exit 4-bytes addressing mode (without sending WREN before) */
89int spi_exit_4ba_e9(struct flashctx *flash)
90{
Nico Huberf43c6542017-10-14 17:47:28 +020091 int result;
Ed Swierkd94d2542017-07-03 13:02:18 -070092 const unsigned char cmd[JEDEC_EXIT_4_BYTE_ADDR_MODE_OUTSIZE] = { JEDEC_EXIT_4_BYTE_ADDR_MODE };
93
94 msg_trace("-> %s\n", __func__);
95
96 /* Switch to 3-bytes addressing mode */
Nico Huberf43c6542017-10-14 17:47:28 +020097 result = spi_send_command(flash, sizeof(cmd), 0, cmd, NULL);
98 if (!result)
99 flash->in_4ba_mode = false;
100
101 return result;
Ed Swierkd94d2542017-07-03 13:02:18 -0700102}
103
104/* Exit 4-bytes addressing mode with sending WREN before */
105int spi_exit_4ba_e9_we(struct flashctx *flash)
106{
107 int result;
108 struct spi_command cmds[] = {
109 {
110 .writecnt = JEDEC_WREN_OUTSIZE,
111 .writearr = (const unsigned char[]){ JEDEC_WREN },
112 .readcnt = 0,
113 .readarr = NULL,
114 }, {
115 .writecnt = JEDEC_EXIT_4_BYTE_ADDR_MODE_OUTSIZE,
116 .writearr = (const unsigned char[]){ JEDEC_EXIT_4_BYTE_ADDR_MODE },
117 .readcnt = 0,
118 .readarr = NULL,
119 }, {
120 .writecnt = 0,
121 .writearr = NULL,
122 .readcnt = 0,
123 .readarr = NULL,
124 }};
125
126 msg_trace("-> %s\n", __func__);
127
128 /* Switch to 3-bytes addressing mode */
129 result = spi_send_multicommand(flash, cmds);
Nico Huberf43c6542017-10-14 17:47:28 +0200130 if (result)
Ed Swierkd94d2542017-07-03 13:02:18 -0700131 msg_cerr("%s failed during command execution\n", __func__);
Nico Huberf43c6542017-10-14 17:47:28 +0200132 else
133 flash->in_4ba_mode = false;
Ed Swierkd94d2542017-07-03 13:02:18 -0700134 return result;
135}
136
Boris Baykov50a56602016-06-11 18:28:59 +0200137/* Program one flash byte from 4-bytes addressing mode */
Boris Baykovb1f88362016-06-11 18:28:59 +0200138int spi_byte_program_4ba(struct flashctx *flash, unsigned int addr, uint8_t databyte)
Boris Baykov50a56602016-06-11 18:28:59 +0200139{
140 int result;
141 struct spi_command cmds[] = {
142 {
143 .writecnt = JEDEC_WREN_OUTSIZE,
144 .writearr = (const unsigned char[]){ JEDEC_WREN },
145 .readcnt = 0,
146 .readarr = NULL,
147 }, {
148 .writecnt = JEDEC_BYTE_PROGRAM_OUTSIZE + 1,
149 .writearr = (const unsigned char[]){
150 JEDEC_BYTE_PROGRAM,
151 (addr >> 24) & 0xff,
152 (addr >> 16) & 0xff,
153 (addr >> 8) & 0xff,
154 (addr & 0xff),
155 databyte
156 },
157 .readcnt = 0,
158 .readarr = NULL,
159 }, {
160 .writecnt = 0,
161 .writearr = NULL,
162 .readcnt = 0,
163 .readarr = NULL,
164 }};
165
166 msg_trace("-> %s (0x%08X)\n", __func__, addr);
167
168 result = spi_send_multicommand(flash, cmds);
Boris Baykovb1f88362016-06-11 18:28:59 +0200169 if (result)
170 msg_cerr("%s failed during command execution at address 0x%x\n", __func__, addr);
Boris Baykov50a56602016-06-11 18:28:59 +0200171 return result;
172}
173
174/* Program flash bytes from 4-bytes addressing mode */
Boris Baykovb1f88362016-06-11 18:28:59 +0200175int spi_nbyte_program_4ba(struct flashctx *flash, unsigned int addr, const uint8_t *bytes, unsigned int len)
Boris Baykov50a56602016-06-11 18:28:59 +0200176{
177 int result;
178 unsigned char cmd[(JEDEC_BYTE_PROGRAM_OUTSIZE + 1) - 1 + 256] = {
179 JEDEC_BYTE_PROGRAM,
180 (addr >> 24) & 0xff,
181 (addr >> 16) & 0xff,
182 (addr >> 8) & 0xff,
183 (addr >> 0) & 0xff
184 };
185 struct spi_command cmds[] = {
186 {
187 .writecnt = JEDEC_WREN_OUTSIZE,
188 .writearr = (const unsigned char[]){ JEDEC_WREN },
189 .readcnt = 0,
190 .readarr = NULL,
191 }, {
192 .writecnt = (JEDEC_BYTE_PROGRAM_OUTSIZE + 1) - 1 + len,
193 .writearr = cmd,
194 .readcnt = 0,
195 .readarr = NULL,
196 }, {
197 .writecnt = 0,
198 .writearr = NULL,
199 .readcnt = 0,
200 .readarr = NULL,
201 }};
202
203 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + len - 1);
204
205 if (!len) {
206 msg_cerr("%s called for zero-length write\n", __func__);
207 return 1;
208 }
209 if (len > 256) {
210 msg_cerr("%s called for too long a write\n", __func__);
211 return 1;
212 }
213
214 memcpy(&cmd[(JEDEC_BYTE_PROGRAM_OUTSIZE + 1) - 1], bytes, len);
215
216 result = spi_send_multicommand(flash, cmds);
217 if (result) {
218 msg_cerr("%s failed during command execution at address 0x%x\n",
219 __func__, addr);
220 }
221 return result;
222}
223
224/* Read flash bytes from 4-bytes addressing mode */
Boris Baykovb1f88362016-06-11 18:28:59 +0200225int spi_nbyte_read_4ba(struct flashctx *flash, unsigned int addr, uint8_t *bytes, unsigned int len)
Boris Baykov50a56602016-06-11 18:28:59 +0200226{
227 const unsigned char cmd[JEDEC_READ_OUTSIZE + 1] = {
228 JEDEC_READ,
229 (addr >> 24) & 0xff,
230 (addr >> 16) & 0xff,
231 (addr >> 8) & 0xff,
232 (addr >> 0) & 0xff
233 };
234
235 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + len - 1);
236
237 /* Send Read */
238 return spi_send_command(flash, sizeof(cmd), len, cmd, bytes);
239}
240
Boris Baykovb1f88362016-06-11 18:28:59 +0200241/* Erase one sector of flash from 4-bytes addressing mode */
242int spi_block_erase_20_4ba(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
Boris Baykov50a56602016-06-11 18:28:59 +0200243{
244 int result;
245 struct spi_command cmds[] = {
246 {
247 .writecnt = JEDEC_WREN_OUTSIZE,
248 .writearr = (const unsigned char[]){ JEDEC_WREN },
249 .readcnt = 0,
250 .readarr = NULL,
251 }, {
252 .writecnt = JEDEC_SE_OUTSIZE + 1,
253 .writearr = (const unsigned char[]){
254 JEDEC_SE,
255 (addr >> 24) & 0xff,
256 (addr >> 16) & 0xff,
257 (addr >> 8) & 0xff,
258 (addr & 0xff)
259 },
260 .readcnt = 0,
261 .readarr = NULL,
262 }, {
263 .writecnt = 0,
264 .writearr = NULL,
265 .readcnt = 0,
266 .readarr = NULL,
267 }};
268
269 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
270
271 result = spi_send_multicommand(flash, cmds);
272 if (result) {
273 msg_cerr("%s failed during command execution at address 0x%x\n",
274 __func__, addr);
275 return result;
276 }
277 /* Wait until the Write-In-Progress bit is cleared.
278 * This usually takes 15-800 ms, so wait in 10 ms steps.
279 */
280 while (spi_read_status_register(flash) & SPI_SR_WIP)
281 programmer_delay(10 * 1000);
282 /* FIXME: Check the status register for errors. */
283 return 0;
284}
285
Boris Baykovb1f88362016-06-11 18:28:59 +0200286/* Erase one sector of flash from 4-bytes addressing mode */
287int spi_block_erase_52_4ba(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
Boris Baykov50a56602016-06-11 18:28:59 +0200288{
289 int result;
290 struct spi_command cmds[] = {
291 {
292 .writecnt = JEDEC_WREN_OUTSIZE,
293 .writearr = (const unsigned char[]){ JEDEC_WREN },
294 .readcnt = 0,
295 .readarr = NULL,
296 }, {
297 .writecnt = JEDEC_BE_52_OUTSIZE + 1,
298 .writearr = (const unsigned char[]){
299 JEDEC_BE_52,
300 (addr >> 24) & 0xff,
301 (addr >> 16) & 0xff,
302 (addr >> 8) & 0xff,
303 (addr & 0xff)
304 },
305 .readcnt = 0,
306 .readarr = NULL,
307 }, {
308 .writecnt = 0,
309 .writearr = NULL,
310 .readcnt = 0,
311 .readarr = NULL,
312 }};
313
314 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
315
316 result = spi_send_multicommand(flash, cmds);
317 if (result) {
318 msg_cerr("%s failed during command execution at address 0x%x\n",
319 __func__, addr);
320 return result;
321 }
322 /* Wait until the Write-In-Progress bit is cleared.
323 * This usually takes 100-4000 ms, so wait in 100 ms steps.
324 */
325 while (spi_read_status_register(flash) & SPI_SR_WIP)
326 programmer_delay(100 * 1000);
327 /* FIXME: Check the status register for errors. */
328 return 0;
329}
330
Boris Baykovb1f88362016-06-11 18:28:59 +0200331/* Erase one sector of flash from 4-bytes addressing mode */
Boris Baykov50a56602016-06-11 18:28:59 +0200332int spi_block_erase_d8_4ba(struct flashctx *flash, unsigned int addr,
333 unsigned int blocklen)
334{
335 int result;
336 struct spi_command cmds[] = {
337 {
338 .writecnt = JEDEC_WREN_OUTSIZE,
339 .writearr = (const unsigned char[]){ JEDEC_WREN },
340 .readcnt = 0,
341 .readarr = NULL,
342 }, {
343 .writecnt = JEDEC_BE_D8_OUTSIZE + 1,
344 .writearr = (const unsigned char[]){
345 JEDEC_BE_D8,
346 (addr >> 24) & 0xff,
347 (addr >> 16) & 0xff,
348 (addr >> 8) & 0xff,
349 (addr & 0xff)
350 },
351 .readcnt = 0,
352 .readarr = NULL,
353 }, {
354 .writecnt = 0,
355 .writearr = NULL,
356 .readcnt = 0,
357 .readarr = NULL,
358 }};
359
360 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
361
362 result = spi_send_multicommand(flash, cmds);
363 if (result) {
364 msg_cerr("%s failed during command execution at address 0x%x\n",
365 __func__, addr);
366 return result;
367 }
368 /* Wait until the Write-In-Progress bit is cleared.
369 * This usually takes 100-4000 ms, so wait in 100 ms steps.
370 */
371 while (spi_read_status_register(flash) & SPI_SR_WIP)
372 programmer_delay(100 * 1000);
373 /* FIXME: Check the status register for errors. */
374 return 0;
375}
Boris Baykov5de3b9b2016-06-11 18:29:02 +0200376
377/* Write Extended Address Register value */
378int spi_write_extended_address_register(struct flashctx *flash, uint8_t regdata)
379{
380 int result;
381 struct spi_command cmds[] = {
382 {
383 .writecnt = JEDEC_WREN_OUTSIZE,
384 .writearr = (const unsigned char[]){ JEDEC_WREN },
385 .readcnt = 0,
386 .readarr = NULL,
387 }, {
388 .writecnt = JEDEC_WRITE_EXT_ADDR_REG_OUTSIZE,
389 .writearr = (const unsigned char[]){
390 JEDEC_WRITE_EXT_ADDR_REG,
391 regdata
392 },
393 .readcnt = 0,
394 .readarr = NULL,
395 }, {
396 .writecnt = 0,
397 .writearr = NULL,
398 .readcnt = 0,
399 .readarr = NULL,
400 }};
401
402 msg_trace("-> %s (%02X)\n", __func__, regdata);
403
404 result = spi_send_multicommand(flash, cmds);
405 if (result) {
406 msg_cerr("%s failed during command execution\n", __func__);
407 return result;
408 }
409 return 0;
410}
411
412/* Assign required value of Extended Address Register. This function
413 keeps last value of the register and writes the register if the
414 value has to be changed only. */
415int set_extended_address_register(struct flashctx *flash, uint8_t data)
416{
417 static uint8_t ext_addr_reg_state; /* memory for last register state */
418 static int ext_addr_reg_state_valid = 0;
419 int result;
420
421 if (ext_addr_reg_state_valid == 0 || data != ext_addr_reg_state) {
422 result = spi_write_extended_address_register(flash, data);
423 if (result) {
424 ext_addr_reg_state_valid = 0;
425 return result;
426 }
427 ext_addr_reg_state = data;
428 ext_addr_reg_state_valid = 1;
429 }
430 return 0;
431}
432
433/* Program one flash byte using Extended Address Register
434 from 3-bytes addressing mode */
435int spi_byte_program_4ba_ereg(struct flashctx *flash, unsigned int addr,
436 uint8_t databyte)
437{
438 int result;
439 struct spi_command cmds[] = {
440 {
441 .writecnt = JEDEC_WREN_OUTSIZE,
442 .writearr = (const unsigned char[]){ JEDEC_WREN },
443 .readcnt = 0,
444 .readarr = NULL,
445 }, {
446 .writecnt = JEDEC_BYTE_PROGRAM_OUTSIZE,
447 .writearr = (const unsigned char[]){
448 JEDEC_BYTE_PROGRAM,
449 (addr >> 16) & 0xff,
450 (addr >> 8) & 0xff,
451 (addr & 0xff),
452 databyte
453 },
454 .readcnt = 0,
455 .readarr = NULL,
456 }, {
457 .writecnt = 0,
458 .writearr = NULL,
459 .readcnt = 0,
460 .readarr = NULL,
461 }};
462
463 msg_trace("-> %s (0x%08X)\n", __func__, addr);
464
465 result = set_extended_address_register(flash, (addr >> 24) & 0xff);
466 if (result)
467 return result;
468
469 result = spi_send_multicommand(flash, cmds);
470 if (result) {
471 msg_cerr("%s failed during command execution at address 0x%x\n",
472 __func__, addr);
473 }
474 return result;
475}
476
477/* Program flash bytes using Extended Address Register
478 from 3-bytes addressing mode */
479int spi_nbyte_program_4ba_ereg(struct flashctx *flash, unsigned int addr,
480 const uint8_t *bytes, unsigned int len)
481{
482 int result;
483 unsigned char cmd[JEDEC_BYTE_PROGRAM_OUTSIZE - 1 + 256] = {
484 JEDEC_BYTE_PROGRAM,
485 (addr >> 16) & 0xff,
486 (addr >> 8) & 0xff,
487 (addr >> 0) & 0xff
488 };
489 struct spi_command cmds[] = {
490 {
491 .writecnt = JEDEC_WREN_OUTSIZE,
492 .writearr = (const unsigned char[]){ JEDEC_WREN },
493 .readcnt = 0,
494 .readarr = NULL,
495 }, {
496 .writecnt = JEDEC_BYTE_PROGRAM_OUTSIZE - 1 + len,
497 .writearr = cmd,
498 .readcnt = 0,
499 .readarr = NULL,
500 }, {
501 .writecnt = 0,
502 .writearr = NULL,
503 .readcnt = 0,
504 .readarr = NULL,
505 }};
506
507 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + len - 1);
508
509 if (!len) {
510 msg_cerr("%s called for zero-length write\n", __func__);
511 return 1;
512 }
513 if (len > 256) {
514 msg_cerr("%s called for too long a write\n", __func__);
515 return 1;
516 }
517
518 memcpy(&cmd[JEDEC_BYTE_PROGRAM_OUTSIZE - 1], bytes, len);
519
520 result = set_extended_address_register(flash, (addr >> 24) & 0xff);
521 if (result)
522 return result;
523
524 result = spi_send_multicommand(flash, cmds);
525 if (result) {
526 msg_cerr("%s failed during command execution at address 0x%x\n",
527 __func__, addr);
528 }
529 return result;
530}
531
532/* Read flash bytes using Extended Address Register
533 from 3-bytes addressing mode */
534int spi_nbyte_read_4ba_ereg(struct flashctx *flash, unsigned int addr,
535 uint8_t *bytes, unsigned int len)
536{
537 int result;
538 const unsigned char cmd[JEDEC_READ_OUTSIZE] = {
539 JEDEC_READ,
540 (addr >> 16) & 0xff,
541 (addr >> 8) & 0xff,
542 (addr >> 0) & 0xff
543 };
544
545 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + len - 1);
546
547 result = set_extended_address_register(flash, (addr >> 24) & 0xff);
548 if (result)
549 return result;
550
551 /* Send Read */
552 return spi_send_command(flash, sizeof(cmd), len, cmd, bytes);
553}
554
555/* Erases 4 KB of flash using Extended Address Register
556 from 3-bytes addressing mode */
557int spi_block_erase_20_4ba_ereg(struct flashctx *flash, unsigned int addr,
558 unsigned int blocklen)
559{
560 int result;
561 struct spi_command cmds[] = {
562 {
563 .writecnt = JEDEC_WREN_OUTSIZE,
564 .writearr = (const unsigned char[]){ JEDEC_WREN },
565 .readcnt = 0,
566 .readarr = NULL,
567 }, {
568 .writecnt = JEDEC_SE_OUTSIZE,
569 .writearr = (const unsigned char[]){
570 JEDEC_SE,
571 (addr >> 16) & 0xff,
572 (addr >> 8) & 0xff,
573 (addr & 0xff)
574 },
575 .readcnt = 0,
576 .readarr = NULL,
577 }, {
578 .writecnt = 0,
579 .writearr = NULL,
580 .readcnt = 0,
581 .readarr = NULL,
582 }};
583
584 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
585
586 result = set_extended_address_register(flash, (addr >> 24) & 0xff);
587 if (result)
588 return result;
589
590 result = spi_send_multicommand(flash, cmds);
591 if (result) {
592 msg_cerr("%s failed during command execution at address 0x%x\n",
593 __func__, addr);
594 return result;
595 }
596 /* Wait until the Write-In-Progress bit is cleared.
597 * This usually takes 15-800 ms, so wait in 10 ms steps.
598 */
599 while (spi_read_status_register(flash) & SPI_SR_WIP)
600 programmer_delay(10 * 1000);
601 /* FIXME: Check the status register for errors. */
602 return 0;
603}
604
605/* Erases 32 KB of flash using Extended Address Register
606 from 3-bytes addressing mode */
607int spi_block_erase_52_4ba_ereg(struct flashctx *flash, unsigned int addr,
608 unsigned int blocklen)
609{
610 int result;
611 struct spi_command cmds[] = {
612 {
613 .writecnt = JEDEC_WREN_OUTSIZE,
614 .writearr = (const unsigned char[]){ JEDEC_WREN },
615 .readcnt = 0,
616 .readarr = NULL,
617 }, {
618 .writecnt = JEDEC_BE_52_OUTSIZE,
619 .writearr = (const unsigned char[]){
620 JEDEC_BE_52,
621 (addr >> 16) & 0xff,
622 (addr >> 8) & 0xff,
623 (addr & 0xff)
624 },
625 .readcnt = 0,
626 .readarr = NULL,
627 }, {
628 .writecnt = 0,
629 .writearr = NULL,
630 .readcnt = 0,
631 .readarr = NULL,
632 }};
633
634 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
635
636 result = set_extended_address_register(flash, (addr >> 24) & 0xff);
637 if (result)
638 return result;
639
640 result = spi_send_multicommand(flash, cmds);
641 if (result) {
642 msg_cerr("%s failed during command execution at address 0x%x\n",
643 __func__, addr);
644 return result;
645 }
646 /* Wait until the Write-In-Progress bit is cleared.
647 * This usually takes 100-4000 ms, so wait in 100 ms steps.
648 */
649 while (spi_read_status_register(flash) & SPI_SR_WIP)
650 programmer_delay(100 * 1000);
651 /* FIXME: Check the status register for errors. */
652 return 0;
653}
654
655/* Erases 64 KB of flash using Extended Address Register
656 from 3-bytes addressing mode */
657int spi_block_erase_d8_4ba_ereg(struct flashctx *flash, unsigned int addr,
658 unsigned int blocklen)
659{
660 int result;
661 struct spi_command cmds[] = {
662 {
663 .writecnt = JEDEC_WREN_OUTSIZE,
664 .writearr = (const unsigned char[]){ JEDEC_WREN },
665 .readcnt = 0,
666 .readarr = NULL,
667 }, {
668 .writecnt = JEDEC_BE_D8_OUTSIZE,
669 .writearr = (const unsigned char[]){
670 JEDEC_BE_D8,
671 (addr >> 16) & 0xff,
672 (addr >> 8) & 0xff,
673 (addr & 0xff)
674 },
675 .readcnt = 0,
676 .readarr = NULL,
677 }, {
678 .writecnt = 0,
679 .writearr = NULL,
680 .readcnt = 0,
681 .readarr = NULL,
682 }};
683
684 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
685
686 result = set_extended_address_register(flash, (addr >> 24) & 0xff);
687 if (result)
688 return result;
689
690 result = spi_send_multicommand(flash, cmds);
691 if (result) {
692 msg_cerr("%s failed during command execution at address 0x%x\n",
693 __func__, addr);
694 return result;
695 }
696 /* Wait until the Write-In-Progress bit is cleared.
697 * This usually takes 100-4000 ms, so wait in 100 ms steps.
698 */
699 while (spi_read_status_register(flash) & SPI_SR_WIP)
700 programmer_delay(100 * 1000);
701 /* FIXME: Check the status register for errors. */
702 return 0;
703}
Boris Baykov7fe85692016-06-11 18:29:03 +0200704
705/* Program one flash byte with 4-bytes address from ANY mode (3-bytes or 4-bytes)
706 JEDEC_BYTE_PROGRAM_4BA (12h) instruction is new for 4-bytes addressing flash chips.
707 The presence of this instruction for an exact chip should be checked
708 by its datasheet or from SFDP 4-Bytes Address Instruction Table (JESD216B). */
709int spi_byte_program_4ba_direct(struct flashctx *flash, unsigned int addr,
710 uint8_t databyte)
711{
712 int result;
713 struct spi_command cmds[] = {
714 {
715 .writecnt = JEDEC_WREN_OUTSIZE,
716 .writearr = (const unsigned char[]){ JEDEC_WREN },
717 .readcnt = 0,
718 .readarr = NULL,
719 }, {
720 .writecnt = JEDEC_BYTE_PROGRAM_4BA_OUTSIZE,
721 .writearr = (const unsigned char[]){
722 JEDEC_BYTE_PROGRAM_4BA,
723 (addr >> 24) & 0xff,
724 (addr >> 16) & 0xff,
725 (addr >> 8) & 0xff,
726 (addr & 0xff),
727 databyte
728 },
729 .readcnt = 0,
730 .readarr = NULL,
731 }, {
732 .writecnt = 0,
733 .writearr = NULL,
734 .readcnt = 0,
735 .readarr = NULL,
736 }};
737
738 msg_trace("-> %s (0x%08X)\n", __func__, addr);
739
740 result = spi_send_multicommand(flash, cmds);
741 if (result) {
742 msg_cerr("%s failed during command execution at address 0x%x\n",
743 __func__, addr);
744 }
745 return result;
746}
747
748/* Program flash bytes with 4-bytes address from ANY mode (3-bytes or 4-bytes)
749 JEDEC_BYTE_PROGRAM_4BA (12h) instruction is new for 4-bytes addressing flash chips.
750 The presence of this instruction for an exact chip should be checked
751 by its datasheet or from SFDP 4-Bytes Address Instruction Table (JESD216B). */
752int spi_nbyte_program_4ba_direct(struct flashctx *flash, unsigned int addr,
753 const uint8_t *bytes, unsigned int len)
754{
755 int result;
756 unsigned char cmd[JEDEC_BYTE_PROGRAM_4BA_OUTSIZE - 1 + 256] = {
757 JEDEC_BYTE_PROGRAM_4BA,
758 (addr >> 24) & 0xff,
759 (addr >> 16) & 0xff,
760 (addr >> 8) & 0xff,
761 (addr >> 0) & 0xff
762 };
763 struct spi_command cmds[] = {
764 {
765 .writecnt = JEDEC_WREN_OUTSIZE,
766 .writearr = (const unsigned char[]){ JEDEC_WREN },
767 .readcnt = 0,
768 .readarr = NULL,
769 }, {
770 .writecnt = JEDEC_BYTE_PROGRAM_4BA_OUTSIZE - 1 + len,
771 .writearr = cmd,
772 .readcnt = 0,
773 .readarr = NULL,
774 }, {
775 .writecnt = 0,
776 .writearr = NULL,
777 .readcnt = 0,
778 .readarr = NULL,
779 }};
780
781 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + len - 1);
782
783 if (!len) {
784 msg_cerr("%s called for zero-length write\n", __func__);
785 return 1;
786 }
787 if (len > 256) {
788 msg_cerr("%s called for too long a write\n", __func__);
789 return 1;
790 }
791
792 memcpy(&cmd[JEDEC_BYTE_PROGRAM_4BA_OUTSIZE - 1], bytes, len);
793
794 result = spi_send_multicommand(flash, cmds);
795 if (result) {
796 msg_cerr("%s failed during command execution at address 0x%x\n",
797 __func__, addr);
798 }
799 return result;
800}
801
802/* Read flash bytes with 4-bytes address from ANY mode (3-bytes or 4-bytes)
803 JEDEC_READ_4BA (13h) instruction is new for 4-bytes addressing flash chips.
804 The presence of this instruction for an exact chip should be checked
805 by its datasheet or from SFDP 4-Bytes Address Instruction Table (JESD216B). */
806int spi_nbyte_read_4ba_direct(struct flashctx *flash, unsigned int addr,
807 uint8_t *bytes, unsigned int len)
808{
809 const unsigned char cmd[JEDEC_READ_4BA_OUTSIZE] = {
810 JEDEC_READ_4BA,
811 (addr >> 24) & 0xff,
812 (addr >> 16) & 0xff,
813 (addr >> 8) & 0xff,
814 (addr >> 0) & 0xff
815 };
816
817 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + len - 1);
818
819 /* Send Read */
820 return spi_send_command(flash, sizeof(cmd), len, cmd, bytes);
821}
822
823/* Erase 4 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes)
824 JEDEC_SE_4BA (21h) instruction is new for 4-bytes addressing flash chips.
825 The presence of this instruction for an exact chip should be checked
826 by its datasheet or from SFDP 4-Bytes Address Instruction Table (JESD216B). */
827int spi_block_erase_21_4ba_direct(struct flashctx *flash, unsigned int addr,
828 unsigned int blocklen)
829{
830 int result;
831 struct spi_command cmds[] = {
832 {
833 .writecnt = JEDEC_WREN_OUTSIZE,
834 .writearr = (const unsigned char[]){ JEDEC_WREN },
835 .readcnt = 0,
836 .readarr = NULL,
837 }, {
838 .writecnt = JEDEC_SE_4BA_OUTSIZE,
839 .writearr = (const unsigned char[]){
840 JEDEC_SE_4BA,
841 (addr >> 24) & 0xff,
842 (addr >> 16) & 0xff,
843 (addr >> 8) & 0xff,
844 (addr & 0xff)
845 },
846 .readcnt = 0,
847 .readarr = NULL,
848 }, {
849 .writecnt = 0,
850 .writearr = NULL,
851 .readcnt = 0,
852 .readarr = NULL,
853 }};
854
855 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
856
857 result = spi_send_multicommand(flash, cmds);
858 if (result) {
859 msg_cerr("%s failed during command execution at address 0x%x\n",
860 __func__, addr);
861 return result;
862 }
863 /* Wait until the Write-In-Progress bit is cleared.
864 * This usually takes 15-800 ms, so wait in 10 ms steps.
865 */
866 while (spi_read_status_register(flash) & SPI_SR_WIP)
867 programmer_delay(10 * 1000);
868 /* FIXME: Check the status register for errors. */
869 return 0;
870}
871
872/* Erase 32 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes)
873 JEDEC_BE_5C_4BA (5Ch) instruction is new for 4-bytes addressing flash chips.
874 The presence of this instruction for an exact chip should be checked
875 by its datasheet or from SFDP 4-Bytes Address Instruction Table (JESD216B). */
876int spi_block_erase_5c_4ba_direct(struct flashctx *flash, unsigned int addr,
877 unsigned int blocklen)
878{
879 int result;
880 struct spi_command cmds[] = {
881 {
882 .writecnt = JEDEC_WREN_OUTSIZE,
883 .writearr = (const unsigned char[]){ JEDEC_WREN },
884 .readcnt = 0,
885 .readarr = NULL,
886 }, {
887 .writecnt = JEDEC_BE_5C_4BA_OUTSIZE,
888 .writearr = (const unsigned char[]){
889 JEDEC_BE_5C_4BA,
890 (addr >> 24) & 0xff,
891 (addr >> 16) & 0xff,
892 (addr >> 8) & 0xff,
893 (addr & 0xff)
894 },
895 .readcnt = 0,
896 .readarr = NULL,
897 }, {
898 .writecnt = 0,
899 .writearr = NULL,
900 .readcnt = 0,
901 .readarr = NULL,
902 }};
903
904 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
905
906 result = spi_send_multicommand(flash, cmds);
907 if (result) {
908 msg_cerr("%s failed during command execution at address 0x%x\n",
909 __func__, addr);
910 return result;
911 }
912 /* Wait until the Write-In-Progress bit is cleared.
913 * This usually takes 100-4000 ms, so wait in 100 ms steps.
914 */
915 while (spi_read_status_register(flash) & SPI_SR_WIP)
916 programmer_delay(100 * 1000);
917 /* FIXME: Check the status register for errors. */
918 return 0;
919}
920
921/* Erase 64 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes)
922 JEDEC_BE_DC_4BA (DCh) instruction is new for 4-bytes addressing flash chips.
923 The presence of this instruction for an exact chip should be checked
924 by its datasheet or from SFDP 4-Bytes Address Instruction Table (JESD216B). */
925int spi_block_erase_dc_4ba_direct(struct flashctx *flash, unsigned int addr,
926 unsigned int blocklen)
927{
928 int result;
929 struct spi_command cmds[] = {
930 {
931 .writecnt = JEDEC_WREN_OUTSIZE,
932 .writearr = (const unsigned char[]){ JEDEC_WREN },
933 .readcnt = 0,
934 .readarr = NULL,
935 }, {
936 .writecnt = JEDEC_BE_DC_4BA_OUTSIZE,
937 .writearr = (const unsigned char[]){
938 JEDEC_BE_DC_4BA,
939 (addr >> 24) & 0xff,
940 (addr >> 16) & 0xff,
941 (addr >> 8) & 0xff,
942 (addr & 0xff)
943 },
944 .readcnt = 0,
945 .readarr = NULL,
946 }, {
947 .writecnt = 0,
948 .writearr = NULL,
949 .readcnt = 0,
950 .readarr = NULL,
951 }};
952
953 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
954
955 result = spi_send_multicommand(flash, cmds);
956 if (result) {
957 msg_cerr("%s failed during command execution at address 0x%x\n",
958 __func__, addr);
959 return result;
960 }
961 /* Wait until the Write-In-Progress bit is cleared.
962 * This usually takes 100-4000 ms, so wait in 100 ms steps.
963 */
964 while (spi_read_status_register(flash) & SPI_SR_WIP)
965 programmer_delay(100 * 1000);
966 /* FIXME: Check the status register for errors. */
967 return 0;
968}