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