MINI2440: Auto probe for SDRAM size
[u-boot-openmoko/mini2440.git] / board / qt2410 / flash.c
blob57345f6fb2592dc0ae6132730983f69fe6860c43
1 /*
2 * (C) Copyright 2002
3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4 * Alex Zuepke <azu@sysgo.de>
6 * See file CREDITS for list of people who contributed to this
7 * project.
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
25 #include <common.h>
27 ulong myflush (void);
30 #define FLASH_BANK_SIZE PHYS_FLASH_SIZE
31 #define MAIN_SECT_SIZE 0x10000 /* 64 KB */
33 flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
36 #define CMD_READ_ARRAY 0x000000F0
37 #define CMD_UNLOCK1 0x000000AA
38 #define CMD_UNLOCK2 0x00000055
39 #define CMD_ERASE_SETUP 0x00000080
40 #define CMD_ERASE_CONFIRM 0x00000030
41 #define CMD_PROGRAM 0x000000A0
42 #define CMD_UNLOCK_BYPASS 0x00000020
44 #define MEM_FLASH_ADDR1 (*(volatile u16 *)(CFG_FLASH_BASE + (0x00000555 << 1)))
45 #define MEM_FLASH_ADDR2 (*(volatile u16 *)(CFG_FLASH_BASE + (0x000002AA << 1)))
47 #define BIT_ERASE_DONE 0x00000080
48 #define BIT_RDY_MASK 0x00000080
49 #define BIT_PROGRAM_ERROR 0x00000020
50 #define BIT_TIMEOUT 0x80000000 /* our flag */
52 #define READY 1
53 #define ERR 2
54 #define TMO 4
56 /*-----------------------------------------------------------------------
59 ulong flash_init (void)
61 int i, j;
62 ulong size = 0;
64 for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
65 ulong flashbase = 0;
67 flash_info[i].flash_id =
68 #if defined(CONFIG_AMD_LV400)
69 (AMD_MANUFACT & FLASH_VENDMASK) |
70 (AMD_ID_LV400B & FLASH_TYPEMASK);
71 #elif defined(CONFIG_AMD_LV800)
72 (AMD_MANUFACT & FLASH_VENDMASK) |
73 (AMD_ID_LV800B & FLASH_TYPEMASK);
74 #else
75 #error "Unknown flash configured"
76 #endif
77 flash_info[i].size = FLASH_BANK_SIZE;
78 flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
79 memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
80 if (i == 0)
81 flashbase = PHYS_FLASH_1;
82 else
83 panic ("configured too many flash banks!\n");
84 for (j = 0; j < flash_info[i].sector_count; j++) {
85 if (j <= 3) {
86 /* 1st one is 16 KB */
87 if (j == 0) {
88 flash_info[i].start[j] =
89 flashbase + 0;
92 /* 2nd and 3rd are both 8 KB */
93 if ((j == 1) || (j == 2)) {
94 flash_info[i].start[j] =
95 flashbase + 0x4000 + (j -
96 1) *
97 0x2000;
100 /* 4th 32 KB */
101 if (j == 3) {
102 flash_info[i].start[j] =
103 flashbase + 0x8000;
105 } else {
106 flash_info[i].start[j] =
107 flashbase + (j - 3) * MAIN_SECT_SIZE;
110 size += flash_info[i].size;
113 flash_protect (FLAG_PROTECT_SET,
114 CFG_FLASH_BASE,
115 CFG_FLASH_BASE + monitor_flash_len - 1,
116 &flash_info[0]);
118 #if 0
119 flash_protect (FLAG_PROTECT_SET,
120 CFG_ENV_ADDR,
121 CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);
122 #endif
124 return size;
127 /*-----------------------------------------------------------------------
129 void flash_print_info (flash_info_t * info)
131 int i;
133 switch (info->flash_id & FLASH_VENDMASK) {
134 case (AMD_MANUFACT & FLASH_VENDMASK):
135 printf ("AMD: ");
136 break;
137 default:
138 printf ("Unknown Vendor ");
139 break;
142 switch (info->flash_id & FLASH_TYPEMASK) {
143 case (AMD_ID_LV400B & FLASH_TYPEMASK):
144 printf ("1x Amd29LV400BB (4Mbit)\n");
145 break;
146 case (AMD_ID_LV800B & FLASH_TYPEMASK):
147 printf ("1x Amd29LV800BB (8Mbit)\n");
148 break;
149 default:
150 printf ("Unknown Chip Type\n");
151 goto Done;
152 break;
155 printf (" Size: %ld MB in %d Sectors\n",
156 info->size >> 20, info->sector_count);
158 printf (" Sector Start Addresses:");
159 for (i = 0; i < info->sector_count; i++) {
160 if ((i % 5) == 0) {
161 printf ("\n ");
163 printf (" %08lX%s", info->start[i],
164 info->protect[i] ? " (RO)" : " ");
166 printf ("\n");
168 Done:;
171 /*-----------------------------------------------------------------------
174 int flash_erase (flash_info_t * info, int s_first, int s_last)
176 ushort result;
177 int iflag, cflag, prot, sect;
178 int rc = ERR_OK;
179 int chip;
181 /* first look for protection bits */
183 if (info->flash_id == FLASH_UNKNOWN)
184 return ERR_UNKNOWN_FLASH_TYPE;
186 if ((s_first < 0) || (s_first > s_last)) {
187 return ERR_INVAL;
190 if ((info->flash_id & FLASH_VENDMASK) !=
191 (AMD_MANUFACT & FLASH_VENDMASK)) {
192 return ERR_UNKNOWN_FLASH_VENDOR;
195 prot = 0;
196 for (sect = s_first; sect <= s_last; ++sect) {
197 if (info->protect[sect]) {
198 prot++;
201 if (prot)
202 return ERR_PROTECTED;
205 * Disable interrupts which might cause a timeout
206 * here. Remember that our exception vectors are
207 * at address 0 in the flash, and we don't want a
208 * (ticker) exception to happen while the flash
209 * chip is in programming mode.
211 cflag = icache_status ();
212 icache_disable ();
213 iflag = disable_interrupts ();
215 /* Start erase on unprotected sectors */
216 for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
217 printf ("Erasing sector %2d ... ", sect);
219 /* arm simple, non interrupt dependent timer */
220 reset_timer_masked ();
222 if (info->protect[sect] == 0) { /* not protected */
223 vu_short *addr = (vu_short *) (info->start[sect]);
225 MEM_FLASH_ADDR1 = CMD_UNLOCK1;
226 MEM_FLASH_ADDR2 = CMD_UNLOCK2;
227 MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
229 MEM_FLASH_ADDR1 = CMD_UNLOCK1;
230 MEM_FLASH_ADDR2 = CMD_UNLOCK2;
231 *addr = CMD_ERASE_CONFIRM;
233 /* wait until flash is ready */
234 chip = 0;
236 do {
237 result = *addr;
239 /* check timeout */
240 if (get_timer_masked () >
241 CFG_FLASH_ERASE_TOUT) {
242 MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
243 chip = TMO;
244 break;
247 if (!chip
248 && (result & 0xFFFF) & BIT_ERASE_DONE)
249 chip = READY;
251 if (!chip
252 && (result & 0xFFFF) & BIT_PROGRAM_ERROR)
253 chip = ERR;
255 } while (!chip);
257 MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
259 if (chip == ERR) {
260 rc = ERR_PROG_ERROR;
261 goto outahere;
263 if (chip == TMO) {
264 rc = ERR_TIMOUT;
265 goto outahere;
268 printf ("ok.\n");
269 } else { /* it was protected */
271 printf ("protected!\n");
275 if (ctrlc ())
276 printf ("User Interrupt!\n");
278 outahere:
279 /* allow flash to settle - wait 10 ms */
280 udelay_masked (10000);
282 if (iflag)
283 enable_interrupts ();
285 if (cflag)
286 icache_enable ();
288 return rc;
291 /*-----------------------------------------------------------------------
292 * Copy memory to flash
295 volatile static int write_hword (flash_info_t * info, ulong dest, ushort data)
297 vu_short *addr = (vu_short *) dest;
298 ushort result;
299 int rc = ERR_OK;
300 int cflag, iflag;
301 int chip;
304 * Check if Flash is (sufficiently) erased
306 result = *addr;
307 if ((result & data) != data)
308 return ERR_NOT_ERASED;
312 * Disable interrupts which might cause a timeout
313 * here. Remember that our exception vectors are
314 * at address 0 in the flash, and we don't want a
315 * (ticker) exception to happen while the flash
316 * chip is in programming mode.
318 cflag = icache_status ();
319 icache_disable ();
320 iflag = disable_interrupts ();
322 MEM_FLASH_ADDR1 = CMD_UNLOCK1;
323 MEM_FLASH_ADDR2 = CMD_UNLOCK2;
324 MEM_FLASH_ADDR1 = CMD_UNLOCK_BYPASS;
325 *addr = CMD_PROGRAM;
326 *addr = data;
328 /* arm simple, non interrupt dependent timer */
329 reset_timer_masked ();
331 /* wait until flash is ready */
332 chip = 0;
333 do {
334 result = *addr;
336 /* check timeout */
337 if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) {
338 chip = ERR | TMO;
339 break;
341 if (!chip && ((result & 0x80) == (data & 0x80)))
342 chip = READY;
344 if (!chip && ((result & 0xFFFF) & BIT_PROGRAM_ERROR)) {
345 result = *addr;
347 if ((result & 0x80) == (data & 0x80))
348 chip = READY;
349 else
350 chip = ERR;
353 } while (!chip);
355 *addr = CMD_READ_ARRAY;
357 if (chip == ERR || *addr != data)
358 rc = ERR_PROG_ERROR;
360 if (iflag)
361 enable_interrupts ();
363 if (cflag)
364 icache_enable ();
366 return rc;
369 /*-----------------------------------------------------------------------
370 * Copy memory to flash.
373 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
375 ulong cp, wp;
376 int l;
377 int i, rc;
378 ushort data;
380 wp = (addr & ~1); /* get lower word aligned address */
383 * handle unaligned start bytes
385 if ((l = addr - wp) != 0) {
386 data = 0;
387 for (i = 0, cp = wp; i < l; ++i, ++cp) {
388 data = (data >> 8) | (*(uchar *) cp << 8);
390 for (; i < 2 && cnt > 0; ++i) {
391 data = (data >> 8) | (*src++ << 8);
392 --cnt;
393 ++cp;
395 for (; cnt == 0 && i < 2; ++i, ++cp) {
396 data = (data >> 8) | (*(uchar *) cp << 8);
399 if ((rc = write_hword (info, wp, data)) != 0) {
400 return (rc);
402 wp += 2;
406 * handle word aligned part
408 while (cnt >= 2) {
409 data = *((vu_short *) src);
410 if ((rc = write_hword (info, wp, data)) != 0) {
411 return (rc);
413 src += 2;
414 wp += 2;
415 cnt -= 2;
418 if (cnt == 0) {
419 return ERR_OK;
423 * handle unaligned tail bytes
425 data = 0;
426 for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) {
427 data = (data >> 8) | (*src++ << 8);
428 --cnt;
430 for (; i < 2; ++i, ++cp) {
431 data = (data >> 8) | (*(uchar *) cp << 8);
434 return write_hword (info, wp, data);