3
* Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
6
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
8
* SPDX-License-Identifier: GPL-2.0+
12
#include <linux/byteorder/swab.h>
15
flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
17
/* Board support for 1 or 2 flash devices */
18
#define FLASH_PORT_WIDTH32
19
#undef FLASH_PORT_WIDTH16
21
#ifdef FLASH_PORT_WIDTH16
22
#define FLASH_PORT_WIDTH ushort
23
#define FLASH_PORT_WIDTHV vu_short
24
#define SWAP(x) __swab16(x)
26
#define FLASH_PORT_WIDTH ulong
27
#define FLASH_PORT_WIDTHV vu_long
28
#define SWAP(x) __swab32(x)
31
#define FPW FLASH_PORT_WIDTH
32
#define FPWV FLASH_PORT_WIDTHV
34
#define mb() __asm__ __volatile__ ("" : : : "memory")
36
/*-----------------------------------------------------------------------
39
static ulong flash_get_size (FPW *addr, flash_info_t *info);
40
static int write_data (flash_info_t *info, ulong dest, FPW data);
41
static void flash_get_offsets (ulong base, flash_info_t *info);
42
void inline spin_wheel (void);
44
/*-----------------------------------------------------------------------
47
unsigned long flash_init (void)
52
for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
55
flash_get_size ((FPW *) PHYS_FLASH_1, &flash_info[i]);
56
flash_get_offsets (PHYS_FLASH_1, &flash_info[i]);
59
flash_get_size ((FPW *) PHYS_FLASH_2, &flash_info[i]);
60
flash_get_offsets (PHYS_FLASH_2, &flash_info[i]);
63
panic ("configured too many flash banks!\n");
66
size += flash_info[i].size;
69
/* Protect monitor and environment sectors
71
flash_protect ( FLAG_PROTECT_SET,
72
CONFIG_SYS_FLASH_BASE,
73
CONFIG_SYS_FLASH_BASE + monitor_flash_len - 1,
76
flash_protect ( FLAG_PROTECT_SET,
78
CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1, &flash_info[0] );
83
/*-----------------------------------------------------------------------
85
static void flash_get_offsets (ulong base, flash_info_t *info)
89
if (info->flash_id == FLASH_UNKNOWN) {
93
if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) {
94
for (i = 0; i < info->sector_count; i++) {
95
info->start[i] = base + (i * PHYS_FLASH_SECT_SIZE);
101
/*-----------------------------------------------------------------------
103
void flash_print_info (flash_info_t *info)
107
if (info->flash_id == FLASH_UNKNOWN) {
108
printf ("missing or unknown FLASH type\n");
112
switch (info->flash_id & FLASH_VENDMASK) {
113
case FLASH_MAN_INTEL:
117
printf ("Unknown Vendor ");
121
switch (info->flash_id & FLASH_TYPEMASK) {
122
case FLASH_28F128J3A:
123
printf ("28F128J3A\n");
126
printf ("Unknown Chip Type\n");
130
printf (" Size: %ld MB in %d Sectors\n",
131
info->size >> 20, info->sector_count);
133
printf (" Sector Start Addresses:");
134
for (i = 0; i < info->sector_count; ++i) {
139
info->protect[i] ? " (RO)" : " ");
146
* The following code cannot be run from FLASH!
148
static ulong flash_get_size (FPW *addr, flash_info_t *info)
152
/* Write auto select command: read Manufacturer ID */
153
addr[0x5555] = (FPW) 0x00AA00AA;
154
addr[0x2AAA] = (FPW) 0x00550055;
155
addr[0x5555] = (FPW) 0x00900090;
162
case (FPW) INTEL_MANUFACT:
163
info->flash_id = FLASH_MAN_INTEL;
167
info->flash_id = FLASH_UNKNOWN;
168
info->sector_count = 0;
170
addr[0] = (FPW) 0x00FF00FF; /* restore read mode */
171
return (0); /* no or unknown flash */
175
value = addr[1]; /* device ID */
179
case (FPW) INTEL_ID_28F128J3A:
180
info->flash_id += FLASH_28F128J3A;
181
info->sector_count = 128;
182
info->size = 0x02000000;
183
break; /* => 16 MB */
186
info->flash_id = FLASH_UNKNOWN;
190
if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
191
printf ("** ERROR: sector count %d > max (%d) **\n",
192
info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
193
info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
196
addr[0] = (FPW) 0x00FF00FF; /* restore read mode */
202
/*-----------------------------------------------------------------------
205
int flash_erase (flash_info_t *info, int s_first, int s_last)
211
if ((s_first < 0) || (s_first > s_last)) {
212
if (info->flash_id == FLASH_UNKNOWN) {
213
printf ("- missing\n");
215
printf ("- no sectors to erase\n");
220
type = (info->flash_id & FLASH_VENDMASK);
221
if ((type != FLASH_MAN_INTEL)) {
222
printf ("Can't erase unknown flash type %08lx - aborted\n",
228
for (sect = s_first; sect <= s_last; ++sect) {
229
if (info->protect[sect]) {
235
printf ("- Warning: %d protected sectors will not be erased!\n",
241
/* Disable interrupts which might cause a timeout here */
242
disable_interrupts();
244
/* Start erase on unprotected sectors */
245
for (sect = s_first; sect <= s_last; sect++) {
246
if (info->protect[sect] == 0) { /* not protected */
247
FPWV *addr = (FPWV *) (info->start[sect]);
250
printf ("Erasing sector %2d ... ", sect);
252
/* arm simple, non interrupt dependent timer */
253
start = get_timer(0);
255
*addr = (FPW) 0x00500050; /* clear status register */
256
*addr = (FPW) 0x00200020; /* erase setup */
257
*addr = (FPW) 0x00D000D0; /* erase confirm */
259
while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) {
260
if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
261
printf ("Timeout\n");
262
*addr = (FPW) 0x00B000B0; /* suspend erase */
263
*addr = (FPW) 0x00FF00FF; /* reset to read mode */
269
*addr = 0x00500050; /* clear status register cmd. */
270
*addr = 0x00FF00FF; /* resest to read mode */
278
/*-----------------------------------------------------------------------
279
* Copy memory to flash, returns:
282
* 2 - Flash not erased
283
* 4 - Flash not identified
286
int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
290
int count, i, l, rc, port_width;
292
if (info->flash_id == FLASH_UNKNOWN) {
295
/* get lower word aligned address */
296
#ifdef FLASH_PORT_WIDTH16
305
* handle unaligned start bytes
307
if ((l = addr - wp) != 0) {
309
for (i = 0, cp = wp; i < l; ++i, ++cp) {
310
data = (data << 8) | (*(uchar *) cp);
312
for (; i < port_width && cnt > 0; ++i) {
313
data = (data << 8) | *src++;
317
for (; cnt == 0 && i < port_width; ++i, ++cp) {
318
data = (data << 8) | (*(uchar *) cp);
321
if ((rc = write_data (info, wp, SWAP (data))) != 0) {
328
* handle word aligned part
331
while (cnt >= port_width) {
333
for (i = 0; i < port_width; ++i) {
334
data = (data << 8) | *src++;
336
if ((rc = write_data (info, wp, SWAP (data))) != 0) {
341
if (count++ > 0x800) {
352
* handle unaligned tail bytes
355
for (i = 0, cp = wp; i < port_width && cnt > 0; ++i, ++cp) {
356
data = (data << 8) | *src++;
359
for (; i < port_width; ++i, ++cp) {
360
data = (data << 8) | (*(uchar *) cp);
363
return (write_data (info, wp, SWAP (data)));
366
/*-----------------------------------------------------------------------
367
* Write a word or halfword to Flash, returns:
370
* 2 - Flash not erased
372
static int write_data (flash_info_t *info, ulong dest, FPW data)
374
FPWV *addr = (FPWV *) dest;
378
/* Check if Flash is (sufficiently) erased */
379
if ((*addr & data) != data) {
380
printf ("not erased at %08lx (%lx)\n", (ulong) addr, *addr);
383
/* Disable interrupts which might cause a timeout here */
384
disable_interrupts();
386
*addr = (FPW) 0x00400040; /* write setup */
389
/* arm simple, non interrupt dependent timer */
390
start = get_timer(0);
392
/* wait while polling the status register */
393
while (((status = *addr) & (FPW) 0x00800080) != (FPW) 0x00800080) {
394
if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
395
*addr = (FPW) 0x00FF00FF; /* restore read mode */
400
*addr = (FPW) 0x00FF00FF; /* restore read mode */
405
void inline spin_wheel (void)
408
static char w[] = "\\/-";
410
printf ("\010%c", w[p]);
411
(++p == 3) ? (p = 0) : 0;