]> hackdaworld.org Git - my-code/arm.git/blob - betty/flash.c
Merge branch 'master' of hackdaworld.org:/chroot/git/my-code/arm
[my-code/arm.git] / betty / flash.c
1 /*
2  * flash.c - low level flash handling
3  *
4  * author: hackbard@hackdaworld.org
5  *
6  */
7
8 #include "flash.h"
9
10 /*
11  * sector addresses
12  */
13
14 unsigned long sector_address[20]={
15         0x00000,0x02000,0x03000,0x04000,0x08000,
16         0x10000,0x18000,
17         0x20000,0x28000,
18         0x30000,0x38000,
19         0x40000,0x48000,
20         0x50000,0x58000,
21         0x60000,0x68000,
22         0x70000,0x78000,
23         0x80000                 // not a sector, end of flash!
24 };
25
26 /*
27  * functions
28  */
29
30 void flash_init(void) {
31
32         flash_reset('0');
33         flash_reset('2');
34 }
35
36 void flash_reset(u8 bank) {
37
38         if((bank!='0')&(bank!='2'))
39                 return;
40
41         if(bank=='0')
42                 FLASH_B0F=0xf0;
43         else
44                 FLASH_B2F=0xf0;
45 }
46
47 void flash_sector_erase(u8 bank,u8 sector) {
48
49         u32 a18_12;
50
51         if(sector>18)
52                 return;
53         a18_12=sector_address[sector]<<1;
54
55         switch(bank) {
56                 case '0':
57                         FLASH_B0F555=0xaa;
58                         FLASH_B0F2AA=0x55;
59                         FLASH_B0F555=0x80;
60                         FLASH_B0F555=0xaa;
61                         FLASH_B0F2AA=0x55;
62                         *((volatile u16 *)(FLASH_BANK0|a18_12))=0x30;
63                         break;
64                 case '2': 
65                         FLASH_B2F555=0xaa;
66                         FLASH_B2F2AA=0x55;
67                         FLASH_B2F555=0x80;
68                         FLASH_B2F555=0xaa;
69                         FLASH_B2F2AA=0x55;
70                         *((volatile u16 *)(FLASH_BANK2|a18_12))=0x30;
71                         break;
72                 default:
73                         return;
74         }
75
76         return;
77 }
78
79 int flash_sec_erase(u32 addr) {
80
81         u32 a18_12;
82         u32 base;
83
84         a18_12=addr&0x00000fffff;
85         base=addr&0xff000000;
86         
87         *((volatile u16 *)(base|(0x555<<1)))=0xaa;
88         *((volatile u16 *)(base|(0x2aa<<1)))=0x55;
89         *((volatile u16 *)(base|(0x555<<1)))=0x80;
90         *((volatile u16 *)(base|(0x555<<1)))=0xaa;
91         *((volatile u16 *)(base|(0x2aa<<1)))=0x55;
92         *((volatile u16 *)(base|(a18_12<<1)))=0x30;
93
94         return 0;
95 }
96
97 void flash_chip_erase(u8 bank) {
98
99         u8 status;
100
101         if((bank!='0')&(bank!='2'))
102                 return;
103
104         if(bank=='0') {
105                 FLASH_B0F555=0xaa;
106                 FLASH_B0F2AA=0x55;
107                 FLASH_B0F555=0x80;
108                 FLASH_B0F555=0xaa;
109                 FLASH_B0F2AA=0x55;
110                 FLASH_B0F555=0x10;
111         }
112         else {
113                 FLASH_B2F555=0xaa;
114                 FLASH_B2F2AA=0x55;
115                 FLASH_B2F555=0x80;
116                 FLASH_B2F555=0xaa;
117                 FLASH_B2F2AA=0x55;
118                 FLASH_B2F555=0x10;
119         }
120
121         while(1) {
122                 if(bank=='0')
123                         status=FLASH_B0F;
124                 else
125                         status=FLASH_B2F;
126                 if(status&0x80)
127                         break;
128         }
129 }
130
131 void flash_unlock_bypass(u8 bank) {
132
133         if((bank!='0')&(bank!='2'))
134                 return;
135
136         if(bank=='0') {
137                 FLASH_B0F555=0xaa;
138                 FLASH_B0F2AA=0x55;
139                 FLASH_B0F555=0x20;
140         }
141         else {
142                 FLASH_B2F555=0xaa;
143                 FLASH_B2F2AA=0x55;
144                 FLASH_B2F555=0x20;
145         }
146 }
147
148 void flash_unlock_bypass_reset(u8 bank) {
149
150         if((bank!='0')&(bank!='2'))
151                 return;
152
153         if(bank=='0') {
154                 FLASH_B0F=0x90;
155                 FLASH_B0F=0x00;
156         }
157         else {
158                 FLASH_B2F=0x90;
159                 FLASH_B2F=0x00;
160         }
161 }
162
163 int flash_write_word(u32 addr,u16 data) {
164
165         u16 check;
166
167         if(data==0xffff)
168                 return 0;
169
170         *((unsigned volatile short *)addr)=0xa0;
171         *((unsigned volatile short *)addr)=data;
172         while(1) {
173                 check=*((unsigned short *)addr);
174                 if((data&0x80)==(check&0x80))
175                         break;
176         }
177         if(data!=check)
178                 return -1;
179
180         return 0;
181 }
182
183 #define flash_read_word(addr,data) *(data)=*((unsigned volatile short *)(addr))
184
185 int flash_write_buf(u32 addr,u16 *buf,int len) {
186
187         int cnt,ret;
188         u8 bank;
189
190         /* len must be a multiple of 2 */
191         if(len&0x1)
192                 return -1;
193
194         /* decide the bank */
195         if(addr<0x82000000)
196                 bank='0';
197         else
198                 bank='2';
199
200         /* unlock */
201         flash_unlock_bypass(bank);
202
203         /* write the data */
204         ret=0;
205         for(cnt=0;cnt<len/2;cnt++) {
206                 if(flash_write_word(addr,*(buf+cnt))==0)
207                         ret+=2;
208                 addr+=2;
209         }
210
211         /* relock */
212         flash_unlock_bypass_reset(bank);
213
214         return ret;
215 }
216
217 void flash_read_buf(u32 addr,u16 *buf,int len) {
218
219         int cnt;
220
221         /* len must be a multiple of 2 */
222         if(len&0x1)
223                 return;
224
225         for(cnt=0;cnt<len/2;cnt++)
226                 flash_read_word(addr,buf+cnt);
227 }
228