]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - board/altera/common/flash.c
* Patch by Ronen Shitrit, 10 Dec 2003:
[karo-tx-uboot.git] / board / altera / common / flash.c
1 /*
2  * (C) Copyright 2000-2004
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24
25 #include <common.h>
26 #include <nios.h>
27
28 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
29
30 /*--------------------------------------------------------------------*/
31 void flash_print_info (flash_info_t * info)
32 {
33         int i, k;
34         unsigned long size;
35         int erased;
36         volatile unsigned char *flash;
37
38         printf ("  Size: %ld KB in %d Sectors\n",
39                 info->size >> 10, info->sector_count);
40         printf ("  Sector Start Addresses:");
41         for (i = 0; i < info->sector_count; ++i) {
42
43                 /* Check if whole sector is erased */
44                 if (i != (info->sector_count - 1))
45                         size = info->start[i + 1] - info->start[i];
46                 else
47                         size = info->start[0] + info->size - info->start[i];
48                 erased = 1;
49                 flash = (volatile unsigned char *) info->start[i];
50                 for (k = 0; k < size; k++) {
51                         if (*flash++ != 0xff) {
52                                 erased = 0;
53                                 break;
54                         }
55                 }
56
57                 /* Print the info */
58                 if ((i % 5) == 0)
59                         printf ("\n   ");
60                 printf (" %08lX%s%s", info->start[i], erased ? " E" : "  ",
61                         info->protect[i] ? "RO " : "   ");
62         }
63         printf ("\n");
64 }
65
66 /*-------------------------------------------------------------------*/
67
68
69 int flash_erase (flash_info_t * info, int s_first, int s_last)
70 {
71         volatile CFG_FLASH_WORD_SIZE *addr = (CFG_FLASH_WORD_SIZE *) (info->start[0]);
72         volatile CFG_FLASH_WORD_SIZE *addr2;
73         int prot, sect;
74         int any = 0;
75         unsigned oldpri;
76         ulong start;
77
78         /* Some sanity checking */
79         if ((s_first < 0) || (s_first > s_last)) {
80                 printf ("- no sectors to erase\n");
81                 return 1;
82         }
83
84         prot = 0;
85         for (sect = s_first; sect <= s_last; ++sect) {
86                 if (info->protect[sect]) {
87                         prot++;
88                 }
89         }
90         if (prot) {
91                 printf ("- Warning: %d protected sectors will not be erased!\n",
92                         prot);
93         } else {
94                 printf ("\n");
95         }
96
97         /* NOTE: disabling interrupts on Nios can be very bad since it
98          * also disables the LO_LIMIT exception. It's better here to
99          * set the interrupt priority to 3 & restore it when we're done.
100          */
101         oldpri = ipri (3);
102
103         /* It's ok to erase multiple sectors provided we don't delay more
104          * than 50 usec between cmds ... at which point the erase time-out
105          * occurs. So don't go and put printf() calls in the loop ... it
106          * won't be very helpful ;-)
107          */
108         for (sect = s_first; sect <= s_last; sect++) {
109                 if (info->protect[sect] == 0) { /* not protected */
110                         addr2 = (CFG_FLASH_WORD_SIZE *) (info->start[sect]);
111                         *addr = 0xaa;
112                         *addr = 0x55;
113                         *addr = 0x80;
114                         *addr = 0xaa;
115                         *addr = 0x55;
116                         *addr2 = 0x30;
117                         any = 1;
118                 }
119         }
120
121         /* Now just wait for 0xff & provide some user feedback while
122          * we wait.
123          */
124         if (any) {
125                 addr2 = (CFG_FLASH_WORD_SIZE *) (info->start[sect]);
126                 start = get_timer (0);
127                 while (*addr2 != 0xff) {
128                         udelay (1000 * 1000);
129                         putc ('.');
130                         if (get_timer (start) > CFG_FLASH_ERASE_TOUT) {
131                                 printf ("timeout\n");
132                                 return 1;
133                         }
134                 }
135                 printf ("\n");
136         }
137
138         /* Restore interrupt priority */
139         ipri (oldpri);
140
141         return 0;
142 }
143
144 /*-----------------------------------------------------------------------
145  * Copy memory to flash, returns:
146  * 0 - OK
147  * 1 - write timeout
148  * 2 - Flash not erased
149  */
150
151 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
152 {
153
154         vu_char *cmd = (vu_char *) info->start[0];
155         vu_char *dst = (vu_char *) addr;
156         unsigned char b;
157         unsigned oldpri;
158         ulong start;
159
160         while (cnt) {
161                 /* Check for sufficient erase */
162                 b = *src;
163                 if ((*dst & b) != b) {
164                         printf ("%02x : %02x\n", *dst, b);
165                         return (2);
166                 }
167
168                 /* Disable interrupts other than window underflow
169                  * (interrupt priority 2)
170                  */
171                 oldpri = ipri (3);
172                 *cmd = 0xaa;
173                 *cmd = 0x55;
174                 *cmd = 0xa0;
175                 *dst = b;
176
177                 /* Verify write */
178                 start = get_timer (0);
179                 while (*dst != b) {
180                         if (get_timer (start) > CFG_FLASH_WRITE_TOUT) {
181                                 ipri (oldpri);
182                                 return 1;
183                         }
184                 }
185                 dst++;
186                 src++;
187                 cnt--;
188                 ipri (oldpri);
189         }
190
191         return (0);
192 }