]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/flash.c
Initial revision
[karo-tx-uboot.git] / common / flash.c
1 /*
2  * (C) Copyright 2000
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 #include <common.h>
25 #include <flash.h>
26
27 #if !defined(CFG_NO_FLASH)
28
29 extern flash_info_t  flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
30
31 /*-----------------------------------------------------------------------
32  * Functions
33  */
34
35 /*-----------------------------------------------------------------------
36  * Set protection status for monitor sectors
37  *
38  * The monitor is always located in the _first_ Flash bank.
39  * If necessary you have to map the second bank at lower addresses.
40  */
41 void
42 flash_protect (int flag, ulong from, ulong to, flash_info_t *info)
43 {
44         ulong b_end = info->start[0] + info->size - 1;  /* bank end address */
45         short s_end = info->sector_count - 1;   /* index of last sector */
46         int i;
47
48         /* Do nothing if input data is bad. */
49         if (info->sector_count == 0 || info->size == 0 || to < from) {
50                 return;
51         }
52
53         /* There is nothing to do if we have no data about the flash
54          * or the protect range and flash range don't overlap.
55          */
56         if (info->flash_id == FLASH_UNKNOWN ||
57             to < info->start[0] || from > b_end) {
58                 return;
59         }
60
61         for (i=0; i<info->sector_count; ++i) {
62                 ulong end;              /* last address in current sect */
63
64                 end = (i == s_end) ? b_end : info->start[i + 1] - 1;
65
66                 /* Update protection if any part of the sector
67                  * is in the specified range.
68                  */
69                 if (from <= end && to >= info->start[i]) {
70                         if (flag & FLAG_PROTECT_CLEAR) {
71 #if defined(CFG_FLASH_PROTECTION)
72                                 flash_real_protect(info, i, 0);
73 #else
74                                 info->protect[i] = 0;
75 #endif  /* CFG_FLASH_PROTECTION */
76                         }
77                         else if (flag & FLAG_PROTECT_SET) {
78 #if defined(CFG_FLASH_PROTECTION)
79                                 flash_real_protect(info, i, 1);
80 #else
81                                 info->protect[i] = 1;
82 #endif  /* CFG_FLASH_PROTECTION */
83                         }
84                 }
85         }
86 }
87
88 /*-----------------------------------------------------------------------
89  */
90
91 flash_info_t *
92 addr2info (ulong addr)
93 {
94 #ifndef CONFIG_SPD823TS
95         flash_info_t *info;
96         int i;
97
98         for (i=0, info=&flash_info[0]; i<CFG_MAX_FLASH_BANKS; ++i, ++info) {
99                 if (info->flash_id != FLASH_UNKNOWN &&
100                     addr >= info->start[0] &&
101                     /* WARNING - The '- 1' is needed if the flash
102                      * is at the end of the address space, since
103                      * info->start[0] + info->size wraps back to 0.
104                      * Please don't change this unless you understand this.
105                      */
106                     addr <= info->start[0] + info->size - 1) {
107                         return (info);
108                 }
109         }
110 #endif /* CONFIG_SPD823TS */
111
112         return (NULL);
113 }
114
115 /*-----------------------------------------------------------------------
116  * Copy memory to flash.
117  * Make sure all target addresses are within Flash bounds,
118  * and no protected sectors are hit.
119  * Returns:
120  * ERR_OK          0 - OK
121  * ERR_TIMOUT      1 - write timeout
122  * ERR_NOT_ERASED  2 - Flash not erased
123  * ERR_PROTECTED   4 - target range includes protected sectors
124  * ERR_INVAL       8 - target address not in Flash memory
125  * ERR_ALIGN       16 - target address not aligned on boundary
126  *                      (only some targets require alignment)
127  */
128 int
129 flash_write (uchar *src, ulong addr, ulong cnt)
130 {
131 #ifdef CONFIG_SPD823TS
132         return (ERR_TIMOUT);    /* any other error codes are possible as well */
133 #else
134         int i;
135         ulong         end        = addr + cnt - 1;
136         flash_info_t *info_first = addr2info (addr);
137         flash_info_t *info_last  = addr2info (end );
138         flash_info_t *info;
139
140         if (cnt == 0) {
141                 return (ERR_OK);
142         }
143
144         if (!info_first || !info_last) {
145                 return (ERR_INVAL);
146         }
147
148         for (info = info_first; info <= info_last; ++info) {
149                 ulong b_end = info->start[0] + info->size;      /* bank end addr */
150                 short s_end = info->sector_count - 1;
151                 for (i=0; i<info->sector_count; ++i) {
152                         ulong e_addr = (i == s_end) ? b_end : info->start[i + 1];
153
154                         if ((end >= info->start[i]) && (addr < e_addr) &&
155                             (info->protect[i] != 0) ) {
156                                 return (ERR_PROTECTED);
157                         }
158                 }
159         }
160
161         /* finally write data to flash */
162         for (info = info_first; info <= info_last && cnt>0; ++info) {
163                 ulong len;
164
165                 len = info->start[0] + info->size - addr;
166                 if (len > cnt)
167                         len = cnt;
168                 if ((i = write_buff(info, src, addr, len)) != 0) {
169                         return (i);
170                 }
171                 cnt  -= len;
172                 addr += len;
173                 src  += len;
174         }
175         return (ERR_OK);
176 #endif /* CONFIG_SPD823TS */
177 }
178
179 /*-----------------------------------------------------------------------
180  */
181
182 void flash_perror (int err)
183 {
184         switch (err) {
185         case ERR_OK:
186                 break;
187         case ERR_TIMOUT:
188                 puts ("Timeout writing to Flash\n");
189                 break;
190         case ERR_NOT_ERASED:
191                 puts ("Flash not Erased\n");
192                 break;
193         case ERR_PROTECTED:
194                 puts ("Can't write to protected Flash sectors\n");
195                 break;
196         case ERR_INVAL:
197                 puts ("Outside available Flash\n");
198                 break;
199         case ERR_ALIGN:
200                 puts ("Start and/or end address not on sector boundary\n");
201                 break;
202         case ERR_UNKNOWN_FLASH_VENDOR:
203                 puts ("Unknown Vendor of Flash\n");
204                 break;
205         case ERR_UNKNOWN_FLASH_TYPE:
206                 puts ("Unknown Type of Flash\n");
207                 break;
208         case ERR_PROG_ERROR:
209                 puts ("General Flash Programming Error\n");
210                 break;
211         default:
212                 printf ("%s[%d] FIXME: rc=%d\n", __FILE__, __LINE__, err);
213                 break;
214         }
215 }
216
217 /*-----------------------------------------------------------------------
218  */
219 #endif /* !CFG_NO_FLASH */