source: rtems/c/src/lib/libbsp/arm/nds/libfat/source/disc_io/io_efa2.c @ ef4c461

4.115
Last change on this file since ef4c461 was ef4c461, checked in by Joel Sherrill <joel.sherrill@…>, on 10/09/14 at 20:35:10

arm/nds: Warning clean up

This patch eliminates most of the warnings in this BSP but attempts
very little clean up. This BSP includes copies of a lot of code
from free NDS libraries and modifications should be kept to a minimum.

  • Property mode set to 100644
File size: 8.7 KB
Line 
1/*
2io_efa2.c by CyteX
3
4Based on io_mpfc.c by chishm (Michael Chisholm)
5
6Hardware Routines for reading the NAND flash located on
7EFA2 flash carts
8
9This software is completely free. No warranty is provided.
10If you use it, please give me credit and email me about your
11project at cytex <at> gmx <dot> de and do not forget to also
12drop chishm <at> hotmail <dot> com a line
13
14 Use with permission by Michael "Chishm" Chisholm
15*/
16
17#include "io_efa2.h"
18
19//
20// EFA2 register addresses
21//
22
23// RTC registers
24#define REG_RTC_CLK        (*(vu16*)0x080000c4)
25#define REG_RTC_EN         (*(vu16*)0x080000c8)
26
27// "Magic" registers used for unlock/lock sequences
28#define REG_EFA2_MAGIC_A   (*(vu16*)0x09fe0000)
29#define REG_EFA2_MAGIC_B   (*(vu16*)0x08000000)
30#define REG_EFA2_MAGIC_C   (*(vu16*)0x08020000)
31#define REG_EFA2_MAGIC_D   (*(vu16*)0x08040000)
32#define REG_EFA2_MAGIC_E   (*(vu16*)0x09fc0000)
33
34// NAND flash lock/unlock register
35#define REG_EFA2_NAND_LOCK (*(vu16*)0x09c40000)
36// NAND flash enable register
37#define REG_EFA2_NAND_EN   (*(vu16*)0x09400000)
38// NAND flash command write register
39#define REG_EFA2_NAND_CMD   (*(vu8*)0x09ffffe2)
40// NAND flash address/data write register
41#define REG_EFA2_NAND_WR    (*(vu8*)0x09ffffe0)
42// NAND flash data read register
43#define REG_EFA2_NAND_RD    (*(vu8*)0x09ffc000)
44
45// ID of Samsung K9K1G NAND flash chip
46#define EFA2_NAND_ID 0xEC79A5C0
47
48// first sector of udisk
49#define EFA2_UDSK_START 0x40
50
51//
52// EFA2 access functions
53//
54
55// deactivate RTC ports
56static inline void _EFA2_rtc_deactivate(void) {
57        REG_RTC_EN = 0;
58}
59
60// unlock register access
61static void _EFA2_reg_unlock(void) {
62        REG_EFA2_MAGIC_A = 0x0d200;
63        REG_EFA2_MAGIC_B = 0x01500;
64        REG_EFA2_MAGIC_C = 0x0d200;
65        REG_EFA2_MAGIC_D = 0x01500;
66}
67
68// finish/lock register access
69static inline void _EFA2_reg_lock(void) {
70        REG_EFA2_MAGIC_E = 0x1500;
71}
72
73// global reset/init/enable/unlock ?
74static void _EFA2_global_unlock(void) {
75        _EFA2_reg_unlock();
76        *(vu16*)0x09880000 = 0x08000;
77        _EFA2_reg_lock();
78}
79
80// global lock, stealth mode
81/*static void _EFA2_global_lock(void) {
82        // quite sure there is such a sequence, but haven't had
83        // a look for it upto now
84}*/
85
86// unlock NAND Flash
87static void _EFA2_nand_unlock(void) {
88        _EFA2_reg_unlock();
89        REG_EFA2_NAND_LOCK = 0x01500;
90        _EFA2_reg_lock();
91}
92
93// lock NAND Flash
94static void _EFA2_nand_lock(void) {
95        _EFA2_reg_unlock();
96        REG_EFA2_NAND_LOCK = 0x0d200;
97        _EFA2_reg_lock();
98}
99
100//
101// Set NAND Flash chip enable and write protection bits ?
102//
103//   val | ~CE | ~WP |
104//  -----+-----+-----+
105//     0 |  0  |  0  |
106//     1 |  1  |  0  |
107//     3 |  1  |  1  |
108//  -----+-----+-----+
109//
110static void _EFA2_nand_enable(u16 val) {
111        _EFA2_reg_unlock();
112        REG_EFA2_NAND_EN = val;
113        _EFA2_reg_lock();
114}
115
116//
117// Perform NAND reset
118// NAND has to be unlocked and enabled when called
119//
120static inline void _EFA2_nand_reset(void) {
121        REG_EFA2_NAND_CMD = 0xff; // write reset command
122}
123
124//
125// Read out NAND ID information, could be used for card detection
126//
127//                    | EFA2 1GBit |
128//  ------------------+------------+
129//         maker code |    0xEC    |
130//        device code |    0x79    |
131//         don't care |    0xA5    |
132//   multi plane code |    0xC0    |
133//  ------------------+------------+
134//
135static u32 _EFA2_nand_id(void) {
136        u8 byte;
137        u32 id;
138
139        _EFA2_nand_unlock();
140        _EFA2_nand_enable(1);
141
142        REG_EFA2_NAND_CMD = 0x90;  // write id command
143        REG_EFA2_NAND_WR  = 0x00;  // (dummy) address cycle
144        byte = REG_EFA2_NAND_RD;   // read maker code
145        id   = byte;
146        byte = REG_EFA2_NAND_RD;   // read device code
147        id   = (id << 8) | byte;
148        byte = REG_EFA2_NAND_RD;   // read don't care
149        id   = (id << 8) | byte;
150        byte = REG_EFA2_NAND_RD;   // read multi plane code
151        id   = (id << 8) | byte;
152
153        _EFA2_nand_enable(0);
154        _EFA2_nand_lock();
155        return (id);
156}
157
158//
159// Start of gba_nds_fat block device description
160//
161
162/*-----------------------------------------------------------------
163EFA2_clearStatus
164Reads and checks NAND status information
165bool return OUT:  true if NAND is idle
166-----------------------------------------------------------------*/
167static bool _EFA2_clearStatus (void)
168{
169        // tbd: currently there is no write support, so always return
170        // true, there is no possibility for pending operations
171        return true;
172}
173
174/*-----------------------------------------------------------------
175EFA2_isInserted
176Checks to see if the NAND chip used by the EFA2 is present
177bool return OUT:  true if the correct NAND chip is found
178-----------------------------------------------------------------*/
179static bool _EFA2_isInserted (void)
180{
181        _EFA2_clearStatus();
182        return (_EFA2_nand_id() == EFA2_NAND_ID);
183}
184
185/*-----------------------------------------------------------------
186EFA2_readSectors
187Read "numSecs" 512 byte sectors starting from "sector" into "buffer"
188No error correction, no use of spare cells, no use of R/~B signal
189u32 sector IN: number of first 512 byte sector to be read
190u32 numSecs IN: number of 512 byte sectors to read,
191void* buffer OUT: pointer to 512 byte buffer to store data in
192bool return OUT: true if successful
193-----------------------------------------------------------------*/
194static bool _EFA2_readSectors (u32 sector, u32 numSecs, void* buffer)
195{
196        int  i;
197
198#ifndef _IO_ALLOW_UNALIGNED
199        u8  byte;
200        u16  word;
201#endif
202
203        // NAND page 0x40 (EFA2_UDSK_START) contains the MBR of the
204        // udisk and thus is sector 0. The original EFA2 firmware
205        // does never look at this, it only watches page 0x60, which
206        // contains the boot block of the FAT16 partition. That is
207        // fixed, so the EFA2 udisk must not be reformated, else
208        // the ARK Octopus and also the original Firmware won't be
209        // able to access the udisk anymore and I have to write a
210        // recovery tool.
211        u32 page = EFA2_UDSK_START + sector;
212
213        // future enhancement: wait for possible write operations to
214        // be finisched
215        if (!_EFA2_clearStatus()) return false;
216
217        _EFA2_nand_unlock();
218        _EFA2_nand_enable(1);
219        _EFA2_nand_reset();
220
221        // set NAND to READ1 operation mode and transfer page address
222        REG_EFA2_NAND_CMD = 0x00;                // write READ1 command
223        REG_EFA2_NAND_WR  = 0x00;                // write address  [7:0]
224        REG_EFA2_NAND_WR  = (page      ) & 0xff; // write address [15:8]
225        REG_EFA2_NAND_WR  = (page >> 8 ) & 0xff; // write address[23:16]
226        REG_EFA2_NAND_WR  = (page >> 16) & 0xff; // write address[26:24]
227
228        // Due to a bug in EFA2 design there is need to waste some cycles
229        // "by hand" instead the possibility to check the R/~B port of
230        // the NAND flash via a register. The RTC deactivation is only
231        // there to make sure the loop won't be optimized by the compiler
232        for (i=0 ; i < 3 ; i++) _EFA2_rtc_deactivate();
233
234        while (numSecs--)
235        {
236                // read page data
237#ifdef _IO_ALLOW_UNALIGNED
238                // slow byte access to RAM, but works in principle
239                for (i=0 ; i < 512 ; i++)
240                        ((u8*)buffer)[i] = REG_EFA2_NAND_RD;
241#else
242                // a bit faster, but DMA is not possible
243                for (i=0 ; i < 256 ; i++) {
244                        byte = REG_EFA2_NAND_RD;   // read lo-byte
245                        word = byte;
246                        byte = REG_EFA2_NAND_RD;   // read hi-byte
247                        word = word | (byte << 8);
248                        ((u16*)buffer)[i] = word;
249                }
250#endif
251        }
252
253        _EFA2_nand_enable(0);
254        _EFA2_nand_lock();
255        return true;
256}
257
258
259/*-----------------------------------------------------------------
260EFA2_writeSectors
261Write "numSecs" 512 byte sectors starting at "sector" from "buffer"
262u32 sector IN: address of 512 byte sector on card to write
263u32 numSecs IN: number of 512 byte sectors to write
2641 to 256 sectors can be written, 0 = 256
265void* buffer IN: pointer to 512 byte buffer to read data from
266bool return OUT: true if successful
267-----------------------------------------------------------------*/
268static bool _EFA2_writeSectors (u32 sector, u8 numSecs, void* buffer)
269{
270        // Upto now I focused on reading NAND, write operations
271        // will follow
272        return false;
273}
274
275/*-----------------------------------------------------------------
276EFA2_shutdown
277unload the EFA2 interface
278-----------------------------------------------------------------*/
279static bool _EFA2_shutdown(void)
280{
281        return _EFA2_clearStatus();
282}
283
284/*-----------------------------------------------------------------
285EFA2_startUp
286initializes the EFA2 card, returns true if successful,
287otherwise returns false
288-----------------------------------------------------------------*/
289static bool _EFA2_startUp(void)
290{
291        _EFA2_global_unlock();
292        return (_EFA2_nand_id() == EFA2_NAND_ID);
293}
294
295/*-----------------------------------------------------------------
296the actual interface structure
297-----------------------------------------------------------------*/
298const IO_INTERFACE _io_efa2 = {
299        DEVICE_TYPE_EFA2,
300        FEATURE_MEDIUM_CANREAD | FEATURE_SLOT_GBA,
301        (FN_MEDIUM_STARTUP)&_EFA2_startUp,
302        (FN_MEDIUM_ISINSERTED)&_EFA2_isInserted,
303        (FN_MEDIUM_READSECTORS)&_EFA2_readSectors,
304        (FN_MEDIUM_WRITESECTORS)&_EFA2_writeSectors,
305        (FN_MEDIUM_CLEARSTATUS)&_EFA2_clearStatus,
306        (FN_MEDIUM_SHUTDOWN)&_EFA2_shutdown
307};
Note: See TracBrowser for help on using the repository browser.