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