0e6ba954581abc99c95e45fc13f5f411af7690c9
[SCSI2SD.git] / software / SCSI2SD / src / flash.c
1 //    Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
2 //
3 //    This file is part of SCSI2SD.
4 //
5 //    SCSI2SD is free software: you can redistribute it and/or modify
6 //    it under the terms of the GNU General Public License as published by
7 //    the Free Software Foundation, either version 3 of the License, or
8 //    (at your option) any later version.
9 //
10 //    SCSI2SD 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 SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.
17
18 #include "device.h"
19 #include "flash.h"
20
21 #include "config.h"
22 #include "led.h"
23 #include "time.h"
24
25 typedef struct
26 {
27     S2S_Device dev;
28
29     S2S_Target targets[MAX_SCSI_TARGETS];
30     
31     uint32_t capacity; // in 512 byte blocks
32     
33     // CFI info
34     uint8_t manufacturerID;
35     uint8_t deviceID[2];
36     
37
38 } SpiFlash;
39
40 static void spiFlash_earlyInit(S2S_Device* dev);
41 static void spiFlash_init(S2S_Device* dev);
42 static S2S_Target* spiFlash_getTargets(S2S_Device* dev, int* count);
43 static uint32_t spiFlash_getCapacity(S2S_Device* dev);
44 static int spiFlash_pollMediaChange(S2S_Device* dev);
45 static void spiFlash_pollMediaBusy(S2S_Device* dev);
46 static void spiFlash_erase(S2S_Device* dev, uint32_t sectorNumber, uint32_t count);
47 static void spiFlash_read(S2S_Device* dev, uint32_t sectorNumber, uint32_t count, uint8_t* buffer);
48 static void spiFlash_readAsync(S2S_Device* dev, uint32_t sectorNumber, uint32_t count, uint8_t* buffer);
49 static int  spiFlash_readAsyncPoll(S2S_Device* dev);
50 static void spiFlash_write(S2S_Device* dev, uint32_t sectorNumber, uint32_t count, uint8_t* buffer);
51
52 SpiFlash spiFlash = {
53     {
54         spiFlash_earlyInit,
55         spiFlash_init,
56         spiFlash_getTargets,
57         spiFlash_getCapacity,
58         spiFlash_pollMediaChange,
59         spiFlash_pollMediaBusy,
60         spiFlash_erase,
61         spiFlash_read,
62         spiFlash_readAsync,
63         spiFlash_readAsyncPoll,
64         spiFlash_write,
65         0, // initial mediaState
66         CONFIG_STOREDEVICE_FLASH
67     }
68 };
69
70 S2S_Device* spiFlashDevice = &(spiFlash.dev);
71
72 // Private DMA variables.
73 static uint8 spiFlashDMARxChan = CY_DMA_INVALID_CHANNEL;
74 static uint8 spiFlashDMATxChan = CY_DMA_INVALID_CHANNEL;
75 static uint8_t spiFlashDmaRxTd[2] = { CY_DMA_INVALID_TD, CY_DMA_INVALID_TD };
76 static uint8_t spiFlashDmaTxTd[2] = { CY_DMA_INVALID_TD, CY_DMA_INVALID_TD };
77
78 // Source of dummy SPI bytes for DMA
79 static uint8_t dummyBuffer[2]  __attribute__((aligned(4))) = {0xFF, 0xFF};
80 // Dummy location for DMA to sink usless data to
81 static uint8 discardBuffer[2] __attribute__((aligned(4)));
82
83
84 volatile uint8_t spiFlashRxDMAComplete = 1;
85 volatile uint8_t spiFlashTxDMAComplete = 1;
86
87 CY_ISR_PROTO(spiFlashRxISR);
88 CY_ISR(spiFlashRxISR)
89 {
90         spiFlashRxDMAComplete = 1;
91 }
92 CY_ISR_PROTO(spiFlashTxISR);
93 CY_ISR(spiFlashTxISR)
94 {
95         spiFlashTxDMAComplete = 1;
96 }
97
98 // Read and write 1 byte.
99 static uint8_t spiFlashByte(uint8_t value)
100 {
101     NOR_SPI_WriteTxData(value);
102     while (!(NOR_SPI_ReadRxStatus() & NOR_SPI_STS_RX_FIFO_NOT_EMPTY)) {}
103     return NOR_SPI_ReadRxData();
104 }
105
106 static void spiFlash_earlyInit(S2S_Device* dev)
107 {
108     SpiFlash* spiFlash = (SpiFlash*)dev;
109
110     for (int i = 0; i < MAX_SCSI_TARGETS; ++i)
111     {
112         spiFlash->targets[i].device = dev;
113         
114         const S2S_TargetCfg* cfg = getConfigByIndex(i);
115         if (cfg->storageDevice == CONFIG_STOREDEVICE_FLASH)
116         {
117             spiFlash->targets[i].cfg = (S2S_TargetCfg*)cfg;
118         }
119         else
120         {
121             spiFlash->targets[i].cfg = NULL;
122         }
123     }
124
125     // Don't require the host to send us a START STOP UNIT command
126     spiFlash->dev.mediaState = MEDIA_STARTED | MEDIA_WP;
127     
128     // DMA stuff
129         spiFlashDMATxChan =
130                 NOR_TX_DMA_DmaInitialize(
131                         2, // Bytes per burst
132                         1, // request per burst
133                         HI16(CYDEV_SRAM_BASE),
134                         HI16(CYDEV_PERIPH_BASE)
135                         );
136
137         spiFlashDMARxChan =
138                 NOR_RX_DMA_DmaInitialize(
139                         1, // Bytes per burst
140                         1, // request per burst
141                         HI16(CYDEV_PERIPH_BASE),
142                         HI16(CYDEV_SRAM_BASE)
143                         );
144
145         CyDmaChDisable(spiFlashDMATxChan);
146         CyDmaChDisable(spiFlashDMARxChan);
147
148         NOR_RX_DMA_COMPLETE_StartEx(spiFlashRxISR);
149         NOR_TX_DMA_COMPLETE_StartEx(spiFlashTxISR);
150     
151     spiFlashDmaRxTd[0] = CyDmaTdAllocate();
152     spiFlashDmaRxTd[1] = CyDmaTdAllocate();
153     
154     spiFlashDmaTxTd[0] = CyDmaTdAllocate();
155     spiFlashDmaTxTd[1] = CyDmaTdAllocate();
156 }
157
158 static void spiFlash_init(S2S_Device* dev)
159 {
160     SpiFlash* spiFlash = (SpiFlash*)dev;
161     spiFlash->capacity = 0;
162
163     nNOR_WP_Write(1); // We don't need write Protect
164     nNOR_CS_Write(1); // Deselect
165     
166     NOR_SPI_Start();
167     CyDelayUs(50); // tRPH is 35 uS. Wait a bit longer
168
169     // Mode-bit-reset (go back to normal from high performance mode)
170     nNOR_CS_Write(0); // Select
171     CyDelayCycles(4); // Tiny delay
172     spiFlashByte(0xFF);
173     nNOR_CS_Write(1); // Deselect
174     CyDelayCycles(4); // Tiny delay
175
176     // Software-reset
177     nNOR_CS_Write(0); // Select
178     CyDelayCycles(4); // Tiny delay
179     spiFlashByte(0xF0);
180     nNOR_CS_Write(1); // Deselect - reset is triggered on the deselect
181     CyDelayUs(50); // tRPH is 35 uS. Wait a bit longer
182
183     nNOR_CS_Write(0); // Select
184     // JEDEC standard "Read Identification" command
185     // returns CFI information
186     spiFlashByte(0x9F);
187     
188     // 1 byte manufacturer ID
189     spiFlash->manufacturerID = spiFlashByte(0xFF);
190     
191     // 2 bytes device ID
192     spiFlash->deviceID[0] = spiFlashByte(0xFF);
193     spiFlash->deviceID[1] = spiFlashByte(0xFF);
194
195     uint8_t bytesFollowing = spiFlashByte(0xFF);
196     
197     // Chances are this says 0, which means up to 512 bytes.
198     // But ignore it for now and just get the capacity.
199     for (int i = 0; i < 0x23; ++i)
200     {
201         spiFlashByte(0xFF);
202     }
203     
204     // Capacity is 2^n at offset 0x27
205     //spiFlash->capacity = (1 << spiFlashByte(0xFF)) / 512;
206     // Record value in 512-byte sectors.
207     spiFlash->capacity = 1 << (spiFlashByte(0xFF) - 9);
208     
209     if (spiFlash->capacity > 0)
210     {
211         spiFlash->dev.mediaState |= MEDIA_PRESENT | MEDIA_INITIALISED;
212     }
213
214     // Don't bother reading the rest. Deselecting will cancel the command.
215     
216     nNOR_CS_Write(1); // Deselect
217 }
218
219 static S2S_Target* spiFlash_getTargets(S2S_Device* dev, int* count)
220 {
221     SpiFlash* spiFlash = (SpiFlash*)dev;
222     *count = MAX_SCSI_TARGETS;
223     return spiFlash->targets;
224 }
225
226 static uint32_t spiFlash_getCapacity(S2S_Device* dev)
227 {
228     SpiFlash* spiFlash = (SpiFlash*)dev;
229     return spiFlash->capacity;
230 }
231
232 static int spiFlash_pollMediaChange(S2S_Device* dev)
233 {
234     // Non-removable
235     return 0;
236 }
237
238 static void spiFlash_pollMediaBusy(S2S_Device* dev)
239 {
240     // Non-removable
241 }
242
243 static void spiFlash_WaitForWIP()
244 {
245     int inProgress = 1;
246     while (inProgress)
247     {
248         nNOR_CS_Write(0);
249         uint8_t status = spiFlashByte(0x05); // Read Status Register 1;
250         inProgress = status & 1;
251         nNOR_CS_Write(1);
252     }
253 }
254
255 static void spiFlash_erase(S2S_Device* dev, uint32_t sectorNumber, uint32_t count)
256 {
257     // SpiFlash* spiFlash = (SpiFlash*)dev;
258
259     nNOR_CS_Write(0); // Select
260
261     // Send the WREN - Write Enable command
262     spiFlashByte(0x06);
263
264     // We NEED to deselect the device now for writes to work
265     nNOR_CS_Write(1);
266     
267     // For now we assume 256kb sectors. This needs to be expanded to cater for 
268     // different sector sizes. We safely assume it will always be >= 512 bytes.
269     const uint32_t flashSectorSize = 256*1024;
270
271     // We don't have enough memory to do a read-modify-write cycle, so the caller
272     // had better line these up on sector boundaries.
273     for (uint32_t linearAddress = sectorNumber * 512;
274         linearAddress < (sectorNumber + count) * 512;
275         linearAddress += flashSectorSize)
276     {
277         nNOR_CS_Write(0);
278
279         spiFlashByte(0xDC);
280
281         // 4-byte address
282         spiFlashByte(linearAddress >> 24);
283         spiFlashByte(linearAddress >> 16);
284         spiFlashByte(linearAddress >> 8);
285         spiFlashByte(linearAddress);
286
287         // Initiate erase
288         nNOR_CS_Write(1);
289
290         spiFlash_WaitForWIP();
291     }
292
293     nNOR_CS_Write(0);
294
295     // Send the WREN - Write Disable command
296     spiFlashByte(0x04);
297     
298     nNOR_CS_Write(1); // Deselect
299 }
300
301 static void spiFlash_write(S2S_Device* dev, uint32_t sectorNumber, uint32_t count, uint8_t* buffer)
302 {
303     // SpiFlash* spiFlash = (SpiFlash*)dev;
304
305     nNOR_CS_Write(0); // Select
306
307     // Send the WREN - Write Enable command
308     spiFlashByte(0x06);
309
310     // We NEED to deselect the device now for writes to work
311     nNOR_CS_Write(1);
312     
313     // We're assuming here that the page size is 512 bytes or more.
314     for (unsigned int i = 0; i < count; ++i)
315     {
316         nNOR_CS_Write(0);
317
318         spiFlashByte(0x12);
319
320         uint32_t linearAddress = (sectorNumber + i) * 512;
321         spiFlashByte(linearAddress >> 24);
322         spiFlashByte(linearAddress >> 16);
323         spiFlashByte(linearAddress >> 8);
324         spiFlashByte(linearAddress);
325
326         for (int off = 0; off < 512; ++off)
327         {
328             spiFlashByte(buffer[i * 512 + off]);
329         }
330
331         // Initiate write 
332         nNOR_CS_Write(1);
333
334         spiFlash_WaitForWIP();
335     }
336
337     nNOR_CS_Write(0);
338
339     // Send the WREN - Write Disable command
340     spiFlashByte(0x04);
341     
342     nNOR_CS_Write(1); // Deselect
343 }
344
345 static void spiFlash_read(S2S_Device* dev, uint32_t sectorNumber, uint32_t count, uint8_t* buffer)
346 {
347     // SpiFlash* spiFlash = (SpiFlash*)dev;
348
349     nNOR_CS_Write(0); // Select
350     spiFlashByte(0x13);
351
352     uint32_t linearAddress = sectorNumber * 512;
353     spiFlashByte(linearAddress >> 24);
354     spiFlashByte(linearAddress >> 16);
355     spiFlashByte(linearAddress >> 8);
356     spiFlashByte(linearAddress);
357     
358     // There's no harm in reading -extra- data, so keep the FIFO
359     // one step ahead.
360     NOR_SPI_WriteTxData(0xFF);
361     NOR_SPI_WriteTxData(0xFF);
362     NOR_SPI_WriteTxData(0xFF);
363
364     for (int off = 0; off < count * 512; ++off)
365     {
366         NOR_SPI_WriteTxData(0xFF);
367
368         while (!(NOR_SPI_ReadRxStatus() & NOR_SPI_STS_RX_FIFO_NOT_EMPTY)) {}
369         buffer[off] = NOR_SPI_ReadRxData();
370     }
371
372     // Read and discard the extra bytes of data. It was only used to improve
373     // performance with a full FIFO.
374     for (int i = 0; i < 3; ++i)
375     {
376         while (!(NOR_SPI_ReadRxStatus() & NOR_SPI_STS_RX_FIFO_NOT_EMPTY)) {}
377         NOR_SPI_ReadRxData();
378     }
379     
380     nNOR_CS_Write(1); // Deselect
381 }
382
383 static void spiFlash_readAsync(S2S_Device* dev, uint32_t sectorNumber, uint32_t count, uint8_t* buffer)
384 {
385     // SpiFlash* spiFlash = (SpiFlash*)dev;
386
387     nNOR_CS_Write(0); // Select
388     spiFlashByte(0x13);
389
390     uint32_t linearAddress = sectorNumber * 512;
391     
392     // DMA implementation
393     // send is static as the address must remain consistent for the static
394         // DMA descriptors to work.
395         // Size must be divisible by 2 to suit 2-byte-burst TX DMA channel.
396         static uint8_t send[4] __attribute__((aligned(4)));
397     send[0] = linearAddress >> 24;
398     send[1] = linearAddress >> 16;
399     send[2] = linearAddress >> 8;
400     send[3] = linearAddress;
401     
402         // Prepare DMA transfer
403     CyDmaTdSetConfiguration(spiFlashDmaTxTd[0], sizeof(send), spiFlashDmaTxTd[1], TD_INC_SRC_ADR);
404     CyDmaTdSetAddress(spiFlashDmaTxTd[0], LO16((uint32)&send), LO16((uint32)NOR_SPI_TXDATA_PTR));
405         
406         CyDmaTdSetConfiguration(
407                 spiFlashDmaTxTd[1],
408                 count * 512,
409                 CY_DMA_DISABLE_TD, // Disable the DMA channel when TD completes count bytes
410                 NOR_TX_DMA__TD_TERMOUT_EN // Trigger interrupt when complete
411                 );
412     CyDmaTdSetAddress(
413                 spiFlashDmaTxTd[1],
414                 LO16((uint32)&dummyBuffer),
415                 LO16((uint32)NOR_SPI_TXDATA_PTR));
416     
417     CyDmaTdSetConfiguration(spiFlashDmaRxTd[0], sizeof(send), spiFlashDmaRxTd[1], 0);
418     CyDmaTdSetAddress(spiFlashDmaRxTd[0], LO16((uint32)NOR_SPI_RXDATA_PTR), LO16((uint32)&discardBuffer));
419         
420         CyDmaTdSetConfiguration(
421                 spiFlashDmaRxTd[1],
422                 count * 512,
423                 CY_DMA_DISABLE_TD, // Disable the DMA channel when TD completes count bytes
424                 TD_INC_DST_ADR |
425                         NOR_RX_DMA__TD_TERMOUT_EN // Trigger interrupt when complete
426                 );
427         
428         CyDmaTdSetAddress(
429                 spiFlashDmaRxTd[1],
430                 LO16((uint32)NOR_SPI_RXDATA_PTR),
431                 LO16((uint32)buffer)
432                 );
433
434         CyDmaChSetInitialTd(spiFlashDMATxChan, spiFlashDmaTxTd[0]);
435         CyDmaChSetInitialTd(spiFlashDMARxChan, spiFlashDmaRxTd[0]);
436
437         // The DMA controller is a bit trigger-happy. It will retain
438         // a drq request that was triggered while the channel was
439         // disabled.
440         CyDmaChSetRequest(spiFlashDMATxChan, CY_DMA_CPU_REQ);
441         CyDmaClearPendingDrq(spiFlashDMARxChan);
442
443         spiFlashTxDMAComplete = 0;
444         spiFlashRxDMAComplete = 0;
445
446         CyDmaChEnable(spiFlashDMARxChan, 1);
447         CyDmaChEnable(spiFlashDMATxChan, 1);
448 }
449
450 static int spiFlash_readAsyncPoll(S2S_Device* dev)
451 {
452     // SpiFlash* spiFlash = (SpiFlash*)dev;
453
454     int allComplete = 0;
455     uint8_t intr = CyEnterCriticalSection();
456         allComplete = spiFlashTxDMAComplete && spiFlashRxDMAComplete;
457         CyExitCriticalSection(intr);
458
459     if (allComplete)
460     {
461         nNOR_CS_Write(1); // Deselect
462     }
463     
464     return allComplete;
465 }