]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/rsdproto/flash.c
Merge branch 'u-boot/master' into u-boot-arm/master
[karo-tx-uboot.git] / board / rsdproto / flash.c
1 /*
2  * (C) Copyright 2000
3  * Marius Groeger <mgroeger@sysgo.de>
4  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
5  *
6  * (C) Copyright 2000
7  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
8  *
9  * Flash Routines for AM290[48]0B devices
10  *
11  *--------------------------------------------------------------------
12  * SPDX-License-Identifier:     GPL-2.0+
13  */
14
15 #include <common.h>
16 #include <mpc8xx.h>
17
18 /* flash hardware ids */
19 #define VENDOR_AMD     0x0001
20 #define AMD_29DL323C_B 0x2253
21
22 /* Define this to include autoselect sequence in flash_init(). Does NOT
23  * work when executing from flash itself, so this should be turned
24  * on only when debugging the RAM version.
25  */
26 #undef WITH_AUTOSELECT
27
28 flash_info_t    flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
29
30 #if 1
31 #define D(x)
32 #else
33 #define D(x) printf x
34 #endif
35
36 /*-----------------------------------------------------------------------
37  * Functions
38  */
39
40 static unsigned char write_ull(flash_info_t *info,
41                                unsigned long address,
42                                volatile unsigned long long data);
43
44 /* from flash_asm.S */
45 extern void ull_write(unsigned long long volatile *address,
46                       unsigned long long volatile *data);
47 extern void ull_read(unsigned long long volatile *address,
48                      unsigned long long volatile *data);
49
50 /*-----------------------------------------------------------------------
51  */
52
53 unsigned long flash_init (void)
54 {
55     int i;
56     ulong addr;
57
58 #ifdef WITH_AUTOSELECT
59         {
60                 unsigned long long *f_addr = (unsigned long long *)PHYS_FLASH;
61                 unsigned long long f_command, vendor, device;
62                 /* Perform Autoselect */
63                 f_command       = 0x00AA00AA00AA00AAULL;
64                 ull_write(&f_addr[0x555], &f_command);
65                 f_command       = 0x0055005500550055ULL;
66                 ull_write(&f_addr[0x2AA], &f_command);
67                 f_command       = 0x0090009000900090ULL;
68                 ull_write(&f_addr[0x555], &f_command);
69                 ull_read(&f_addr[0], &vendor);
70                 vendor &= 0xffff;
71                 ull_read(&f_addr[1], &device);
72                 device &= 0xffff;
73                 f_command       = 0x00F000F000F000F0ULL;
74                 ull_write(&f_addr[0x555], &f_command);
75                 if (vendor != VENDOR_AMD || device != AMD_29DL323C_B)
76                   return 0;
77         }
78 #endif
79
80     /* Init: no FLASHes known */
81     for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
82                 flash_info[i].flash_id = FLASH_UNKNOWN;
83     }
84
85         /* 1st bank: 8 x 32 KB sectors */
86         flash_info[0].flash_id = VENDOR_AMD << 16 | AMD_29DL323C_B;
87         flash_info[0].sector_count = 8;
88         flash_info[0].size = flash_info[0].sector_count * 32 * 1024;
89         addr = PHYS_FLASH;
90     for(i = 0; i < flash_info[0].sector_count; i++) {
91                 flash_info[0].start[i] = addr;
92                 addr += flash_info[0].size / flash_info[0].sector_count;
93         }
94         /* 1st bank: 63 x 256 KB sectors */
95         flash_info[1].flash_id = VENDOR_AMD << 16 | AMD_29DL323C_B;
96         flash_info[1].sector_count = 63;
97         flash_info[1].size = flash_info[1].sector_count * 256 * 1024;
98     for(i = 0; i < flash_info[1].sector_count; i++) {
99                 flash_info[1].start[i] = addr;
100                 addr += flash_info[1].size / flash_info[1].sector_count;
101         }
102
103         /*
104          * protect monitor and environment sectors
105          */
106
107 #if CONFIG_SYS_MONITOR_BASE >= PHYS_FLASH
108         flash_protect(FLAG_PROTECT_SET,
109                       CONFIG_SYS_MONITOR_BASE,
110                       CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
111                       &flash_info[0]);
112         flash_protect(FLAG_PROTECT_SET,
113                       CONFIG_SYS_MONITOR_BASE,
114                       CONFIG_SYS_MONITOR_BASE+monitor_flash_len-1,
115                       &flash_info[1]);
116 #endif
117
118 #if defined(CONFIG_ENV_IS_IN_FLASH) && defined(CONFIG_ENV_ADDR)
119 # ifndef  CONFIG_ENV_SIZE
120 #  define CONFIG_ENV_SIZE       CONFIG_ENV_SECT_SIZE
121 # endif
122         flash_protect(FLAG_PROTECT_SET,
123                       CONFIG_ENV_ADDR,
124                       CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
125                       &flash_info[0]);
126         flash_protect(FLAG_PROTECT_SET,
127                       CONFIG_ENV_ADDR,
128                       CONFIG_ENV_ADDR + CONFIG_ENV_SIZE - 1,
129                       &flash_info[1]);
130 #endif
131
132     return flash_info[0].size + flash_info[1].size;
133 }
134
135 /*-----------------------------------------------------------------------
136  */
137 void flash_print_info  (flash_info_t *info)
138 {
139     int i;
140
141     if (info->flash_id == FLASH_UNKNOWN) {
142                 printf ("missing or unknown FLASH type\n");
143                 return;
144     }
145
146     switch (info->flash_id >> 16) {
147     case VENDOR_AMD:
148                 printf ("AMD ");
149                 break;
150     default:
151                 printf ("Unknown Vendor ");
152                 break;
153     }
154
155     switch (info->flash_id & FLASH_TYPEMASK) {
156     case AMD_29DL323C_B:
157                 printf ("AM29DL323CB (32 Mbit)\n");
158                 break;
159     default:
160                 printf ("Unknown Chip Type\n");
161                 break;
162     }
163
164     printf ("  Size: %ld MB in %d Sectors\n",
165                         info->size >> 20, info->sector_count);
166
167     printf ("  Sector Start Addresses:");
168     for (i=0; i<info->sector_count; ++i) {
169                 if ((i % 5) == 0)
170                   printf ("\n   ");
171                 printf (" %08lX%s",
172                                 info->start[i],
173                                 info->protect[i] ? " (RO)" : "     "
174                                 );
175     }
176     printf ("\n");
177     return;
178 }
179
180 /*-----------------------------------------------------------------------
181  */
182
183 int     flash_erase (flash_info_t *info, int s_first, int s_last)
184 {
185     int flag, prot, sect, l_sect;
186     ulong start;
187         unsigned long long volatile *f_addr;
188         unsigned long long volatile f_command;
189
190     if ((s_first < 0) || (s_first > s_last)) {
191                 if (info->flash_id == FLASH_UNKNOWN) {
192                         printf ("- missing\n");
193                 } else {
194                         printf ("- no sectors to erase\n");
195                 }
196                 return 1;
197     }
198
199     prot = 0;
200     for (sect = s_first; sect <= s_last; sect++) {
201                 if (info->protect[sect]) {
202                         prot++;
203                 }
204     }
205     if (prot) {
206                 printf ("- Warning: %d protected sectors will not be erased!\n",
207                                 prot);
208     } else {
209                 printf ("\n");
210     }
211
212         f_addr  = (unsigned long long *)info->start[0];
213         f_command       = 0x00AA00AA00AA00AAULL;
214         ull_write(&f_addr[0x555], &f_command);
215         f_command       = 0x0055005500550055ULL;
216         ull_write(&f_addr[0x2AA], &f_command);
217         f_command       = 0x0080008000800080ULL;
218         ull_write(&f_addr[0x555], &f_command);
219         f_command       = 0x00AA00AA00AA00AAULL;
220         ull_write(&f_addr[0x555], &f_command);
221         f_command       = 0x0055005500550055ULL;
222         ull_write(&f_addr[0x2AA], &f_command);
223
224     /* Disable interrupts which might cause a timeout here */
225     flag = disable_interrupts();
226
227     /* Start erase on unprotected sectors */
228     for (l_sect = -1, sect = s_first; sect<=s_last; sect++) {
229                 if (info->protect[sect] == 0) { /* not protected */
230
231                         f_addr  =
232                           (unsigned long long *)(info->start[sect]);
233                         f_command       = 0x0030003000300030ULL;
234                         ull_write(f_addr, &f_command);
235                         l_sect = sect;
236                 }
237     }
238
239     /* re-enable interrupts if necessary */
240     if (flag)
241       enable_interrupts();
242
243         start = get_timer (0);
244         do
245         {
246                 if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT)
247                 {       /* write reset command, command address is unimportant */
248                         /* this command turns the flash back to read mode     */
249                         f_addr =
250                           (unsigned long long *)(info->start[l_sect]);
251                         f_command       = 0x00F000F000F000F0ULL;
252                         ull_write(f_addr, &f_command);
253                         printf (" timeout\n");
254                         return 1;
255         }
256         } while(*f_addr != 0xFFFFFFFFFFFFFFFFULL);
257
258     printf (" done\n");
259     return 0;
260 }
261
262 /*-----------------------------------------------------------------------
263  * Copy memory to flash, returns:
264  * 0 - OK
265  * 1 - write timeout
266  * 2 - Flash not erased
267  */
268
269 int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
270 {
271     unsigned long cp, wp;
272         unsigned long long data;
273     int i, l, rc;
274
275     wp = (addr & ~7);   /* get lower long long aligned address */
276
277     /*
278      * handle unaligned start bytes
279      */
280     if ((l = addr - wp) != 0) {
281                 data = 0;
282                 for (i=0, cp=wp; i<l; ++i, ++cp) {
283                         data = (data << 8) | (*(uchar *)cp);
284                 }
285                 for (; i<8 && cnt>0; ++i) {
286                         data = (data << 8) | *src++;
287                         --cnt;
288                         ++cp;
289                 }
290                 for (; cnt==0 && i<8; ++i, ++cp) {
291                         data = (data << 8) | (*(uchar *)cp);
292                 }
293
294                 if ((rc = write_ull(info, wp, data)) != 0) {
295                         return rc;
296                 }
297                 wp += 4;
298     }
299
300     /*
301      * handle long long aligned part
302      */
303     while (cnt >= 8) {
304                 data = 0;
305                 for (i=0; i<8; ++i) {
306                         data = (data << 8) | *src++;
307                 }
308                 if ((rc = write_ull(info, wp, data)) != 0) {
309                         return rc;
310                 }
311                 wp  += 8;
312                 cnt -= 8;
313     }
314
315     if (cnt == 0) {
316                 return ERR_OK;
317     }
318
319     /*
320      * handle unaligned tail bytes
321      */
322     data = 0;
323     for (i=0, cp=wp; i<8 && cnt>0; ++i, ++cp) {
324                 data = (data << 8) | *src++;
325                 --cnt;
326     }
327     for (; i<8; ++i, ++cp) {
328                 data = (data << 8) | (*(uchar *)cp);
329     }
330
331     return write_ull(info, wp, data);
332 }
333
334 /*---------------------------------------------------------------------------
335 *
336 * FUNCTION NAME:  write_ull
337 *
338 * DESCRIPTION:   writes 8 bytes to flash
339 *
340 * EXTERNAL EFFECT: nothing
341 *
342 * PARAMETERS:   32 bit long pointer to address, 64 bit long pointer to data
343 *
344 * RETURNS:      0 if OK, 1 if timeout, 4 if parameter error
345 *--------------------------------------------------------------------------*/
346
347 static unsigned char write_ull(flash_info_t *info,
348                                                            unsigned long address,
349                                                            volatile unsigned long long data)
350 {
351         static unsigned long long f_command;
352         static unsigned long long *f_addr;
353         ulong start;
354
355         /* address muss be 8-aligned! */
356         if (address & 0x7)
357           return ERR_ALIGN;
358
359         f_addr  = (unsigned long long *)info->start[0];
360         f_command       = 0x00AA00AA00AA00AAULL;
361         ull_write(&f_addr[0x555], &f_command);
362         f_command       = 0x0055005500550055ULL;
363         ull_write(&f_addr[0x2AA], &f_command);
364         f_command       = 0x00A000A000A000A0ULL;
365         ull_write(&f_addr[0x555], &f_command);
366
367         f_addr  = (unsigned long long *)address;
368         f_command       = data;
369         ull_write(f_addr, &f_command);
370
371         start = get_timer (0);
372         do
373         {
374                 if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT)
375                 {
376                         /* write reset command, command address is unimportant */
377                         /* this command turns the flash back to read mode     */
378                         f_addr  = (unsigned long long *)info->start[0];
379                         f_command       = 0x00F000F000F000F0ULL;
380                         ull_write(f_addr, &f_command);
381                         return ERR_TIMOUT;
382                 }
383         } while(*((unsigned long long *)address) != data);
384
385         return 0;
386 }