first pseudo flash filesystem code (not working yet)
[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[19]={
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 };
24
25 /*
26  * functions
27  */
28
29 void flash_init(void) {
30
31         /*
32          * idle clocks between rad & write: 0+1
33          * length of read access: 1+3
34          * bls lines high during write access
35          * length of write access: 0+1
36          * no write protect, no burst-rom
37          * 16 bit data width
38          */
39
40         BCFG0=0x10000420;       // flash 1
41         BCFG2=0x10000420;       // flash 2
42
43         /*
44          * p3.27: write enable
45          * p3.25: chip select 2
46          * p2.15 - p2.8: data bus
47          * a[1:15] -> address lines
48          */
49
50         PINSEL2=(PINSEL2&P2MASK)|(1<<8);
51         PINSEL2=(PINSEL2&P2MASK&~((1<<15)|(1<<14)))|(1<<14);
52         PINSEL2=(PINSEL2&P2MASK&~((1<<5)|(1<<4)))|(1<<4);
53         PINSEL2=(PINSEL2&P2MASK)|(1<<24);
54         PINSEL2=(PINSEL2&P2MASK&~((1<<27)|(1<<26)|(1<<25)))|(1<<27)|(1<<26);
55 }
56
57 void flash_reset(u8 bank) {
58
59         if((bank!='0')&(bank!='2'))
60                 return;
61
62         if(bank=='0')
63                 FLASH_B0F=0xf0;
64         else
65                 FLASH_B2F=0xf0;
66 }
67
68 void flash_sector_erase(u8 bank,u8 sector) {
69
70         u32 a18_12;
71
72         if(sector>18)
73                 return;
74         a18_12=sector_address[sector]<<1;
75
76         switch(bank) {
77                 case '0':
78                         FLASH_B0F555=0xaa;
79                         FLASH_B0F2AA=0x55;
80                         FLASH_B0F555=0x80;
81                         FLASH_B0F555=0xaa;
82                         FLASH_B0F2AA=0x55;
83                         *((volatile u16 *)(FLASH_BANK0|a18_12))=0x30;
84                         break;
85                 case '2': 
86                         FLASH_B2F555=0xaa;
87                         FLASH_B2F2AA=0x55;
88                         FLASH_B2F555=0x80;
89                         FLASH_B2F555=0xaa;
90                         FLASH_B2F2AA=0x55;
91                         *((volatile u16 *)(FLASH_BANK2|a18_12))=0x30;
92                         break;
93                 default:
94                         return;
95         }
96
97         return;
98 }
99
100 int flash_sec_erase(u32 addr) {
101
102         u32 a18_12;
103         u32 base;
104
105         a18_12=addr&0x00000fffff;
106         base=addr&0xff000000;
107         
108         *((volatile u16 *)(base|(0x555<<1)))=0xaa;
109         *((volatile u16 *)(base|(0x2aa<<1)))=0x55;
110         *((volatile u16 *)(base|(0x555<<1)))=0x80;
111         *((volatile u16 *)(base|(0x555<<1)))=0xaa;
112         *((volatile u16 *)(base|(0x2aa<<1)))=0x55;
113         *((volatile u16 *)(base|(a18_12<<1)))=0x30;
114
115         return 0;
116 }
117
118 void flash_chip_erase(u8 bank) {
119
120         u8 status;
121
122         if((bank!='0')&(bank!='2'))
123                 return;
124
125         if(bank=='0') {
126                 FLASH_B0F555=0xaa;
127                 FLASH_B0F2AA=0x55;
128                 FLASH_B0F555=0x80;
129                 FLASH_B0F555=0xaa;
130                 FLASH_B0F2AA=0x55;
131                 FLASH_B0F555=0x10;
132         }
133         else {
134                 FLASH_B2F555=0xaa;
135                 FLASH_B2F2AA=0x55;
136                 FLASH_B2F555=0x80;
137                 FLASH_B2F555=0xaa;
138                 FLASH_B2F2AA=0x55;
139                 FLASH_B2F555=0x10;
140         }
141
142         while(1) {
143                 if(bank=='0')
144                         status=FLASH_B0F;
145                 else
146                         status=FLASH_B2F;
147                 if(status&0x80)
148                         break;
149         }
150 }
151
152 void flash_unlock_bypass(u8 bank) {
153
154         if((bank!='0')&(bank!='2'))
155                 return;
156
157         if(bank=='0') {
158                 FLASH_B0F555=0xaa;
159                 FLASH_B0F2AA=0x55;
160                 FLASH_B0F555=0x20;
161         }
162         else {
163                 FLASH_B2F555=0xaa;
164                 FLASH_B2F2AA=0x55;
165                 FLASH_B2F555=0x20;
166         }
167 }
168
169 void flash_unlock_bypass_reset(u8 bank) {
170
171         if((bank!='0')&(bank!='2'))
172                 return;
173
174         if(bank=='0') {
175                 FLASH_B0F=0x90;
176                 FLASH_B0F=0x00;
177         }
178         else {
179                 FLASH_B2F=0x90;
180                 FLASH_B2F=0x00;
181         }
182 }
183
184 int flash_write_word(u32 addr,u16 data) {
185
186         u16 check;
187
188         if(data==0xffff)
189                 return 0;
190
191         *((unsigned volatile short *)addr)=0xa0;
192         *((unsigned volatile short *)addr)=data;
193         while(1) {
194                 check=*((unsigned short *)addr);
195                 if((data&0x80)==(check&0x80))
196                         break;
197         }
198         if(data!=check)
199                 return -1;
200
201         return 0;
202 }
203
204 #define flash_read_word(addr,data) *(data)=*((unsigned volatile short *)(addr))
205
206 int flash_write_buf(u32 addr,u16 *buf,int len) {
207
208         int cnt,ret;
209         u8 bank;
210
211         /* len must be a multiple of 2 */
212         if(len&0x1)
213                 return -1;
214
215         /* decide the bank */
216         if(addr<0x82000000)
217                 bank='0';
218         else
219                 bank='2';
220
221         /* unlock */
222         flash_unlock_bypass(bank);
223
224         /* write the data */
225         ret=0;
226         for(cnt=0;cnt<len/2;cnt++) {
227                 if(flash_write_word(addr,*(buf+cnt))==0)
228                         ret+=2;
229                 addr+=2;
230         }
231
232         /* relock */
233         flash_unlock_bypass_reset(bank);
234
235         return ret;
236 }
237
238 void flash_read_buf(u32 addr,u16 *buf,int len) {
239
240         int cnt;
241
242         /* len must be a multiple of 2 */
243         if(len&0x1)
244                 return;
245
246         for(cnt=0;cnt<len/2;cnt++)
247                 flash_read_word(addr,buf+cnt);
248 }
249