1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2000-2003
4  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5  *
6  * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
7  * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
8  */
9 
10 #include <common.h>
11 
12 #include <asm/immap.h>
13 
14 #ifndef CONFIG_SYS_FLASH_CFI
15 typedef unsigned short FLASH_PORT_WIDTH;
16 typedef volatile unsigned short FLASH_PORT_WIDTHV;
17 
18 #define FPW             FLASH_PORT_WIDTH
19 #define FPWV            FLASH_PORT_WIDTHV
20 
21 #define FLASH_CYCLE1    0x5555
22 #define FLASH_CYCLE2    0x2aaa
23 
24 #define SYNC			__asm__("nop")
25 
26 /*-----------------------------------------------------------------------
27  * Functions
28  */
29 
30 ulong flash_get_size(FPWV * addr, flash_info_t * info);
31 int flash_get_offsets(ulong base, flash_info_t * info);
32 int write_word(flash_info_t * info, FPWV * dest, u16 data);
33 static inline void spin_wheel(void);
34 
35 flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS];
36 
37 ulong flash_init(void)
38 {
39 	ulong size = 0;
40 	ulong fbase = 0;
41 
42 	fbase = (ulong) CONFIG_SYS_FLASH_BASE;
43 	flash_get_size((FPWV *) fbase, &flash_info[0]);
44 	flash_get_offsets((ulong) fbase, &flash_info[0]);
45 	fbase += flash_info[0].size;
46 	size += flash_info[0].size;
47 
48 	/* Protect monitor and environment sectors */
49 	flash_protect(FLAG_PROTECT_SET,
50 		      CONFIG_SYS_MONITOR_BASE,
51 		      CONFIG_SYS_MONITOR_BASE + monitor_flash_len - 1, &flash_info[0]);
52 
53 	return size;
54 }
55 
56 int flash_get_offsets(ulong base, flash_info_t * info)
57 {
58 	int i;
59 
60 	if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
61 
62 		info->start[0] = base;
63 		info->protect[0] = 0;
64 		for (i = 1; i < CONFIG_SYS_SST_SECT; i++) {
65 			info->start[i] = info->start[i - 1]
66 						+ CONFIG_SYS_SST_SECTSZ;
67 			info->protect[i] = 0;
68 		}
69 	}
70 
71 	return ERR_OK;
72 }
73 
74 void flash_print_info(flash_info_t * info)
75 {
76 	int i;
77 
78 	switch (info->flash_id & FLASH_VENDMASK) {
79 	case FLASH_MAN_SST:
80 		printf("SST ");
81 		break;
82 	default:
83 		printf("Unknown Vendor ");
84 		break;
85 	}
86 
87 	switch (info->flash_id & FLASH_TYPEMASK) {
88 	case FLASH_SST6401B:
89 		printf("SST39VF6401B\n");
90 		break;
91 	default:
92 		printf("Unknown Chip Type\n");
93 		return;
94 	}
95 
96 	if (info->size > 0x100000) {
97 		int remainder;
98 
99 		printf("  Size: %ld", info->size >> 20);
100 
101 		remainder = (info->size % 0x100000);
102 		if (remainder) {
103 			remainder >>= 10;
104 			remainder = (int)((float)
105 					  (((float)remainder / (float)1024) *
106 					   10000));
107 			printf(".%d ", remainder);
108 		}
109 
110 		printf("MB in %d Sectors\n", info->sector_count);
111 	} else
112 		printf("  Size: %ld KB in %d Sectors\n",
113 		       info->size >> 10, info->sector_count);
114 
115 	printf("  Sector Start Addresses:");
116 	for (i = 0; i < info->sector_count; ++i) {
117 		if ((i % 5) == 0)
118 			printf("\n   ");
119 		printf(" %08lX%s",
120 		       info->start[i], info->protect[i] ? " (RO)" : "     ");
121 	}
122 	printf("\n");
123 }
124 
125 /*
126  * The following code cannot be run from FLASH!
127  */
128 ulong flash_get_size(FPWV * addr, flash_info_t * info)
129 {
130 	u16 value;
131 
132 	addr[FLASH_CYCLE1] = (FPWV) 0x00AA00AA;	/* for Atmel, Intel ignores this */
133 	addr[FLASH_CYCLE2] = (FPWV) 0x00550055;	/* for Atmel, Intel ignores this */
134 	addr[FLASH_CYCLE1] = (FPWV) 0x00900090;	/* selects Intel or Atmel */
135 
136 	switch (addr[0] & 0xffff) {
137 	case (u8) SST_MANUFACT:
138 		info->flash_id = FLASH_MAN_SST;
139 		value = addr[1];
140 		break;
141 	default:
142 		printf("Unknown Flash\n");
143 		info->flash_id = FLASH_UNKNOWN;
144 		info->sector_count = 0;
145 		info->size = 0;
146 
147 		*addr = (FPW) 0x00F000F0;
148 		return (0);	/* no or unknown flash  */
149 	}
150 
151 	switch (value) {
152 	case (u16) SST_ID_xF6401B:
153 		info->flash_id += FLASH_SST6401B;
154 		break;
155 	default:
156 		info->flash_id = FLASH_UNKNOWN;
157 		break;
158 	}
159 
160 	info->sector_count = 0;
161 	info->size = 0;
162 	info->sector_count = CONFIG_SYS_SST_SECT;
163 	info->size = CONFIG_SYS_SST_SECT * CONFIG_SYS_SST_SECTSZ;
164 
165 	/* reset ID mode */
166 	*addr = (FPWV) 0x00F000F0;
167 
168 	if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) {
169 		printf("** ERROR: sector count %d > max (%d) **\n",
170 		       info->sector_count, CONFIG_SYS_MAX_FLASH_SECT);
171 		info->sector_count = CONFIG_SYS_MAX_FLASH_SECT;
172 	}
173 
174 	return (info->size);
175 }
176 
177 int flash_erase(flash_info_t * info, int s_first, int s_last)
178 {
179 	FPWV *addr;
180 	int flag, prot, sect, count;
181 	ulong type, start;
182 	int rcode = 0, flashtype = 0;
183 
184 	if ((s_first < 0) || (s_first > s_last)) {
185 		if (info->flash_id == FLASH_UNKNOWN)
186 			printf("- missing\n");
187 		else
188 			printf("- no sectors to erase\n");
189 		return 1;
190 	}
191 
192 	type = (info->flash_id & FLASH_VENDMASK);
193 
194 	switch (type) {
195 	case FLASH_MAN_SST:
196 		flashtype = 1;
197 		break;
198 	default:
199 		type = (info->flash_id & FLASH_VENDMASK);
200 		printf("Can't erase unknown flash type %08lx - aborted\n",
201 		       info->flash_id);
202 		return 1;
203 	}
204 
205 	prot = 0;
206 	for (sect = s_first; sect <= s_last; ++sect) {
207 		if (info->protect[sect]) {
208 			prot++;
209 		}
210 	}
211 
212 	if (prot)
213 		printf("- Warning: %d protected sectors will not be erased!\n",
214 		       prot);
215 	else
216 		printf("\n");
217 
218 	flag = disable_interrupts();
219 
220 	start = get_timer(0);
221 
222 	if ((s_last - s_first) == (CONFIG_SYS_SST_SECT - 1)) {
223 		if (prot == 0) {
224 			addr = (FPWV *) info->start[0];
225 
226 			addr[FLASH_CYCLE1] = 0x00AA;	/* unlock */
227 			addr[FLASH_CYCLE2] = 0x0055;	/* unlock */
228 			addr[FLASH_CYCLE1] = 0x0080;	/* erase mode */
229 			addr[FLASH_CYCLE1] = 0x00AA;	/* unlock */
230 			addr[FLASH_CYCLE2] = 0x0055;	/* unlock */
231 			*addr = 0x0030;	/* erase chip */
232 
233 			count = 0;
234 			start = get_timer(0);
235 
236 			while ((*addr & 0x0080) != 0x0080) {
237 				if (count++ > 0x10000) {
238 					spin_wheel();
239 					count = 0;
240 				}
241 
242 				if (get_timer(start) > CONFIG_SYS_FLASH_ERASE_TOUT) {
243 					printf("Timeout\n");
244 					*addr = 0x00F0;	/* reset to read mode */
245 
246 					return 1;
247 				}
248 			}
249 
250 			*addr = 0x00F0;	/* reset to read mode */
251 
252 			printf("\b. done\n");
253 
254 			if (flag)
255 				enable_interrupts();
256 
257 			return 0;
258 		} else if (prot == CONFIG_SYS_SST_SECT) {
259 			return 1;
260 		}
261 	}
262 
263 	/* Start erase on unprotected sectors */
264 	for (sect = s_first; sect <= s_last; sect++) {
265 		if (info->protect[sect] == 0) {	/* not protected */
266 
267 			addr = (FPWV *) (info->start[sect]);
268 
269 			printf(".");
270 
271 			/* arm simple, non interrupt dependent timer */
272 			start = get_timer(0);
273 
274 			switch (flashtype) {
275 			case 1:
276 				{
277 					FPWV *base;	/* first address in bank */
278 
279 					flag = disable_interrupts();
280 
281 					base = (FPWV *) (CONFIG_SYS_FLASH_BASE);	/* First sector */
282 
283 					base[FLASH_CYCLE1] = 0x00AA;	/* unlock */
284 					base[FLASH_CYCLE2] = 0x0055;	/* unlock */
285 					base[FLASH_CYCLE1] = 0x0080;	/* erase mode */
286 					base[FLASH_CYCLE1] = 0x00AA;	/* unlock */
287 					base[FLASH_CYCLE2] = 0x0055;	/* unlock */
288 					*addr = 0x0050;	/* erase sector */
289 
290 					if (flag)
291 						enable_interrupts();
292 
293 					while ((*addr & 0x0080) != 0x0080) {
294 						if (get_timer(start) >
295 						    CONFIG_SYS_FLASH_ERASE_TOUT) {
296 							printf("Timeout\n");
297 							*addr = 0x00F0;	/* reset to read mode */
298 
299 							rcode = 1;
300 							break;
301 						}
302 					}
303 
304 					*addr = 0x00F0;	/* reset to read mode */
305 					break;
306 				}
307 			}	/* switch (flashtype) */
308 		}
309 	}
310 	printf(" done\n");
311 
312 	if (flag)
313 		enable_interrupts();
314 
315 	return rcode;
316 }
317 
318 int write_buff(flash_info_t * info, uchar * src, ulong addr, ulong cnt)
319 {
320 	ulong wp, count;
321 	u16 data;
322 	int rc;
323 
324 	if (info->flash_id == FLASH_UNKNOWN)
325 		return 4;
326 
327 	/* get lower word aligned address */
328 	wp = addr;
329 
330 	/* handle unaligned start bytes */
331 	if (wp & 1) {
332 		data = *((FPWV *) wp);
333 		data = (data << 8) | *src;
334 
335 		if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
336 			return (rc);
337 
338 		wp++;
339 		cnt -= 1;
340 		src++;
341 	}
342 
343 	while (cnt >= 2) {
344 		/*
345 		 * handle word aligned part
346 		 */
347 		count = 0;
348 		data = *((FPWV *) src);
349 
350 		if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
351 			return (rc);
352 
353 		wp += 2;
354 		src += 2;
355 		cnt -= 2;
356 
357 		if (count++ > 0x800) {
358 			spin_wheel();
359 			count = 0;
360 		}
361 	}
362 	/* handle word aligned part */
363 	if (cnt) {
364 		/* handle word aligned part */
365 		count = 0;
366 		data = *((FPWV *) wp);
367 
368 		data = (data & 0x00FF) | (*src << 8);
369 
370 		if ((rc = write_word(info, (FPWV *) wp, data)) != 0)
371 			return (rc);
372 
373 		wp++;
374 		src++;
375 		cnt -= 1;
376 		if (count++ > 0x800) {
377 			spin_wheel();
378 			count = 0;
379 		}
380 	}
381 
382 	if (cnt == 0)
383 		return ERR_OK;
384 
385 	return ERR_OK;
386 }
387 
388 /*-----------------------------------------------------------------------
389  * Write a word to Flash
390  * A word is 16 bits, whichever the bus width of the flash bank
391  * (not an individual chip) is.
392  *
393  * returns:
394  * 0 - OK
395  * 1 - write timeout
396  * 2 - Flash not erased
397  */
398 int write_word(flash_info_t * info, FPWV * dest, u16 data)
399 {
400 	ulong start;
401 	int flag;
402 	int res = 0;		/* result, assume success */
403 	FPWV *base;		/* first address in flash bank */
404 
405 	/* Check if Flash is (sufficiently) erased */
406 	if ((*dest & (u8) data) != (u8) data) {
407 		return (2);
408 	}
409 
410 	base = (FPWV *) (CONFIG_SYS_FLASH_BASE);
411 
412 	/* Disable interrupts which might cause a timeout here */
413 	flag = disable_interrupts();
414 
415 	base[FLASH_CYCLE1] = (u8) 0x00AA00AA;	/* unlock */
416 	base[FLASH_CYCLE2] = (u8) 0x00550055;	/* unlock */
417 	base[FLASH_CYCLE1] = (u8) 0x00A000A0;	/* selects program mode */
418 
419 	*dest = data;		/* start programming the data */
420 
421 	/* re-enable interrupts if necessary */
422 	if (flag)
423 		enable_interrupts();
424 
425 	start = get_timer(0);
426 
427 	/* data polling for D7 */
428 	while (res == 0
429 	       && (*dest & (u8) 0x00800080) != (data & (u8) 0x00800080)) {
430 		if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) {
431 			*dest = (u8) 0x00F000F0;	/* reset bank */
432 			res = 1;
433 		}
434 	}
435 
436 	*dest++ = (u8) 0x00F000F0;	/* reset bank */
437 
438 	return (res);
439 }
440 
441 static inline void spin_wheel(void)
442 {
443 	static int p = 0;
444 	static char w[] = "\\/-";
445 
446 	printf("\010%c", w[p]);
447 	(++p == 3) ? (p = 0) : 0;
448 }
449 
450 #endif
451