OpenCores
URL https://opencores.org/ocsvn/qspiflash/qspiflash/trunk

Subversion Repositories qspiflash

[/] [qspiflash/] [trunk/] [bench/] [cpp/] [eqspiflashsim.cpp] - Blame information for rev 16

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    eqspiflashsim.cpp
4
//
5 16 dgisselq
// Project:     Wishbone Controlled Quad SPI Flash Controller
6 12 dgisselq
//
7
// Purpose:     This library simulates the operation of a Quad-SPI commanded
8
//              flash, such as the Micron N25Q128A used on the Arty development
9
//              board by Digilent.  As such, it is defined by 16 MBytes of
10
//              memory (4 MWord).
11
//
12
//              This simulator is useful for testing in a Verilator/C++
13
//              environment, where this simulator can be used in place of
14
//              the actual hardware.
15
//
16
// Creator:     Dan Gisselquist, Ph.D.
17
//              Gisselquist Technology, LLC
18
//
19
////////////////////////////////////////////////////////////////////////////////
20
//
21 16 dgisselq
// Copyright (C) 2015-2017, Gisselquist Technology, LLC
22 12 dgisselq
//
23
// This program is free software (firmware): you can redistribute it and/or
24
// modify it under the terms of  the GNU General Public License as published
25
// by the Free Software Foundation, either version 3 of the License, or (at
26
// your option) any later version.
27
//
28
// This program is distributed in the hope that it will be useful, but WITHOUT
29
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
30
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
31
// for more details.
32
//
33
// You should have received a copy of the GNU General Public License along
34 16 dgisselq
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
35 12 dgisselq
// target there if the PDF file isn't present.)  If not, see
36
// <http://www.gnu.org/licenses/> for a copy.
37
//
38
// License:     GPL, v3, as defined and found on www.gnu.org,
39
//              http://www.gnu.org/licenses/gpl.html
40
//
41
//
42
////////////////////////////////////////////////////////////////////////////////
43
//
44
//
45
#include <stdio.h>
46
#include <string.h>
47
#include <assert.h>
48
#include <stdlib.h>
49 16 dgisselq
#include <stdint.h>
50 12 dgisselq
 
51
#include "eqspiflashsim.h"
52
 
53
static  const unsigned
54
        DEVESD = 0x014,
55
        // MICROSECONDS = 200,
56
        // MILLISECONDS = MICROSECONDS * 1000,
57
        // SECONDS = MILLISECONDS * 1000,
58
        MICROSECONDS = 20,
59
        MILLISECONDS = MICROSECONDS * 10,
60
        SECONDS = MILLISECONDS * 10,
61
        tSHSL1 =    4, // S# deselect time after a read command
62
        tSHSL2 =   10, // S# deselect time after a non-read command
63
        tW     =   1300 * MICROSECONDS, // write config cycle time
64
        tWNVCR =    200 * MILLISECONDS, // write nonvolatile-config cycle time
65
        tWVECR =    8, // write volatile enhanced config cycle time
66
        tBE    =   32 * SECONDS,        // Bulk erase time
67
        tDP    =   10 * SECONDS,        // Deep power down
68
        tRES   =   30 * SECONDS,
69
// Shall we artificially speed up this process?
70
// These numbers are the "typical" times
71
        tPP    = 500 * MICROSECONDS,    // Page program time
72
        tSE    = 700 * MILLISECONDS,    // Sector erase time
73
        tSS    = 250 * MILLISECONDS;    // Subsector erase time
74
// These are the maximum times
75
        // tW     = 8300 * MICROSECONDS, // write config cycle time
76
        // tWNVCR = 3000 * MILLISECONDS, // write nonvolatile-config cycle time
77
        // tWVECR =    8, // write volatile enhanced config cycle time
78
        // tPP    = 5000 * MICROSECONDS,
79
        // tSE    = 3000 * MILLISECONDS;
80
        // tSS    =  800 * MILLISECONDS;
81
 
82
static  const   char    IDSTR[20]= {
83
                0x20,           // Micron's ID, assigned by JEDEC
84
                (char)0xba, (char)0x18, // Memory type and capacity
85
                (char)0x10,             // Length of data to follow
86
                (char)0xfe, (char)0xfd, // Extended device ID and device config info
87
                (char)0xfc, (char)0xfb, (char)0xfa, (char)0xf9,
88
                (char)0xf8, (char)0xf7, (char)0xf6, (char)0xf5,
89
                (char)0xf4, (char)0xf3, (char)0xf2, (char)0xf1,
90
                (char)0xf0, (char)0xef
91
        };
92
 
93 16 dgisselq
EQSPIFLASHSIM::EQSPIFLASHSIM(const int lglen, bool debug) {
94
        int     nsectors;
95
        m_membytes = (1<<lglen);
96
        m_memmask = (m_membytes - 1);
97
        m_mem = new char[m_membytes];
98 12 dgisselq
        m_pmem = new char[256];
99
        m_otp  = new char[65];
100
        for(int i=0; i<65; i++)
101
                m_otp[i] = 0x0ff;
102
        m_otp[64] = 1;
103
        m_otp_wp = false;
104 16 dgisselq
        nsectors = m_membytes>>16;
105
        m_lockregs = new char[nsectors];
106
        for(int i=0; i<nsectors; i++)
107 12 dgisselq
                m_lockregs[i] = 0;
108
 
109
        m_state = EQSPIF_IDLE;
110
        m_last_sck = 1;
111
        m_write_count = 0;
112
        m_ireg = m_oreg = 0;
113
        m_sreg = 0x01c;
114
        m_creg = 0x001; // Initial creg on delivery
115 16 dgisselq
        m_vconfig   = 0x83; // Volatile configuration register
116 12 dgisselq
        m_nvconfig = 0x0fff; // Nonvolatile configuration register
117 16 dgisselq
        m_quad_mode = EQSPIF_QMODE_SPI;
118 12 dgisselq
        m_mode_byte = 0;
119
        m_flagreg = 0x0a5;
120
 
121
        m_debug = true;
122
 
123 16 dgisselq
        memset(m_mem, 0x0ff, m_membytes);
124 12 dgisselq
}
125
 
126
void    EQSPIFLASHSIM::load(const unsigned addr, const char *fname) {
127
        FILE    *fp;
128 16 dgisselq
        size_t  len, nr = 0;
129 12 dgisselq
 
130 16 dgisselq
        if (addr >= m_membytes)
131 12 dgisselq
                return; // return void
132
 
133 16 dgisselq
        // If not given, then length is from the given address until the end
134
        // of the flash memory
135
        len = m_membytes-addr*4;
136
 
137 12 dgisselq
        if (NULL != (fp = fopen(fname, "r"))) {
138
                nr = fread(&m_mem[addr*4], sizeof(char), len, fp);
139
                fclose(fp);
140
                if (nr == 0) {
141 16 dgisselq
                        fprintf(stderr, "EQSPI-FLASH: Could not read %s\n", fname);
142 12 dgisselq
                        perror("O/S Err:");
143
                }
144
        } else {
145 16 dgisselq
                fprintf(stderr, "EQSPI-FLASH: Could not open %s\n", fname);
146 12 dgisselq
                perror("O/S Err:");
147
        }
148 16 dgisselq
 
149
        for(unsigned i=nr; i<m_membytes; i++)
150
                m_mem[i] = 0x0ff;
151 12 dgisselq
}
152
 
153 16 dgisselq
void    EQSPIFLASHSIM::load(const uint32_t offset, const char *data, const uint32_t len) {
154
        uint32_t        moff = (offset & (m_memmask));
155
 
156
        memcpy(&m_mem[moff], data, len);
157
}
158
 
159 12 dgisselq
#define QOREG(A)        m_oreg = ((m_oreg & (~0x0ff))|(A&0x0ff))
160
 
161
int     EQSPIFLASHSIM::operator()(const int csn, const int sck, const int dat) {
162
        // Keep track of a timer to determine when page program and erase
163
        // cycles complete.
164
 
165
        if (m_write_count > 0) {
166
                if (0 == (--m_write_count)) {// When done with erase/page pgm,
167
                        // Clear the write in progress bit, together with the
168
                        // write enable bit.
169
                        m_sreg &= 0x0fc;
170
                        if (m_debug) printf("Write complete, clearing WIP (inside SIM)\n");
171
                }
172
        }
173
 
174
        if (csn) {
175
                m_last_sck = 1;
176
                m_ireg = 0; m_oreg = 0;
177
 
178
                if ((EQSPIF_PP == m_state)||(EQSPIF_QPP == m_state)) {
179
                        // Start a page program
180
                        if (m_debug) printf("EQSPI: Page Program write cycle begins\n");
181
                        if (m_debug) printf("CK = %d & 7 = %d\n", m_count, m_count & 0x07);
182
                        if (m_debug) printf("EQSPI: pmem = %08lx\n", (unsigned long)m_pmem);
183
                        assert((m_lockregs[(m_addr>>16)&0x0ff]&0x1)==0);
184
                        assert((m_count & 7)==0);
185
                        m_write_count = tPP;
186
                        m_state = EQSPIF_IDLE;
187
                        m_sreg &= (~EQSPIF_WEL_FLAG);
188
                        m_sreg |= (EQSPIF_WIP_FLAG);
189
                        for(int i=0; i<256; i++) {
190
                                /*
191
                                if (m_debug) printf("%02x: m_mem[%02x] = %02x &= %02x = %02x\n",
192
                                        i, (m_addr&(~0x0ff))+i,
193
                                        m_mem[(m_addr&(~0x0ff))+i]&0x0ff, m_pmem[i]&0x0ff,
194
                                        m_mem[(m_addr&(~0x0ff))+i]& m_pmem[i]&0x0ff);
195
                                */
196
                                m_mem[(m_addr&(~0x0ff))+i] &= m_pmem[i];
197
                        }
198 16 dgisselq
                        m_quad_mode = EQSPIF_QMODE_SPI;
199 12 dgisselq
                } else if (EQSPIF_WRCR == m_state) {
200 16 dgisselq
                        if (m_debug) printf("Actually writing volatile config register: VCONFIG = 0x%04x\n", m_vconfig);
201 12 dgisselq
                        if (m_debug) printf("CK = %d & 7 = %d\n", m_count, m_count & 0x07);
202
                        m_state = EQSPIF_IDLE;
203
                } else if (EQSPIF_WRNVCONFIG == m_state) {
204 16 dgisselq
                        if (m_debug) printf("Actually writing nonvolatile config register: VCONFIG = 0x%02x\n", m_nvconfig);
205 12 dgisselq
                        m_write_count = tWNVCR;
206
                        m_state = EQSPIF_IDLE;
207
                } else if (EQSPIF_WREVCONFIG == m_state) {
208
                        if (m_debug) printf("Actually writing Enhanced volatile config register\n");
209
                        m_state = EQSPIF_IDLE;
210
                } else if (EQSPIF_WRSR == m_state) {
211
                        if (m_debug) printf("Actually writing status register\n");
212
                        m_write_count = tW;
213
                        m_state = EQSPIF_IDLE;
214
                        m_sreg &= (~EQSPIF_WEL_FLAG);
215
                        m_sreg |= (EQSPIF_WIP_FLAG);
216
                } else if (EQSPIF_WRLOCK == m_state) {
217
                        if (m_debug) printf("Actually writing lock register\n");
218
                        m_write_count = tW;
219
                        m_state = EQSPIF_IDLE;
220
                } else if (EQSPIF_CLRFLAGS == m_state) {
221
                        if (m_debug) printf("Actually clearing the flags register bits\n");
222
                        m_state = EQSPIF_IDLE;
223
                        m_flagreg &= 0x09f;
224
                } else if (m_state == EQSPIF_SUBSECTOR_ERASE) {
225
                        if (m_debug) printf("Actually Erasing subsector, from %08x\n", m_addr);
226
                        if (m_debug) printf("CK = %d & 7 = %d\n", m_count, m_count & 0x07);
227
                        assert(((m_count & 7)==0)&&(m_count == 32));
228
                        assert((m_lockregs[(m_addr>>16)&0x0ff]&0x1)==0);
229
                        m_write_count = tSS;
230
                        m_state = EQSPIF_IDLE;
231
                        m_sreg &= (~EQSPIF_WEL_FLAG);
232
                        m_sreg |= (EQSPIF_WIP_FLAG);
233
                        m_addr &= (-1<<12);
234
                        for(int i=0; i<(1<<12); i++)
235
                                m_mem[m_addr + i] = 0x0ff;
236
                        if (m_debug) printf("Now waiting %d ticks delay\n", m_write_count);
237
                } else if (m_state == EQSPIF_SECTOR_ERASE) {
238
                        if (m_debug) printf("Actually Erasing sector, from %08x\n", m_addr);
239
                        m_write_count = tSE;
240
                        if (m_debug) printf("CK = %d & 7 = %d\n", m_count, m_count & 0x07);
241
                        assert(((m_count & 7)==0)&&(m_count == 32));
242
                        assert((m_lockregs[(m_addr>>16)&0x0ff]&0x1)==0);
243
                        m_state = EQSPIF_IDLE;
244
                        m_sreg &= (~EQSPIF_WEL_FLAG);
245
                        m_sreg |= (EQSPIF_WIP_FLAG);
246
                        m_addr &= (-1<<16);
247
                        for(int i=0; i<(1<<16); i++)
248
                                m_mem[m_addr + i] = 0x0ff;
249
                        if (m_debug) printf("Now waiting %d ticks delay\n", m_write_count);
250
                } else if (m_state == EQSPIF_BULK_ERASE) {
251
                        m_write_count = tBE;
252
                        m_state = EQSPIF_IDLE;
253
                        m_sreg &= (~EQSPIF_WEL_FLAG);
254
                        m_sreg |= (EQSPIF_WIP_FLAG);
255
                        // Should I be checking the lock register(s) here?
256 16 dgisselq
                        for(unsigned i=0; i<m_membytes; i++)
257 12 dgisselq
                                m_mem[i] = 0x0ff;
258
                } else if (m_state == EQSPIF_PROGRAM_OTP) {
259
                        // Program the One-Time Programmable (OTP memory
260
                        if (m_debug) printf("EQSPI: OTP Program write cycle begins\n");
261
                        if (m_debug) printf("CK = %d & 7 = %d\n", m_count, m_count & 0x07);
262
                        // assert((m_lockregs[(m_addr>>16)&0x0ff]&0x1)==0);
263
                        assert((m_count & 7)==0);
264
                        m_write_count = tPP; // OTP cycle time as well
265
                        m_state = EQSPIF_IDLE;
266
                        m_sreg &= (~EQSPIF_WEL_FLAG);
267
                        m_sreg |= (EQSPIF_WIP_FLAG);
268
                        for(int i=0; i<65; i++)
269
                                m_otp[i] &= m_pmem[i];
270
                        m_otp_wp = ((m_otp[64]&1)==0);
271
                /*
272
                } else if (m_state == EQSPIF_DEEP_POWER_DOWN) {
273
                        m_write_count = tDP;
274
                        m_state = EQSPIF_IDLE;
275
                } else if (m_state == EQSPIF_RELEASE) {
276
                        m_write_count = tRES;
277
                        m_state = EQSPIF_IDLE;
278
                */
279
                } else if (m_state == EQSPIF_QUAD_READ) {
280
                        m_state = EQSPIF_IDLE;
281
                        if (m_mode_byte!=0)
282 16 dgisselq
                                m_quad_mode = EQSPIF_QMODE_SPI;
283
                        else {
284
                                if (m_quad_mode == EQSPIF_QMODE_SPI_ADDR)
285
                                        m_quad_mode = EQSPIF_QMODE_SPI;
286 12 dgisselq
                                m_state = EQSPIF_XIP;
287 16 dgisselq
                        }
288 12 dgisselq
                }
289
 
290
                m_oreg = 0x0fe;
291
                m_count= 0;
292
                int out = m_nxtout[3];
293
                m_nxtout[3] = m_nxtout[2];
294
                m_nxtout[2] = m_nxtout[1];
295
                m_nxtout[1] = m_nxtout[0];
296
                m_nxtout[0] = dat;
297
                return out;
298
        } else if ((!m_last_sck)||(sck == m_last_sck)) {
299
                // Only change on the falling clock edge
300
                // printf("SFLASH-SKIP, CLK=%d -> %d\n", m_last_sck, sck);
301
                m_last_sck = sck;
302
                int out = m_nxtout[3];
303
                m_nxtout[3] = m_nxtout[2];
304
                m_nxtout[2] = m_nxtout[1];
305
                m_nxtout[1] = m_nxtout[0];
306
                if (m_quad_mode)
307
                        m_nxtout[0] = (m_oreg>>8)&0x0f;
308
                else
309
                        // return ((m_oreg & 0x0100)?2:0) | (dat & 0x0d);
310
                        m_nxtout[0] = (m_oreg & 0x0100)?2:0;
311
                return out;
312
        }
313
 
314
        // We'll only get here if ...
315
        //      last_sck = 1, and sck = 0, thus transitioning on the
316
        //      negative edge as with everything else in this interface
317
        if (m_quad_mode) {
318
                m_ireg = (m_ireg << 4) | (dat & 0x0f);
319
                m_count+=4;
320
                m_oreg <<= 4;
321
        } else {
322
                m_ireg = (m_ireg << 1) | (dat & 1);
323
                m_count++;
324
                m_oreg <<= 1;
325
        }
326
 
327
 
328
        // printf("PROCESS, COUNT = %d, IREG = %02x\n", m_count, m_ireg);
329
        if (m_state == EQSPIF_XIP) {
330
                assert(m_quad_mode);
331
                if (m_count == 24) {
332
                        if (m_debug) printf("EQSPI: Entering from Quad-Read Idle to Quad-Read\n");
333
                        if (m_debug) printf("EQSPI: QI/O Idle Addr = %02x\n", m_ireg&0x0ffffff);
334 16 dgisselq
                        m_addr = (m_ireg) & m_memmask;
335
                        assert((m_addr & (~(m_memmask)))==0);
336
                } else if (m_count == 24 + 4*8) {// After the idle bits
337 12 dgisselq
                        m_state = EQSPIF_QUAD_READ;
338 16 dgisselq
                        if (m_debug) printf("EQSPI: QI/O Dummy = %04x\n", m_ireg);
339
                        m_mode_byte = (m_ireg>>24) & 0x10;
340 12 dgisselq
                } m_oreg = 0;
341
        } else if (m_count == 8) {
342
                QOREG(0x0a5);
343
                // printf("SFLASH-CMD = %02x\n", m_ireg & 0x0ff);
344
                // Figure out what command we've been given
345
                if (m_debug) printf("SPI FLASH CMD %02x\n", m_ireg&0x0ff);
346
                switch(m_ireg & 0x0ff) {
347
                case 0x01: // Write status register
348
                        if (2 !=(m_sreg & 0x203)) {
349
                                if (m_debug) printf("EQSPI: WEL not set, cannot write status reg\n");
350
                                m_state = EQSPIF_INVALID;
351
                        } else
352
                                m_state = EQSPIF_WRSR;
353
                        break;
354
                case 0x02: // Normal speed (normal SPI, 1wire MOSI) Page program
355
                        if (2 != (m_sreg & 0x203)) {
356
                                if (m_debug) printf("EQSPI: Cannot program at this time, SREG = %x\n", m_sreg);
357
                                m_state = EQSPIF_INVALID;
358
                        } else {
359
                                m_state = EQSPIF_PP;
360
                                if (m_debug) printf("PAGE-PROGRAM COMMAND ACCEPTED\n");
361
                        }
362
                        break;
363
                case 0x03: // Read data bytes
364
                        // Our clock won't support this command, so go
365
                        // to an invalid state
366
                        if (m_debug) printf("EQSPI INVALID: This sim does not support slow reading\n");
367
                        m_state = EQSPIF_INVALID;
368
                        break;
369
                case 0x04: // Write disable
370
                        m_state = EQSPIF_IDLE;
371
                        m_sreg &= (~EQSPIF_WEL_FLAG);
372
                        break;
373
                case 0x05: // Read status register
374
                        m_state = EQSPIF_RDSR;
375
                        if (m_debug) printf("EQSPI: READING STATUS REGISTER: %02x\n", m_sreg);
376
                        QOREG(m_sreg);
377
                        break;
378
                case 0x06: // Write enable
379
                        m_state = EQSPIF_IDLE;
380
                        m_sreg |= EQSPIF_WEL_FLAG;
381
                        if (m_debug) printf("EQSPI: WRITE-ENABLE COMMAND ACCEPTED\n");
382
                        break;
383
                case 0x0b: // Here's the read that we support
384
                        if (m_debug) printf("EQSPI: FAST-READ (single-bit)\n");
385
                        m_state = EQSPIF_FAST_READ;
386
                        break;
387
                case 0x20: // Subsector Erase
388
                        if (2 != (m_sreg & 0x203)) {
389
                                if (m_debug) printf("EQSPI: WEL not set, cannot do a subsector erase\n");
390
                                m_state = EQSPIF_INVALID;
391
                                assert(0&&"WEL not set");
392 16 dgisselq
                        } else {
393 12 dgisselq
                                m_state = EQSPIF_SUBSECTOR_ERASE;
394 16 dgisselq
                                if (m_debug) printf("EQSPI: SUBSECTOR_ERASE COMMAND\n");
395
                        }
396 12 dgisselq
                        break;
397
                case 0x32: // QUAD Page program, 4 bits at a time
398
                        if (2 != (m_sreg & 0x203)) {
399
                                if (m_debug) printf("EQSPI: Cannot program at this time, SREG = %x\n", m_sreg);
400
                                m_state = EQSPIF_INVALID;
401
                                assert(0&&"WEL not set");
402
                        } else {
403
                                m_state = EQSPIF_QPP;
404
                                if (m_debug) printf("EQSPI: QUAD-PAGE-PROGRAM COMMAND ACCEPTED\n");
405
                                if (m_debug) printf("EQSPI: pmem = %08lx\n", (unsigned long)m_pmem);
406
                        }
407
                        break;
408
                case 0x42: // Program OTP array
409
                        if (2 != (m_sreg & 0x203)) {
410
                                if (m_debug) printf("EQSPI: WEL not set, cannot program OTP\n");
411
                                m_state = EQSPIF_INVALID;
412
                        } else if (m_otp_wp) {
413
                                if (m_debug) printf("EQSPI: OTP Write protect is set, cannot program OTP ever again\n");
414
                                m_state = EQSPIF_INVALID;
415
                        } else
416
                                m_state = EQSPIF_PROGRAM_OTP;
417
                        break;
418
                case 0x4b: // Read OTP array
419
                        m_state = EQSPIF_READ_OTP;
420
                        QOREG(0);
421
                        if (m_debug) printf("EQSPI: Read OTP array command\n");
422
                        break;
423
                case 0x50: // Clear flag status register
424
                        m_state = EQSPIF_CLRFLAGS;
425
                        if (m_debug) printf("EQSPI: Clearing FLAGSTATUS REGISTER: %02x\n", m_flagreg);
426
                        QOREG(m_flagreg);
427
                        break;
428
                case 0x61: // WRITE Enhanced volatile config register
429
                        m_state = EQSPIF_WREVCONFIG;
430
                        if (m_debug) printf("EQSPI: WRITING EVCONFIG REGISTER\n");
431
                        break;
432
                case 0x65: // Read Enhanced volatile config register
433
                        m_state = EQSPIF_RDEVCONFIG;
434
                        if (m_debug) printf("EQSPI: READING EVCONFIG REGISTER: %02x\n", m_evconfig);
435
                        QOREG(m_evconfig);
436
                        break;
437
                case 0x06b:
438 16 dgisselq
                        m_state = EQSPIF_QUAD_OREAD_CMD;
439 12 dgisselq
                        // m_quad_mode = true; // Not yet, need to wait past dummy registers
440
                        break;
441
                case 0x70: // Read flag status register
442
                        m_state = EQSPIF_RDFLAGS;
443
                        if (m_debug) printf("EQSPI: READING FLAGSTATUS REGISTER: %02x\n", m_flagreg);
444
                        QOREG(m_flagreg);
445
                        break;
446
                case 0x81: // Write volatile config register
447
                        m_state = EQSPIF_WRCR;
448 14 dgisselq
                        if (m_debug) printf("EQSPI: WRITING VOLATILE CONFIG REGISTER: %02x\n", m_vconfig);
449 12 dgisselq
                        break;
450
                case 0x85: // Read volatile config register
451
                        m_state = EQSPIF_RDCR;
452 14 dgisselq
                        if (m_debug) printf("EQSPI: READING VOLATILE CONFIG REGISTER: %02x\n", m_vconfig);
453
                        QOREG(m_vconfig);
454 12 dgisselq
                        break;
455
                case 0x9e: // Read ID (fall through)
456
                case 0x9f: // Read ID
457
                        m_state = EQSPIF_RDID; m_addr = 0;
458
                        if (m_debug) printf("EQSPI: READING ID\n");
459
                        QOREG(IDSTR[0]);
460
                        break;
461
                case 0xb1: // Write nonvolatile config register
462
                        m_state = EQSPIF_WRNVCONFIG;
463
                        if (m_debug) printf("EQSPI: WRITING NVCONFIG REGISTER: %02x\n", m_nvconfig);
464
                        break;
465
                case 0xb5: // Read nonvolatile config register
466
                        m_state = EQSPIF_RDNVCONFIG;
467
                        if (m_debug) printf("EQSPI: READING NVCONFIG REGISTER: %02x\n", m_nvconfig);
468
                        QOREG(m_nvconfig>>8);
469
                        break;
470
                case 0xc7: // Bulk Erase
471
                        if (2 != (m_sreg & 0x203)) {
472
                                if (m_debug) printf("EQSPI: WEL not set, cannot erase device\n");
473
                                m_state = EQSPIF_INVALID;
474
                        } else
475
                                m_state = EQSPIF_BULK_ERASE;
476
                        break;
477
                case 0xd8: // Sector Erase
478
                        if (2 != (m_sreg & 0x203)) {
479
                                if (m_debug) printf("EQSPI: WEL not set, cannot erase sector\n");
480
                                m_state = EQSPIF_INVALID;
481
                                assert(0&&"WEL not set");
482
                        } else {
483
                                m_state = EQSPIF_SECTOR_ERASE;
484
                                if (m_debug) printf("EQSPI: SECTOR_ERASE COMMAND\n");
485
                        }
486
                        break;
487
                case 0xe5: // Write lock register
488
                        m_state = EQSPIF_WRLOCK;
489
                        if (m_debug) printf("EQSPI: WRITING LOCK REGISTER\n");
490
                        break;
491
                case 0xe8: // Read lock register
492
                        m_state = EQSPIF_RDLOCK;
493
                        if (m_debug) printf("EQSPI: READ LOCK REGISTER (Waiting on address)\n");
494
                        break;
495
                case 0x0eb: // Here's the (other) read that we support
496 16 dgisselq
                        m_state = EQSPIF_QUAD_IOREAD_CMD;
497
                        m_quad_mode = EQSPIF_QMODE_QSPI_ADDR;
498 12 dgisselq
                        break;
499
                default:
500
                        printf("EQSPI: UNRECOGNIZED SPI FLASH CMD: %02x\n", m_ireg&0x0ff);
501
                        m_state = EQSPIF_INVALID;
502
                        assert(0 && "Unrecognized command\n");
503
                        break;
504
                }
505
        } else if ((0 == (m_count&0x07))&&(m_count != 0)) {
506
                QOREG(0);
507
                switch(m_state) {
508
                case EQSPIF_IDLE:
509
                        printf("TOO MANY CLOCKS, SPIF in IDLE\n");
510
                        break;
511
                case EQSPIF_WRSR:
512
                        if (m_count == 16) {
513
                                m_sreg = (m_sreg & 0x07c) | (m_ireg & 0x07c);
514
                                if (m_debug) printf("Request to set sreg to 0x%02x\n",
515
                                        m_ireg&0x0ff);
516
                        } else {
517
                                printf("TOO MANY CLOCKS FOR WRR!!!\n");
518
                                exit(-2);
519
                                m_state = EQSPIF_IDLE;
520
                        }
521
                        break;
522
                case EQSPIF_WRCR: // Write volatile config register, 0x81
523 16 dgisselq
                        if (m_count == 8+8+8) {
524 14 dgisselq
                                m_vconfig = m_ireg & 0x0ff;
525 16 dgisselq
                                if (m_debug) printf("Setting volatile config register to %08x\n", m_vconfig);
526 14 dgisselq
                                assert((m_vconfig & 0xfb)==0x8b);
527 12 dgisselq
                        } break;
528
                case EQSPIF_WRNVCONFIG: // Write nonvolatile config register
529 16 dgisselq
                        if (m_count == 8+8+8) {
530 12 dgisselq
                                m_nvconfig = m_ireg & 0x0ffdf;
531 16 dgisselq
                                if (m_debug) printf("Setting nonvolatile config register to %08x\n", m_nvconfig);
532 12 dgisselq
                                assert((m_nvconfig & 0xffc5)==0x8fc5);
533
                        } break;
534
                case EQSPIF_WREVCONFIG: // Write enhanced volatile config reg
535 14 dgisselq
                        if (m_count == 8+8) {
536 12 dgisselq
                                m_evconfig = m_ireg & 0x0ff;
537 16 dgisselq
                                if (m_debug) printf("Setting enhanced volatile config register to %08x\n", m_evconfig);
538 12 dgisselq
                                assert((m_evconfig & 0x0d7)==0xd7);
539
                        } break;
540
                case EQSPIF_WRLOCK:
541
                        if (m_count == 32) {
542
                                m_addr = (m_ireg>>24)&0x0ff;
543
                                if ((m_lockregs[m_addr]&2)==0)
544
                                        m_lockregs[m_addr] = m_ireg&3;
545 16 dgisselq
                                if (m_debug) printf("Setting lock register[%02x] to %d\n", m_addr, m_lockregs[m_addr]);
546 12 dgisselq
                        } break;
547
                case EQSPIF_RDLOCK:
548
                        if (m_count == 24) {
549
                                m_addr = (m_ireg>>16)&0x0ff;
550
                                QOREG(m_lockregs[m_addr]);
551 16 dgisselq
                                if (m_debug) printf("Reading lock register[%02x]: %d\n", m_addr, m_lockregs[m_addr]);
552 12 dgisselq
                        } else
553
                                QOREG(m_lockregs[m_addr]);
554
                        break;
555
                case EQSPIF_CLRFLAGS:
556
                        assert(0 && "Too many clocks for CLSR command!!\n");
557
                        break;
558
                case EQSPIF_READ_OTP:
559
                        if (m_count == 32) {
560
                                m_addr = m_ireg & 0x0ffffff;
561
                                assert(m_addr < 65);
562
                                m_otp[64] = (m_otp_wp)?0:1;
563
 
564
                                if (m_debug) printf("READOTP, SETTING ADDR = %08x (%02x:%02x:%02x:%02x)\n", m_addr,
565
                                        ((m_addr<65)?m_otp[m_addr]:0)&0x0ff,
566
                                        ((m_addr<64)?m_otp[m_addr+1]:0)&0x0ff,
567
                                        ((m_addr<63)?m_otp[m_addr+2]:0)&0x0ff,
568
                                        ((m_addr<62)?m_otp[m_addr+3]:0)&0x0ff);
569
                                if (m_debug) printf("READOTP, Array is %s, m_otp[64] = %d\n",
570
                                        (m_otp_wp)?"Locked":"Unlocked",
571
                                        m_otp[64]);
572
                                QOREG(m_otp[m_addr]);
573
                        } else if (m_count < 40) {
574
                        } // else if (m_count == 40)
575
                        else if ((m_count&7)==0) {
576
                                if (m_debug) printf("READOTP, ADDR = %08x\n", m_addr);
577
                                if (m_addr < 65)
578
                                        QOREG(m_otp[m_addr]);
579
                                else
580
                                        QOREG(0);
581
                                if (m_debug) printf("EQSPI: READING OTP, %02x%s\n",
582
                                        (m_addr<65)?m_otp[m_addr]&0x0ff:0xfff,
583
                                        (m_addr > 65)?"-- PAST OTP LENGTH!":"");
584
                                m_addr++;
585
                        }
586
                        break;
587
                case EQSPIF_RDID:
588
                        if ((m_count&7)==0) {
589
                                m_addr++;
590
                                if (m_debug) printf("READID, ADDR = %08x\n", m_addr);
591
                                if (m_addr < sizeof(IDSTR))
592
                                        QOREG(IDSTR[m_addr]);
593
                                else
594
                                        QOREG(0);
595
                                if (m_debug) printf("EQSPI: READING ID, %02x%s\n",
596
                                        IDSTR[m_addr]&0x0ff,
597
                                        (m_addr >= sizeof(IDSTR))?"-- PAST ID LENGTH!":"");
598
                        }
599
                        break;
600
                case EQSPIF_RDSR:
601
                        // printf("Read SREG = %02x, wait = %08x\n", m_sreg,
602
                                // m_write_count);
603
                        QOREG(m_sreg);
604
                        break;
605
                case EQSPIF_RDCR:
606 14 dgisselq
                        if (m_debug) printf("Read VCONF = %02x\n", m_vconfig);
607 12 dgisselq
                        QOREG(m_creg);
608
                        break;
609
                case EQSPIF_FAST_READ:
610
                        if (m_count < 32) {
611
                                QOREG(0x0c3);
612
                        } else if (m_count == 32) {
613 16 dgisselq
                                m_addr = m_ireg & m_memmask;
614 12 dgisselq
                                if (m_debug) printf("FAST READ, ADDR = %08x\n", m_addr);
615
                                QOREG(0x0c3);
616 16 dgisselq
                                if (m_addr & (~(m_memmask))) {
617
                                        printf("EQSPI: ADDR = %08x ? !!\n", m_addr);
618
                                } assert((m_addr & (~(m_memmask)))==0);
619 12 dgisselq
                        } else if ((m_count >= 40)&&(0 == (m_sreg&0x01))) {
620 16 dgisselq
                                if ((m_debug)&&(m_count == 40))
621 12 dgisselq
                                        printf("DUMMY BYTE COMPLETE ...\n");
622
                                QOREG(m_mem[m_addr++]);
623
                                if (m_debug) printf("SPIF[%08x] = %02x -> %02x\n", m_addr-1, m_mem[m_addr-1]&0x0ff, m_oreg);
624
                        } else if (0 != (m_sreg&0x01)) {
625
                                m_oreg = 0;
626
                                if (m_debug) printf("CANNOT READ WHEN WRITE IN PROGRESS, m_sreg = %02x\n", m_sreg);
627
                        } else printf("How did I get here, m_count = %d\n", m_count);
628
                        break;
629 16 dgisselq
                case EQSPIF_QUAD_IOREAD_CMD:
630 12 dgisselq
                        if (m_count == 32) {
631 16 dgisselq
                                m_addr = m_ireg & m_memmask;
632
                                if (m_debug) printf("EQSPI: QUAD I/O READ, ADDR = %06x (%02x:%02x:%02x:%02x)\n", m_addr,
633 12 dgisselq
                                        (m_addr<0x1000000)?(m_mem[m_addr]&0x0ff):0,
634
                                        (m_addr<0x0ffffff)?(m_mem[m_addr+1]&0x0ff):0,
635
                                        (m_addr<0x0fffffe)?(m_mem[m_addr+2]&0x0ff):0,
636
                                        (m_addr<0x0fffffd)?(m_mem[m_addr+3]&0x0ff):0);
637 16 dgisselq
                                assert((m_addr & (~(m_memmask)))==0);
638
                        } else if (m_count == 8+24+8*4) {
639 12 dgisselq
                                QOREG(m_mem[m_addr++]);
640 16 dgisselq
                                m_quad_mode = EQSPIF_QMODE_QSPI_ADDR;
641 12 dgisselq
                                m_mode_byte = (m_ireg & 0x080);
642 16 dgisselq
                                m_state = EQSPIF_QUAD_READ;
643 12 dgisselq
                        } else {
644
                                m_oreg = 0;
645
                        }
646
                        break;
647 16 dgisselq
                case EQSPIF_QUAD_OREAD_CMD:
648
                        if (m_count == 8+24) {
649
                                m_addr = m_ireg & m_memmask;
650
                                // printf("FAST READ, ADDR = %08x\n", m_addr);
651
                                if (m_debug) printf("EQSPI: QUAD READ, ADDR = %06x (%02x:%02x:%02x:%02x)\n", m_addr,
652
                                        (m_addr<0x1000000)?(m_mem[m_addr]&0x0ff):0,
653
                                        (m_addr<0x0ffffff)?(m_mem[m_addr+1]&0x0ff):0,
654
                                        (m_addr<0x0fffffe)?(m_mem[m_addr+2]&0x0ff):0,
655
                                        (m_addr<0x0fffffd)?(m_mem[m_addr+3]&0x0ff):0);
656
                                assert((m_addr & (~(m_memmask)))==0);
657
                        } else if (m_count == 8+24+4*8) {
658
                                QOREG(m_mem[m_addr]);
659
                                m_quad_mode = EQSPIF_QMODE_SPI_ADDR;
660
                                m_mode_byte = (m_ireg & 0x080);
661
                                if (m_debug) printf("EQSPI: (QUAD) MODE BYTE = %02x\n", m_mode_byte);
662
                                m_state = EQSPIF_QUAD_READ;
663
                        }
664
                        break;
665 12 dgisselq
                case EQSPIF_QUAD_READ:
666 16 dgisselq
                        if ((m_count >= 64)&&(0 == (m_sreg&0x01))) {
667 12 dgisselq
                                QOREG(m_mem[m_addr++]);
668 16 dgisselq
                                // printf("EQSPIF[%08x]/QR = %02x\n", m_addr-1, m_oreg & 0x0ff);
669 12 dgisselq
                        } else {
670
                                m_oreg = 0;
671 16 dgisselq
                                if (m_debug) printf("EQSPI/QR ... m_count = %d\n", m_count);
672 12 dgisselq
                        }
673
                        break;
674
                case EQSPIF_PP:
675
                        if (m_count == 32) {
676 16 dgisselq
                                m_addr = m_ireg & m_memmask;
677 12 dgisselq
                                if (m_debug) printf("EQSPI: PAGE-PROGRAM ADDR = %06x\n", m_addr);
678 16 dgisselq
                                assert((m_addr & (~(m_memmask)))==0);
679 12 dgisselq
                                // m_page = m_addr >> 8;
680
                                for(int i=0; i<256; i++)
681
                                        m_pmem[i] = 0x0ff;
682
                        } else if (m_count >= 40) {
683
                                m_pmem[m_addr & 0x0ff] = m_ireg & 0x0ff;
684
                                // printf("EQSPI: PMEM[%02x] = 0x%02x -> %02x\n", m_addr & 0x0ff, m_ireg & 0x0ff, (m_pmem[(m_addr & 0x0ff)]&0x0ff));
685
                                m_addr = (m_addr & (~0x0ff)) | ((m_addr+1)&0x0ff);
686
                        } break;
687
                case EQSPIF_QPP:
688
                        if (m_count == 32) {
689 16 dgisselq
                                m_addr = m_ireg & m_memmask;
690
                                m_quad_mode = EQSPIF_QMODE_SPI_ADDR;
691 12 dgisselq
                                if (m_debug) printf("EQSPI/QR: PAGE-PROGRAM ADDR = %06x\n", m_addr);
692 16 dgisselq
                                assert((m_addr & (~(m_memmask)))==0);
693 12 dgisselq
                                for(int i=0; i<256; i++)
694
                                        m_pmem[i] = 0x0ff;
695
                        } else if (m_count >= 40) {
696 16 dgisselq
                                if (m_debug) printf("EQSPI: PROGRAM[%06x] = %02x\n", m_addr, m_ireg & 0x0ff);
697 12 dgisselq
                                m_pmem[m_addr & 0x0ff] = m_ireg & 0x0ff;
698
                                m_addr = (m_addr & (~0x0ff)) | ((m_addr+1)&0x0ff);
699
                        } break;
700
                case EQSPIF_SUBSECTOR_ERASE:
701
                        if (m_count == 32) {
702
                                m_addr = m_ireg & 0x0fff000;
703
                                if (m_debug) printf("SUBSECTOR_ERASE ADDRESS = %08x\n", m_addr);
704
                                assert((m_addr & 0xff000000)==0);
705
                        } break;
706
                case EQSPIF_SECTOR_ERASE:
707
                        if (m_count == 32) {
708
                                m_addr = m_ireg & 0x0ff0000;
709
                                if (m_debug) printf("SECTOR_ERASE ADDRESS = %08x\n", m_addr);
710
                                assert((m_addr & 0xf000000)==0);
711
                        } break;
712
                case EQSPIF_PROGRAM_OTP:
713
                        if (m_count == 32) {
714
                                m_addr = m_ireg & 0x0ff;
715
                                for(int i=0; i<65; i++)
716
                                        m_pmem[i] = 0x0ff;
717
                        } else if ((m_count >= 40)&&(m_addr < 65)) {
718
                                m_pmem[m_addr++] = m_ireg & 0x0ff;
719
                        } break;
720
                /*
721
                case EQSPIF_RELEASE:
722
                        if (m_count >= 32) {
723
                                QOREG(DEVESD);
724
                        } break;
725
                */
726
                default:
727
                        printf("EQSPI ... DEFAULT OP???\n");
728
                        QOREG(0xff);
729
                        break;
730
                }
731
        } // else printf("SFLASH->count = %d\n", m_count);
732
 
733
        m_last_sck = sck;
734
        int     out = m_nxtout[3];
735
        m_nxtout[3] = m_nxtout[2];
736
        m_nxtout[2] = m_nxtout[1];
737
        m_nxtout[1] = m_nxtout[0];
738
        if (m_quad_mode)
739
                m_nxtout[0] =  (m_oreg>>8)&0x0f;
740
        else
741
                m_nxtout[0] =  (m_oreg & 0x0100)?2:0;
742
        return out;
743
}
744
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.