Subversion Repositories freemyipod

Rev

Rev 15 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 15 Rev 54
Line 20... Line 20...
20
//
20
//
21
//
21
//
22
 
22
 
23
 
23
 
24
#include "global.h"
24
#include "global.h"
-
 
25
#include "panic.h"
-
 
26
#include "thread.h"
25
#include "util.h"
27
#include "util.h"
26
#include "timer.h"
28
#include "timer.h"
27
#include "nand.h"
29
#include "nand.h"
-
 
30
#include "pmu.h"
28
#include "i2c.h"
31
#include "mmu.h"
29
 
32
 
30
#define NAND_CMD_READ       0x00
33
#define NAND_CMD_READ       0x00
31
#define NAND_CMD_PROGCNFRM  0x10
34
#define NAND_CMD_PROGCNFRM  0x10
32
#define NAND_CMD_READ2      0x30
35
#define NAND_CMD_READ2      0x30
33
#define NAND_CMD_BLOCKERASE 0x60
36
#define NAND_CMD_BLOCKERASE 0x60
Line 36... Line 39...
36
#define NAND_CMD_ERASECNFRM 0xD0
39
#define NAND_CMD_ERASECNFRM 0xD0
37
#define NAND_CMD_RESET      0xFF
40
#define NAND_CMD_RESET      0xFF
38
 
41
 
39
#define NAND_STATUS_READY   0x40
42
#define NAND_STATUS_READY   0x40
40
 
43
 
41
#define NAND_DEVICEINFOTABLE_ENTRIES 33
-
 
42
 
-
 
43
static const struct nand_device_info_type nand_deviceinfotable[] =
44
static const struct nand_device_info_type nand_deviceinfotable[] =
44
{
45
{
45
    {0x1580F1EC, 1024, 968, 0x40, 6, 2, 1, 2, 1},
46
    {0x1580F1EC, 1024, 968, 0x40, 6, 2, 1, 2, 1},
46
    {0x1580DAEC, 2048, 1936, 0x40, 6, 2, 1, 2, 1},
47
    {0x1580DAEC, 2048, 1936, 0x40, 6, 2, 1, 2, 1},
47
    {0x15C1DAEC, 2048, 1936, 0x40, 6, 2, 1, 2, 1},
48
    {0x15C1DAEC, 2048, 1936, 0x40, 6, 2, 1, 2, 1},
Line 80... Line 81...
80
uint8_t nand_tunk1[4];
81
uint8_t nand_tunk1[4];
81
uint8_t nand_twp[4];
82
uint8_t nand_twp[4];
82
uint8_t nand_tunk2[4];
83
uint8_t nand_tunk2[4];
83
uint8_t nand_tunk3[4];
84
uint8_t nand_tunk3[4];
84
uint32_t nand_type[4];
85
uint32_t nand_type[4];
-
 
86
int nand_powered = 0;
-
 
87
int nand_interleaved = 0;
-
 
88
int nand_cached = 0;
-
 
89
long nand_last_activity_value = -1;
-
 
90
static uint32_t nand_stack[0x80];
-
 
91
 
-
 
92
static struct mutex nand_mtx;
-
 
93
static struct wakeup nand_wakeup;
-
 
94
static struct mutex ecc_mtx;
-
 
95
static struct wakeup ecc_wakeup;
-
 
96
 
-
 
97
static uint8_t nand_data[0x800] CACHEALIGN_ATTR;
-
 
98
static uint8_t nand_ctrl[0x200] CACHEALIGN_ATTR;
-
 
99
static uint8_t nand_spare[0x40] CACHEALIGN_ATTR;
-
 
100
static uint8_t nand_ecc[0x30] CACHEALIGN_ATTR;
-
 
101
 
85
 
102
 
86
static uint8_t nand_ctrl[0x200] __attribute__((aligned(16)));
103
uint32_t nand_unlock(uint32_t rc)
-
 
104
{
87
static uint8_t nand_spare[0x40] __attribute__((aligned(16)));
105
    nand_last_activity_value = USEC_TIMER;
88
static uint8_t nand_ecc[0x30] __attribute__((aligned(16)));
106
    mutex_unlock(&nand_mtx);
-
 
107
    return rc;
-
 
108
}
89
 
109
 
-
 
110
uint32_t ecc_unlock(uint32_t rc)
-
 
111
{
-
 
112
    mutex_unlock(&ecc_mtx);
-
 
113
    return rc;
-
 
114
}
-
 
115
 
-
 
116
uint32_t nand_timeout(uint32_t timeout)
-
 
117
{
-
 
118
    if (TIME_AFTER(USEC_TIMER, timeout)) return 1;
-
 
119
    else
-
 
120
    {
-
 
121
        yield();
-
 
122
        return 0;
-
 
123
    }
-
 
124
}
90
 
125
 
91
uint32_t nand_wait_rbbdone(void)
126
uint32_t nand_wait_rbbdone(void)
92
{
127
{
93
    uint32_t timeout = USEC_TIMER;
128
    uint32_t timeout = USEC_TIMER + 20000;
94
    while ((FMCSTAT & FMCSTAT_RBBDONE) == 0) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
129
    while (!(FMCSTAT & FMCSTAT_RBBDONE))
-
 
130
        if (nand_timeout(timeout)) return 1;
95
    FMCSTAT = FMCSTAT_RBBDONE;
131
    FMCSTAT = FMCSTAT_RBBDONE;
96
    return 0;
132
    return 0;
97
}
133
}
98
 
134
 
99
uint32_t nand_wait_cmddone(void)
135
uint32_t nand_wait_cmddone(void)
100
{
136
{
101
    uint32_t timeout = USEC_TIMER;
137
    uint32_t timeout = USEC_TIMER + 20000;
102
    while ((FMCSTAT & FMCSTAT_CMDDONE) == 0) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
138
    while (!(FMCSTAT & FMCSTAT_CMDDONE))
-
 
139
        if (nand_timeout(timeout)) return 1;
103
    FMCSTAT = FMCSTAT_CMDDONE;
140
    FMCSTAT = FMCSTAT_CMDDONE;
104
    return 0;
141
    return 0;
105
}
142
}
106
 
143
 
107
uint32_t nand_wait_addrdone(void)
144
uint32_t nand_wait_addrdone(void)
108
{
145
{
109
    uint32_t timeout = USEC_TIMER;
146
    uint32_t timeout = USEC_TIMER + 20000;
110
    while ((FMCSTAT & FMCSTAT_ADDRDONE) == 0) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
147
    while (!(FMCSTAT & FMCSTAT_ADDRDONE))
-
 
148
        if (nand_timeout(timeout)) return 1;
111
    FMCSTAT = FMCSTAT_ADDRDONE;
149
    FMCSTAT = FMCSTAT_ADDRDONE;
112
    return 0;
150
    return 0;
113
}
151
}
114
 
152
 
115
uint32_t nand_wait_chip_ready(uint32_t bank)
153
uint32_t nand_wait_chip_ready(uint32_t bank)
116
{
154
{
117
    uint32_t timeout = USEC_TIMER;
155
    uint32_t timeout = USEC_TIMER + 20000;
118
    while ((FMCSTAT & (FMCSTAT_BANK0READY << bank)) == 0) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
156
    while (!(FMCSTAT & (FMCSTAT_BANK0READY << bank)))
-
 
157
        if (nand_timeout(timeout)) return 1;
119
    FMCSTAT = (FMCSTAT_BANK0READY << bank);
158
    FMCSTAT = (FMCSTAT_BANK0READY << bank);
120
    return 0;
159
    return 0;
121
}
160
}
122
 
161
 
123
void nand_set_fmctrl0(uint32_t bank, uint32_t flags)
162
void nand_set_fmctrl0(uint32_t bank, uint32_t flags)
Line 151... Line 190...
151
    return 0;
190
    return 0;
152
}
191
}
153
 
192
 
154
uint32_t nand_wait_status_ready(uint32_t bank)
193
uint32_t nand_wait_status_ready(uint32_t bank)
155
{
194
{
156
    uint32_t timeout = USEC_TIMER;
195
    uint32_t timeout = USEC_TIMER + 20000;
157
    nand_set_fmctrl0(bank, 0);
196
    nand_set_fmctrl0(bank, 0);
158
    if ((FMCSTAT & (FMCSTAT_BANK0READY << bank)))
197
    if ((FMCSTAT & (FMCSTAT_BANK0READY << bank)))
159
        FMCSTAT = (FMCSTAT_BANK0READY << bank);
198
        FMCSTAT = (FMCSTAT_BANK0READY << bank);
160
    FMCTRL1 = FMCTRL1_CLEARRFIFO;
199
    FMCTRL1 = FMCTRL1_CLEARRFIFO;
161
    if (nand_send_cmd(NAND_CMD_GET_STATUS)) return 1;
200
    if (nand_send_cmd(NAND_CMD_GET_STATUS)) return 1;
162
    while (1)
201
    while (1)
163
    {
202
    {
164
        if (TIMEOUT_EXPIRED(timeout, 200)) return 1;
203
        if (nand_timeout(timeout)) return 1;
165
        FMDNUM = 0;
204
        FMDNUM = 0;
166
        FMCTRL1 = FMCTRL1_DOREADDATA;
205
        FMCTRL1 = FMCTRL1_DOREADDATA;
167
        if (nand_wait_addrdone()) return 1;
206
        if (nand_wait_addrdone()) return 1;
168
        if ((FMFIFO & NAND_STATUS_READY)) break;
207
        if ((FMFIFO & NAND_STATUS_READY)) break;
169
        FMCTRL1 = FMCTRL1_CLEARRFIFO;
208
        FMCTRL1 = FMCTRL1_CLEARRFIFO;
170
    }
209
    }
171
    FMCTRL1 = FMCTRL1_CLEARRFIFO;
210
    FMCTRL1 = FMCTRL1_CLEARRFIFO;
172
    return nand_send_cmd(NAND_CMD_READ);
211
    return nand_send_cmd(NAND_CMD_READ);
173
}
212
}
174
 
213
 
175
uint32_t nand_transfer_data(uint32_t bank, uint32_t direction, void* buffer, uint32_t size)
214
void nand_transfer_data_start(uint32_t bank, uint32_t direction,
-
 
215
                              void* buffer, uint32_t size)
176
{
216
{
177
    uint32_t timeout = USEC_TIMER;
-
 
178
    nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
217
    nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
179
    FMDNUM = size - 1;
218
    FMDNUM = size - 1;
180
    FMCTRL1 = FMCTRL1_DOREADDATA << direction;
219
    FMCTRL1 = FMCTRL1_DOREADDATA << direction;
181
    DMACON3 = (2 << DMACON_DEVICE_SHIFT)
220
    DMACON3 = (2 << DMACON_DEVICE_SHIFT)
182
            | (direction << DMACON_DIRECTION_SHIFT)
221
            | (direction << DMACON_DIRECTION_SHIFT)
Line 186... Line 225...
186
        DMACOM3 = DMACOM_CLEARBOTHDONE;
225
        DMACOM3 = DMACOM_CLEARBOTHDONE;
187
    DMABASE3 = (uint32_t)buffer;
226
    DMABASE3 = (uint32_t)buffer;
188
    DMATCNT3 = (size >> 4) - 1;
227
    DMATCNT3 = (size >> 4) - 1;
189
    clean_dcache();
228
    clean_dcache();
190
    DMACOM3 = 4;
229
    DMACOM3 = 4;
-
 
230
}
-
 
231
 
-
 
232
uint32_t nand_transfer_data_collect(uint32_t direction)
-
 
233
{
-
 
234
    uint32_t timeout = USEC_TIMER + 20000;
191
    while ((DMAALLST & DMAALLST_DMABUSY3)) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
235
    while ((DMAALLST & DMAALLST_DMABUSY3))
-
 
236
        if (nand_timeout(timeout)) return 1;
192
    if (!direction) invalidate_dcache();
237
    if (!direction) invalidate_dcache();
193
    if (nand_wait_addrdone()) return 1;
238
    if (nand_wait_addrdone()) return 1;
194
    if (!direction) FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
239
    if (!direction) FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
195
    else FMCTRL1 = FMCTRL1_CLEARRFIFO;
240
    else FMCTRL1 = FMCTRL1_CLEARRFIFO;
196
    return 0;
241
    return 0;
197
}
242
}
198
 
243
 
199
uint32_t ecc_decode(uint32_t size, void* databuffer, void* sparebuffer)
244
uint32_t nand_transfer_data(uint32_t bank, uint32_t direction,
-
 
245
                            void* buffer, uint32_t size)
200
{
246
{
-
 
247
    nand_transfer_data_start(bank, direction, buffer, size);
-
 
248
    uint32_t rc = nand_transfer_data_collect(direction);
-
 
249
    return rc;
-
 
250
}
-
 
251
 
-
 
252
void ecc_start(uint32_t size, void* databuffer, void* sparebuffer, uint32_t type)
-
 
253
{
201
    uint32_t timeout = USEC_TIMER;
254
    mutex_lock(&ecc_mtx, TIMEOUT_BLOCK);
202
    ECC_INT_CLR = 1;
255
    ECC_INT_CLR = 1;
203
    SRCPND = INTMSK_ECC;
256
    SRCPND = INTMSK_ECC;
204
    ECC_UNK1 = size;
257
    ECC_UNK1 = size;
205
    ECC_DATA_PTR = (uint32_t)databuffer;
258
    ECC_DATA_PTR = (uint32_t)databuffer;
206
    ECC_SPARE_PTR = (uint32_t)sparebuffer;
259
    ECC_SPARE_PTR = (uint32_t)sparebuffer;
207
    clean_dcache();
260
    clean_dcache();
208
    ECC_CTRL = ECCCTRL_STARTDECODING;
261
    ECC_CTRL = type;
-
 
262
}
-
 
263
 
-
 
264
uint32_t ecc_collect(void)
-
 
265
{
-
 
266
    uint32_t timeout = USEC_TIMER + 20000;
209
    while (!(SRCPND & INTMSK_ECC)) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
267
    while (!(SRCPND & INTMSK_ECC))
-
 
268
        if (nand_timeout(timeout)) return ecc_unlock(1);
210
    invalidate_dcache();
269
    invalidate_dcache();
211
    ECC_INT_CLR = 1;
270
    ECC_INT_CLR = 1;
212
    SRCPND = INTMSK_ECC;
271
    SRCPND = INTMSK_ECC;
213
    return ECC_RESULT;
272
    return ecc_unlock(ECC_RESULT);
-
 
273
}
-
 
274
 
-
 
275
uint32_t ecc_decode(uint32_t size, void* databuffer, void* sparebuffer)
-
 
276
{
-
 
277
    ecc_start(size, databuffer, sparebuffer, ECCCTRL_STARTDECODING);
-
 
278
    uint32_t rc = ecc_collect();
-
 
279
    return rc;
214
}
280
}
215
 
281
 
216
uint32_t ecc_encode(uint32_t size, void* databuffer, void* sparebuffer)
282
uint32_t ecc_encode(uint32_t size, void* databuffer, void* sparebuffer)
217
{
283
{
218
    uint32_t timeout = USEC_TIMER;
-
 
219
    ECC_INT_CLR = 1;
-
 
220
    SRCPND = INTMSK_ECC;
-
 
221
    ECC_UNK1 = size;
-
 
222
    ECC_DATA_PTR = (uint32_t)databuffer;
-
 
223
    ECC_SPARE_PTR = (uint32_t)sparebuffer;
284
    ecc_start(size, databuffer, sparebuffer, ECCCTRL_STARTENCODING);
224
    clean_dcache();
285
    ecc_collect();
225
    ECC_CTRL = ECCCTRL_STARTENCODING;
-
 
226
    while (!(SRCPND & INTMSK_ECC)) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
-
 
227
    invalidate_dcache();
-
 
228
    ECC_INT_CLR = 1;
-
 
229
    SRCPND = INTMSK_ECC;
-
 
230
    return 0;
286
    return 0;
231
}
287
}
232
 
288
 
233
uint32_t nand_check_empty(uint8_t* buffer)
289
uint32_t nand_check_empty(uint8_t* buffer)
234
{
290
{
Line 239... Line 295...
239
    return 0;
295
    return 0;
240
}
296
}
241
 
297
 
242
uint32_t nand_get_chip_type(uint32_t bank)
298
uint32_t nand_get_chip_type(uint32_t bank)
243
{
299
{
-
 
300
    mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
244
    uint32_t result;
301
    uint32_t result;
245
    if (nand_reset(bank)) return 0xFFFFFFFF;
302
    if (nand_reset(bank)) return nand_unlock(0xFFFFFFFF);
246
    if (nand_send_cmd(0x90)) return 0xFFFFFFFF;
303
    if (nand_send_cmd(0x90)) return nand_unlock(0xFFFFFFFF);
247
    FMANUM = 0;
304
    FMANUM = 0;
248
    FMADDR0 = 0;
305
    FMADDR0 = 0;
249
    FMCTRL1 = FMCTRL1_DOTRANSADDR;
306
    FMCTRL1 = FMCTRL1_DOTRANSADDR;
250
    if (nand_wait_cmddone()) return 0xFFFFFFFF;
307
    if (nand_wait_cmddone()) return nand_unlock(0xFFFFFFFF);
251
    FMDNUM = 4;
308
    FMDNUM = 4;
252
    FMCTRL1 = FMCTRL1_DOREADDATA;
309
    FMCTRL1 = FMCTRL1_DOREADDATA;
253
    if (nand_wait_addrdone()) return 0xFFFFFFFF;
310
    if (nand_wait_addrdone()) return nand_unlock(0xFFFFFFFF);
254
    result = FMFIFO;
311
    result = FMFIFO;
255
    FMCTRL1 = FMCTRL1_CLEARRFIFO;
312
    FMCTRL1 = FMCTRL1_CLEARRFIFO;
256
    return result;
313
    return nand_unlock(result);
257
}
314
}
258
 
315
 
259
uint32_t nand_read_page(uint32_t bank, uint32_t page, void* data,
316
void nand_set_active(void)
260
                        void* sparebuffer, uint32_t doecc, uint32_t checkempty)
-
 
261
{
317
{
-
 
318
    nand_last_activity_value = USEC_TIMER;
-
 
319
}
-
 
320
 
-
 
321
long nand_last_activity(void)
-
 
322
{
-
 
323
    return nand_last_activity_value;
-
 
324
}
-
 
325
 
-
 
326
void nand_power_up(void)
-
 
327
{
-
 
328
    uint32_t i;
-
 
329
    mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
-
 
330
    nand_last_activity_value = USEC_TIMER;
-
 
331
    PWRCONEXT &= ~0x40;
-
 
332
    PWRCON &= ~0x100000;
-
 
333
    PCON2 = 0x33333333;
-
 
334
    PDAT2 = 0;
-
 
335
    PCON3 = 0x11113333;
-
 
336
    PDAT3 = 0;
-
 
337
    PCON4 = 0x33333333;
-
 
338
    PDAT4 = 0;
-
 
339
    PCON5 = (PCON5 & ~0xF) | 3;
-
 
340
    PUNK5 = 1;
-
 
341
    pmu_ldo_set_voltage(4, 0x15);
-
 
342
    pmu_ldo_power_on(4);
-
 
343
    sleep(50000);
-
 
344
    nand_last_activity_value = USEC_TIMER;
-
 
345
    for (i = 0; i < 4; i++)
-
 
346
    {
-
 
347
        if(nand_type[i] != 0xFFFFFFFF)
-
 
348
        {
-
 
349
            if(nand_reset(i))
-
 
350
                
-
 
351
				panicf(PANIC_FATAL, "nand_power_up: nand_reset(bank=%d) failed.", (unsigned int)i);
-
 
352
        }
-
 
353
    }
-
 
354
    nand_powered = 1;
-
 
355
    nand_last_activity_value = USEC_TIMER;
-
 
356
    mutex_unlock(&nand_mtx);
-
 
357
}
-
 
358
 
-
 
359
void nand_power_down(void)
-
 
360
{
-
 
361
    if (!nand_powered) return;
-
 
362
    mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
-
 
363
    pmu_ldo_power_off(4);
-
 
364
    PCON2 = 0x11111111;
-
 
365
    PDAT2 = 0;
-
 
366
    PCON3 = 0x11111111;
-
 
367
    PDAT3 = 0;
-
 
368
    PCON4 = 0x11111111;
-
 
369
    PDAT4 = 0;
-
 
370
    PCON5 = (PCON5 & ~0xF) | 1;
-
 
371
    PUNK5 = 1;
-
 
372
    PWRCONEXT |= 0x40;
-
 
373
    PWRCON |= 0x100000;
-
 
374
    nand_powered = 0;
-
 
375
    mutex_unlock(&nand_mtx);
-
 
376
}
-
 
377
 
-
 
378
uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer,
-
 
379
                        void* sparebuffer, uint32_t doecc,
-
 
380
                        uint32_t checkempty)
-
 
381
{
262
    uint32_t rc, eccresult;
382
    uint8_t* data = nand_data;
263
    uint8_t* spare = nand_spare;
383
    uint8_t* spare = nand_spare;
-
 
384
    if (databuffer && !((uint32_t)databuffer & 0xf))
-
 
385
        data = (uint8_t*)databuffer;
-
 
386
    if (sparebuffer && !((uint32_t)sparebuffer & 0xf))
264
    if (sparebuffer) spare = sparebuffer;
387
        spare = (uint8_t*)sparebuffer;
-
 
388
    mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
-
 
389
    nand_last_activity_value = USEC_TIMER;
-
 
390
    if (!nand_powered) nand_power_up();
-
 
391
    uint32_t rc, eccresult;
265
    nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
392
    nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
266
    if (nand_send_cmd(NAND_CMD_READ)) return 1;
393
    if (nand_send_cmd(NAND_CMD_READ)) return nand_unlock(1);
267
    if (nand_send_address(page, data ? 0 : 0x800)) return 1;
394
    if (nand_send_address(page, databuffer ? 0 : 0x800))
-
 
395
        return nand_unlock(1);
268
    if (nand_send_cmd(NAND_CMD_READ2)) return 1;
396
    if (nand_send_cmd(NAND_CMD_READ2)) return nand_unlock(1);
269
    if (nand_wait_status_ready(bank)) return 1;
397
    if (nand_wait_status_ready(bank)) return nand_unlock(1);
-
 
398
    if (databuffer)
270
    if (data) if (nand_transfer_data(bank, 0, data, 0x800)) return 1;
399
        if (nand_transfer_data(bank, 0, data, 0x800))
-
 
400
            return nand_unlock(1);
271
    rc = 0;
401
    rc = 0;
272
    if (!doecc)
402
    if (!doecc)
273
    {
403
    {
-
 
404
        if (databuffer && data != databuffer) memcpy(databuffer, data, 0x800);
274
        if (sparebuffer)
405
        if (sparebuffer)
275
        {
406
        {
276
            if (nand_transfer_data(bank, 0, spare, 0x40)) return 1;
407
            if (nand_transfer_data(bank, 0, spare, 0x40))
-
 
408
                return nand_unlock(1);
-
 
409
            if (sparebuffer && spare != sparebuffer) 
-
 
410
                memcpy(sparebuffer, spare, 0x800);
277
            if (checkempty)
411
            if (checkempty)
278
                rc = nand_check_empty((uint8_t*)spare) << 1;
412
                rc = nand_check_empty((uint8_t*)sparebuffer) << 1;
279
        }
413
        }
280
        return rc;
414
        return nand_unlock(rc);
281
    }
415
    }
282
    if (nand_transfer_data(bank, 0, spare, 0x40)) return 1;
416
    if (nand_transfer_data(bank, 0, spare, 0x40)) return nand_unlock(1);
283
    if (data)
417
    if (databuffer)
284
    {
418
    {
285
        memcpy(nand_ecc, &((uint8_t*)spare)[0xC], 0x28);
419
        memcpy(nand_ecc, &spare[0xC], 0x28);
286
        rc |= (ecc_decode(3, data, nand_ecc) & 0xF) << 4;
420
        rc |= (ecc_decode(3, data, nand_ecc) & 0xF) << 4;
-
 
421
        if (data != databuffer) memcpy(databuffer, data, 0x800);
287
    }
422
    }
288
    memset(nand_ctrl, 0xFF, 0x200);
423
    memset(nand_ctrl, 0xFF, 0x200);
289
    memcpy(nand_ctrl, spare, 0xC);
424
    memcpy(nand_ctrl, spare, 0xC);
290
    memcpy(nand_ecc, &((uint8_t*)spare)[0x34], 0xC);
425
    memcpy(nand_ecc, &spare[0x34], 0xC);
291
    eccresult = ecc_decode(0, nand_ctrl, nand_ecc);
426
    eccresult = ecc_decode(0, nand_ctrl, nand_ecc);
292
    rc |= (eccresult & 0xF) << 8;
427
    rc |= (eccresult & 0xF) << 8;
293
    if (spare)
428
    if (sparebuffer)
294
    {
429
    {
-
 
430
        if (spare != sparebuffer) memcpy(sparebuffer, spare, 0x40);
295
        if (eccresult & 1) memset(spare, 0xFF, 0xC);
431
        if (eccresult & 1) memset(sparebuffer, 0xFF, 0xC);
296
        else memcpy(spare, nand_ctrl, 0xC);
432
        else memcpy(sparebuffer, nand_ctrl, 0xC);
297
    }
433
    }
298
    if (checkempty) rc |= nand_check_empty(spare) << 1;
434
    if (checkempty) rc |= nand_check_empty(spare) << 1;
-
 
435
 
299
    return rc;
436
    return nand_unlock(rc);
300
}
437
}
301
 
438
 
302
uint32_t nand_write_page(uint32_t bank, uint32_t page, void* data,
439
uint32_t nand_write_page_int(uint32_t bank, uint32_t page, void* databuffer,
303
                         void* sparebuffer, uint32_t doecc)
440
                             void* sparebuffer, uint32_t doecc, uint32_t wait)
304
{
441
{
-
 
442
    uint8_t* data = nand_data;
305
    uint8_t* spare = nand_spare;
443
    uint8_t* spare = nand_spare;
-
 
444
    if (databuffer && !((uint32_t)databuffer & 0xf))
-
 
445
        data = (uint8_t*)databuffer;
-
 
446
    if (sparebuffer && !((uint32_t)sparebuffer & 0xf))
306
    if (sparebuffer) spare = sparebuffer;
447
        spare = (uint8_t*)sparebuffer;
-
 
448
    mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
-
 
449
    nand_last_activity_value = USEC_TIMER;
-
 
450
    if (!nand_powered) nand_power_up();
-
 
451
    if (sparebuffer)
-
 
452
    {
-
 
453
        if (spare != sparebuffer) memcpy(spare, sparebuffer, 0x40);
-
 
454
    }
307
    else memset(spare, 0xFF, 0x40);
455
    else memset(spare, 0xFF, 0x40);
-
 
456
    nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
-
 
457
    if (nand_send_cmd(NAND_CMD_PROGRAM)) return nand_unlock(1);
-
 
458
    if (nand_send_address(page, databuffer ? 0 : 0x800))
-
 
459
        return nand_unlock(1);
-
 
460
    if (databuffer && data != databuffer) memcpy(data, databuffer, 0x800);
-
 
461
    if (databuffer) nand_transfer_data_start(bank, 1, data, 0x800);
308
    if (doecc)
462
    if (doecc)
309
    {
463
    {
310
        if (ecc_encode(3, data, nand_ecc)) return 1;
464
        if (ecc_encode(3, data, nand_ecc)) return nand_unlock(1);
311
        memcpy(&spare[0xC], nand_ecc, 0x28);
465
        memcpy(&spare[0xC], nand_ecc, 0x28);
312
        memset(nand_ctrl, 0xFF, 0x200);
466
        memset(nand_ctrl, 0xFF, 0x200);
313
        memcpy(nand_ctrl, spare, 0xC);
467
        memcpy(nand_ctrl, spare, 0xC);
314
        if (ecc_encode(0, nand_ctrl, nand_ecc)) return 1;
468
        if (ecc_encode(0, nand_ctrl, nand_ecc)) return nand_unlock(1);
315
        memcpy(&spare[0x34], nand_ecc, 0xC);
469
        memcpy(&spare[0x34], nand_ecc, 0xC);
316
    }
470
    }
317
    nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
-
 
318
    if (nand_send_cmd(NAND_CMD_PROGRAM)) return 1;
471
    if (databuffer)
319
    if (nand_send_address(page, data ? 0 : 0x800)) return 1;
472
        if (nand_transfer_data_collect(1))
320
    if (data) if (nand_transfer_data(bank, 1, data, 0x800)) return 1;
473
            return nand_unlock(1);
321
    if (sparebuffer || doecc)
474
    if (sparebuffer || doecc)
322
        if (nand_transfer_data(bank, 1, spare, 0x40)) return 1;
475
        if (nand_transfer_data(bank, 1, spare, 0x40))
-
 
476
            return nand_unlock(1);
323
    if (nand_send_cmd(NAND_CMD_PROGCNFRM)) return 1;
477
    if (nand_send_cmd(NAND_CMD_PROGCNFRM)) return nand_unlock(1);
-
 
478
    if (wait) if (nand_wait_status_ready(bank)) return nand_unlock(1);
324
    return nand_wait_status_ready(bank);
479
    return nand_unlock(0);
325
}
480
}
326
 
481
 
327
uint32_t nand_block_erase(uint32_t bank, uint32_t page)
482
uint32_t nand_block_erase(uint32_t bank, uint32_t page)
328
{
483
{
-
 
484
    mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
-
 
485
    nand_last_activity_value = USEC_TIMER;
-
 
486
    if (!nand_powered) nand_power_up();
329
    nand_set_fmctrl0(bank, 0);
487
    nand_set_fmctrl0(bank, 0);
330
    if (nand_send_cmd(NAND_CMD_BLOCKERASE)) return 1;
488
    if (nand_send_cmd(NAND_CMD_BLOCKERASE)) return nand_unlock(1);
331
    FMANUM = 2;
489
    FMANUM = 2;
332
    FMADDR0 = page;
490
    FMADDR0 = page;
333
    FMCTRL1 = FMCTRL1_DOTRANSADDR;
491
    FMCTRL1 = FMCTRL1_DOTRANSADDR;
334
    if (nand_wait_cmddone()) return 1;
492
    if (nand_wait_cmddone()) return nand_unlock(1);
335
    if (nand_send_cmd(NAND_CMD_ERASECNFRM)) return 1;
493
    if (nand_send_cmd(NAND_CMD_ERASECNFRM)) return nand_unlock(1);
-
 
494
    if (nand_wait_status_ready(bank)) return nand_unlock(1);
-
 
495
    return nand_unlock(0);
-
 
496
}
-
 
497
 
-
 
498
uint32_t nand_read_page_fast(uint32_t page, void* databuffer,
-
 
499
                             void* sparebuffer, uint32_t doecc,
-
 
500
                             uint32_t checkempty)
-
 
501
{
-
 
502
    uint32_t i, rc = 0;
-
 
503
    if (((uint32_t)databuffer & 0xf) || ((uint32_t)sparebuffer & 0xf)
-
 
504
     || !databuffer || !sparebuffer || !doecc)
-
 
505
    {
-
 
506
        for (i = 0; i < 4; i++)
-
 
507
        {
-
 
508
            if (nand_type[i] == 0xFFFFFFFF) continue;
-
 
509
            void* databuf = (void*)0;
-
 
510
            void* sparebuf = (void*)0;
-
 
511
            if (databuffer) databuf = (void*)((uint32_t)databuffer + 0x800 * i);
-
 
512
            if (sparebuffer) sparebuf = (void*)((uint32_t)sparebuffer + 0x40 * i);
-
 
513
            uint32_t ret = nand_read_page(i, page, databuf, sparebuf, doecc, checkempty);
-
 
514
            if (ret & 1) rc |= 1 << (i << 2);
-
 
515
            if (ret & 2) rc |= 2 << (i << 2);
-
 
516
            if (ret & 0x10) rc |= 4 << (i << 2);
-
 
517
            if (ret & 0x100) rc |= 8 << (i << 2);
-
 
518
        }
-
 
519
        return rc;
-
 
520
    }
-
 
521
    mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
-
 
522
    nand_last_activity_value = USEC_TIMER;
-
 
523
    if (!nand_powered) nand_power_up();
-
 
524
    uint8_t status[4];
-
 
525
    for (i = 0; i < 4; i++) status[i] = (nand_type[i] == 0xFFFFFFFF);
-
 
526
    for (i = 0; i < 4; i++)
-
 
527
    {
-
 
528
        if (!status[i])
-
 
529
        {
-
 
530
            nand_set_fmctrl0(i, FMCTRL0_ENABLEDMA);
-
 
531
            if (nand_send_cmd(NAND_CMD_READ))
-
 
532
                status[i] = 1;
-
 
533
        }
-
 
534
        if (!status[i])
-
 
535
            if (nand_send_address(page, 0))
-
 
536
                status[i] = 1;
-
 
537
        if (!status[i])
-
 
538
            if (nand_send_cmd(NAND_CMD_READ2))
-
 
539
                status[i] = 1;
-
 
540
    }
-
 
541
    if (!status[0])
-
 
542
        if (nand_wait_status_ready(0))
-
 
543
            status[0] = 1;
-
 
544
    if (!status[0])
-
 
545
        if (nand_transfer_data(0, 0, databuffer, 0x800))
-
 
546
            status[0] = 1;
-
 
547
    if (!status[0])
-
 
548
        if (nand_transfer_data(0, 0, sparebuffer, 0x40))
-
 
549
            status[0] = 1;
-
 
550
    for (i = 1; i < 4; i++)
-
 
551
    {
-
 
552
        if (!status[i])
-
 
553
            if (nand_wait_status_ready(i))
-
 
554
                status[i] = 1;
-
 
555
        if (!status[i])
-
 
556
            nand_transfer_data_start(i, 0, (void*)((uint32_t)databuffer
-
 
557
                                                 + 0x800 * i), 0x800);
-
 
558
        if (!status[i - 1])
-
 
559
        {
-
 
560
            memcpy(nand_ecc, (void*)((uint32_t)sparebuffer + 0x40 * (i - 1) + 0xC), 0x28);
-
 
561
            ecc_start(3, (void*)((uint32_t)databuffer
-
 
562
                               + 0x800 * (i - 1)), nand_ecc, ECCCTRL_STARTDECODING);
-
 
563
        }
-
 
564
        if (!status[i])
-
 
565
            if (nand_transfer_data_collect(0))
-
 
566
                status[i] = 1;
-
 
567
        if (!status[i])
-
 
568
            nand_transfer_data_start(i, 0, (void*)((uint32_t)sparebuffer
-
 
569
                                                 + 0x40 * i), 0x40);
-
 
570
        if (!status[i - 1])
-
 
571
            if (ecc_collect() & 1)
-
 
572
                status[i - 1] = 4;
-
 
573
        if (!status[i - 1])
-
 
574
        {
-
 
575
            memset(nand_ctrl, 0xFF, 0x200);
-
 
576
            memcpy(nand_ctrl, (void*)((uint32_t)sparebuffer + 0x40 * (i - 1)), 0xC);
-
 
577
            memcpy(nand_ecc, (void*)((uint32_t)sparebuffer + 0x40 * (i - 1) + 0x34), 0xC);
-
 
578
            ecc_start(0, nand_ctrl, nand_ecc, ECCCTRL_STARTDECODING);
-
 
579
        }
-
 
580
        if (!status[i])
-
 
581
            if (nand_transfer_data_collect(0))
-
 
582
                status[i] = 1;
-
 
583
        if (!status[i - 1])
-
 
584
        {
-
 
585
            if (ecc_collect() & 1)
-
 
586
            {
-
 
587
                status[i - 1] |= 8;
-
 
588
                memset((void*)((uint32_t)sparebuffer + 0x40 * (i - 1)), 0xFF, 0xC);
-
 
589
            }
-
 
590
            else memcpy((void*)((uint32_t)sparebuffer + 0x40 * (i - 1)), nand_ctrl, 0xC);
-
 
591
            if (checkempty)
-
 
592
                status[i - 1] |= nand_check_empty((void*)((uint32_t)sparebuffer
-
 
593
                                                        + 0x40 * (i - 1))) << 1;
-
 
594
        }
-
 
595
    }
-
 
596
    if (!status[i - 1])
-
 
597
    {
-
 
598
        memcpy(nand_ecc,(void*)((uint32_t)sparebuffer + 0x40 * (i - 1) + 0xC), 0x28);
-
 
599
        if (ecc_decode(3, (void*)((uint32_t)databuffer
-
 
600
                                + 0x800 * (i - 1)), nand_ecc) & 1)
-
 
601
            status[i - 1] = 4;
-
 
602
    }
-
 
603
    if (!status[i - 1])
-
 
604
    {
-
 
605
        memset(nand_ctrl, 0xFF, 0x200);
-
 
606
        memcpy(nand_ctrl, (void*)((uint32_t)sparebuffer + 0x40 * (i - 1)), 0xC);
-
 
607
        memcpy(nand_ecc, (void*)((uint32_t)sparebuffer + 0x40 * (i - 1) + 0x34), 0xC);
-
 
608
        if (ecc_decode(0, nand_ctrl, nand_ecc) & 1)
-
 
609
        {
-
 
610
            status[i - 1] |= 8;
-
 
611
            memset((void*)((uint32_t)sparebuffer + 0x40 * (i - 1)), 0xFF, 0xC);
-
 
612
        }
-
 
613
        else memcpy((void*)((uint32_t)sparebuffer + 0x40 * (i - 1)), nand_ctrl, 0xC);
-
 
614
        if (checkempty)
-
 
615
            status[i - 1] |= nand_check_empty((void*)((uint32_t)sparebuffer
-
 
616
                                                    + 0x40 * (i - 1))) << 1;
-
 
617
    }
-
 
618
    for (i = 0; i < 4; i++)
-
 
619
        if (nand_type[i] != 0xFFFFFFFF)
-
 
620
            rc |= status[i] << (i << 2);
-
 
621
    return nand_unlock(rc);
-
 
622
}
-
 
623
 
-
 
624
uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer,
-
 
625
                         void* sparebuffer, uint32_t doecc)
-
 
626
{
-
 
627
    return nand_write_page_int(bank, page, databuffer, sparebuffer, doecc, 1);
-
 
628
}
-
 
629
 
-
 
630
uint32_t nand_write_page_start(uint32_t bank, uint32_t page, void* databuffer,
-
 
631
                               void* sparebuffer, uint32_t doecc)
-
 
632
{
-
 
633
    if (((uint32_t)databuffer & 0xf) || ((uint32_t)sparebuffer & 0xf)
-
 
634
     || !databuffer || !sparebuffer || !doecc || !nand_interleaved)
-
 
635
        return nand_write_page_int(bank, page, databuffer, sparebuffer, doecc, !nand_interleaved);
-
 
636
 
-
 
637
    mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
-
 
638
    nand_last_activity_value = USEC_TIMER;
-
 
639
    if (!nand_powered) nand_power_up();
-
 
640
    nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
-
 
641
    if (nand_send_cmd(NAND_CMD_PROGRAM))
-
 
642
        return nand_unlock(1);
-
 
643
    if (nand_send_address(page, 0))
-
 
644
        return nand_unlock(1);
-
 
645
    nand_transfer_data_start(bank, 1, databuffer, 0x800);
-
 
646
    if (ecc_encode(3, databuffer, nand_ecc))
-
 
647
        return nand_unlock(1);
-
 
648
    memcpy((void*)((uint32_t)sparebuffer + 0xC), nand_ecc, 0x28);
-
 
649
    memset(nand_ctrl, 0xFF, 0x200);
-
 
650
    memcpy(nand_ctrl, sparebuffer, 0xC);
-
 
651
    if (ecc_encode(0, nand_ctrl, nand_ecc))
-
 
652
        return nand_unlock(1);
-
 
653
    memcpy((void*)((uint32_t)sparebuffer + 0x34), nand_ecc, 0xC);
-
 
654
    if (nand_transfer_data_collect(0))
-
 
655
        return nand_unlock(1);
-
 
656
    if (nand_transfer_data(bank, 1, sparebuffer, 0x40))
-
 
657
        return nand_unlock(1);
-
 
658
    return nand_unlock(nand_send_cmd(NAND_CMD_PROGCNFRM));
-
 
659
}
-
 
660
 
-
 
661
uint32_t nand_write_page_collect(uint32_t bank)
-
 
662
{
336
    return nand_wait_status_ready(bank);
663
    return nand_wait_status_ready(bank);
337
}
664
}
338
 
665
 
339
uint32_t nand_block_erase_fast(uint32_t page)
666
uint32_t nand_block_erase_fast(uint32_t page)
340
{
667
{
341
    uint32_t i, rc = 0;
668
    uint32_t i, rc = 0;
-
 
669
    mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
-
 
670
    nand_last_activity_value = USEC_TIMER;
-
 
671
    if (!nand_powered) nand_power_up();
342
    for (i = 0; i < 4; i++)
672
    for (i = 0; i < 4; i++)
343
    {
673
    {
344
        if (nand_type[i] == 0xFFFFFFFF) continue;
674
        if (nand_type[i] == 0xFFFFFFFF) continue;
345
        nand_set_fmctrl0(i, 0);
675
        nand_set_fmctrl0(i, 0);
346
        if (nand_send_cmd(NAND_CMD_BLOCKERASE))
676
        if (nand_send_cmd(NAND_CMD_BLOCKERASE))
Line 362... Line 692...
362
    {
692
    {
363
        if (nand_type[i] == 0xFFFFFFFF) continue;
693
        if (nand_type[i] == 0xFFFFFFFF) continue;
364
        if (rc & (1 << i)) continue;
694
        if (rc & (1 << i)) continue;
365
        if (nand_wait_status_ready(i)) rc |= 1 << i;
695
        if (nand_wait_status_ready(i)) rc |= 1 << i;
366
    }
696
    }
367
    return rc;
697
    return nand_unlock(rc);
368
}
698
}
369
 
699
 
370
const struct nand_device_info_type* nand_get_device_type(uint32_t bank)
700
const struct nand_device_info_type* nand_get_device_type(uint32_t bank)
371
{
701
{
372
    if (nand_type[bank] == 0xFFFFFFFF)
702
    if (nand_type[bank] == 0xFFFFFFFF)
373
        return (struct nand_device_info_type*)0;
703
        return (struct nand_device_info_type*)0;
374
    return &nand_deviceinfotable[nand_type[bank]];
704
    return &nand_deviceinfotable[nand_type[bank]];
375
}
705
}
376
 
706
 
-
 
707
static void nand_thread(void)
-
 
708
{
-
 
709
    while (1)
-
 
710
    {
-
 
711
        if (TIME_AFTER(USEC_TIMER, nand_last_activity_value + 200000) && nand_powered)
-
 
712
            nand_power_down();
-
 
713
        sleep(100000);
-
 
714
    }
-
 
715
}
-
 
716
 
377
uint32_t nand_init()
717
uint32_t nand_device_init(void)
378
{
718
{
-
 
719
    mutex_init(&nand_mtx);
-
 
720
    wakeup_init(&nand_wakeup);
-
 
721
    mutex_init(&ecc_mtx);
-
 
722
    wakeup_init(&ecc_wakeup);
-
 
723
 
379
    uint32_t type;
724
    uint32_t type;
380
    uint32_t i, j;
725
    uint32_t i, j;
381
    PWRCONEXT &= ~0x40;
-
 
382
    PWRCON &= ~0x100010;
-
 
-
 
726
 
383
    i2c_sendbyte(0, 0xE6, 0x35, 0x15);
727
    /* Assume there are 0 banks, to prevent
384
    i2c_sendbyte(0, 0xE6, 0x36, 0x01);
728
       nand_power_up from talking with them yet. */
385
    PCON2 = 0x33333333;
729
    for(i = 0; i < 4; i++) nand_type[i] = 0xFFFFFFFF;
386
    PDAT2 = 0;
-
 
387
    PCON3 = 0x11113333;
730
    nand_power_up();
388
    PDAT3 = 0;
731
 
389
    PCON4 = 0x33333333;
732
    /* Now that the flash is powered on, detect how
390
    PDAT4 = 0;
-
 
391
    PCON5 = (PCON5 & ~0xF) | 3;
733
       many banks we really have and initialize them. */
392
    PUNK5 = 1;
-
 
393
    sleep(10000);
-
 
394
    for (i = 0; i < 4; i++)
734
    for (i = 0; i < 4; i++)
395
    {
735
    {
396
        nand_tunk1[i] = 7;
736
        nand_tunk1[i] = 7;
397
        nand_twp[i] = 7;
737
        nand_twp[i] = 7;
398
        nand_tunk2[i] = 7;
738
        nand_tunk2[i] = 7;
399
        nand_tunk3[i] = 7;
739
        nand_tunk3[i] = 7;
400
        type = nand_get_chip_type(i);
740
        type = nand_get_chip_type(i);
401
        nand_type[i] = 0xFFFFFFFF;
-
 
402
        if (type == 0xFFFFFFFF) continue;
741
        if (type == 0xFFFFFFFF) continue;
403
        for (j = 0; ; j++)
742
        for (j = 0; ; j++)
404
        {
743
        {
405
            if (j == NAND_DEVICEINFOTABLE_ENTRIES) break;
744
            if (j == sizeof(nand_deviceinfotable) / sizeof(nand_deviceinfotable[0])) break;
406
            else if (nand_deviceinfotable[j].id == type)
745
            else if (nand_deviceinfotable[j].id == type)
407
            {
746
            {
408
                nand_type[i] = j;
747
                nand_type[i] = j;
409
                break;
748
                break;
410
            }
749
            }
Line 413... Line 752...
413
        nand_twp[i] = nand_deviceinfotable[nand_type[i]].twp;
752
        nand_twp[i] = nand_deviceinfotable[nand_type[i]].twp;
414
        nand_tunk2[i] = nand_deviceinfotable[nand_type[i]].tunk2;
753
        nand_tunk2[i] = nand_deviceinfotable[nand_type[i]].tunk2;
415
        nand_tunk3[i] = nand_deviceinfotable[nand_type[i]].tunk3;
754
        nand_tunk3[i] = nand_deviceinfotable[nand_type[i]].tunk3;
416
    }
755
    }
417
    if (nand_type[0] == 0xFFFFFFFF) return 1;
756
    if (nand_type[0] == 0xFFFFFFFF) return 1;
-
 
757
    nand_interleaved = ((nand_type[0] >> 22) & 1);
-
 
758
    nand_cached = ((nand_type[0] >> 23) & 1);
-
 
759
 
-
 
760
    nand_last_activity_value = USEC_TIMER;
-
 
761
    thread_create("NAND idle monitor", nand_thread, nand_stack,
-
 
762
                  sizeof(nand_stack), USER_THREAD, 1, true);
-
 
763
 
418
    return 0;
764
    return 0;
419
}
765
}