]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/idmr/flash.c
Merge branch 'master' of git://git.denx.de/u-boot-mpc85xx
[karo-tx-uboot.git] / board / idmr / flash.c
1 /*
2  * (C) Copyright 2000-2006
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9
10 #define PHYS_FLASH_1 CONFIG_SYS_FLASH_BASE
11 #define FLASH_BANK_SIZE 0x800000
12 #define EN29LV640 0x227e227e
13
14 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
15
16 void flash_print_info (flash_info_t * info)
17 {
18         int i;
19
20         switch (info->flash_id & FLASH_VENDMASK) {
21         case (AMD_MANUFACT & FLASH_VENDMASK):
22                 printf ("AMD: ");
23                 break;
24         default:
25                 printf ("Unknown Vendor ");
26                 break;
27         }
28
29         switch (info->flash_id & FLASH_TYPEMASK) {
30         case (EN29LV640 & FLASH_TYPEMASK):
31                 printf ("EN29LV640 (16Mbit)\n");
32                 break;
33         default:
34                 printf ("Unknown Chip Type\n");
35                 goto Done;
36                 break;
37         }
38
39         printf ("  Size: %ld MB in %d Sectors\n",
40                 info->size >> 20, info->sector_count);
41
42         printf ("  Sector Start Addresses:");
43         for (i = 0; i < info->sector_count; i++) {
44                 if ((i % 5) == 0) {
45                         printf ("\n   ");
46                 }
47                 printf (" %08lX%s", info->start[i],
48                         info->protect[i] ? " (RO)" : "     ");
49         }
50         printf ("\n");
51
52       Done:
53         return;
54 }
55
56
57 unsigned long flash_init (void)
58 {
59         int i, j;
60         ulong size = 0;
61
62         for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
63                 ulong flashbase = 0;
64
65                 flash_info[i].flash_id =
66                         (AMD_MANUFACT & FLASH_VENDMASK) |
67                         (EN29LV640 & FLASH_TYPEMASK);
68                 flash_info[i].size = FLASH_BANK_SIZE;
69                 flash_info[i].sector_count = CONFIG_SYS_MAX_FLASH_SECT;
70                 memset (flash_info[i].protect, 0, CONFIG_SYS_MAX_FLASH_SECT);
71                 if (i == 0)
72                         flashbase = PHYS_FLASH_1;
73                 else
74                         panic ("configured to many flash banks!\n");
75
76                 for (j = 0; j < flash_info[i].sector_count; j++) {
77                         flash_info[i].start[j] = flashbase + 0x10000 * j;
78                 }
79                 size += flash_info[i].size;
80         }
81
82         flash_protect (FLAG_PROTECT_SET,
83                        CONFIG_SYS_FLASH_BASE,
84                        CONFIG_SYS_FLASH_BASE + 0x2ffff, &flash_info[0]);
85
86         return size;
87 }
88
89
90 #define CMD_READ_ARRAY          0x00F0
91 #define CMD_UNLOCK1             0x00AA
92 #define CMD_UNLOCK2             0x0055
93 #define CMD_ERASE_SETUP         0x0080
94 #define CMD_ERASE_CONFIRM       0x0030
95 #define CMD_PROGRAM             0x00A0
96 #define CMD_UNLOCK_BYPASS       0x0020
97
98 #define MEM_FLASH_ADDR1         (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x00000555<<1)))
99 #define MEM_FLASH_ADDR2         (*(volatile u16 *)(CONFIG_SYS_FLASH_BASE + (0x000002AA<<1)))
100
101 #define BIT_ERASE_DONE          0x0080
102 #define BIT_RDY_MASK            0x0080
103 #define BIT_PROGRAM_ERROR       0x0020
104 #define BIT_TIMEOUT             0x80000000      /* our flag */
105
106 #define READY 1
107 #define ERR   2
108 #define TMO   4
109
110
111 int flash_erase (flash_info_t * info, int s_first, int s_last)
112 {
113         ulong result;
114         int iflag, prot, sect;
115         int rc = ERR_OK;
116         int chip1;
117         ulong start;
118
119         /* first look for protection bits */
120
121         if (info->flash_id == FLASH_UNKNOWN)
122                 return ERR_UNKNOWN_FLASH_TYPE;
123
124         if ((s_first < 0) || (s_first > s_last)) {
125                 return ERR_INVAL;
126         }
127
128         if ((info->flash_id & FLASH_VENDMASK) !=
129             (AMD_MANUFACT & FLASH_VENDMASK)) {
130                 return ERR_UNKNOWN_FLASH_VENDOR;
131         }
132
133         prot = 0;
134         for (sect = s_first; sect <= s_last; ++sect) {
135                 if (info->protect[sect]) {
136                         prot++;
137                 }
138         }
139         if (prot)
140                 return ERR_PROTECTED;
141
142         /*
143          * Disable interrupts which might cause a timeout
144          * here. Remember that our exception vectors are
145          * at address 0 in the flash, and we don't want a
146          * (ticker) exception to happen while the flash
147          * chip is in programming mode.
148          */
149         iflag = disable_interrupts ();
150
151         printf ("\n");
152
153         /* Start erase on unprotected sectors */
154         for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
155                 printf ("Erasing sector %2d ... ", sect);
156
157                 /* arm simple, non interrupt dependent timer */
158                 start = get_timer(0);
159
160                 if (info->protect[sect] == 0) { /* not protected */
161                         volatile u16 *addr =
162                                 (volatile u16 *) (info->start[sect]);
163
164                         MEM_FLASH_ADDR1 = CMD_UNLOCK1;
165                         MEM_FLASH_ADDR2 = CMD_UNLOCK2;
166                         MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;
167
168                         MEM_FLASH_ADDR1 = CMD_UNLOCK1;
169                         MEM_FLASH_ADDR2 = CMD_UNLOCK2;
170                         *addr = CMD_ERASE_CONFIRM;
171
172                         /* wait until flash is ready */
173                         chip1 = 0;
174
175                         do {
176                                 result = *addr;
177
178                                 /* check timeout */
179                                 if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT * CONFIG_SYS_HZ / 1000) {
180                                         MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
181                                         chip1 = TMO;
182                                         break;
183                                 }
184
185                                 if (!chip1
186                                     && (result & 0xFFFF) & BIT_ERASE_DONE)
187                                         chip1 = READY;
188
189                         } while (!chip1);
190
191                         MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
192
193                         if (chip1 == ERR) {
194                                 rc = ERR_PROG_ERROR;
195                                 goto outahere;
196                         }
197                         if (chip1 == TMO) {
198                                 rc = ERR_TIMOUT;
199                                 goto outahere;
200                         }
201
202                         printf ("ok.\n");
203                 } else {        /* it was protected */
204
205                         printf ("protected!\n");
206                 }
207         }
208
209         if (ctrlc ())
210                 printf ("User Interrupt!\n");
211
212       outahere:
213         /* allow flash to settle - wait 10 ms */
214         printf("Waiting 10 ms...");
215          udelay (10000);
216
217 /*      for (i = 0; i < 10 * 1000 * 1000; ++i)
218                 asm(" nop");
219 */
220
221         printf("done\n");
222         if (iflag)
223                 enable_interrupts ();
224
225
226         return rc;
227 }
228
229 static int write_word (flash_info_t * info, ulong dest, ulong data)
230 {
231         volatile u16 *addr = (volatile u16 *) dest;
232         ulong result;
233         int rc = ERR_OK;
234         int iflag;
235         int chip1;
236         ulong start;
237
238         /*
239          * Check if Flash is (sufficiently) erased
240          */
241         result = *addr;
242         if ((result & data) != data)
243                 return ERR_NOT_ERASED;
244
245
246         /*
247          * Disable interrupts which might cause a timeout
248          * here. Remember that our exception vectors are
249          * at address 0 in the flash, and we don't want a
250          * (ticker) exception to happen while the flash
251          * chip is in programming mode.
252          */
253         iflag = disable_interrupts ();
254
255         MEM_FLASH_ADDR1 = CMD_UNLOCK1;
256         MEM_FLASH_ADDR2 = CMD_UNLOCK2;
257         MEM_FLASH_ADDR1 = CMD_PROGRAM;
258         *addr = data;
259
260         /* arm simple, non interrupt dependent timer */
261         start = get_timer(0);
262
263         /* wait until flash is ready */
264         chip1 = 0;
265         do {
266                 result = *addr;
267
268                 /* check timeout */
269                 if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT * CONFIG_SYS_HZ / 1000) {
270                         chip1 = ERR | TMO;
271                         break;
272                 }
273                 if (!chip1 && ((result & 0x80) == (data & 0x80)))
274                         chip1 = READY;
275
276         } while (!chip1);
277
278         *addr = CMD_READ_ARRAY;
279
280         if (chip1 == ERR || *addr != data)
281                 rc = ERR_PROG_ERROR;
282
283         if (iflag)
284                 enable_interrupts ();
285
286         return rc;
287 }
288
289
290 int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
291 {
292         ulong wp, data;
293         int rc;
294
295         if (addr & 1) {
296                 printf ("unaligned destination not supported\n");
297                 return ERR_ALIGN;
298         }
299
300 #if 0
301         if (cnt & 1) {
302                 printf ("odd transfer sizes not supported\n");
303                 return ERR_ALIGN;
304         }
305 #endif
306
307         wp = addr;
308
309         if (addr & 1) {
310                 data = (*((volatile u8 *) addr) << 8) | *((volatile u8 *)
311                                                           src);
312                 if ((rc = write_word (info, wp - 1, data)) != 0) {
313                         return (rc);
314                 }
315                 src += 1;
316                 wp += 1;
317                 cnt -= 1;
318         }
319
320         while (cnt >= 2) {
321                 data = *((volatile u16 *) src);
322                 if ((rc = write_word (info, wp, data)) != 0) {
323                         return (rc);
324                 }
325                 src += 2;
326                 wp += 2;
327                 cnt -= 2;
328         }
329
330         if (cnt == 1) {
331                 data = (*((volatile u8 *) src) << 8) |
332                         *((volatile u8 *) (wp + 1));
333                 if ((rc = write_word (info, wp, data)) != 0) {
334                         return (rc);
335                 }
336                 src += 1;
337                 wp += 1;
338                 cnt -= 1;
339         }
340
341         return ERR_OK;
342 }