blob: 9acc3a00106e889d1e0f5c5504f6ccd2aab3b3e7 [file] [log] [blame]
wdenkaffae2b2002-08-17 09:36:01 +00001/*
2 * (C) Copyright 2000
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
wdenkaffae2b2002-08-17 09:36:01 +00006 * Hacked for the Hymod board by Murray.Jensen@cmst.csiro.au, 20-Oct-00
7 */
8
9#include <common.h>
10#include <mpc8xx.h>
11#include <galileo/gt64260R.h>
12#include <galileo/memory.h>
13#include "intel_flash.h"
14
15
16/*-----------------------------------------------------------------------
17 * Protection Flags:
18 */
19#define FLAG_PROTECT_SET 0x01
20#define FLAG_PROTECT_CLEAR 0x02
21
22static void
23bank_reset(flash_info_t *info, int sect)
24{
25 bank_addr_t addrw, eaddrw;
26
27 addrw = (bank_addr_t)info->start[sect];
28 eaddrw = BANK_ADDR_NEXT_WORD(addrw);
29
30 while (addrw < eaddrw) {
31#ifdef FLASH_DEBUG
32 printf(" writing reset cmd to addr 0x%08lx\n",
33 (unsigned long)addrw);
34#endif
35 *addrw = BANK_CMD_RST;
36 addrw++;
37 }
38}
39
40static void
41bank_erase_init(flash_info_t *info, int sect)
42{
43 bank_addr_t addrw, saddrw, eaddrw;
44 int flag;
45
46#ifdef FLASH_DEBUG
47 printf("0x%08x BANK_CMD_PROG\n", BANK_CMD_PROG);
48 printf("0x%08x BANK_CMD_ERASE1\n", BANK_CMD_ERASE1);
49 printf("0x%08x BANK_CMD_ERASE2\n", BANK_CMD_ERASE2);
50 printf("0x%08x BANK_CMD_CLR_STAT\n", BANK_CMD_CLR_STAT);
51 printf("0x%08x BANK_CMD_RST\n", BANK_CMD_RST);
52 printf("0x%08x BANK_STAT_RDY\n", BANK_STAT_RDY);
53 printf("0x%08x BANK_STAT_ERR\n", BANK_STAT_ERR);
54#endif
55
56 saddrw = (bank_addr_t)info->start[sect];
57 eaddrw = BANK_ADDR_NEXT_WORD(saddrw);
58
59#ifdef FLASH_DEBUG
60 printf("erasing sector %d, start addr = 0x%08lx "
61 "(bank next word addr = 0x%08lx)\n", sect,
62 (unsigned long)saddrw, (unsigned long)eaddrw);
63#endif
64
65 /* Disable intrs which might cause a timeout here */
66 flag = disable_interrupts();
67
68 for (addrw = saddrw; addrw < eaddrw; addrw++) {
69#ifdef FLASH_DEBUG
70 printf(" writing erase cmd to addr 0x%08lx\n",
71 (unsigned long)addrw);
72#endif
73 *addrw = BANK_CMD_ERASE1;
74 *addrw = BANK_CMD_ERASE2;
75 }
76
77 /* re-enable interrupts if necessary */
78 if (flag)
79 enable_interrupts();
80}
81
82static int
83bank_erase_poll(flash_info_t *info, int sect)
84{
85 bank_addr_t addrw, saddrw, eaddrw;
86 int sectdone, haderr;
87
88 saddrw = (bank_addr_t)info->start[sect];
89 eaddrw = BANK_ADDR_NEXT_WORD(saddrw);
90
91 sectdone = 1;
92 haderr = 0;
93
94 for (addrw = saddrw; addrw < eaddrw; addrw++) {
95 bank_word_t stat = *addrw;
96
97#ifdef FLASH_DEBUG
98 printf(" checking status at addr "
99 "0x%08x [0x%08x]\n",
100 (unsigned long)addrw, stat);
101#endif
102 if ((stat & BANK_STAT_RDY) != BANK_STAT_RDY)
103 sectdone = 0;
104 else if ((stat & BANK_STAT_ERR) != 0) {
105 printf(" failed on sector %d "
106 "(stat = 0x%08x) at "
107 "address 0x%p\n",
108 sect, stat, addrw);
109 *addrw = BANK_CMD_CLR_STAT;
110 haderr = 1;
111 }
112 }
113
114 if (haderr)
115 return (-1);
116 else
117 return (sectdone);
118}
119
120int
121write_word_intel(bank_addr_t addr, bank_word_t value)
122{
123 bank_word_t stat;
124 ulong start;
125 int flag, retval;
126
127 /* Disable interrupts which might cause a timeout here */
128 flag = disable_interrupts();
129
130 *addr = BANK_CMD_PROG;
131
132 *addr = value;
133
134 /* re-enable interrupts if necessary */
135 if (flag)
136 enable_interrupts();
137
138 retval = 0;
139
140 /* data polling for D7 */
141 start = get_timer (0);
142 do {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200143 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
wdenkaffae2b2002-08-17 09:36:01 +0000144 retval = 1;
145 goto done;
146 }
147 stat = *addr;
148 } while ((stat & BANK_STAT_RDY) != BANK_STAT_RDY);
149
150 if ((stat & BANK_STAT_ERR) != 0) {
151 printf("flash program failed (stat = 0x%08lx) "
152 "at address 0x%08lx\n", (ulong)stat, (ulong)addr);
153 *addr = BANK_CMD_CLR_STAT;
154 retval = 3;
155 }
156
157done:
158 /* reset to read mode */
159 *addr = BANK_CMD_RST;
160
161 return (retval);
162}
163
164/*-----------------------------------------------------------------------
165 */
166
167int
168flash_erase_intel(flash_info_t *info, int s_first, int s_last)
169{
170 int prot, sect, haderr;
171 ulong start, now, last;
172
173#ifdef FLASH_DEBUG
174 printf("\nflash_erase: erase %d sectors (%d to %d incl.) from\n"
175 " Bank # %d: ", s_last - s_first + 1, s_first, s_last,
176 (info - flash_info) + 1);
177 flash_print_info(info);
178#endif
179
180 if ((s_first < 0) || (s_first > s_last)) {
181 if (info->flash_id == FLASH_UNKNOWN) {
182 printf ("- missing\n");
183 } else {
184 printf ("- no sectors to erase\n");
185 }
186 return 1;
187 }
188
189 prot = 0;
190 for (sect=s_first; sect<=s_last; ++sect) {
191 if (info->protect[sect]) {
192 prot++;
193 }
194 }
195
196 if (prot) {
197 printf("- Warning: %d protected sector%s will not be erased!\n",
198 prot, (prot > 1 ? "s" : ""));
199 }
200
201 start = get_timer (0);
202 last = 0;
203 haderr = 0;
204
205 for (sect = s_first; sect <= s_last; sect++) {
206 if (info->protect[sect] == 0) { /* not protected */
207 ulong estart;
208 int sectdone;
209
210 bank_erase_init(info, sect);
211
212 /* wait at least 80us - let's wait 1 ms */
213 udelay (1000);
214
215 estart = get_timer(start);
216
217 do {
218 now = get_timer(start);
219
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200220 if (now - estart > CONFIG_SYS_FLASH_ERASE_TOUT) {
wdenkaffae2b2002-08-17 09:36:01 +0000221 printf ("Timeout (sect %d)\n", sect);
222 haderr = 1;
223 break;
224 }
225
226#ifndef FLASH_DEBUG
227 /* show that we're waiting */
228 if ((now - last) > 1000) { /* every second */
229 putc ('.');
230 last = now;
231 }
232#endif
233
234 sectdone = bank_erase_poll(info, sect);
235
236 if (sectdone < 0) {
237 haderr = 1;
238 break;
239 }
240
241 } while (!sectdone);
242
243 if (haderr)
244 break;
245 }
246 }
247
248 if (haderr > 0)
249 printf (" failed\n");
250 else
251 printf (" done\n");
252
253 /* reset to read mode */
254 for (sect = s_first; sect <= s_last; sect++) {
255 if (info->protect[sect] == 0) { /* not protected */
256 bank_reset(info, sect);
257 }
258 }
259 return haderr;
260}