Blame view
board/lubbock/flash.c
8.9 KB
ea8015b85 Initial revision |
1 |
/* |
db2f721ff * Patch by Rune T... |
2 |
* (C) Copyright 2001 |
ea8015b85 Initial revision |
3 4 |
* Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net * |
db2f721ff * Patch by Rune T... |
5 6 |
* (C) Copyright 2001 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
ea8015b85 Initial revision |
7 |
* |
1a4596601 Add GPL-2.0+ SPDX... |
8 |
* SPDX-License-Identifier: GPL-2.0+ |
ea8015b85 Initial revision |
9 10 11 |
*/ #include <common.h> |
db2f721ff * Patch by Rune T... |
12 |
#include <linux/byteorder/swab.h> |
ea8015b85 Initial revision |
13 |
|
ea8015b85 Initial revision |
14 |
|
6d0f6bcf3 rename CFG_ macro... |
15 |
flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */ |
ea8015b85 Initial revision |
16 |
|
db2f721ff * Patch by Rune T... |
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
/* Board support for 1 or 2 flash devices */ #define FLASH_PORT_WIDTH32 #undef FLASH_PORT_WIDTH16 #ifdef FLASH_PORT_WIDTH16 #define FLASH_PORT_WIDTH ushort #define FLASH_PORT_WIDTHV vu_short #define SWAP(x) __swab16(x) #else #define FLASH_PORT_WIDTH ulong #define FLASH_PORT_WIDTHV vu_long #define SWAP(x) __swab32(x) #endif #define FPW FLASH_PORT_WIDTH #define FPWV FLASH_PORT_WIDTHV #define mb() __asm__ __volatile__ ("" : : : "memory") |
ea8015b85 Initial revision |
35 36 |
/*----------------------------------------------------------------------- |
db2f721ff * Patch by Rune T... |
37 |
* Functions |
ea8015b85 Initial revision |
38 |
*/ |
db2f721ff * Patch by Rune T... |
39 |
static ulong flash_get_size (FPW *addr, flash_info_t *info); |
06d01dbe0 * Avoid flicker o... |
40 41 42 |
static int write_data (flash_info_t *info, ulong dest, FPW data); static void flash_get_offsets (ulong base, flash_info_t *info); void inline spin_wheel (void); |
ea8015b85 Initial revision |
43 |
|
db2f721ff * Patch by Rune T... |
44 45 46 47 |
/*----------------------------------------------------------------------- */ unsigned long flash_init (void) |
ea8015b85 Initial revision |
48 |
{ |
06d01dbe0 * Avoid flicker o... |
49 50 |
int i; ulong size = 0; |
6d0f6bcf3 rename CFG_ macro... |
51 |
for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) { |
06d01dbe0 * Avoid flicker o... |
52 53 54 55 56 57 58 59 60 61 |
switch (i) { case 0: flash_get_size ((FPW *) PHYS_FLASH_1, &flash_info[i]); flash_get_offsets (PHYS_FLASH_1, &flash_info[i]); break; case 1: flash_get_size ((FPW *) PHYS_FLASH_2, &flash_info[i]); flash_get_offsets (PHYS_FLASH_2, &flash_info[i]); break; default: |
5f535fe17 * Patches by Ande... |
62 63 |
panic ("configured too many flash banks! "); |
06d01dbe0 * Avoid flicker o... |
64 65 66 67 68 69 70 71 |
break; } size += flash_info[i].size; } /* Protect monitor and environment sectors */ flash_protect ( FLAG_PROTECT_SET, |
6d0f6bcf3 rename CFG_ macro... |
72 73 |
CONFIG_SYS_FLASH_BASE, CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1, |
06d01dbe0 * Avoid flicker o... |
74 75 76 |
&flash_info[0] ); flash_protect ( FLAG_PROTECT_SET, |
0e8d15866 rename CFG_ENV ma... |
77 78 |
CONFIG_ENV_ADDR, CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0] ); |
06d01dbe0 * Avoid flicker o... |
79 80 |
return size; |
ea8015b85 Initial revision |
81 82 83 84 |
} /*----------------------------------------------------------------------- */ |
db2f721ff * Patch by Rune T... |
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
static void flash_get_offsets (ulong base, flash_info_t *info) { int i; if (info->flash_id == FLASH_UNKNOWN) { return; } if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { for (i = 0; i < info->sector_count; i++) { info->start[i] = base + (i * PHYS_FLASH_SECT_SIZE); info->protect[i] = 0; } } } /*----------------------------------------------------------------------- */ |
06d01dbe0 * Avoid flicker o... |
103 |
void flash_print_info (flash_info_t *info) |
ea8015b85 Initial revision |
104 |
{ |
db2f721ff * Patch by Rune T... |
105 |
int i; |
ea8015b85 Initial revision |
106 |
|
db2f721ff * Patch by Rune T... |
107 108 109 110 |
if (info->flash_id == FLASH_UNKNOWN) { printf ("missing or unknown FLASH type "); return; |
06d01dbe0 * Avoid flicker o... |
111 |
} |
ea8015b85 Initial revision |
112 |
|
db2f721ff * Patch by Rune T... |
113 |
switch (info->flash_id & FLASH_VENDMASK) { |
06d01dbe0 * Avoid flicker o... |
114 115 116 117 118 119 |
case FLASH_MAN_INTEL: printf ("INTEL "); break; default: printf ("Unknown Vendor "); break; |
db2f721ff * Patch by Rune T... |
120 121 122 |
} switch (info->flash_id & FLASH_TYPEMASK) { |
06d01dbe0 * Avoid flicker o... |
123 124 125 126 127 128 129 130 131 |
case FLASH_28F128J3A: printf ("28F128J3A "); break; default: printf ("Unknown Chip Type "); break; } |
ea8015b85 Initial revision |
132 |
|
db2f721ff * Patch by Rune T... |
133 134 |
printf (" Size: %ld MB in %d Sectors ", |
06d01dbe0 * Avoid flicker o... |
135 |
info->size >> 20, info->sector_count); |
ea8015b85 Initial revision |
136 |
|
db2f721ff * Patch by Rune T... |
137 |
printf (" Sector Start Addresses:"); |
06d01dbe0 * Avoid flicker o... |
138 139 140 141 |
for (i = 0; i < info->sector_count; ++i) { if ((i % 5) == 0) printf (" "); |
db2f721ff * Patch by Rune T... |
142 143 |
printf (" %08lX%s", info->start[i], |
06d01dbe0 * Avoid flicker o... |
144 145 146 147 |
info->protect[i] ? " (RO)" : " "); } printf (" "); |
db2f721ff * Patch by Rune T... |
148 149 150 151 152 153 154 155 156 157 158 |
return; } /* * The following code cannot be run from FLASH! */ static ulong flash_get_size (FPW *addr, flash_info_t *info) { volatile FPW value; /* Write auto select command: read Manufacturer ID */ |
06d01dbe0 * Avoid flicker o... |
159 160 161 |
addr[0x5555] = (FPW) 0x00AA00AA; addr[0x2AAA] = (FPW) 0x00550055; addr[0x5555] = (FPW) 0x00900090; |
db2f721ff * Patch by Rune T... |
162 |
|
06d01dbe0 * Avoid flicker o... |
163 |
mb (); |
db2f721ff * Patch by Rune T... |
164 |
value = addr[0]; |
06d01dbe0 * Avoid flicker o... |
165 |
switch (value) { |
db2f721ff * Patch by Rune T... |
166 |
|
06d01dbe0 * Avoid flicker o... |
167 168 169 |
case (FPW) INTEL_MANUFACT: info->flash_id = FLASH_MAN_INTEL; break; |
db2f721ff * Patch by Rune T... |
170 171 172 173 174 |
default: info->flash_id = FLASH_UNKNOWN; info->sector_count = 0; info->size = 0; |
06d01dbe0 * Avoid flicker o... |
175 176 |
addr[0] = (FPW) 0x00FF00FF; /* restore read mode */ return (0); /* no or unknown flash */ |
db2f721ff * Patch by Rune T... |
177 |
} |
06d01dbe0 * Avoid flicker o... |
178 179 |
mb (); value = addr[1]; /* device ID */ |
db2f721ff * Patch by Rune T... |
180 |
|
06d01dbe0 * Avoid flicker o... |
181 |
switch (value) { |
db2f721ff * Patch by Rune T... |
182 |
|
06d01dbe0 * Avoid flicker o... |
183 184 185 186 187 |
case (FPW) INTEL_ID_28F128J3A: info->flash_id += FLASH_28F128J3A; info->sector_count = 128; info->size = 0x02000000; break; /* => 16 MB */ |
db2f721ff * Patch by Rune T... |
188 189 190 191 192 |
default: info->flash_id = FLASH_UNKNOWN; break; } |
6d0f6bcf3 rename CFG_ macro... |
193 |
if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) { |
db2f721ff * Patch by Rune T... |
194 195 |
printf ("** ERROR: sector count %d > max (%d) ** ", |
6d0f6bcf3 rename CFG_ macro... |
196 197 |
info->sector_count, CONFIG_SYS_MAX_FLASH_SECT); info->sector_count = CONFIG_SYS_MAX_FLASH_SECT; |
06d01dbe0 * Avoid flicker o... |
198 |
} |
ea8015b85 Initial revision |
199 |
|
06d01dbe0 * Avoid flicker o... |
200 |
addr[0] = (FPW) 0x00FF00FF; /* restore read mode */ |
db2f721ff * Patch by Rune T... |
201 202 |
return (info->size); |
ea8015b85 Initial revision |
203 |
} |
db2f721ff * Patch by Rune T... |
204 |
|
ea8015b85 Initial revision |
205 206 |
/*----------------------------------------------------------------------- */ |
06d01dbe0 * Avoid flicker o... |
207 |
int flash_erase (flash_info_t *info, int s_first, int s_last) |
ea8015b85 Initial revision |
208 |
{ |
90729c023 board/lubbock/fla... |
209 |
int prot, sect; |
a60d1e5b8 Timer: Fix misuse... |
210 |
ulong type, start; |
db2f721ff * Patch by Rune T... |
211 |
int rcode = 0; |
ea8015b85 Initial revision |
212 |
|
06d01dbe0 * Avoid flicker o... |
213 |
if ((s_first < 0) || (s_first > s_last)) { |
db2f721ff * Patch by Rune T... |
214 215 216 217 218 219 220 221 |
if (info->flash_id == FLASH_UNKNOWN) { printf ("- missing "); } else { printf ("- no sectors to erase "); } return 1; |
06d01dbe0 * Avoid flicker o... |
222 |
} |
ea8015b85 Initial revision |
223 |
|
db2f721ff * Patch by Rune T... |
224 225 226 227 228 229 |
type = (info->flash_id & FLASH_VENDMASK); if ((type != FLASH_MAN_INTEL)) { printf ("Can't erase unknown flash type %08lx - aborted ", info->flash_id); return 1; |
06d01dbe0 * Avoid flicker o... |
230 |
} |
ea8015b85 Initial revision |
231 |
|
06d01dbe0 * Avoid flicker o... |
232 233 234 235 236 |
prot = 0; for (sect = s_first; sect <= s_last; ++sect) { if (info->protect[sect]) { prot++; } |
ea8015b85 Initial revision |
237 |
} |
ea8015b85 Initial revision |
238 |
|
db2f721ff * Patch by Rune T... |
239 240 241 242 243 244 245 246 |
if (prot) { printf ("- Warning: %d protected sectors will not be erased! ", prot); } else { printf (" "); } |
06d01dbe0 * Avoid flicker o... |
247 |
/* Disable interrupts which might cause a timeout here */ |
90729c023 board/lubbock/fla... |
248 |
disable_interrupts(); |
ea8015b85 Initial revision |
249 |
|
06d01dbe0 * Avoid flicker o... |
250 251 |
/* Start erase on unprotected sectors */ for (sect = s_first; sect <= s_last; sect++) { |
db2f721ff * Patch by Rune T... |
252 |
if (info->protect[sect] == 0) { /* not protected */ |
06d01dbe0 * Avoid flicker o... |
253 |
FPWV *addr = (FPWV *) (info->start[sect]); |
db2f721ff * Patch by Rune T... |
254 |
FPW status; |
ea8015b85 Initial revision |
255 |
|
06d01dbe0 * Avoid flicker o... |
256 |
printf ("Erasing sector %2d ... ", sect); |
ea8015b85 Initial revision |
257 |
|
06d01dbe0 * Avoid flicker o... |
258 |
/* arm simple, non interrupt dependent timer */ |
a60d1e5b8 Timer: Fix misuse... |
259 |
start = get_timer(0); |
ea8015b85 Initial revision |
260 |
|
06d01dbe0 * Avoid flicker o... |
261 262 263 |
*addr = (FPW) 0x00500050; /* clear status register */ *addr = (FPW) 0x00200020; /* erase setup */ *addr = (FPW) 0x00D000D0; /* erase confirm */ |
ea8015b85 Initial revision |
264 |
|
06d01dbe0 * Avoid flicker o... |
265 |
while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) { |
a60d1e5b8 Timer: Fix misuse... |
266 |
if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) { |
db2f721ff * Patch by Rune T... |
267 268 |
printf ("Timeout "); |
06d01dbe0 * Avoid flicker o... |
269 270 |
*addr = (FPW) 0x00B000B0; /* suspend erase */ *addr = (FPW) 0x00FF00FF; /* reset to read mode */ |
db2f721ff * Patch by Rune T... |
271 272 |
rcode = 1; break; |
06d01dbe0 * Avoid flicker o... |
273 274 |
} } |
ea8015b85 Initial revision |
275 |
|
06d01dbe0 * Avoid flicker o... |
276 277 |
*addr = 0x00500050; /* clear status register cmd. */ *addr = 0x00FF00FF; /* resest to read mode */ |
ea8015b85 Initial revision |
278 |
|
db2f721ff * Patch by Rune T... |
279 280 |
printf (" done "); |
06d01dbe0 * Avoid flicker o... |
281 282 |
} } |
db2f721ff * Patch by Rune T... |
283 |
return rcode; |
ea8015b85 Initial revision |
284 285 286 |
} /*----------------------------------------------------------------------- |
db2f721ff * Patch by Rune T... |
287 288 289 290 291 |
* Copy memory to flash, returns: * 0 - OK * 1 - write timeout * 2 - Flash not erased * 4 - Flash not identified |
ea8015b85 Initial revision |
292 293 294 295 |
*/ int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) { |
06d01dbe0 * Avoid flicker o... |
296 |
ulong cp, wp; |
db2f721ff * Patch by Rune T... |
297 298 |
FPW data; int count, i, l, rc, port_width; |
ea8015b85 Initial revision |
299 |
|
db2f721ff * Patch by Rune T... |
300 301 302 303 304 305 306 307 308 309 310 |
if (info->flash_id == FLASH_UNKNOWN) { return 4; } /* get lower word aligned address */ #ifdef FLASH_PORT_WIDTH16 wp = (addr & ~1); port_width = 2; #else wp = (addr & ~3); port_width = 4; #endif |
ea8015b85 Initial revision |
311 |
|
06d01dbe0 * Avoid flicker o... |
312 313 314 315 316 317 318 319 320 |
/* * handle unaligned start bytes */ if ((l = addr - wp) != 0) { data = 0; for (i = 0, cp = wp; i < l; ++i, ++cp) { data = (data << 8) | (*(uchar *) cp); } for (; i < port_width && cnt > 0; ++i) { |
db2f721ff * Patch by Rune T... |
321 |
data = (data << 8) | *src++; |
06d01dbe0 * Avoid flicker o... |
322 323 324 325 326 327 |
--cnt; ++cp; } for (; cnt == 0 && i < port_width; ++i, ++cp) { data = (data << 8) | (*(uchar *) cp); } |
ea8015b85 Initial revision |
328 |
|
06d01dbe0 * Avoid flicker o... |
329 330 331 |
if ((rc = write_data (info, wp, SWAP (data))) != 0) { return (rc); } |
db2f721ff * Patch by Rune T... |
332 |
wp += port_width; |
06d01dbe0 * Avoid flicker o... |
333 |
} |
ea8015b85 Initial revision |
334 |
|
06d01dbe0 * Avoid flicker o... |
335 336 337 |
/* * handle word aligned part */ |
db2f721ff * Patch by Rune T... |
338 339 340 |
count = 0; while (cnt >= port_width) { data = 0; |
06d01dbe0 * Avoid flicker o... |
341 |
for (i = 0; i < port_width; ++i) { |
db2f721ff * Patch by Rune T... |
342 343 |
data = (data << 8) | *src++; } |
06d01dbe0 * Avoid flicker o... |
344 345 346 347 |
if ((rc = write_data (info, wp, SWAP (data))) != 0) { return (rc); } wp += port_width; |
db2f721ff * Patch by Rune T... |
348 |
cnt -= port_width; |
06d01dbe0 * Avoid flicker o... |
349 350 |
if (count++ > 0x800) { spin_wheel (); |
db2f721ff * Patch by Rune T... |
351 352 |
count = 0; } |
06d01dbe0 * Avoid flicker o... |
353 |
} |
ea8015b85 Initial revision |
354 |
|
06d01dbe0 * Avoid flicker o... |
355 |
if (cnt == 0) { |
db2f721ff * Patch by Rune T... |
356 |
return (0); |
06d01dbe0 * Avoid flicker o... |
357 |
} |
ea8015b85 Initial revision |
358 |
|
06d01dbe0 * Avoid flicker o... |
359 360 361 362 363 |
/* * handle unaligned tail bytes */ data = 0; for (i = 0, cp = wp; i < port_width && cnt > 0; ++i, ++cp) { |
db2f721ff * Patch by Rune T... |
364 |
data = (data << 8) | *src++; |
06d01dbe0 * Avoid flicker o... |
365 366 367 368 |
--cnt; } for (; i < port_width; ++i, ++cp) { data = (data << 8) | (*(uchar *) cp); |
db2f721ff * Patch by Rune T... |
369 |
} |
06d01dbe0 * Avoid flicker o... |
370 |
return (write_data (info, wp, SWAP (data))); |
db2f721ff * Patch by Rune T... |
371 372 373 374 375 376 377 378 379 380 |
} /*----------------------------------------------------------------------- * Write a word or halfword to Flash, returns: * 0 - OK * 1 - write timeout * 2 - Flash not erased */ static int write_data (flash_info_t *info, ulong dest, FPW data) { |
06d01dbe0 * Avoid flicker o... |
381 |
FPWV *addr = (FPWV *) dest; |
db2f721ff * Patch by Rune T... |
382 |
ulong status; |
a60d1e5b8 Timer: Fix misuse... |
383 |
ulong start; |
db2f721ff * Patch by Rune T... |
384 385 386 |
/* Check if Flash is (sufficiently) erased */ if ((*addr & data) != data) { |
06d01dbe0 * Avoid flicker o... |
387 388 |
printf ("not erased at %08lx (%lx) ", (ulong) addr, *addr); |
db2f721ff * Patch by Rune T... |
389 390 391 |
return (2); } /* Disable interrupts which might cause a timeout here */ |
90729c023 board/lubbock/fla... |
392 |
disable_interrupts(); |
db2f721ff * Patch by Rune T... |
393 |
|
06d01dbe0 * Avoid flicker o... |
394 |
*addr = (FPW) 0x00400040; /* write setup */ |
db2f721ff * Patch by Rune T... |
395 396 397 |
*addr = data; /* arm simple, non interrupt dependent timer */ |
a60d1e5b8 Timer: Fix misuse... |
398 |
start = get_timer(0); |
db2f721ff * Patch by Rune T... |
399 400 |
/* wait while polling the status register */ |
06d01dbe0 * Avoid flicker o... |
401 |
while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) { |
c4f4c760c PXA: Fix Lubbock,... |
402 |
if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) { |
06d01dbe0 * Avoid flicker o... |
403 |
*addr = (FPW) 0x00FF00FF; /* restore read mode */ |
db2f721ff * Patch by Rune T... |
404 405 |
return (1); } |
06d01dbe0 * Avoid flicker o... |
406 |
} |
ea8015b85 Initial revision |
407 |
|
06d01dbe0 * Avoid flicker o... |
408 |
*addr = (FPW) 0x00FF00FF; /* restore read mode */ |
db2f721ff * Patch by Rune T... |
409 410 411 |
return (0); } |
06d01dbe0 * Avoid flicker o... |
412 |
void inline spin_wheel (void) |
db2f721ff * Patch by Rune T... |
413 |
{ |
06d01dbe0 * Avoid flicker o... |
414 415 |
static int p = 0; static char w[] = "\\/-"; |
db2f721ff * Patch by Rune T... |
416 |
|
06d01dbe0 * Avoid flicker o... |
417 418 |
printf ("\010%c", w[p]); (++p == 3) ? (p = 0) : 0; |
ea8015b85 Initial revision |
419 |
} |