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