]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - tools/updater/flash.c
* Patch by Thomas Frieden, 13 Nov 2002:
[karo-tx-uboot.git] / tools / updater / 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 extern flash_info_t  flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */
28
29 /*-----------------------------------------------------------------------
30  * Functions
31  */
32
33 /*-----------------------------------------------------------------------
34  * Set protection status for monitor sectors
35  *
36  * The monitor is always located in the _first_ Flash bank.
37  * If necessary you have to map the second bank at lower addresses.
38  */
39 void
40 flash_protect (int flag, ulong from, ulong to, flash_info_t *info)
41 {
42         ulong b_end = info->start[0] + info->size - 1;  /* bank end address */
43         short s_end = info->sector_count - 1;   /* index of last sector */
44         int i;
45
46         /* Do nothing if input data is bad. */
47         if (info->sector_count == 0 || info->size == 0 || to < from) {
48                 return;
49         }
50
51         /* There is nothing to do if we have no data about the flash
52          * or the protect range and flash range don't overlap.
53          */
54         if (info->flash_id == FLASH_UNKNOWN ||
55             to < info->start[0] || from > b_end) {
56                 return;
57         }
58
59         for (i=0; i<info->sector_count; ++i) {
60                 ulong end;              /* last address in current sect */
61
62                 end = (i == s_end) ? b_end : info->start[i + 1] - 1;
63
64                 /* Update protection if any part of the sector
65                  * is in the specified range.
66                  */
67                 if (from <= end && to >= info->start[i]) {
68                         if (flag & FLAG_PROTECT_CLEAR) {
69 #if defined(CFG_FLASH_PROTECTION)
70                                 flash_real_protect(info, i, 0);
71 #else
72                                 info->protect[i] = 0;
73 #endif  /* CFG_FLASH_PROTECTION */
74                         }
75                         else if (flag & FLAG_PROTECT_SET) {
76 #if defined(CFG_FLASH_PROTECTION)
77                                 flash_real_protect(info, i, 1);
78 #else
79                                 info->protect[i] = 1;
80 #endif  /* CFG_FLASH_PROTECTION */
81                         }
82                 }
83         }
84 }
85
86 /*-----------------------------------------------------------------------
87  */
88
89 flash_info_t *
90 addr2info (ulong addr)
91 {
92 #ifndef CONFIG_SPD823TS
93         flash_info_t *info;
94         int i;
95
96         for (i=0, info=&flash_info[0]; i<CFG_MAX_FLASH_BANKS; ++i, ++info) {
97                 if (info->flash_id != FLASH_UNKNOWN &&
98                     addr >= info->start[0] &&
99                     /* WARNING - The '- 1' is needed if the flash
100                      * is at the end of the address space, since
101                      * info->start[0] + info->size wraps back to 0.
102                      * Please don't change this unless you understand this.
103                      */
104                     addr <= info->start[0] + info->size - 1) {
105                         return (info);
106                 }
107         }
108 #endif /* CONFIG_SPD823TS */
109
110         return (NULL);
111 }
112
113 /*-----------------------------------------------------------------------
114  * Copy memory to flash.
115  * Make sure all target addresses are within Flash bounds,
116  * and no protected sectors are hit.
117  * Returns:
118  * ERR_OK          0 - OK
119  * ERR_TIMOUT      1 - write timeout
120  * ERR_NOT_ERASED  2 - Flash not erased
121  * ERR_PROTECTED   4 - target range includes protected sectors
122  * ERR_INVAL       8 - target address not in Flash memory
123  * ERR_ALIGN       16 - target address not aligned on boundary
124  *                      (only some targets require alignment)
125  */
126 int
127 flash_write (uchar *src, ulong addr, ulong cnt)
128 {
129 #ifdef CONFIG_SPD823TS
130         return (ERR_TIMOUT);    /* any other error codes are possible as well */
131 #else
132         int i;
133         ulong         end        = addr + cnt - 1;
134         flash_info_t *info_first = addr2info (addr);
135         flash_info_t *info_last  = addr2info (end );
136         flash_info_t *info;
137         int j;
138
139         if (cnt == 0) {
140                 return (ERR_OK);
141         }
142
143         if (!info_first || !info_last) {
144                 return (ERR_INVAL);
145         }
146
147         for (info = info_first; info <= info_last; ++info) {
148                 ulong b_end = info->start[0] + info->size;      /* bank end addr */
149                 short s_end = info->sector_count - 1;
150                 for (i=0; i<info->sector_count; ++i) {
151                         ulong e_addr = (i == s_end) ? b_end : info->start[i + 1];
152
153                         if ((end >= info->start[i]) && (addr < e_addr) &&
154                             (info->protect[i] != 0) ) {
155                                 return (ERR_PROTECTED);
156                         }
157                 }
158         }
159
160         mon_printf("\rWriting ");
161         for (j=0; j<20; j++) mon_putc(177);
162         mon_printf("\rWriting ");
163
164         /* finally write data to flash */
165         for (info = info_first; info <= info_last && cnt>0; ++info) {
166                 ulong len;
167
168                 len = info->start[0] + info->size - addr;
169                 if (len > cnt)
170                         len = cnt;
171
172                 if ((i = write_buff(info, src, addr, len)) != 0) {
173                         return (i);
174                 }
175                 cnt  -= len;
176                 addr += len;
177                 src  += len;
178         }
179         return (ERR_OK);
180 #endif /* CONFIG_SPD823TS */
181 }
182
183 /*-----------------------------------------------------------------------
184  */