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