blob: 93f19c499275e38e9ab11b93810c655752045409 [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{
42 const unsigned char cmd[JEDEC_ENTER_4_BYTE_ADDR_MODE_OUTSIZE] = { JEDEC_ENTER_4_BYTE_ADDR_MODE };
43
44 msg_trace("-> %s\n", __func__);
45
Boris Baykovb1f88362016-06-11 18:28:59 +020046 /* Switch to 4-bytes addressing mode */
Boris Baykov50a56602016-06-11 18:28:59 +020047 return spi_send_command(flash, sizeof(cmd), 0, cmd, NULL);
48}
49
50/* Enter 4-bytes addressing mode with sending WREN before */
51int spi_enter_4ba_b7_we(struct flashctx *flash)
52{
53 int result;
54 struct spi_command cmds[] = {
55 {
56 .writecnt = JEDEC_WREN_OUTSIZE,
57 .writearr = (const unsigned char[]){ JEDEC_WREN },
58 .readcnt = 0,
59 .readarr = NULL,
60 }, {
61 .writecnt = JEDEC_ENTER_4_BYTE_ADDR_MODE_OUTSIZE,
62 .writearr = (const unsigned char[]){ JEDEC_ENTER_4_BYTE_ADDR_MODE },
63 .readcnt = 0,
64 .readarr = NULL,
65 }, {
66 .writecnt = 0,
67 .writearr = NULL,
68 .readcnt = 0,
69 .readarr = NULL,
70 }};
71
72 msg_trace("-> %s\n", __func__);
73
Boris Baykovb1f88362016-06-11 18:28:59 +020074 /* Switch to 4-bytes addressing mode */
Boris Baykov50a56602016-06-11 18:28:59 +020075 result = spi_send_multicommand(flash, cmds);
Boris Baykovb1f88362016-06-11 18:28:59 +020076 if (result)
Boris Baykov50a56602016-06-11 18:28:59 +020077 msg_cerr("%s failed during command execution\n", __func__);
Boris Baykov50a56602016-06-11 18:28:59 +020078 return result;
79}
80
81/* Program one flash byte from 4-bytes addressing mode */
Boris Baykovb1f88362016-06-11 18:28:59 +020082int spi_byte_program_4ba(struct flashctx *flash, unsigned int addr, uint8_t databyte)
Boris Baykov50a56602016-06-11 18:28:59 +020083{
84 int result;
85 struct spi_command cmds[] = {
86 {
87 .writecnt = JEDEC_WREN_OUTSIZE,
88 .writearr = (const unsigned char[]){ JEDEC_WREN },
89 .readcnt = 0,
90 .readarr = NULL,
91 }, {
92 .writecnt = JEDEC_BYTE_PROGRAM_OUTSIZE + 1,
93 .writearr = (const unsigned char[]){
94 JEDEC_BYTE_PROGRAM,
95 (addr >> 24) & 0xff,
96 (addr >> 16) & 0xff,
97 (addr >> 8) & 0xff,
98 (addr & 0xff),
99 databyte
100 },
101 .readcnt = 0,
102 .readarr = NULL,
103 }, {
104 .writecnt = 0,
105 .writearr = NULL,
106 .readcnt = 0,
107 .readarr = NULL,
108 }};
109
110 msg_trace("-> %s (0x%08X)\n", __func__, addr);
111
112 result = spi_send_multicommand(flash, cmds);
Boris Baykovb1f88362016-06-11 18:28:59 +0200113 if (result)
114 msg_cerr("%s failed during command execution at address 0x%x\n", __func__, addr);
Boris Baykov50a56602016-06-11 18:28:59 +0200115 return result;
116}
117
118/* Program flash bytes from 4-bytes addressing mode */
Boris Baykovb1f88362016-06-11 18:28:59 +0200119int spi_nbyte_program_4ba(struct flashctx *flash, unsigned int addr, const uint8_t *bytes, unsigned int len)
Boris Baykov50a56602016-06-11 18:28:59 +0200120{
121 int result;
122 unsigned char cmd[(JEDEC_BYTE_PROGRAM_OUTSIZE + 1) - 1 + 256] = {
123 JEDEC_BYTE_PROGRAM,
124 (addr >> 24) & 0xff,
125 (addr >> 16) & 0xff,
126 (addr >> 8) & 0xff,
127 (addr >> 0) & 0xff
128 };
129 struct spi_command cmds[] = {
130 {
131 .writecnt = JEDEC_WREN_OUTSIZE,
132 .writearr = (const unsigned char[]){ JEDEC_WREN },
133 .readcnt = 0,
134 .readarr = NULL,
135 }, {
136 .writecnt = (JEDEC_BYTE_PROGRAM_OUTSIZE + 1) - 1 + len,
137 .writearr = cmd,
138 .readcnt = 0,
139 .readarr = NULL,
140 }, {
141 .writecnt = 0,
142 .writearr = NULL,
143 .readcnt = 0,
144 .readarr = NULL,
145 }};
146
147 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + len - 1);
148
149 if (!len) {
150 msg_cerr("%s called for zero-length write\n", __func__);
151 return 1;
152 }
153 if (len > 256) {
154 msg_cerr("%s called for too long a write\n", __func__);
155 return 1;
156 }
157
158 memcpy(&cmd[(JEDEC_BYTE_PROGRAM_OUTSIZE + 1) - 1], bytes, len);
159
160 result = spi_send_multicommand(flash, cmds);
161 if (result) {
162 msg_cerr("%s failed during command execution at address 0x%x\n",
163 __func__, addr);
164 }
165 return result;
166}
167
168/* Read flash bytes from 4-bytes addressing mode */
Boris Baykovb1f88362016-06-11 18:28:59 +0200169int spi_nbyte_read_4ba(struct flashctx *flash, unsigned int addr, uint8_t *bytes, unsigned int len)
Boris Baykov50a56602016-06-11 18:28:59 +0200170{
171 const unsigned char cmd[JEDEC_READ_OUTSIZE + 1] = {
172 JEDEC_READ,
173 (addr >> 24) & 0xff,
174 (addr >> 16) & 0xff,
175 (addr >> 8) & 0xff,
176 (addr >> 0) & 0xff
177 };
178
179 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + len - 1);
180
181 /* Send Read */
182 return spi_send_command(flash, sizeof(cmd), len, cmd, bytes);
183}
184
Boris Baykovb1f88362016-06-11 18:28:59 +0200185/* Erase one sector of flash from 4-bytes addressing mode */
186int spi_block_erase_20_4ba(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
Boris Baykov50a56602016-06-11 18:28:59 +0200187{
188 int result;
189 struct spi_command cmds[] = {
190 {
191 .writecnt = JEDEC_WREN_OUTSIZE,
192 .writearr = (const unsigned char[]){ JEDEC_WREN },
193 .readcnt = 0,
194 .readarr = NULL,
195 }, {
196 .writecnt = JEDEC_SE_OUTSIZE + 1,
197 .writearr = (const unsigned char[]){
198 JEDEC_SE,
199 (addr >> 24) & 0xff,
200 (addr >> 16) & 0xff,
201 (addr >> 8) & 0xff,
202 (addr & 0xff)
203 },
204 .readcnt = 0,
205 .readarr = NULL,
206 }, {
207 .writecnt = 0,
208 .writearr = NULL,
209 .readcnt = 0,
210 .readarr = NULL,
211 }};
212
213 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
214
215 result = spi_send_multicommand(flash, cmds);
216 if (result) {
217 msg_cerr("%s failed during command execution at address 0x%x\n",
218 __func__, addr);
219 return result;
220 }
221 /* Wait until the Write-In-Progress bit is cleared.
222 * This usually takes 15-800 ms, so wait in 10 ms steps.
223 */
224 while (spi_read_status_register(flash) & SPI_SR_WIP)
225 programmer_delay(10 * 1000);
226 /* FIXME: Check the status register for errors. */
227 return 0;
228}
229
Boris Baykovb1f88362016-06-11 18:28:59 +0200230/* Erase one sector of flash from 4-bytes addressing mode */
231int spi_block_erase_52_4ba(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
Boris Baykov50a56602016-06-11 18:28:59 +0200232{
233 int result;
234 struct spi_command cmds[] = {
235 {
236 .writecnt = JEDEC_WREN_OUTSIZE,
237 .writearr = (const unsigned char[]){ JEDEC_WREN },
238 .readcnt = 0,
239 .readarr = NULL,
240 }, {
241 .writecnt = JEDEC_BE_52_OUTSIZE + 1,
242 .writearr = (const unsigned char[]){
243 JEDEC_BE_52,
244 (addr >> 24) & 0xff,
245 (addr >> 16) & 0xff,
246 (addr >> 8) & 0xff,
247 (addr & 0xff)
248 },
249 .readcnt = 0,
250 .readarr = NULL,
251 }, {
252 .writecnt = 0,
253 .writearr = NULL,
254 .readcnt = 0,
255 .readarr = NULL,
256 }};
257
258 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
259
260 result = spi_send_multicommand(flash, cmds);
261 if (result) {
262 msg_cerr("%s failed during command execution at address 0x%x\n",
263 __func__, addr);
264 return result;
265 }
266 /* Wait until the Write-In-Progress bit is cleared.
267 * This usually takes 100-4000 ms, so wait in 100 ms steps.
268 */
269 while (spi_read_status_register(flash) & SPI_SR_WIP)
270 programmer_delay(100 * 1000);
271 /* FIXME: Check the status register for errors. */
272 return 0;
273}
274
Boris Baykovb1f88362016-06-11 18:28:59 +0200275/* Erase one sector of flash from 4-bytes addressing mode */
Boris Baykov50a56602016-06-11 18:28:59 +0200276int spi_block_erase_d8_4ba(struct flashctx *flash, unsigned int addr,
277 unsigned int blocklen)
278{
279 int result;
280 struct spi_command cmds[] = {
281 {
282 .writecnt = JEDEC_WREN_OUTSIZE,
283 .writearr = (const unsigned char[]){ JEDEC_WREN },
284 .readcnt = 0,
285 .readarr = NULL,
286 }, {
287 .writecnt = JEDEC_BE_D8_OUTSIZE + 1,
288 .writearr = (const unsigned char[]){
289 JEDEC_BE_D8,
290 (addr >> 24) & 0xff,
291 (addr >> 16) & 0xff,
292 (addr >> 8) & 0xff,
293 (addr & 0xff)
294 },
295 .readcnt = 0,
296 .readarr = NULL,
297 }, {
298 .writecnt = 0,
299 .writearr = NULL,
300 .readcnt = 0,
301 .readarr = NULL,
302 }};
303
304 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
305
306 result = spi_send_multicommand(flash, cmds);
307 if (result) {
308 msg_cerr("%s failed during command execution at address 0x%x\n",
309 __func__, addr);
310 return result;
311 }
312 /* Wait until the Write-In-Progress bit is cleared.
313 * This usually takes 100-4000 ms, so wait in 100 ms steps.
314 */
315 while (spi_read_status_register(flash) & SPI_SR_WIP)
316 programmer_delay(100 * 1000);
317 /* FIXME: Check the status register for errors. */
318 return 0;
319}
Boris Baykov5de3b9b2016-06-11 18:29:02 +0200320
321/* Write Extended Address Register value */
322int spi_write_extended_address_register(struct flashctx *flash, uint8_t regdata)
323{
324 int result;
325 struct spi_command cmds[] = {
326 {
327 .writecnt = JEDEC_WREN_OUTSIZE,
328 .writearr = (const unsigned char[]){ JEDEC_WREN },
329 .readcnt = 0,
330 .readarr = NULL,
331 }, {
332 .writecnt = JEDEC_WRITE_EXT_ADDR_REG_OUTSIZE,
333 .writearr = (const unsigned char[]){
334 JEDEC_WRITE_EXT_ADDR_REG,
335 regdata
336 },
337 .readcnt = 0,
338 .readarr = NULL,
339 }, {
340 .writecnt = 0,
341 .writearr = NULL,
342 .readcnt = 0,
343 .readarr = NULL,
344 }};
345
346 msg_trace("-> %s (%02X)\n", __func__, regdata);
347
348 result = spi_send_multicommand(flash, cmds);
349 if (result) {
350 msg_cerr("%s failed during command execution\n", __func__);
351 return result;
352 }
353 return 0;
354}
355
356/* Assign required value of Extended Address Register. This function
357 keeps last value of the register and writes the register if the
358 value has to be changed only. */
359int set_extended_address_register(struct flashctx *flash, uint8_t data)
360{
361 static uint8_t ext_addr_reg_state; /* memory for last register state */
362 static int ext_addr_reg_state_valid = 0;
363 int result;
364
365 if (ext_addr_reg_state_valid == 0 || data != ext_addr_reg_state) {
366 result = spi_write_extended_address_register(flash, data);
367 if (result) {
368 ext_addr_reg_state_valid = 0;
369 return result;
370 }
371 ext_addr_reg_state = data;
372 ext_addr_reg_state_valid = 1;
373 }
374 return 0;
375}
376
377/* Program one flash byte using Extended Address Register
378 from 3-bytes addressing mode */
379int spi_byte_program_4ba_ereg(struct flashctx *flash, unsigned int addr,
380 uint8_t databyte)
381{
382 int result;
383 struct spi_command cmds[] = {
384 {
385 .writecnt = JEDEC_WREN_OUTSIZE,
386 .writearr = (const unsigned char[]){ JEDEC_WREN },
387 .readcnt = 0,
388 .readarr = NULL,
389 }, {
390 .writecnt = JEDEC_BYTE_PROGRAM_OUTSIZE,
391 .writearr = (const unsigned char[]){
392 JEDEC_BYTE_PROGRAM,
393 (addr >> 16) & 0xff,
394 (addr >> 8) & 0xff,
395 (addr & 0xff),
396 databyte
397 },
398 .readcnt = 0,
399 .readarr = NULL,
400 }, {
401 .writecnt = 0,
402 .writearr = NULL,
403 .readcnt = 0,
404 .readarr = NULL,
405 }};
406
407 msg_trace("-> %s (0x%08X)\n", __func__, addr);
408
409 result = set_extended_address_register(flash, (addr >> 24) & 0xff);
410 if (result)
411 return result;
412
413 result = spi_send_multicommand(flash, cmds);
414 if (result) {
415 msg_cerr("%s failed during command execution at address 0x%x\n",
416 __func__, addr);
417 }
418 return result;
419}
420
421/* Program flash bytes using Extended Address Register
422 from 3-bytes addressing mode */
423int spi_nbyte_program_4ba_ereg(struct flashctx *flash, unsigned int addr,
424 const uint8_t *bytes, unsigned int len)
425{
426 int result;
427 unsigned char cmd[JEDEC_BYTE_PROGRAM_OUTSIZE - 1 + 256] = {
428 JEDEC_BYTE_PROGRAM,
429 (addr >> 16) & 0xff,
430 (addr >> 8) & 0xff,
431 (addr >> 0) & 0xff
432 };
433 struct spi_command cmds[] = {
434 {
435 .writecnt = JEDEC_WREN_OUTSIZE,
436 .writearr = (const unsigned char[]){ JEDEC_WREN },
437 .readcnt = 0,
438 .readarr = NULL,
439 }, {
440 .writecnt = JEDEC_BYTE_PROGRAM_OUTSIZE - 1 + len,
441 .writearr = cmd,
442 .readcnt = 0,
443 .readarr = NULL,
444 }, {
445 .writecnt = 0,
446 .writearr = NULL,
447 .readcnt = 0,
448 .readarr = NULL,
449 }};
450
451 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + len - 1);
452
453 if (!len) {
454 msg_cerr("%s called for zero-length write\n", __func__);
455 return 1;
456 }
457 if (len > 256) {
458 msg_cerr("%s called for too long a write\n", __func__);
459 return 1;
460 }
461
462 memcpy(&cmd[JEDEC_BYTE_PROGRAM_OUTSIZE - 1], bytes, len);
463
464 result = set_extended_address_register(flash, (addr >> 24) & 0xff);
465 if (result)
466 return result;
467
468 result = spi_send_multicommand(flash, cmds);
469 if (result) {
470 msg_cerr("%s failed during command execution at address 0x%x\n",
471 __func__, addr);
472 }
473 return result;
474}
475
476/* Read flash bytes using Extended Address Register
477 from 3-bytes addressing mode */
478int spi_nbyte_read_4ba_ereg(struct flashctx *flash, unsigned int addr,
479 uint8_t *bytes, unsigned int len)
480{
481 int result;
482 const unsigned char cmd[JEDEC_READ_OUTSIZE] = {
483 JEDEC_READ,
484 (addr >> 16) & 0xff,
485 (addr >> 8) & 0xff,
486 (addr >> 0) & 0xff
487 };
488
489 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + len - 1);
490
491 result = set_extended_address_register(flash, (addr >> 24) & 0xff);
492 if (result)
493 return result;
494
495 /* Send Read */
496 return spi_send_command(flash, sizeof(cmd), len, cmd, bytes);
497}
498
499/* Erases 4 KB of flash using Extended Address Register
500 from 3-bytes addressing mode */
501int spi_block_erase_20_4ba_ereg(struct flashctx *flash, unsigned int addr,
502 unsigned int blocklen)
503{
504 int result;
505 struct spi_command cmds[] = {
506 {
507 .writecnt = JEDEC_WREN_OUTSIZE,
508 .writearr = (const unsigned char[]){ JEDEC_WREN },
509 .readcnt = 0,
510 .readarr = NULL,
511 }, {
512 .writecnt = JEDEC_SE_OUTSIZE,
513 .writearr = (const unsigned char[]){
514 JEDEC_SE,
515 (addr >> 16) & 0xff,
516 (addr >> 8) & 0xff,
517 (addr & 0xff)
518 },
519 .readcnt = 0,
520 .readarr = NULL,
521 }, {
522 .writecnt = 0,
523 .writearr = NULL,
524 .readcnt = 0,
525 .readarr = NULL,
526 }};
527
528 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
529
530 result = set_extended_address_register(flash, (addr >> 24) & 0xff);
531 if (result)
532 return result;
533
534 result = spi_send_multicommand(flash, cmds);
535 if (result) {
536 msg_cerr("%s failed during command execution at address 0x%x\n",
537 __func__, addr);
538 return result;
539 }
540 /* Wait until the Write-In-Progress bit is cleared.
541 * This usually takes 15-800 ms, so wait in 10 ms steps.
542 */
543 while (spi_read_status_register(flash) & SPI_SR_WIP)
544 programmer_delay(10 * 1000);
545 /* FIXME: Check the status register for errors. */
546 return 0;
547}
548
549/* Erases 32 KB of flash using Extended Address Register
550 from 3-bytes addressing mode */
551int spi_block_erase_52_4ba_ereg(struct flashctx *flash, unsigned int addr,
552 unsigned int blocklen)
553{
554 int result;
555 struct spi_command cmds[] = {
556 {
557 .writecnt = JEDEC_WREN_OUTSIZE,
558 .writearr = (const unsigned char[]){ JEDEC_WREN },
559 .readcnt = 0,
560 .readarr = NULL,
561 }, {
562 .writecnt = JEDEC_BE_52_OUTSIZE,
563 .writearr = (const unsigned char[]){
564 JEDEC_BE_52,
565 (addr >> 16) & 0xff,
566 (addr >> 8) & 0xff,
567 (addr & 0xff)
568 },
569 .readcnt = 0,
570 .readarr = NULL,
571 }, {
572 .writecnt = 0,
573 .writearr = NULL,
574 .readcnt = 0,
575 .readarr = NULL,
576 }};
577
578 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
579
580 result = set_extended_address_register(flash, (addr >> 24) & 0xff);
581 if (result)
582 return result;
583
584 result = spi_send_multicommand(flash, cmds);
585 if (result) {
586 msg_cerr("%s failed during command execution at address 0x%x\n",
587 __func__, addr);
588 return result;
589 }
590 /* Wait until the Write-In-Progress bit is cleared.
591 * This usually takes 100-4000 ms, so wait in 100 ms steps.
592 */
593 while (spi_read_status_register(flash) & SPI_SR_WIP)
594 programmer_delay(100 * 1000);
595 /* FIXME: Check the status register for errors. */
596 return 0;
597}
598
599/* Erases 64 KB of flash using Extended Address Register
600 from 3-bytes addressing mode */
601int spi_block_erase_d8_4ba_ereg(struct flashctx *flash, unsigned int addr,
602 unsigned int blocklen)
603{
604 int result;
605 struct spi_command cmds[] = {
606 {
607 .writecnt = JEDEC_WREN_OUTSIZE,
608 .writearr = (const unsigned char[]){ JEDEC_WREN },
609 .readcnt = 0,
610 .readarr = NULL,
611 }, {
612 .writecnt = JEDEC_BE_D8_OUTSIZE,
613 .writearr = (const unsigned char[]){
614 JEDEC_BE_D8,
615 (addr >> 16) & 0xff,
616 (addr >> 8) & 0xff,
617 (addr & 0xff)
618 },
619 .readcnt = 0,
620 .readarr = NULL,
621 }, {
622 .writecnt = 0,
623 .writearr = NULL,
624 .readcnt = 0,
625 .readarr = NULL,
626 }};
627
628 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
629
630 result = set_extended_address_register(flash, (addr >> 24) & 0xff);
631 if (result)
632 return result;
633
634 result = spi_send_multicommand(flash, cmds);
635 if (result) {
636 msg_cerr("%s failed during command execution at address 0x%x\n",
637 __func__, addr);
638 return result;
639 }
640 /* Wait until the Write-In-Progress bit is cleared.
641 * This usually takes 100-4000 ms, so wait in 100 ms steps.
642 */
643 while (spi_read_status_register(flash) & SPI_SR_WIP)
644 programmer_delay(100 * 1000);
645 /* FIXME: Check the status register for errors. */
646 return 0;
647}
Boris Baykov7fe85692016-06-11 18:29:03 +0200648
649/* Program one flash byte with 4-bytes address from ANY mode (3-bytes or 4-bytes)
650 JEDEC_BYTE_PROGRAM_4BA (12h) instruction is new for 4-bytes addressing flash chips.
651 The presence of this instruction for an exact chip should be checked
652 by its datasheet or from SFDP 4-Bytes Address Instruction Table (JESD216B). */
653int spi_byte_program_4ba_direct(struct flashctx *flash, unsigned int addr,
654 uint8_t databyte)
655{
656 int result;
657 struct spi_command cmds[] = {
658 {
659 .writecnt = JEDEC_WREN_OUTSIZE,
660 .writearr = (const unsigned char[]){ JEDEC_WREN },
661 .readcnt = 0,
662 .readarr = NULL,
663 }, {
664 .writecnt = JEDEC_BYTE_PROGRAM_4BA_OUTSIZE,
665 .writearr = (const unsigned char[]){
666 JEDEC_BYTE_PROGRAM_4BA,
667 (addr >> 24) & 0xff,
668 (addr >> 16) & 0xff,
669 (addr >> 8) & 0xff,
670 (addr & 0xff),
671 databyte
672 },
673 .readcnt = 0,
674 .readarr = NULL,
675 }, {
676 .writecnt = 0,
677 .writearr = NULL,
678 .readcnt = 0,
679 .readarr = NULL,
680 }};
681
682 msg_trace("-> %s (0x%08X)\n", __func__, addr);
683
684 result = spi_send_multicommand(flash, cmds);
685 if (result) {
686 msg_cerr("%s failed during command execution at address 0x%x\n",
687 __func__, addr);
688 }
689 return result;
690}
691
692/* Program flash bytes with 4-bytes address from ANY mode (3-bytes or 4-bytes)
693 JEDEC_BYTE_PROGRAM_4BA (12h) instruction is new for 4-bytes addressing flash chips.
694 The presence of this instruction for an exact chip should be checked
695 by its datasheet or from SFDP 4-Bytes Address Instruction Table (JESD216B). */
696int spi_nbyte_program_4ba_direct(struct flashctx *flash, unsigned int addr,
697 const uint8_t *bytes, unsigned int len)
698{
699 int result;
700 unsigned char cmd[JEDEC_BYTE_PROGRAM_4BA_OUTSIZE - 1 + 256] = {
701 JEDEC_BYTE_PROGRAM_4BA,
702 (addr >> 24) & 0xff,
703 (addr >> 16) & 0xff,
704 (addr >> 8) & 0xff,
705 (addr >> 0) & 0xff
706 };
707 struct spi_command cmds[] = {
708 {
709 .writecnt = JEDEC_WREN_OUTSIZE,
710 .writearr = (const unsigned char[]){ JEDEC_WREN },
711 .readcnt = 0,
712 .readarr = NULL,
713 }, {
714 .writecnt = JEDEC_BYTE_PROGRAM_4BA_OUTSIZE - 1 + len,
715 .writearr = cmd,
716 .readcnt = 0,
717 .readarr = NULL,
718 }, {
719 .writecnt = 0,
720 .writearr = NULL,
721 .readcnt = 0,
722 .readarr = NULL,
723 }};
724
725 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + len - 1);
726
727 if (!len) {
728 msg_cerr("%s called for zero-length write\n", __func__);
729 return 1;
730 }
731 if (len > 256) {
732 msg_cerr("%s called for too long a write\n", __func__);
733 return 1;
734 }
735
736 memcpy(&cmd[JEDEC_BYTE_PROGRAM_4BA_OUTSIZE - 1], bytes, len);
737
738 result = spi_send_multicommand(flash, cmds);
739 if (result) {
740 msg_cerr("%s failed during command execution at address 0x%x\n",
741 __func__, addr);
742 }
743 return result;
744}
745
746/* Read flash bytes with 4-bytes address from ANY mode (3-bytes or 4-bytes)
747 JEDEC_READ_4BA (13h) instruction is new for 4-bytes addressing flash chips.
748 The presence of this instruction for an exact chip should be checked
749 by its datasheet or from SFDP 4-Bytes Address Instruction Table (JESD216B). */
750int spi_nbyte_read_4ba_direct(struct flashctx *flash, unsigned int addr,
751 uint8_t *bytes, unsigned int len)
752{
753 const unsigned char cmd[JEDEC_READ_4BA_OUTSIZE] = {
754 JEDEC_READ_4BA,
755 (addr >> 24) & 0xff,
756 (addr >> 16) & 0xff,
757 (addr >> 8) & 0xff,
758 (addr >> 0) & 0xff
759 };
760
761 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + len - 1);
762
763 /* Send Read */
764 return spi_send_command(flash, sizeof(cmd), len, cmd, bytes);
765}
766
767/* Erase 4 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes)
768 JEDEC_SE_4BA (21h) instruction is new for 4-bytes addressing flash chips.
769 The presence of this instruction for an exact chip should be checked
770 by its datasheet or from SFDP 4-Bytes Address Instruction Table (JESD216B). */
771int spi_block_erase_21_4ba_direct(struct flashctx *flash, unsigned int addr,
772 unsigned int blocklen)
773{
774 int result;
775 struct spi_command cmds[] = {
776 {
777 .writecnt = JEDEC_WREN_OUTSIZE,
778 .writearr = (const unsigned char[]){ JEDEC_WREN },
779 .readcnt = 0,
780 .readarr = NULL,
781 }, {
782 .writecnt = JEDEC_SE_4BA_OUTSIZE,
783 .writearr = (const unsigned char[]){
784 JEDEC_SE_4BA,
785 (addr >> 24) & 0xff,
786 (addr >> 16) & 0xff,
787 (addr >> 8) & 0xff,
788 (addr & 0xff)
789 },
790 .readcnt = 0,
791 .readarr = NULL,
792 }, {
793 .writecnt = 0,
794 .writearr = NULL,
795 .readcnt = 0,
796 .readarr = NULL,
797 }};
798
799 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
800
801 result = spi_send_multicommand(flash, cmds);
802 if (result) {
803 msg_cerr("%s failed during command execution at address 0x%x\n",
804 __func__, addr);
805 return result;
806 }
807 /* Wait until the Write-In-Progress bit is cleared.
808 * This usually takes 15-800 ms, so wait in 10 ms steps.
809 */
810 while (spi_read_status_register(flash) & SPI_SR_WIP)
811 programmer_delay(10 * 1000);
812 /* FIXME: Check the status register for errors. */
813 return 0;
814}
815
816/* Erase 32 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes)
817 JEDEC_BE_5C_4BA (5Ch) instruction is new for 4-bytes addressing flash chips.
818 The presence of this instruction for an exact chip should be checked
819 by its datasheet or from SFDP 4-Bytes Address Instruction Table (JESD216B). */
820int spi_block_erase_5c_4ba_direct(struct flashctx *flash, unsigned int addr,
821 unsigned int blocklen)
822{
823 int result;
824 struct spi_command cmds[] = {
825 {
826 .writecnt = JEDEC_WREN_OUTSIZE,
827 .writearr = (const unsigned char[]){ JEDEC_WREN },
828 .readcnt = 0,
829 .readarr = NULL,
830 }, {
831 .writecnt = JEDEC_BE_5C_4BA_OUTSIZE,
832 .writearr = (const unsigned char[]){
833 JEDEC_BE_5C_4BA,
834 (addr >> 24) & 0xff,
835 (addr >> 16) & 0xff,
836 (addr >> 8) & 0xff,
837 (addr & 0xff)
838 },
839 .readcnt = 0,
840 .readarr = NULL,
841 }, {
842 .writecnt = 0,
843 .writearr = NULL,
844 .readcnt = 0,
845 .readarr = NULL,
846 }};
847
848 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
849
850 result = spi_send_multicommand(flash, cmds);
851 if (result) {
852 msg_cerr("%s failed during command execution at address 0x%x\n",
853 __func__, addr);
854 return result;
855 }
856 /* Wait until the Write-In-Progress bit is cleared.
857 * This usually takes 100-4000 ms, so wait in 100 ms steps.
858 */
859 while (spi_read_status_register(flash) & SPI_SR_WIP)
860 programmer_delay(100 * 1000);
861 /* FIXME: Check the status register for errors. */
862 return 0;
863}
864
865/* Erase 64 KB of flash with 4-bytes address from ANY mode (3-bytes or 4-bytes)
866 JEDEC_BE_DC_4BA (DCh) instruction is new for 4-bytes addressing flash chips.
867 The presence of this instruction for an exact chip should be checked
868 by its datasheet or from SFDP 4-Bytes Address Instruction Table (JESD216B). */
869int spi_block_erase_dc_4ba_direct(struct flashctx *flash, unsigned int addr,
870 unsigned int blocklen)
871{
872 int result;
873 struct spi_command cmds[] = {
874 {
875 .writecnt = JEDEC_WREN_OUTSIZE,
876 .writearr = (const unsigned char[]){ JEDEC_WREN },
877 .readcnt = 0,
878 .readarr = NULL,
879 }, {
880 .writecnt = JEDEC_BE_DC_4BA_OUTSIZE,
881 .writearr = (const unsigned char[]){
882 JEDEC_BE_DC_4BA,
883 (addr >> 24) & 0xff,
884 (addr >> 16) & 0xff,
885 (addr >> 8) & 0xff,
886 (addr & 0xff)
887 },
888 .readcnt = 0,
889 .readarr = NULL,
890 }, {
891 .writecnt = 0,
892 .writearr = NULL,
893 .readcnt = 0,
894 .readarr = NULL,
895 }};
896
897 msg_trace("-> %s (0x%08X-0x%08X)\n", __func__, addr, addr + blocklen - 1);
898
899 result = spi_send_multicommand(flash, cmds);
900 if (result) {
901 msg_cerr("%s failed during command execution at address 0x%x\n",
902 __func__, addr);
903 return result;
904 }
905 /* Wait until the Write-In-Progress bit is cleared.
906 * This usually takes 100-4000 ms, so wait in 100 ms steps.
907 */
908 while (spi_read_status_register(flash) & SPI_SR_WIP)
909 programmer_delay(100 * 1000);
910 /* FIXME: Check the status register for errors. */
911 return 0;
912}