]>
git.ipfire.org Git - people/ms/u-boot.git/blob - arch/arm/cpu/arm720t/lpc2292/flash.c
2 * (C) Copyright 2006 Embedded Artists AB <www.embeddedartists.com>
4 * Modified to remove all but the IAP-command related code by
5 * Gary Jennejohn <garyj@denx.de>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24 #include <asm/arch/hardware.h>
26 /* IAP commands use 32 bytes at the top of CPU internal sram, we
27 use 512 bytes below that */
28 #define COPY_BUFFER_LOCATION 0x40003de0
30 #define IAP_LOCATION 0x7ffffff1
31 #define IAP_CMD_PREPARE 50
32 #define IAP_CMD_COPY 51
33 #define IAP_CMD_ERASE 52
34 #define IAP_CMD_CHECK 53
36 #define IAP_CMD_VERSION 55
37 #define IAP_CMD_COMPARE 56
39 #define IAP_RET_CMD_SUCCESS 0
41 static unsigned long command
[5];
42 static unsigned long result
[2];
44 extern void iap_entry(unsigned long * command
, unsigned long * result
);
46 /*-----------------------------------------------------------------------
49 static int get_flash_sector(flash_info_t
* info
, ulong flash_addr
)
53 for(i
= 1; i
< (info
->sector_count
); i
++) {
54 if (flash_addr
< (info
->start
[i
]))
61 /*-----------------------------------------------------------------------
62 * This function assumes that flash_addr is aligned on 512 bytes boundary
63 * in flash. This function also assumes that prepare have been called
64 * for the sector in question.
66 int lpc2292_copy_buffer_to_flash(flash_info_t
* info
, ulong flash_addr
)
71 first_sector
= get_flash_sector(info
, flash_addr
);
72 last_sector
= get_flash_sector(info
, flash_addr
+ 512 - 1);
74 /* prepare sectors for write */
75 command
[0] = IAP_CMD_PREPARE
;
76 command
[1] = first_sector
;
77 command
[2] = last_sector
;
78 iap_entry(command
, result
);
79 if (result
[0] != IAP_RET_CMD_SUCCESS
) {
80 printf("IAP prepare failed\n");
81 return ERR_PROG_ERROR
;
84 command
[0] = IAP_CMD_COPY
;
85 command
[1] = flash_addr
;
86 command
[2] = COPY_BUFFER_LOCATION
;
88 command
[4] = CONFIG_SYS_SYS_CLK_FREQ
>> 10;
89 iap_entry(command
, result
);
90 if (result
[0] != IAP_RET_CMD_SUCCESS
) {
91 printf("IAP copy failed\n");
98 /*-----------------------------------------------------------------------
101 int lpc2292_flash_erase (flash_info_t
* info
, int s_first
, int s_last
)
108 for (sect
= s_first
; sect
<= s_last
; ++sect
) {
109 if (info
->protect
[sect
]) {
114 return ERR_PROTECTED
;
117 flag
= disable_interrupts();
119 printf ("Erasing %d sectors starting at sector %2d.\n"
120 "This make take some time ... ",
121 s_last
- s_first
+ 1, s_first
);
123 command
[0] = IAP_CMD_PREPARE
;
124 command
[1] = s_first
;
126 iap_entry(command
, result
);
127 if (result
[0] != IAP_RET_CMD_SUCCESS
) {
128 printf("IAP prepare failed\n");
129 return ERR_PROTECTED
;
132 command
[0] = IAP_CMD_ERASE
;
133 command
[1] = s_first
;
135 command
[3] = CONFIG_SYS_SYS_CLK_FREQ
>> 10;
136 iap_entry(command
, result
);
137 if (result
[0] != IAP_RET_CMD_SUCCESS
) {
138 printf("IAP erase failed\n");
139 return ERR_PROTECTED
;
148 int lpc2292_write_buff (flash_info_t
* info
, uchar
* src
, ulong addr
,
163 dst_org
= (uchar
*)addr
;
165 first_block
= addr
/ 512;
166 last_block
= (addr
+ cnt
) / 512;
167 nbr_mid_blocks
= last_block
- first_block
- 1;
169 first_copy_size
= 512 - (addr
% 512);
170 last_copy_size
= (addr
+ cnt
) % 512;
172 debug("\ncopy first block: (1) %lX -> %lX 0x200 bytes, "
173 "(2) %lX -> %lX 0x%X bytes, (3) %lX -> %lX 0x200 bytes\n",
174 (ulong
)(first_block
* 512),
175 (ulong
)COPY_BUFFER_LOCATION
,
177 (ulong
)(COPY_BUFFER_LOCATION
+ 512 - first_copy_size
),
179 (ulong
)COPY_BUFFER_LOCATION
,
180 (ulong
)(first_block
* 512));
182 /* copy first block */
183 memcpy((void*)COPY_BUFFER_LOCATION
,
184 (void*)(first_block
* 512), 512);
185 memcpy((void*)(COPY_BUFFER_LOCATION
+ 512 - first_copy_size
),
186 src
, first_copy_size
);
187 lpc2292_copy_buffer_to_flash(info
, first_block
* 512);
188 src
+= first_copy_size
;
189 addr
+= first_copy_size
;
191 /* copy middle blocks */
192 for (i
= 0; i
< nbr_mid_blocks
; i
++) {
193 debug("copy middle block: %lX -> %lX 512 bytes, "
194 "%lX -> %lX 512 bytes\n",
196 (ulong
)COPY_BUFFER_LOCATION
,
197 (ulong
)COPY_BUFFER_LOCATION
,
200 memcpy((void*)COPY_BUFFER_LOCATION
, src
, 512);
201 lpc2292_copy_buffer_to_flash(info
, addr
);
207 if (last_copy_size
> 0) {
208 debug("copy last block: (1) %lX -> %lX 0x200 bytes, "
209 "(2) %lX -> %lX 0x%X bytes, (3) %lX -> %lX x200 bytes\n",
210 (ulong
)(last_block
* 512),
211 (ulong
)COPY_BUFFER_LOCATION
,
213 (ulong
)(COPY_BUFFER_LOCATION
),
215 (ulong
)COPY_BUFFER_LOCATION
,
218 /* copy last block */
219 memcpy((void*)COPY_BUFFER_LOCATION
,
220 (void*)(last_block
* 512), 512);
221 memcpy((void*)COPY_BUFFER_LOCATION
,
222 src
, last_copy_size
);
223 lpc2292_copy_buffer_to_flash(info
, addr
);
227 memmap_value
= GET8(MEMMAP
);
229 disable_interrupts();
231 PUT8(MEMMAP
, 01); /* we must make sure that initial 64
232 bytes are taken from flash when we
235 for (i
= 0; i
< cnt
; i
++) {
236 if (*dst_org
!= *src_org
){
237 printf("Write failed. Byte %lX differs\n", i
);
238 ret
= ERR_PROG_ERROR
;
245 PUT8(MEMMAP
, memmap_value
);