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 
flash_print_info(flash_info_t * info)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 
flash_init(void)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 
flash_erase(flash_info_t * info,int s_first,int s_last)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 
write_word(flash_info_t * info,ulong dest,ulong data)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 
write_buff(flash_info_t * info,uchar * src,ulong addr,ulong cnt)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 }
370