]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/mtd/dataflash.c
Merge branch 'master' of git://git.denx.de/u-boot-nand-flash
[karo-tx-uboot.git] / drivers / mtd / dataflash.c
1 /* LowLevel function for ATMEL DataFlash support
2  * Author : Hamid Ikdoumi (Atmel)
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
17  * MA 02111-1307 USA
18  *
19  */
20 #include <common.h>
21 #include <config.h>
22 #include <asm/hardware.h>
23 #include <dataflash.h>
24
25 static AT91S_DataFlash DataFlashInst;
26
27 extern void AT91F_SpiInit (void);
28 extern int AT91F_DataflashProbe (int i, AT91PS_DataflashDesc pDesc);
29 extern int AT91F_DataFlashRead (AT91PS_DataFlash pDataFlash,
30                                 unsigned long addr,
31                                 unsigned long size, char *buffer);
32 extern int AT91F_DataFlashWrite( AT91PS_DataFlash pDataFlash,
33                                 unsigned char *src,
34                                 int dest,
35                                 int size );
36
37 int AT91F_DataflashInit (void)
38 {
39         int i, j;
40         int dfcode;
41         int part;
42         int found[CONFIG_SYS_MAX_DATAFLASH_BANKS];
43         unsigned char protected;
44
45         AT91F_SpiInit ();
46
47         for (i = 0; i < CONFIG_SYS_MAX_DATAFLASH_BANKS; i++) {
48                 found[i] = 0;
49                 dataflash_info[i].Desc.state = IDLE;
50                 dataflash_info[i].id = 0;
51                 dataflash_info[i].Device.pages_number = 0;
52                 dfcode = AT91F_DataflashProbe (cs[i].cs,
53                                 &dataflash_info[i].Desc);
54
55                 switch (dfcode) {
56                 case AT45DB021:
57                         dataflash_info[i].Device.pages_number = 1024;
58                         dataflash_info[i].Device.pages_size = 264;
59                         dataflash_info[i].Device.page_offset = 9;
60                         dataflash_info[i].Device.byte_mask = 0x300;
61                         dataflash_info[i].Device.cs = cs[i].cs;
62                         dataflash_info[i].Desc.DataFlash_state = IDLE;
63                         dataflash_info[i].logical_address = cs[i].addr;
64                         dataflash_info[i].id = dfcode;
65                         found[i] += dfcode;;
66                         break;
67
68                 case AT45DB081:
69                         dataflash_info[i].Device.pages_number = 4096;
70                         dataflash_info[i].Device.pages_size = 264;
71                         dataflash_info[i].Device.page_offset = 9;
72                         dataflash_info[i].Device.byte_mask = 0x300;
73                         dataflash_info[i].Device.cs = cs[i].cs;
74                         dataflash_info[i].Desc.DataFlash_state = IDLE;
75                         dataflash_info[i].logical_address = cs[i].addr;
76                         dataflash_info[i].id = dfcode;
77                         found[i] += dfcode;;
78                         break;
79
80                 case AT45DB161:
81                         dataflash_info[i].Device.pages_number = 4096;
82                         dataflash_info[i].Device.pages_size = 528;
83                         dataflash_info[i].Device.page_offset = 10;
84                         dataflash_info[i].Device.byte_mask = 0x300;
85                         dataflash_info[i].Device.cs = cs[i].cs;
86                         dataflash_info[i].Desc.DataFlash_state = IDLE;
87                         dataflash_info[i].logical_address = cs[i].addr;
88                         dataflash_info[i].id = dfcode;
89                         found[i] += dfcode;;
90                         break;
91
92                 case AT45DB321:
93                         dataflash_info[i].Device.pages_number = 8192;
94                         dataflash_info[i].Device.pages_size = 528;
95                         dataflash_info[i].Device.page_offset = 10;
96                         dataflash_info[i].Device.byte_mask = 0x300;
97                         dataflash_info[i].Device.cs = cs[i].cs;
98                         dataflash_info[i].Desc.DataFlash_state = IDLE;
99                         dataflash_info[i].logical_address = cs[i].addr;
100                         dataflash_info[i].id = dfcode;
101                         found[i] += dfcode;;
102                         break;
103
104                 case AT45DB642:
105                         dataflash_info[i].Device.pages_number = 8192;
106                         dataflash_info[i].Device.pages_size = 1056;
107                         dataflash_info[i].Device.page_offset = 11;
108                         dataflash_info[i].Device.byte_mask = 0x700;
109                         dataflash_info[i].Device.cs = cs[i].cs;
110                         dataflash_info[i].Desc.DataFlash_state = IDLE;
111                         dataflash_info[i].logical_address = cs[i].addr;
112                         dataflash_info[i].id = dfcode;
113                         found[i] += dfcode;;
114                         break;
115
116                 case AT45DB128:
117                         dataflash_info[i].Device.pages_number = 16384;
118                         dataflash_info[i].Device.pages_size = 1056;
119                         dataflash_info[i].Device.page_offset = 11;
120                         dataflash_info[i].Device.byte_mask = 0x700;
121                         dataflash_info[i].Device.cs = cs[i].cs;
122                         dataflash_info[i].Desc.DataFlash_state = IDLE;
123                         dataflash_info[i].logical_address = cs[i].addr;
124                         dataflash_info[i].id = dfcode;
125                         found[i] += dfcode;;
126                         break;
127
128                 default:
129                         dfcode = 0;
130                         break;
131                 }
132                 /* set the last area end to the dataflash size*/
133                 dataflash_info[i].end_address =
134                                 (dataflash_info[i].Device.pages_number *
135                                 dataflash_info[i].Device.pages_size) - 1;
136
137                 part = 0;
138                 /* set the area addresses */
139                 for(j = 0; j < NB_DATAFLASH_AREA; j++) {
140                         if(found[i]!=0) {
141                                 dataflash_info[i].Device.area_list[j].start =
142                                         area_list[part].start +
143                                         dataflash_info[i].logical_address;
144                                 if(area_list[part].end == 0xffffffff) {
145                                         dataflash_info[i].Device.area_list[j].end =
146                                                 dataflash_info[i].end_address +
147                                                 dataflash_info[i].logical_address;
148                                 } else {
149                                         dataflash_info[i].Device.area_list[j].end =
150                                                 area_list[part].end +
151                                                 dataflash_info[i].logical_address;
152                                 }
153                                 protected = area_list[part].protected;
154                                 /* Set the environment according to the label...*/
155                                 if(protected == FLAG_PROTECT_INVALID) {
156                                         dataflash_info[i].Device.area_list[j].protected =
157                                                 FLAG_PROTECT_INVALID;
158                                 } else {
159                                         dataflash_info[i].Device.area_list[j].protected =
160                                                 protected;
161                                 }
162                                 strcpy((char*)(dataflash_info[i].Device.area_list[j].label),
163                                                 (const char *)area_list[part].label);
164                         }
165                         part++;
166                 }
167         }
168         return found[0];
169 }
170
171 void AT91F_DataflashSetEnv (void)
172 {
173         int i, j;
174         int part;
175         unsigned char env;
176         unsigned char s[32];    /* Will fit a long int in hex */
177         unsigned long start;
178
179         for (i = 0, part= 0; i < CONFIG_SYS_MAX_DATAFLASH_BANKS; i++) {
180                 for(j = 0; j < NB_DATAFLASH_AREA; j++) {
181                         env = area_list[part].setenv;
182                         /* Set the environment according to the label...*/
183                         if((env & FLAG_SETENV) == FLAG_SETENV) {
184                                 start = dataflash_info[i].Device.area_list[j].start;
185                                 sprintf((char*) s,"%lX",start);
186                                 setenv((char*) area_list[part].label,(char*) s);
187                         }
188                         part++;
189                 }
190         }
191 }
192
193 void dataflash_print_info (void)
194 {
195         int i, j;
196
197         for (i = 0; i < CONFIG_SYS_MAX_DATAFLASH_BANKS; i++) {
198                 if (dataflash_info[i].id != 0) {
199                         printf("DataFlash:");
200                         switch (dataflash_info[i].id) {
201                         case AT45DB021:
202                                 printf("AT45DB021\n");
203                                 break;
204                         case AT45DB161:
205                                 printf("AT45DB161\n");
206                                 break;
207
208                         case AT45DB321:
209                                 printf("AT45DB321\n");
210                                 break;
211
212                         case AT45DB642:
213                                 printf("AT45DB642\n");
214                                 break;
215                         case AT45DB128:
216                                 printf("AT45DB128\n");
217                                 break;
218                         }
219
220                         printf("Nb pages: %6d\n"
221                                 "Page Size: %6d\n"
222                                 "Size=%8d bytes\n"
223                                 "Logical address: 0x%08X\n",
224                                 (unsigned int) dataflash_info[i].Device.pages_number,
225                                 (unsigned int) dataflash_info[i].Device.pages_size,
226                                 (unsigned int) dataflash_info[i].Device.pages_number *
227                                 dataflash_info[i].Device.pages_size,
228                                 (unsigned int) dataflash_info[i].logical_address);
229                         for (j = 0; j < NB_DATAFLASH_AREA; j++) {
230                                 switch(dataflash_info[i].Device.area_list[j].protected) {
231                                 case    FLAG_PROTECT_SET:
232                                 case    FLAG_PROTECT_CLEAR:
233                                         printf("Area %i:\t%08lX to %08lX %s", j,
234                                                 dataflash_info[i].Device.area_list[j].start,
235                                                 dataflash_info[i].Device.area_list[j].end,
236                                                 (dataflash_info[i].Device.area_list[j].protected==FLAG_PROTECT_SET) ? "(RO)" : "    ");
237                                                 printf(" %s\n", dataflash_info[i].Device.area_list[j].label);
238                                         break;
239                                 case    FLAG_PROTECT_INVALID:
240                                         break;
241                                 }
242                         }
243                 }
244         }
245 }
246
247 /*---------------------------------------------------------------------------*/
248 /* Function Name       : AT91F_DataflashSelect                               */
249 /* Object              : Select the correct device                           */
250 /*---------------------------------------------------------------------------*/
251 AT91PS_DataFlash AT91F_DataflashSelect (AT91PS_DataFlash pFlash,
252                                 unsigned long *addr)
253 {
254         char addr_valid = 0;
255         int i;
256
257         for (i = 0; i < CONFIG_SYS_MAX_DATAFLASH_BANKS; i++)
258                 if ( dataflash_info[i].id
259                         && ((((int) *addr) & 0xFF000000) ==
260                         dataflash_info[i].logical_address)) {
261                         addr_valid = 1;
262                         break;
263                 }
264         if (!addr_valid) {
265                 pFlash = (AT91PS_DataFlash) 0;
266                 return pFlash;
267         }
268         pFlash->pDataFlashDesc = &(dataflash_info[i].Desc);
269         pFlash->pDevice = &(dataflash_info[i].Device);
270         *addr -= dataflash_info[i].logical_address;
271         return (pFlash);
272 }
273
274 /*---------------------------------------------------------------------------*/
275 /* Function Name       : addr_dataflash                                      */
276 /* Object              : Test if address is valid                            */
277 /*---------------------------------------------------------------------------*/
278 int addr_dataflash (unsigned long addr)
279 {
280         int addr_valid = 0;
281         int i;
282
283         for (i = 0; i < CONFIG_SYS_MAX_DATAFLASH_BANKS; i++) {
284                 if ((((int) addr) & 0xFF000000) ==
285                         dataflash_info[i].logical_address) {
286                         addr_valid = 1;
287                         break;
288                 }
289         }
290
291         return addr_valid;
292 }
293
294 /*---------------------------------------------------------------------------*/
295 /* Function Name       : size_dataflash                                      */
296 /* Object              : Test if address is valid regarding the size         */
297 /*---------------------------------------------------------------------------*/
298 int size_dataflash (AT91PS_DataFlash pdataFlash, unsigned long addr,
299                         unsigned long size)
300 {
301         /* is outside the dataflash */
302         if (((int)addr & 0x0FFFFFFF) > (pdataFlash->pDevice->pages_size *
303                 pdataFlash->pDevice->pages_number)) return 0;
304         /* is too large for the dataflash */
305         if (size > ((pdataFlash->pDevice->pages_size *
306                 pdataFlash->pDevice->pages_number) -
307                 ((int)addr & 0x0FFFFFFF))) return 0;
308
309         return 1;
310 }
311
312 /*---------------------------------------------------------------------------*/
313 /* Function Name       : prot_dataflash                                      */
314 /* Object              : Test if destination area is protected               */
315 /*---------------------------------------------------------------------------*/
316 int prot_dataflash (AT91PS_DataFlash pdataFlash, unsigned long addr)
317 {
318         int area;
319
320         /* find area */
321         for (area = 0; area < NB_DATAFLASH_AREA; area++) {
322                 if ((addr >= pdataFlash->pDevice->area_list[area].start) &&
323                         (addr < pdataFlash->pDevice->area_list[area].end))
324                         break;
325         }
326         if (area == NB_DATAFLASH_AREA)
327                 return -1;
328
329         /*test protection value*/
330         if (pdataFlash->pDevice->area_list[area].protected == FLAG_PROTECT_SET)
331                 return 0;
332         if (pdataFlash->pDevice->area_list[area].protected == FLAG_PROTECT_INVALID)
333                 return 0;
334
335         return 1;
336 }
337
338 /*--------------------------------------------------------------------------*/
339 /* Function Name       : dataflash_real_protect                             */
340 /* Object              : protect/unprotect area                             */
341 /*--------------------------------------------------------------------------*/
342 int dataflash_real_protect (int flag, unsigned long start_addr,
343                                 unsigned long end_addr)
344 {
345         int i,j, area1, area2, addr_valid = 0;
346
347         /* find dataflash */
348         for (i = 0; i < CONFIG_SYS_MAX_DATAFLASH_BANKS; i++) {
349                 if ((((int) start_addr) & 0xF0000000) ==
350                         dataflash_info[i].logical_address) {
351                                 addr_valid = 1;
352                                 break;
353                 }
354         }
355         if (!addr_valid) {
356                 return -1;
357         }
358         /* find start area */
359         for (area1 = 0; area1 < NB_DATAFLASH_AREA; area1++) {
360                 if (start_addr == dataflash_info[i].Device.area_list[area1].start)
361                         break;
362         }
363         if (area1 == NB_DATAFLASH_AREA) return -1;
364         /* find end area */
365         for (area2 = 0; area2 < NB_DATAFLASH_AREA; area2++) {
366                 if (end_addr == dataflash_info[i].Device.area_list[area2].end)
367                         break;
368         }
369         if (area2 == NB_DATAFLASH_AREA)
370                 return -1;
371
372         /*set protection value*/
373         for(j = area1; j < area2 + 1 ; j++)
374                 if(dataflash_info[i].Device.area_list[j].protected
375                                 != FLAG_PROTECT_INVALID) {
376                         if (flag == 0) {
377                                 dataflash_info[i].Device.area_list[j].protected
378                                         = FLAG_PROTECT_CLEAR;
379                         } else {
380                                 dataflash_info[i].Device.area_list[j].protected
381                                         = FLAG_PROTECT_SET;
382                         }
383                 }
384
385         return (area2 - area1 + 1);
386 }
387
388 /*---------------------------------------------------------------------------*/
389 /* Function Name       : read_dataflash                                      */
390 /* Object              : dataflash memory read                               */
391 /*---------------------------------------------------------------------------*/
392 int read_dataflash (unsigned long addr, unsigned long size, char *result)
393 {
394         unsigned long AddrToRead = addr;
395         AT91PS_DataFlash pFlash = &DataFlashInst;
396
397         pFlash = AT91F_DataflashSelect (pFlash, &AddrToRead);
398
399         if (pFlash == 0)
400                 return ERR_UNKNOWN_FLASH_TYPE;
401
402         if (size_dataflash(pFlash,addr,size) == 0)
403                 return ERR_INVAL;
404
405         return (AT91F_DataFlashRead (pFlash, AddrToRead, size, result));
406 }
407
408 /*---------------------------------------------------------------------------*/
409 /* Function Name       : write_dataflash                                     */
410 /* Object              : write a block in dataflash                          */
411 /*---------------------------------------------------------------------------*/
412 int write_dataflash (unsigned long addr_dest, unsigned long addr_src,
413                         unsigned long size)
414 {
415         unsigned long AddrToWrite = addr_dest;
416         AT91PS_DataFlash pFlash = &DataFlashInst;
417
418         pFlash = AT91F_DataflashSelect (pFlash, &AddrToWrite);
419
420         if (pFlash == 0)
421                 return ERR_UNKNOWN_FLASH_TYPE;
422
423         if (size_dataflash(pFlash,addr_dest,size) == 0)
424                 return ERR_INVAL;
425
426         if (prot_dataflash(pFlash,addr_dest) == 0)
427                 return ERR_PROTECTED;
428
429         if (AddrToWrite == -1)
430                 return -1;
431
432         return AT91F_DataFlashWrite (pFlash, (uchar *)addr_src,
433                                                 AddrToWrite, size);
434 }
435
436 void dataflash_perror (int err)
437 {
438         switch (err) {
439         case ERR_OK:
440                 break;
441         case ERR_TIMOUT:
442                 printf("Timeout writing to DataFlash\n");
443                 break;
444         case ERR_PROTECTED:
445                 printf("Can't write to protected/invalid DataFlash sectors\n");
446                 break;
447         case ERR_INVAL:
448                 printf("Outside available DataFlash\n");
449                 break;
450         case ERR_UNKNOWN_FLASH_TYPE:
451                 printf("Unknown Type of DataFlash\n");
452                 break;
453         case ERR_PROG_ERROR:
454                 printf("General DataFlash Programming Error\n");
455                 break;
456         default:
457                 printf("%s[%d] FIXME: rc=%d\n", __FILE__, __LINE__, err);
458                 break;
459         }
460 }