GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / shared / spiflash.c
blob443347594ff2ad6092b96765970671a3e6166d5d
1 /*
2 * Broadcom QSPI serial flash interface
4 * Copyright (C) 2012, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * $Id: $
21 #include <bcm_cfg.h>
22 #include <typedefs.h>
23 #include <osl.h>
24 #include <bcmutils.h>
25 #include <siutils.h>
26 #include <hndsoc.h>
27 #include <sbhndcpu.h>
28 #include <bcmdevs.h>
29 #include <qspi_core.h>
30 #include <hndsflash.h>
31 #include <chipcommonb.h>
33 #ifndef FLASH_SPI_MAX_PAGE_SIZE
34 #define FLASH_SPI_MAX_PAGE_SIZE (256)
35 #endif
37 #ifdef BCMDBG
38 #define SPIFL_MSG(args) printf args
39 #else
40 #define SPIFL_MSG(args)
41 #endif /* BCMDBG */
43 #define MSPI_CALC_TIMEOUT(bytes, baud) ((((bytes * 9000)/baud) * 110)/100 + 1)
45 /* Private global state */
46 static hndsflash_t spiflash;
48 static int bspi_enabled = 1;
49 static bool firsttime = TRUE;
51 /* Prototype */
52 static int spiflash_read(hndsflash_t *spifl, uint offset, uint len, const uchar *buf);
53 static int spiflash_write(hndsflash_t *spifl, uint offset, uint len, const uchar *buf);
54 static int spiflash_erase(hndsflash_t *spifl, uint offset);
55 static int spiflash_poll(hndsflash_t *spifl, uint offset);
56 static int spiflash_commit(hndsflash_t *spifl, uint offset, uint len, const uchar *buf);
57 static int spiflash_open(si_t *sih, qspiregs_t *qspi);
59 /* Disable Boot SPI */
60 static void
61 mspi_disable_bspi(osl_t *osh, qspiregs_t *qspi)
63 int i, j;
64 unsigned int lval;
66 if (bspi_enabled == 0)
67 return;
69 lval = R_REG(osh, &qspi->bspi_mast_n_boot_ctrl);
70 if ((lval & 1) == 1)
71 return;
73 for (i = 0; i < 1000; i++) {
74 lval = R_REG(osh, &qspi->bspi_busy_status);
75 if ((lval & 1) == 0) {
76 W_REG(osh, &qspi->bspi_mast_n_boot_ctrl, 0x1);
77 bspi_enabled = 0;
78 for (j = 0; j < 1000; j++);
79 return;
84 /* Enable Boot SPI */
85 static void
86 mspi_enable_bspi(osl_t *osh, qspiregs_t *qspi)
88 unsigned int lval;
90 if (bspi_enabled == 1)
91 return;
93 lval = R_REG(osh, &qspi->bspi_mast_n_boot_ctrl);
94 if ((lval & 1) == 0)
95 return;
97 W_REG(osh, &qspi->bspi_mast_n_boot_ctrl, 0x0);
99 bspi_enabled = 1;
100 return;
103 static int
104 mspi_wait(osl_t *osh, qspiregs_t *qspi, unsigned int timeout_ms)
106 unsigned int lval;
107 unsigned int loopCnt = ((timeout_ms * 1000) / 10) + 1;
108 unsigned int count;
109 int rc = -1;
111 /* We must wait mspi_spcr2 spe bit clear before reading mspi_mspi_status */
112 while (1) {
113 lval = R_REG(osh, &qspi->mspi_spcr2);
114 if ((lval & MSPI_SPCR2_spe_MASK) == 0)
115 break;
118 /* Check status */
119 for (count = 0; count < loopCnt; count++) {
120 lval = R_REG(osh, &qspi->mspi_mspi_status);
121 if (lval & MSPI_MSPI_STATUS_SPIF_MASK) {
122 rc = 0;
123 break;
126 /* Create some delay 5 times bigger */
127 OSL_DELAY(100);
130 W_REG(osh, &qspi->mspi_mspi_status, 0);
131 if (rc) {
132 SPIFL_MSG(("Wait timeout\n"));
135 return rc;
138 static int
139 mspi_writeread(osl_t *osh, qspiregs_t *qspi, unsigned char *w_buf,
140 unsigned char write_len, unsigned char *r_buf, unsigned char read_len)
142 unsigned int lval;
143 unsigned char i, len;
145 len = write_len + read_len;
146 for (i = 0; i < len; i++) {
147 if (i < write_len) {
148 /* Transmit Register File MSB */
149 W_REG(osh, &qspi->mspi_txram[i * 2], (unsigned int)w_buf[i]);
152 lval = SPI_CDRAM_CONT | SPI_CDRAM_PCS_DISABLE_ALL | SPI_CDRAM_PCS_DSCK;
153 lval &= ~(1 << BSPI_Pcs_eUpgSpiPcs2);
154 /* Command Register File */
155 W_REG(osh, &qspi->mspi_cdram[i], lval);
158 lval = SPI_CDRAM_PCS_DISABLE_ALL | SPI_CDRAM_PCS_DSCK;
159 lval &= ~(1 << BSPI_Pcs_eUpgSpiPcs2);
160 /* Command Register File */
161 W_REG(osh, &qspi->mspi_cdram[len - 1], lval);
163 /* Set queue pointers */
164 W_REG(osh, &qspi->mspi_newqp, 0);
165 W_REG(osh, &qspi->mspi_endqp, len - 1);
167 /* Start SPI transfer */
168 lval = R_REG(osh, &qspi->mspi_spcr2);
169 lval |= MSPI_SPCR2_spe_MASK;
170 W_REG(osh, &qspi->mspi_spcr2, lval);
172 /* Wait for SPI to finish */
173 if (mspi_wait(osh, qspi, MSPI_CALC_TIMEOUT(len, MAX_SPI_BAUD)) != 0)
174 return 0;
176 W_REG(osh, &qspi->mspi_write_lock, 0);
178 for (i = write_len; i < len; ++i) {
179 /* Data stored in the transmit register file LSB */
180 r_buf[i-write_len] = (unsigned char)R_REG(osh, &qspi->mspi_rxram[1 + (i * 2)]);
183 return 1;
186 static int
187 mspi_writeread_continue(osl_t *osh, qspiregs_t *qspi, unsigned char *w_buf,
188 unsigned char write_len, unsigned char *r_buf, unsigned char read_len)
190 unsigned int lval;
191 unsigned char i, len;
193 len = write_len + read_len;
194 for (i = 0; i < len; i++) {
195 if (i < write_len)
196 W_REG(osh, &qspi->mspi_txram[i * 2], (unsigned int)w_buf[i]);
198 lval = SPI_CDRAM_CONT | SPI_CDRAM_PCS_DISABLE_ALL | SPI_CDRAM_PCS_DSCK;
199 lval &= ~(1 << BSPI_Pcs_eUpgSpiPcs2);
200 W_REG(osh, &qspi->mspi_cdram[i], lval);
203 /* Set queue pointers */
204 W_REG(osh, &qspi->mspi_newqp, 0);
205 W_REG(osh, &qspi->mspi_endqp, len - 1);
207 W_REG(osh, &qspi->mspi_write_lock, 1);
209 /* Start SPI transfer */
210 lval = R_REG(osh, &qspi->mspi_spcr2);
211 lval |= MSPI_SPCR2_cont_after_cmd_MASK | MSPI_SPCR2_spe_MASK;
212 W_REG(osh, &qspi->mspi_spcr2, lval);
214 /* Wait for SPI to finish */
215 if (mspi_wait(osh, qspi, MSPI_CALC_TIMEOUT(len, MAX_SPI_BAUD)) != 0)
216 return 0;
218 for (i = write_len; i < len; ++i)
219 r_buf[i-write_len] = (unsigned char)R_REG(osh, &qspi->mspi_rxram[1 + (i * 2)]);
221 return 1;
224 /* Command codes for the flash_command routine */
225 #define FLASH_READ 0x03 /* read data from memory array */
226 #define FLASH_READ_FAST 0x0B /* read data from memory array */
227 #define FLASH_PROG 0x02 /* program data into memory array */
228 #define FLASH_WREN 0x06 /* set write enable latch */
229 #define FLASH_WRDI 0x04 /* reset write enable latch */
230 #define FLASH_RDSR 0x05 /* read status register */
231 #define FLASH_WRST 0x01 /* write status register */
232 #define FLASH_EWSR 0x50 /* enable write status */
233 #define FLASH_WORD_AAI 0xAD /* auto address increment word program */
234 #define FLASH_AAI 0xAF /* auto address increment program */
236 #define SST_FLASH_CERASE 0x60 /* erase all sectors in memory array */
237 #define SST_FLASH_SERASE 0x20 /* erase one sector in memroy array */
238 #define SST_FLASH_RDID 0x90 /* read manufacturer and product id */
240 #define ATMEL_FLASH_CERASE 0x62 /* erase all sectors in memory array */
241 #define ATMEL_FLASH_SERASE 0x52 /* erase one sector in memroy array */
242 #define ATMEL_FLASH_RDID 0x15 /* read manufacturer and product id */
244 #define ATMEL_FLASH_PSEC 0x36 /* protect sector */
245 #define ATMEL_FLASH_UNPSEC 0x39 /* unprotect sector */
246 #define ATMEL_FLASH_RDPREG 0x3C /* read protect sector registers */
248 #define AMD_FLASH_CERASE 0xC7 /* erase all sectors in memory array */
249 #define AMD_FLASH_SERASE 0xD8 /* erase one sector in memroy array */
250 #define AMD_FLASH_RDID 0xAB /* read manufacturer and product id */
252 #define SPAN_FLASH_CERASE 0xC7 /* erase all sectors in memory array */
253 #define SPAN_FLASH_SERASE 0xD8 /* erase one sector in memory array */
254 #define SPAN_FLASH_RDID 0x9F /* read manufacturer and product id */
256 /* Spansion commands for 4-byte addressing */
257 #define SPAN_FLASH_BRWR 0x17 /* bank register write */
258 #define SPAN_FLASH_4PP 0x12 /* page program with 4-byte address */
259 #define SPAN_FLASH_4P4E 0x21 /* parameter 4-kB secotor erase with 4-byte address */
260 #define SPAN_FLASH_4SE 0xDC /* sectore erase with 4-byte address */
262 #define ST_FLASH_RDID 0x9F /* read manufacturer and product id */
263 #define ST_FLASH_RDFSR 0x70 /* read flag status register */
265 /* ATMEL's manufacturer ID */
266 #define ATMELPART 0x1F
268 /* A list of ATMEL device ID's - add others as needed */
269 #define ID_AT25F512 0x60
270 #define ID_AT25F512A 0x65
271 #define ID_AT25F2048 0x63
272 #define ID_AT26F004 0x04
273 #define ID_AT25DF041A 0x44
275 /* AMD's device ID */
276 #define AMD_S25FL002D 0x11
278 /* SST's manufacturer ID */
279 #define SSTPART 0xBF
281 /* A list of SST device ID's - add others as needed */
282 #define ID_SST25VF016B 0x41
283 #define ID_SST25VF020 0x43
284 #define ID_SST25VF040 0x44
285 #define ID_SST25VF080 0x80
287 /* NexFlash's manufacturer ID */
288 #define NXPART 0xEF
290 /* A list of NexFlash device ID's - add others as needed */
291 #define ID_NX25P20 0x11
292 #define ID_NX25P40 0x12
293 #define ID_W25X16 0x14
294 #define ID_W25X32 0x15
295 #define ID_W25X64 0x16
297 /* StFlash's manufacturer ID */
298 #define STPART 0x12
300 /* A list of StFlash device ID's - add others as needed */
301 #define ID_M25P40 0x12
303 /* SPANSION manufacturer ID */
304 #define SPANPART 0x01
306 /* SPANSION device ID's */
307 #define ID_SPAN25FL002A 0x11
308 #define ID_SPAN25FL004A 0x12
309 #define ID_SPAN25FL008A 0x13
310 #define ID_SPAN25FL016A 0x14
311 #define ID_SPAN25FL032A 0x15
312 #define ID_SPAN25FL064A 0x16
313 #define ID_SPAN25FL128A 0x17
315 /* EON manufacturer ID */
316 #define EONPART 0x1C
317 /* NUMONYX manufacturer ID */
318 #define NUMONYXPART 0x20
319 /* Macronix manufacturer ID */
320 #define MACRONIXPART 0xC2
322 /* JEDEC device ID */
323 #define ID_M25P64 0x17
325 /* Use READ_ID (0x90) command
326 * Manufacturer Identification - 1 byte
327 * Device Identification - 2 bytes
328 * Extended Device Identification - 2 bytes
330 #define MSPI_IDS_READLEN 5
332 /* Enable/disable BSPI 4-byte mode read */
333 static void
334 spiflash_set_4byte_mode(hndsflash_t *spifl, int enable)
336 osl_t *osh = si_osh(spifl->sih);
337 qspiregs_t *qspi = (qspiregs_t *)spifl->core;
338 unsigned char cmd[1];
340 /* Use MSPI to configure flash for entering/exiting 4-byte mode */
341 mspi_disable_bspi(osh, qspi);
342 cmd[0] = SPI_WREN_CMD;
343 mspi_writeread(osh, qspi, cmd, 1, NULL, 0);
344 if (spifl->vendor_id == SPANPART)
345 cmd[0] = enable? SPAN_FLASH_BRWR : SPI_EX4B_CMD;
346 else
347 cmd[0] = enable? SPI_EN4B_CMD : SPI_EX4B_CMD;
348 mspi_writeread(osh, qspi, cmd, 1, NULL, 0);
349 cmd[0] = SPI_WRDI_CMD;
350 mspi_writeread(osh, qspi, cmd, 1, NULL, 0);
352 if (enable) {
353 /* Enable 32-bit address */
354 OR_REG(osh, &qspi->bspi_bits_per_phase, BSPI_BITS_PER_PHASE_ADDR_MARK);
355 } else {
356 /* Disable 32-bit address */
357 AND_REG(osh, &qspi->bspi_bits_per_phase, ~BSPI_BITS_PER_PHASE_ADDR_MARK);
360 /* BSPI by default */
361 mspi_enable_bspi(osh, qspi);
364 static uint16
365 NTOS(unsigned char *a)
367 uint16 v;
368 v = (a[0]*256) + a[1];
369 return v;
372 static unsigned short
373 mspi_read_id(osl_t *osh, qspiregs_t *qspi)
375 unsigned char cmd[4];
376 unsigned char data[5];
378 /* Try SST flashes read product id command */
379 cmd[0] = SST_FLASH_RDID;
380 cmd[1] = 0;
381 cmd[2] = 0;
382 cmd[3] = 0;
383 if (mspi_writeread(osh, qspi, cmd, 4, data, 2)) {
384 if (data[0] == SSTPART || data[0] == NXPART) {
385 return NTOS(data);
389 /* Try ATMEL flashes read product id command */
390 cmd[0] = ATMEL_FLASH_RDID;
391 if (mspi_writeread(osh, qspi, cmd, 1, data, 2)) {
392 if (data[0] == ATMELPART) {
393 return NTOS(data);
397 /* Try SPANSION flashes read product id command */
398 cmd[0] = SPAN_FLASH_RDID;
399 if (mspi_writeread(osh, qspi, cmd, 1, data, 3)) {
400 if (data[0] == ATMELPART) {
401 return NTOS(data);
404 if ((data[0] == NUMONYXPART) || (data[0] == SPANPART) ||
405 (data[0] == EONPART) || (data[0] == MACRONIXPART)) {
406 data[1] = data[2];
407 return NTOS(data);
412 * AMD_FLASH_RDID is the same as RES command for SPAN,
413 * so it has to be the last one.
415 cmd[0] = AMD_FLASH_RDID;
416 cmd[1] = 0;
417 cmd[2] = 0;
418 cmd[3] = 0;
419 if (mspi_writeread(osh, qspi, cmd, 4, data, 2)) {
420 if (data[0] == AMD_S25FL002D || data[0] == STPART) {
421 return NTOS(data);
425 return 0;
428 static int
429 bspi_sector_erase(hndsflash_t *spifl, qspiregs_t *qspi, unsigned int offset)
431 si_t *sih = spifl->sih;
432 osl_t *osh;
433 int result = 0;
434 unsigned char cmd[5];
435 unsigned char data;
436 int idx;
438 ASSERT(sih);
439 osh = si_osh(sih);
440 switch (spifl->type) {
441 case QSPIFLASH_ST:
442 cmd[0] = SPI_WREN_CMD;
443 if ((result = mspi_writeread(osh, qspi, cmd, 1, NULL, 0)) != 1)
444 break;
446 idx = 0;
447 if (spifl->vendor_id == SPANPART && (spifl->device_id & 0xff) >= 0x19)
448 cmd[idx++] = (spifl->blocksize < (64 * 1024)) ?
449 SPAN_FLASH_4P4E : SPAN_FLASH_4SE;
450 else
451 cmd[idx++] = (spifl->blocksize < (64 * 1024)) ? SPI_SSE_CMD : SPI_SE_CMD;
452 if (spifl->size > 0x1000000) {
453 cmd[idx++] = ((offset & 0xFF000000) >> 24);
455 cmd[idx++] = ((offset & 0x00FF0000) >> 16);
456 cmd[idx++] = ((offset & 0x0000FF00) >> 8);
457 cmd[idx++] = (offset & 0x000000FF);
458 if ((result = mspi_writeread(osh, qspi, cmd, idx, NULL, 0)) != 1)
459 break;
461 /* Check for ST Write In Progress bit */
462 do {
463 cmd[0] = SPI_RDSR_CMD;
464 if ((result = mspi_writeread(osh, qspi, cmd, 1, &data, 1)) != 1)
465 break;
466 } while(data & 0x01); /* busy check */
468 if (result != 1)
469 break;
471 /* disable the write */
472 cmd[0] = SPI_WRDI_CMD;
473 result = mspi_writeread(osh, qspi, cmd, 1, NULL, 0);
474 break;
476 case QSPIFLASH_AT:
477 cmd[0] = SPI_AT_PAGE_ERASE;
478 offset = offset << 1;
479 cmd[1] = ((offset & 0x00FF0000) >> 16);
480 cmd[2] = ((offset & 0x0000FF00) >> 8);
481 cmd[3] = (offset & 0x000000FF);
482 if ((result = mspi_writeread(osh, qspi, cmd, 4, NULL, 0)) != 1)
483 break;
485 /* Check for Atmel Ready bit */
486 do {
487 cmd[0] = SPI_AT_STATUS;
488 if ((result = mspi_writeread(osh, qspi, cmd, 1, &data, 1)) != 1)
489 break;
490 } while(data & 0x80); /* busy check */
492 if (result != 1)
493 break;
495 /* disable the write */
496 cmd[0] = SPI_WRDI_CMD;
497 result = mspi_writeread(osh, qspi, cmd, 1, NULL, 0);
498 break;
501 return result;
504 static int
505 bspi2_st_page_program(hndsflash_t *spifl, qspiregs_t *qspi, unsigned int offset,
506 unsigned char *buf, int len)
508 si_t *sih = spifl->sih;
509 osl_t *osh;
510 int result = 0;
511 int i, len_total;
512 static unsigned char cmd[FLASH_SPI_MAX_PAGE_SIZE+5];
513 unsigned char data;
514 int idx;
516 ASSERT(sih);
517 osh = si_osh(sih);
518 if (len >(FLASH_SPI_MAX_PAGE_SIZE+4)) /* Max bytes per transaction */
519 goto done;
521 cmd[0] = SPI_WREN_CMD;
522 if ((result = mspi_writeread(osh, qspi, cmd, 1, NULL, 0)) != 1)
523 goto done;
525 idx = 0;
526 if (spifl->vendor_id == SPANPART && (spifl->device_id & 0xff) >= 0x19)
527 cmd[idx++] = SPAN_FLASH_4PP;
528 else
529 cmd[idx++] = SPI_PP_CMD;
530 if (spifl->size > 0x1000000) {
531 cmd[idx++] = ((offset & 0xFF000000) >> 24);
533 cmd[idx++] = ((offset & 0x00FF0000) >> 16);
534 cmd[idx++] = ((offset & 0x0000FF00) >> 8);
535 cmd[idx++] = (offset & 0x000000FF);
538 * If new SPI has fix for byte orderig, define FLASH_SPI_BYTE_ORDER_FIX
539 * to 1 in qspi_core.h
541 #if defined(IL_BIGENDIAN) && !defined(FLASH_SPI_BYTE_ORDER_FIX)
543 * mspi does not handle byte ordering for be mode. Handle it here.
544 * Let's assume len is multiple of 4
546 for (i = 0; i < len; i = i+4) {
547 cmd[i + idx + 0] = buf[i + 3];
548 cmd[i + idx + 1] = buf[i + 2];
549 cmd[i + idx + 2] = buf[i + 1];
550 cmd[i + idx + 3] = buf[i + 0];
552 #else
553 for (i = 0; i < len; ++i)
554 cmd[i + idx] = buf[i];
555 #endif
557 i = 0;
558 len_total = len + idx;
560 while (len_total > 16) {
561 if ((result = mspi_writeread_continue(osh, qspi, cmd + i, 16, NULL, 0)) != 1)
562 goto done;
563 i += 16;
564 len_total -= 16;
567 if (len_total <= 16 && len_total > 0) {
568 if ((result = mspi_writeread(osh, qspi, cmd+i, len_total, NULL, 0)) != 1)
569 goto done;
572 do {
573 cmd[0] = SPI_RDSR_CMD;
574 if ((result = mspi_writeread(osh, qspi, cmd, 1, &data, 1)) != 1)
575 goto done;
576 } while(data & 0x01 /* busy*/);
578 /* disable the write */
579 cmd[0] = SPI_WRDI_CMD;
580 if ((result = mspi_writeread(osh, qspi, cmd, 1, NULL, 0)) != 1)
581 goto done;
583 done:
584 return result;
587 static int
588 bspi2_at_page_program(osl_t *osh, qspiregs_t *qspi, hndsflash_t *spifl, unsigned int offset,
589 unsigned char *buf, int len)
591 int result = 0;
592 int i, len_total;
593 static unsigned char cmd[FLASH_SPI_MAX_PAGE_SIZE+4];
594 unsigned char data;
595 uint32 page, byte, mask;
597 mask = spifl->blocksize - 1;
598 page = (offset & ~mask) << 1;
599 byte = offset & mask;
601 /* Read main memory page into buffer 1 */
602 if (byte || (len < spifl->blocksize)) {
603 cmd[0] = SPI_AT_BUF1_LOAD;
604 cmd[1] = ((page & 0x00FF0000) >> 16);
605 cmd[2] = ((page & 0x0000FF00) >> 8);
606 cmd[3] = (page & 0x000000FF);
608 if ((result = mspi_writeread(osh, qspi, cmd, 4, NULL, 0)) != 1)
609 goto done;
611 do {
612 cmd[0] = SPI_AT_STATUS;
613 if ((result = mspi_writeread(osh, qspi, cmd, 1, &data, 1)) != 1)
614 goto done;
615 } while(!(data & SPI_AT_READY) /* not ready */);
618 /* Write into buffer 1 */
619 cmd[0] = SPI_AT_BUF1_WRITE;
620 cmd[1] = ((byte & 0x00FF0000) >> 16);
621 cmd[2] = ((byte & 0x0000FF00) >> 8);
622 cmd[3] = (byte & 0x000000FF);
624 * If new SPI has fix for byte orderig, define FLASH_SPI_BYTE_ORDER_FIX
625 * to 1 in qspi_core.h
627 #if defined(IL_BIGENDIAN) && !defined(FLASH_SPI_BYTE_ORDER_FIX)
629 * mspi does not handle byte ordering for be mode. Handle it here.
630 * Let's assume len is multiple of 4
632 for (i = 0; i < len; i = i+4) {
633 cmd[i+4] = buf[i+3];
634 cmd[i+5] = buf[i+2];
635 cmd[i+6] = buf[i+1];
636 cmd[i+7] = buf[i];
638 #else
639 for (i = 0; i < len; ++i)
640 cmd[i+4] = buf[i];
641 #endif
643 i = 0;
644 len_total = len + 4;
646 while (len_total > 16) {
647 if ((result = mspi_writeread_continue(osh, qspi, cmd + i, 16, NULL, 0)) != 1)
648 goto done;
649 i += 16;
650 len_total -= 16;
653 if (len_total <= 16 && len_total > 0) {
654 if ((result = mspi_writeread(osh, qspi, cmd+i, len_total, NULL, 0)) != 1)
655 goto done;
658 /* Write buffer 1 into main memory page */
659 cmd[0] = SPI_AT_BUF1_PROGRAM;
660 cmd[1] = ((page & 0x00FF0000) >> 16);
661 cmd[2] = ((page & 0x0000FF00) >> 8);
662 cmd[3] = (page & 0x000000FF);
663 result = mspi_writeread(osh, qspi, cmd, 4, NULL, 0);
665 done:
666 return result;
669 static int bspi_poll(hndsflash_t *spifl, qspiregs_t *qspi, unsigned int offset)
671 si_t *sih = spifl->sih;
672 osl_t *osh;
673 int result = 1;
674 unsigned char cmd[4];
675 unsigned char data;
677 ASSERT(sih);
679 osh = si_osh(sih);
681 switch (spifl->device_id & 0x00ff)
683 case 0x20:
684 do {
685 cmd[0] = ST_FLASH_RDFSR;
686 if ((result = mspi_writeread(osh, qspi, cmd, 1, &data, 1)) != 1) {
687 result = 0;
688 break;
690 } while ((data & 0x80) == 0);
691 break;
692 default:
693 break;
696 return result;
699 /* Initialize serial flash access */
700 hndsflash_t *
701 spiflash_init(si_t *sih)
703 qspiregs_t *qspi;
704 uint16 device_id;
705 const char *name = "";
706 osl_t *osh;
707 uint8 vendor_id;
708 int force_3byte_mode = 0;
710 ASSERT(sih);
712 /* Only support chipcommon revision == 42 for now */
713 if (sih->ccrev != 42)
714 return NULL;
716 if ((qspi = (qspiregs_t *)si_setcore(sih, NS_QSPI_CORE_ID, 0)) == NULL)
717 return NULL;
719 if (!firsttime && spiflash.size != 0)
720 return &spiflash;
722 osh = si_osh(sih);
724 bzero(&spiflash, sizeof(spiflash));
725 spiflash.sih = sih;
726 spiflash.core = (void *)qspi;
727 spiflash.read = spiflash_read;
728 spiflash.write = spiflash_write;
729 spiflash.erase = spiflash_erase;
730 spiflash.commit = spiflash_commit;
732 spiflash.device_id = device_id = mspi_read_id(osh, qspi);
733 spiflash.vendor_id = vendor_id = (device_id >> 8);
734 switch (vendor_id) {
735 case SPANPART:
736 case MACRONIXPART:
737 case NUMONYXPART:
738 /* ST compatible */
739 if (vendor_id == SPANPART)
740 name = "ST compatible";
741 else if (vendor_id == MACRONIXPART)
742 name = "ST compatible (Marconix)";
743 else
744 name = "ST compatible (Micron)";
746 spiflash.type = QSPIFLASH_ST;
747 spiflash.blocksize = 64 * 1024;
749 switch ((unsigned short)(device_id & 0x00ff)) {
750 case 0x11:
751 /* ST M25P20 2 Mbit Serial Flash */
752 spiflash.numblocks = 4;
753 break;
754 case 0x12:
755 /* ST M25P40 4 Mbit Serial Flash */
756 spiflash.numblocks = 8;
757 break;
758 case 0x13:
759 spiflash.numblocks = 16;
760 break;
761 case 0x14:
762 /* ST M25P16 16 Mbit Serial Flash */
763 spiflash.numblocks = 32;
764 break;
765 case 0x15:
766 /* ST M25P32 32 Mbit Serial Flash */
767 spiflash.numblocks = 64;
768 break;
769 case 0x16:
770 /* ST M25P64 64 Mbit Serial Flash */
771 spiflash.numblocks = 128;
772 break;
773 case 0x17:
774 case 0x18:
775 /* ST M25FL128 128 Mbit Serial Flash */
776 spiflash.numblocks = 256;
777 break;
778 case 0x19:
779 spiflash.numblocks = 512;
780 break;
781 case 0x20:
782 spiflash.numblocks = 1024;
783 /* Special poll requirement for Micron N25Q512 */
784 spiflash.poll = spiflash_poll;
785 break;
787 break;
789 case SSTPART:
790 name = "SST";
791 spiflash.type = QSPIFLASH_ST;
792 spiflash.blocksize = 4 * 1024;
793 switch ((unsigned char)(device_id & 0x00ff)) {
794 case 1:
795 /* SST25WF512 512 Kbit Serial Flash */
796 spiflash.numblocks = 16;
797 break;
798 case 0x48:
799 /* SST25VF512 512 Kbit Serial Flash */
800 spiflash.numblocks = 16;
801 break;
802 case 2:
803 /* SST25WF010 1 Mbit Serial Flash */
804 spiflash.numblocks = 32;
805 break;
806 case 0x49:
807 /* SST25VF010 1 Mbit Serial Flash */
808 spiflash.numblocks = 32;
809 break;
810 case 3:
811 /* SST25WF020 2 Mbit Serial Flash */
812 spiflash.numblocks = 64;
813 break;
814 case 0x43:
815 /* SST25VF020 2 Mbit Serial Flash */
816 spiflash.numblocks = 64;
817 break;
818 case 4:
819 /* SST25WF040 4 Mbit Serial Flash */
820 spiflash.numblocks = 128;
821 break;
822 case 0x44:
823 /* SST25VF040 4 Mbit Serial Flash */
824 spiflash.numblocks = 128;
825 break;
826 case 0x8d:
827 /* SST25VF040B 4 Mbit Serial Flash */
828 spiflash.numblocks = 128;
829 break;
830 case 5:
831 /* SST25WF080 8 Mbit Serial Flash */
832 spiflash.numblocks = 256;
833 break;
834 case 0x8e:
835 /* SST25VF080B 8 Mbit Serial Flash */
836 spiflash.numblocks = 256;
837 break;
838 case 0x41:
839 /* SST25VF016 16 Mbit Serial Flash */
840 spiflash.numblocks = 512;
841 break;
842 case 0x4a:
843 /* SST25VF032 32 Mbit Serial Flash */
844 spiflash.numblocks = 1024;
845 break;
846 case 0x4b:
847 /* SST25VF064 64 Mbit Serial Flash */
848 spiflash.numblocks = 2048;
849 break;
851 break;
853 case ATMELPART:
854 /* SFLASH_AT_STATUS not implement */
855 name = "Atmel";
856 spiflash.type = QSPIFLASH_AT;
857 switch ((char)(device_id & 0x00ff)) {
858 case ID_AT25F512:
859 spiflash.numblocks = 2;
860 spiflash.blocksize = 32 * 1024;
861 break;
863 case ID_AT25F2048:
864 spiflash.numblocks = 4;
865 spiflash.blocksize = 64 * 1024;
866 break;
867 default:
868 break;
870 break;
872 default:
873 spiflash.numblocks = 0;
874 SPIFL_MSG(("Unknown flash, device_id:0x%02X\n", device_id));
875 return NULL;
878 /* Open device here */
879 spiflash_open(sih, qspi);
881 spiflash.size = spiflash.blocksize * spiflash.numblocks;
883 if (BCM4707_CHIP(CHIPID(sih->chip))) {
884 uint32 chip_rev, straps_ctrl;
885 uint32 *srab_base, *dmu_base;
886 /* Get chip revision */
887 srab_base = (uint32 *)REG_MAP(CHIPCB_SRAB_BASE, SI_CORE_SIZE);
888 W_REG(osh, (uint32 *)((uint32)srab_base + CHIPCB_SRAB_CMDSTAT_OFFSET), 0x02400001);
889 chip_rev = R_REG(osh, (uint32 *)((uint32)srab_base + CHIPCB_SRAB_RDL_OFFSET)) & 0x3;
890 REG_UNMAP(srab_base);
891 if (CHIPID(sih->chip) == BCM4707_CHIP_ID && chip_rev < 2) {
892 force_3byte_mode = 1;
894 /* Check 4BYTE_MODE strap */
895 dmu_base = (uint32 *)REG_MAP(CHIPCB_DMU_BASE, SI_CORE_SIZE);
896 straps_ctrl = R_REG(osh,
897 (uint32 *)((uint32)dmu_base + CHIPCB_CRU_STRAPS_CTRL_OFFSET));
898 REG_UNMAP(dmu_base);
899 if (!(straps_ctrl & CHIPCB_CRU_STRAPS_4BYTE))
900 force_3byte_mode = 1;
902 /* NOR flash size check. */
903 if (force_3byte_mode && (spiflash.size > SI_FLASH_WINDOW)) {
904 SPIFL_MSG(("NOR flash size %dMB is bigger than %dMB, limit it to %dMB\n",
905 (spiflash.size >> 20), (SI_FLASH_WINDOW >> 20),
906 (SI_FLASH_WINDOW >> 20)));
907 spiflash.size = SI_FLASH_WINDOW;
908 } else if (spiflash.size > SI_NS_FLASH_WINDOW) {
909 SPIFL_MSG(("NOR flash size %dMB is bigger than %dMB, limit it to %dMB\n",
910 (spiflash.size >> 20), (SI_NS_FLASH_WINDOW >> 20),
911 (SI_NS_FLASH_WINDOW >> 20)));
912 spiflash.size = SI_NS_FLASH_WINDOW;
915 spiflash.phybase = SI_NS_NORFLASH;
916 if (spiflash.size)
917 spiflash.base = (uint32)REG_MAP(SI_NS_NORFLASH, spiflash.size);
919 if (firsttime) {
920 if (spiflash.size == 0)
921 printf("ERROR: Unknown flash, device_id:0x%02X\n", device_id);
922 else {
923 /* Enter 4-byte mode if size > 16MB */
924 if (spiflash.size > 0x1000000) {
925 spiflash_set_4byte_mode(&spiflash, 1);
926 } else {
927 spiflash_set_4byte_mode(&spiflash, 0);
929 printf("Found a %s serial flash with %d %dKB blocks; total size %dMB\n",
930 name, spiflash.numblocks, spiflash.blocksize / 1024,
931 spiflash.size / (1024 * 1024));
935 firsttime = FALSE;
936 return spiflash.size ? &spiflash : NULL;
939 static int
940 spiflash_open(si_t *sih, qspiregs_t *qspi)
942 osl_t *osh = NULL;
943 unsigned int lval;
945 ASSERT(sih);
947 osh = si_osh(sih);
949 lval = SPI_SYSTEM_CLK / (2 * MAX_SPI_BAUD);
950 W_REG(osh, &qspi->mspi_spcr0_lsb, lval);
951 lval = R_REG(osh, &qspi->mspi_spcr0_msb);
952 lval &= ~(MSPI_SPCR0_MSB_CPOL_MASK | MSPI_SPCR0_MSB_CPHA_MASK | MSPI_SPCR0_MSB_BitS_MASK);
953 lval |= (MSPI_SPCR0_MSB_MSTR_MASK | (MSPI_SPCR0_MSB_CPOL_MASK | MSPI_SPCR0_MSB_CPHA_MASK |
954 (0x8 << MSPI_SPCR0_MSB_BitS_SHIFT)));
955 W_REG(osh, &qspi->mspi_spcr0_msb, lval);
957 /* add delay if it is 7422A0 */
958 W_REG(osh, &qspi->mspi_spcr1_msb, 128);
960 return 0;
963 /* Read len bytes starting at offset into buf. Returns number of bytes read. */
964 static int
965 spiflash_read(hndsflash_t *spifl, uint offset, uint len, const uchar *buf)
967 si_t *sih = spifl->sih;
968 qspiregs_t *qspi = (qspiregs_t *)spifl->core;
969 osl_t *osh;
970 uint8 *from, *to;
971 int cnt, i;
973 ASSERT(sih);
975 osh = si_osh(sih);
977 if (!len)
978 return 0;
980 if ((offset + len) > spifl->size)
981 return -22;
983 if ((len >= 4) && (offset & 3))
984 cnt = 4 - (offset & 3);
985 else if ((len >= 4) && ((uintptr)buf & 3))
986 cnt = 4 - ((uintptr)buf & 3);
987 else
988 cnt = len;
990 from = (uint8 *)((void *)spifl->base + offset);
991 to = (uint8 *)buf;
993 mspi_enable_bspi(osh, qspi);
994 if (cnt < 4) {
995 for (i = 0; i < cnt; i ++) {
996 /* Cannot use R_REG because in bigendian that will
997 * xor the address and we don't want that here.
999 *to = *from;
1000 from ++;
1001 to ++;
1003 return cnt;
1006 while (cnt >= 4) {
1007 *(uint32 *)to = *(uint32 *)from;
1008 from += 4;
1009 to += 4;
1010 cnt -= 4;
1013 return (len - cnt);
1016 /* Write len bytes starting at offset into buf. Returns number of bytes
1017 * written
1019 static int
1020 spiflash_write(hndsflash_t *spifl, uint offset, uint length, const uchar *buffer)
1022 si_t *sih = spifl->sih;
1023 qspiregs_t *qspi = (qspiregs_t *)spifl->core;
1024 const uint8 *buf = buffer;
1025 int ret = 0;
1026 osl_t *osh;
1027 unsigned i, j, number_byte_to_write;
1028 uchar temp[FLASH_SPI_MAX_PAGE_SIZE+28];
1030 ASSERT(sih);
1032 osh = si_osh(sih);
1034 if (!length)
1035 return 0;
1037 if ((offset + length) > spifl->size)
1038 return -22;
1040 mspi_disable_bspi(osh, qspi);
1042 switch (spifl->type) {
1043 case QSPIFLASH_ST:
1044 for (i = 0; i < length; i += number_byte_to_write) {
1045 if (i + FLASH_SPI_MAX_PAGE_SIZE >= length)
1046 number_byte_to_write = length - i;
1047 else
1048 number_byte_to_write = FLASH_SPI_MAX_PAGE_SIZE;
1050 /* to prevent address cross the page boundary of 256 bytes. */
1051 if (number_byte_to_write > (256 - (i&0xFF)))
1052 number_byte_to_write = 256 - (i&0xFF);
1054 for (j = 0; j < number_byte_to_write; j++) {
1055 temp[j] = *buf;
1056 buf += 1;
1058 if (!bspi2_st_page_program(spifl, qspi, offset + i, &temp[0],
1059 number_byte_to_write)) {
1060 SPIFL_MSG(("Program fail\n"));
1061 ret = -11;
1062 break;
1065 if (spifl->poll && !bspi_poll(spifl, qspi, offset + i)) {
1066 SPIFL_MSG(("Poll fail\n"));
1067 ret = -33;
1068 break;
1071 ret += number_byte_to_write;
1073 break;
1075 case QSPIFLASH_AT:
1076 for (i = 0; i < length; i += number_byte_to_write) {
1077 if (i + FLASH_SPI_MAX_PAGE_SIZE >= length)
1078 number_byte_to_write = length - i;
1079 else
1080 number_byte_to_write = FLASH_SPI_MAX_PAGE_SIZE;
1082 /* to prevent address cross the page boundary of 256 bytes. */
1083 if (number_byte_to_write > (256 - (i&0xFF)))
1084 number_byte_to_write = 256 - (i&0xFF);
1086 for (j = 0; j < number_byte_to_write; j++) {
1087 temp[j] = *buf;
1088 buf += 1;
1090 if (!bspi2_at_page_program(osh, qspi, spifl, offset + i, &temp[0],
1091 number_byte_to_write)) {
1092 SPIFL_MSG(("Program fail\n"));
1093 ret = -11;
1094 break;
1096 ret += number_byte_to_write;
1098 break;
1101 mspi_enable_bspi(osh, qspi);
1102 return ret;
1105 /* Erase a region. Returns number of bytes scheduled for erasure.
1106 * Caller should poll for completion.
1108 static int
1109 spiflash_erase(hndsflash_t *spifl, uint offset)
1111 si_t *sih = spifl->sih;
1112 qspiregs_t *qspi = (qspiregs_t *)spifl->core;
1113 int erase_size = 0;
1114 osl_t *osh = NULL;
1116 ASSERT(sih);
1118 osh = si_osh(sih);
1120 if (offset >= spifl->size)
1121 return -22;
1123 mspi_disable_bspi(osh, qspi);
1125 if (bspi_sector_erase(spifl, qspi, offset))
1126 erase_size = spifl->blocksize;
1128 mspi_enable_bspi(osh, qspi);
1130 return erase_size;
1134 * Poll function called after write/erase operations. Returns 0 when poll
1135 * completes.
1137 static int
1138 spiflash_poll(hndsflash_t *spifl, uint offset)
1140 int result = 0;
1141 si_t *sih = spifl->sih;
1142 qspiregs_t *qspi = (qspiregs_t *)spifl->core;
1143 osl_t *osh = NULL;
1145 ASSERT(sih);
1147 osh = si_osh(sih);
1149 if (offset >= spifl->size)
1150 return -22;
1152 mspi_disable_bspi(osh, qspi);
1154 switch (spifl->type) {
1155 case QSPIFLASH_ST:
1156 /* Larger part such as the Micron 25Q512A (64MB) requires the flash status register
1157 * (FSR) polled after write/erase.
1159 if (!bspi_poll(spifl, qspi, offset)) {
1160 result = 1; /* Poll failed */
1162 break;
1164 default:
1165 /* Nothing to do */
1166 break;
1169 mspi_enable_bspi(osh, qspi);
1171 return result;
1175 * writes the appropriate range of flash, a NULL buf simply erases
1176 * the region of flash
1178 static int
1179 spiflash_commit(hndsflash_t *spifl, uint offset, uint len, const uchar *buf)
1181 si_t *sih = spifl->sih;
1182 uchar *block = NULL, *cur_ptr, *blk_ptr;
1183 uint blocksize = 0, mask, cur_offset, cur_length, cur_retlen, remainder;
1184 uint blk_offset, blk_len, copied;
1185 int bytes, ret = 0;
1186 osl_t *osh;
1188 ASSERT(sih);
1190 osh = si_osh(sih);
1192 /* Check address range */
1193 if (len <= 0)
1194 return 0;
1196 if ((offset + len) > spifl->size)
1197 return -1;
1199 blocksize = spifl->blocksize;
1200 mask = blocksize - 1;
1202 /* Allocate a block of mem */
1203 if (!(block = MALLOC(osh, blocksize)))
1204 return -1;
1206 while (len) {
1207 /* Align offset */
1208 cur_offset = offset & ~mask;
1209 cur_length = blocksize;
1210 cur_ptr = block;
1212 remainder = blocksize - (offset & mask);
1213 if (len < remainder)
1214 cur_retlen = len;
1215 else
1216 cur_retlen = remainder;
1218 /* buf == NULL means erase only */
1219 if (buf) {
1220 /* Copy existing data into holding block if necessary */
1221 if ((offset & mask) || (len < blocksize)) {
1222 blk_offset = cur_offset;
1223 blk_len = cur_length;
1224 blk_ptr = cur_ptr;
1226 /* Copy entire block */
1227 while (blk_len) {
1228 copied = spiflash_read(spifl, blk_offset, blk_len,
1229 blk_ptr);
1230 blk_offset += copied;
1231 blk_len -= copied;
1232 blk_ptr += copied;
1236 /* Copy input data into holding block */
1237 memcpy(cur_ptr + (offset & mask), buf, cur_retlen);
1240 /* Erase block */
1241 if ((ret = spiflash_erase(spifl, (uint)cur_offset)) < 0)
1242 goto done;
1244 /* buf == NULL means erase only */
1245 if (!buf) {
1246 offset += cur_retlen;
1247 len -= cur_retlen;
1248 continue;
1251 /* Write holding block */
1252 while (cur_length > 0) {
1253 if ((bytes = spiflash_write(spifl,
1254 (uint)cur_offset,
1255 (uint)cur_length,
1256 (uchar *)cur_ptr)) < 0) {
1257 ret = bytes;
1258 goto done;
1260 cur_offset += bytes;
1261 cur_length -= bytes;
1262 cur_ptr += bytes;
1265 offset += cur_retlen;
1266 len -= cur_retlen;
1267 buf += cur_retlen;
1270 ret = len;
1271 done:
1272 if (block)
1273 MFREE(osh, block, blocksize);
1274 return ret;