-
Notifications
You must be signed in to change notification settings - Fork 0
/
nand.c
executable file
·124 lines (94 loc) · 2.82 KB
/
nand.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#define NFCONF (*(volatile unsigned int *)0xB0E00000)
#define NFCONT (*(volatile unsigned int *)0xB0E00004)
#define NFCMMD (*(volatile unsigned char *)0xB0E00008)
#define NFADDR (*(volatile unsigned char *)0xB0E0000C)
#define NFDATA (*(volatile unsigned char *)0xB0E00010)
#define NFSTAT (*(volatile unsigned int *)0xB0E00028)
#define MP0_3CON (*(volatile unsigned int *)0xE0200320)
#define PAGE_SIZE 2048
void nand_init(void)
{
// [15:12] TACLS = 1 -> (1) 1/133Mhz = 7.5ns
// [11:8] TWRPH0 = 1 -> (1+1) 7.5ns * 2 = 15ns
// [7:4] TWRPH1 = 1 -> (1+1) 7.5ns * 2 = 15ns
NFCONF |= 1<<12 | 1<<8 | 1<<4;
// AddrCycle [1] 1 = 5 address cycle
NFCONF |= 1<<1;
// MODE [0] NAND Flash controller operating mode
// 0 = Disable NAND Flash Controller
// *1 = Enable NAND Flash Controller
NFCONT |= 1<<0;
// Reg_nCE0 [1] NAND Flash Memory nRCS[0] signal control
// *0 = Force nRCS[0] to low (Enable chip select)
// 1 = Force nRCS[0] to High (Disable chip select)
NFCONT &= ~(1<<1);
// reset Nandflash
NFCMMD = 0xFF;
// wait for R/nB -> Ready
while ((NFSTAT & (1<<0)) == 0)
continue;
NFCONT |= (1<<1);
// GPIO functional mux setting
// 0010 = NF_xxx
MP0_3CON = 0x22222222;
return;
}
void nand_read_id(char id[])
{
int i;
// Reg_nCE0 [1] NAND Flash Memory nRCS[0] signal control
// *0 = Force nRCS[0] to low (Enable chip select)
// 1 = Force nRCS[0] to High (Disable chip select)
NFCONT &= ~(1<<1);
// write read_id cmd 90h
NFCMMD = 0x90;
// write address 00h
NFADDR = 0x00;
for (i = 0; i < 5; i++)
id[i] = NFDATA;
NFCONT |= (1<<1);
return;
}
void nand_read_page(int addr, char buf[])
{
int i;
char tmp;
// Reg_nCE0 [1] NAND Flash Memory nRCS[0] signal control
// *0 = Force nRCS[0] to low (Enable chip select)
// 1 = Force nRCS[0] to High (Disable chip select)
NFCONT &= ~(1<<1);
// write read_page cmd 00h
NFCMMD = 0x00;
// write 5 address
NFADDR = (addr>>0) & 0xFF;
NFADDR = (addr>>8) & 0x7;
NFADDR = (addr>>11) & 0xFF;
NFADDR = (addr>>19) & 0xFF;
NFADDR = (addr>>27) & 0x1;
// write read_page cmd 30h
NFCMMD = 0x30;
// wait for R/nB -> Ready
while ((NFSTAT & (1<<0)) == 0)
;
// read data 2048 bytes
for (i = 0; i < PAGE_SIZE; i++)
buf[i] = NFDATA;
for (i = 0; i < 64; i++)
tmp = NFDATA;
NFCONT |= (1<<1);
return;
}
//10 00000 00000 - 1 = 1 11111 11111
#define NAND_BLOCK_MASK 2048-1
int nand_read(int nand_addr, char * sdram_addr, int size)
{
int pages;
int i;
if ((nand_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
return -1;
}
pages = (size - 1)/PAGE_SIZE + 1;
for (i = 0; i < pages; i++)
nand_read_page(nand_addr + i*PAGE_SIZE, sdram_addr + i*PAGE_SIZE);
return 0;
}