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